Skip to content

Commit

Permalink
feat(deno/sdk): native function embedding in typescript (#598)
Browse files Browse the repository at this point in the history
Add support for function or lambda definition typescript sdk for
`deno.func` similarly to how `python.from_def` in python sdk works.

#### Motivation and context

Providing a string is a bit impractical and counter-intuitive espcially
when the sdk language matches with runtime's language.

#### Migration notes

No changes needed.

### Checklist

- [x] The change come with new or modified tests
- [ ] Hard-to-understand functions have explanatory comments
- [ ] End-user documentation is updated to reflect the change

---------

Signed-off-by: Michaël <[email protected]>
  • Loading branch information
michael-0acf4 committed Feb 26, 2024
1 parent a13ab9b commit fffe530
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 30 deletions.
21 changes: 0 additions & 21 deletions typegate/tests/runtimes/deno/deno_static.ts

This file was deleted.

22 changes: 17 additions & 5 deletions typegate/tests/runtimes/deno/deno_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,22 +122,34 @@ Meta.test("Deno runtime: use local imports", async (t) => {
});

Meta.test("Deno runtime with typescript", async (t) => {
const e = await t.engine("runtimes/deno/deno_static.ts");
const e = await t.engine("runtimes/deno/deno_typescript.ts");
await t.should("work with static values", async () => {
await gql`
query {
simpleStatic
structStatic {
static {
a
}
}
`.expectData({
simpleStatic: "One!",
structStatic: {
static: {
a: "Hello World",
},
}).on(e);
});

await t.should("work with native tyepscript code", async () => {
await gql`
query {
hello(name: "World")
helloFn(name: "wOrLd")
}
`
.expectData({
hello: "Hello World",
helloFn: "Hello world",
})
.on(e);
});
});

Meta.test("Deno runtime: file name reloading", async (t) => {
Expand Down
31 changes: 31 additions & 0 deletions typegate/tests/runtimes/deno/deno_typescript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright Metatype OÜ, licensed under the Elastic License 2.0.
// SPDX-License-Identifier: Elastic-2.0

import { Policy, t, typegraph } from "@typegraph/sdk/index.js";
import { DenoRuntime } from "@typegraph/sdk/runtimes/deno.js";

const hello = ({ name }: any) => `Hello ${name}`;
function helloFn({ name }: any) {
return `Hello ${(name as string).toLowerCase()}`;
}

typegraph("test-deno-tyepscript", (g: any) => {
const deno = new DenoRuntime();
const pub = Policy.public();

g.expose({
static: deno.static(t.struct({ a: t.string() }), {
a: "Hello World",
}).withPolicy(pub),
hello: deno.func(
t.struct({ name: t.string() }),
t.string(),
{ code: hello },
).withPolicy(pub),
helloFn: deno.func(
t.struct({ name: t.string() }),
t.string(),
{ code: helloFn },
).withPolicy(pub),
});
});
32 changes: 28 additions & 4 deletions typegraph/node/sdk/src/runtimes/deno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface PredefinedFuncMat extends Materializer {
}

export interface DenoFunc {
code: string;
code: string | Function;
secrets?: Array<string>;
effect?: Effect;
}
Expand All @@ -38,6 +38,26 @@ export interface DenoImport {
effect?: Effect;
}

function stringifyFn(code: string | Function) {
if (typeof code == "function") {
const source = code.toString();
const namedFnMatch = source.match(/function\s*(\*?\s*[a-zA-Z0-9_]+)/);
if (namedFnMatch) {
const [, name] = namedFnMatch;
if (name.replace(/\s/g, "").startsWith("*")) {
throw new Error(`Generator function "${name}" not supported`);
}
if (/function\s[a-zA-Z0-9_]+\(\) { \[native code\] }/.test(source)) {
throw new Error(
`"${name}" is not supported as it is a native function`,
);
}
}
return source;
}
return code;
}

export class DenoRuntime extends Runtime {
constructor() {
super(runtimes.getDenoRuntime());
Expand All @@ -51,10 +71,11 @@ export class DenoRuntime extends Runtime {
out: O,
{ code, secrets = [], effect = fx.read() }: DenoFunc,
): t.Func<I, O, FunMat> {
const matId = runtimes.registerDenoFunc({ code, secrets }, effect);
const source = stringifyFn(code);
const matId = runtimes.registerDenoFunc({ code: source, secrets }, effect);
const mat: FunMat = {
_id: matId,
code,
code: source,
secrets,
effect,
};
Expand Down Expand Up @@ -123,7 +144,10 @@ export class DenoRuntime extends Runtime {

return Policy.create(
name,
runtimes.registerDenoFunc(params, fx.read()),
runtimes.registerDenoFunc(
{ ...params, code: stringifyFn(params.code) },
fx.read(),
),
);
}

Expand Down
26 changes: 26 additions & 0 deletions website/static/specs/0.0.3.json
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,24 @@
"$ref": "#/definitions/InjectionData_for_String"
}
}
},
{
"type": "object",
"required": [
"data",
"source"
],
"properties": {
"source": {
"type": "string",
"enum": [
"random"
]
},
"data": {
"$ref": "#/definitions/InjectionData_for_String"
}
}
}
]
},
Expand Down Expand Up @@ -2363,6 +2381,14 @@
},
"version": {
"type": "string"
},
"random_seed": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
}
}
},
Expand Down

0 comments on commit fffe530

Please sign in to comment.