Skip to content

Commit e2e59f5

Browse files
Fixed functions that return null causing crashes (#31)
--------- Co-authored-by: Daniel Chambers <[email protected]>
1 parent 089e447 commit e2e59f5

File tree

3 files changed

+84
-7
lines changed

3 files changed

+84
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Changes to be included in the next upcoming release
1212
- Support for NDC Spec v0.1.2 via the NDC TypeScript SDK v4.4.0 ([#29](https://github.com/hasura/ndc-nodejs-lambda/pull/29)).
1313
- Built-in scalar types that support equality now define it in the NDC schema.
1414
- Built-in scalar types now have an explicit type representation defined in the NDC schema.
15+
- Fixed functions that return null causing crashes ([#31](https://github.com/hasura/ndc-nodejs-lambda/pull/31))
1516

1617
## [1.2.0] - 2024-03-18
1718
- Improved error messages when unsupported enum types or unions of literal types are found, and allow these types to be used in relaxed types mode ([#17](https://github.com/hasura/ndc-nodejs-lambda/pull/17))

ndc-lambda-sdk/src/execution.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,10 @@ function coerceArgumentValue(value: unknown, type: schema.TypeReference, valuePa
170170
async function invokeFunction(func: Function, preparedArgs: unknown[], functionName: string): Promise<unknown> {
171171
try {
172172
return await withActiveSpan(tracer, `Function: ${functionName}`, async () => {
173-
const result = func.apply(undefined, preparedArgs);
173+
const result: unknown = func.apply(undefined, preparedArgs);
174174
// Await the result if it is a promise
175-
if (typeof result === "object" && 'then' in result && typeof result.then === "function") {
176-
return await result;
175+
if (result !== null && typeof result === "object" && "then" in result && typeof result.then === "function") {
176+
return await (result as PromiseLike<unknown>);
177177
}
178178
return result;
179179
}, { [FUNCTION_NAME_SPAN_ATTR_NAME]: functionName });

ndc-lambda-sdk/test/execution/execute-query.test.ts

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { describe, it } from "mocha";
22
import { assert, expect } from "chai";
33
import * as sdk from "@hasura/ndc-sdk-typescript"
44
import { executeQuery } from "../../src/execution";
5-
import { FunctionNdcKind, FunctionsSchema } from "../../src/schema";
5+
import { FunctionNdcKind, FunctionsSchema, NullOrUndefinability } from "../../src/schema";
66
import { sleep } from "../../src/util";
77

88
describe("execute query", function() {
@@ -389,9 +389,13 @@ describe("execute query", function() {
389389
parallelDegree: null,
390390
arguments: [],
391391
resultType: {
392-
type: "named",
393-
kind: "scalar",
394-
name: "String"
392+
type: "nullable",
393+
nullOrUndefinability: NullOrUndefinability.AcceptsNullOnly,
394+
underlyingType: {
395+
type: "named",
396+
kind: "scalar",
397+
name: "String"
398+
}
395399
}
396400
}
397401
},
@@ -493,5 +497,77 @@ describe("execute query", function() {
493497
]);
494498
assert.equal(functionCallCount, 1);
495499
});
500+
501+
it("function can return null", async function() {
502+
let functionCallCount = 0;
503+
const runtimeFunctions = {
504+
"theFunction": () => {
505+
functionCallCount++;
506+
return null;
507+
}
508+
};
509+
const queryRequest: sdk.QueryRequest = {
510+
collection: "theFunction",
511+
query: {
512+
fields: {
513+
"__value": {
514+
type: "column",
515+
column: "__value"
516+
}
517+
}
518+
},
519+
arguments: {},
520+
collection_relationships: {}
521+
};
522+
523+
const result = await executeQuery(queryRequest, functionSchema, runtimeFunctions);
524+
assert.deepStrictEqual(result, [
525+
{
526+
aggregates: null,
527+
rows: [
528+
{
529+
"__value": null,
530+
}
531+
]
532+
}
533+
]);
534+
assert.equal(functionCallCount, 1);
535+
});
536+
537+
it("async function can return null", async function() {
538+
let functionCallCount = 0;
539+
const runtimeFunctions = {
540+
"theFunction": async () => {
541+
functionCallCount++;
542+
return null;
543+
}
544+
};
545+
const queryRequest: sdk.QueryRequest = {
546+
collection: "theFunction",
547+
query: {
548+
fields: {
549+
"__value": {
550+
type: "column",
551+
column: "__value"
552+
}
553+
}
554+
},
555+
arguments: {},
556+
collection_relationships: {}
557+
};
558+
559+
const result = await executeQuery(queryRequest, functionSchema, runtimeFunctions);
560+
assert.deepStrictEqual(result, [
561+
{
562+
aggregates: null,
563+
rows: [
564+
{
565+
"__value": null,
566+
}
567+
]
568+
}
569+
]);
570+
assert.equal(functionCallCount, 1);
571+
});
496572
});
497573
});

0 commit comments

Comments
 (0)