Skip to content

Commit fffe530

Browse files
feat(deno/sdk): native function embedding in typescript (#598)
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]>
1 parent a13ab9b commit fffe530

File tree

5 files changed

+102
-30
lines changed

5 files changed

+102
-30
lines changed

typegate/tests/runtimes/deno/deno_static.ts

Lines changed: 0 additions & 21 deletions
This file was deleted.

typegate/tests/runtimes/deno/deno_test.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,22 +122,34 @@ Meta.test("Deno runtime: use local imports", async (t) => {
122122
});
123123

124124
Meta.test("Deno runtime with typescript", async (t) => {
125-
const e = await t.engine("runtimes/deno/deno_static.ts");
125+
const e = await t.engine("runtimes/deno/deno_typescript.ts");
126126
await t.should("work with static values", async () => {
127127
await gql`
128128
query {
129-
simpleStatic
130-
structStatic {
129+
static {
131130
a
132131
}
133132
}
134133
`.expectData({
135-
simpleStatic: "One!",
136-
structStatic: {
134+
static: {
137135
a: "Hello World",
138136
},
139137
}).on(e);
140138
});
139+
140+
await t.should("work with native tyepscript code", async () => {
141+
await gql`
142+
query {
143+
hello(name: "World")
144+
helloFn(name: "wOrLd")
145+
}
146+
`
147+
.expectData({
148+
hello: "Hello World",
149+
helloFn: "Hello world",
150+
})
151+
.on(e);
152+
});
141153
});
142154

143155
Meta.test("Deno runtime: file name reloading", async (t) => {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright Metatype OÜ, licensed under the Elastic License 2.0.
2+
// SPDX-License-Identifier: Elastic-2.0
3+
4+
import { Policy, t, typegraph } from "@typegraph/sdk/index.js";
5+
import { DenoRuntime } from "@typegraph/sdk/runtimes/deno.js";
6+
7+
const hello = ({ name }: any) => `Hello ${name}`;
8+
function helloFn({ name }: any) {
9+
return `Hello ${(name as string).toLowerCase()}`;
10+
}
11+
12+
typegraph("test-deno-tyepscript", (g: any) => {
13+
const deno = new DenoRuntime();
14+
const pub = Policy.public();
15+
16+
g.expose({
17+
static: deno.static(t.struct({ a: t.string() }), {
18+
a: "Hello World",
19+
}).withPolicy(pub),
20+
hello: deno.func(
21+
t.struct({ name: t.string() }),
22+
t.string(),
23+
{ code: hello },
24+
).withPolicy(pub),
25+
helloFn: deno.func(
26+
t.struct({ name: t.string() }),
27+
t.string(),
28+
{ code: helloFn },
29+
).withPolicy(pub),
30+
});
31+
});

typegraph/node/sdk/src/runtimes/deno.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ interface PredefinedFuncMat extends Materializer {
2626
}
2727

2828
export interface DenoFunc {
29-
code: string;
29+
code: string | Function;
3030
secrets?: Array<string>;
3131
effect?: Effect;
3232
}
@@ -38,6 +38,26 @@ export interface DenoImport {
3838
effect?: Effect;
3939
}
4040

41+
function stringifyFn(code: string | Function) {
42+
if (typeof code == "function") {
43+
const source = code.toString();
44+
const namedFnMatch = source.match(/function\s*(\*?\s*[a-zA-Z0-9_]+)/);
45+
if (namedFnMatch) {
46+
const [, name] = namedFnMatch;
47+
if (name.replace(/\s/g, "").startsWith("*")) {
48+
throw new Error(`Generator function "${name}" not supported`);
49+
}
50+
if (/function\s[a-zA-Z0-9_]+\(\) { \[native code\] }/.test(source)) {
51+
throw new Error(
52+
`"${name}" is not supported as it is a native function`,
53+
);
54+
}
55+
}
56+
return source;
57+
}
58+
return code;
59+
}
60+
4161
export class DenoRuntime extends Runtime {
4262
constructor() {
4363
super(runtimes.getDenoRuntime());
@@ -51,10 +71,11 @@ export class DenoRuntime extends Runtime {
5171
out: O,
5272
{ code, secrets = [], effect = fx.read() }: DenoFunc,
5373
): t.Func<I, O, FunMat> {
54-
const matId = runtimes.registerDenoFunc({ code, secrets }, effect);
74+
const source = stringifyFn(code);
75+
const matId = runtimes.registerDenoFunc({ code: source, secrets }, effect);
5576
const mat: FunMat = {
5677
_id: matId,
57-
code,
78+
code: source,
5879
secrets,
5980
effect,
6081
};
@@ -123,7 +144,10 @@ export class DenoRuntime extends Runtime {
123144

124145
return Policy.create(
125146
name,
126-
runtimes.registerDenoFunc(params, fx.read()),
147+
runtimes.registerDenoFunc(
148+
{ ...params, code: stringifyFn(params.code) },
149+
fx.read(),
150+
),
127151
);
128152
}
129153

website/static/specs/0.0.3.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,24 @@
12411241
"$ref": "#/definitions/InjectionData_for_String"
12421242
}
12431243
}
1244+
},
1245+
{
1246+
"type": "object",
1247+
"required": [
1248+
"data",
1249+
"source"
1250+
],
1251+
"properties": {
1252+
"source": {
1253+
"type": "string",
1254+
"enum": [
1255+
"random"
1256+
]
1257+
},
1258+
"data": {
1259+
"$ref": "#/definitions/InjectionData_for_String"
1260+
}
1261+
}
12441262
}
12451263
]
12461264
},
@@ -2363,6 +2381,14 @@
23632381
},
23642382
"version": {
23652383
"type": "string"
2384+
},
2385+
"random_seed": {
2386+
"type": [
2387+
"integer",
2388+
"null"
2389+
],
2390+
"format": "uint32",
2391+
"minimum": 0.0
23662392
}
23672393
}
23682394
},

0 commit comments

Comments
 (0)