Skip to content

Commit

Permalink
wip: fix typescript selectAll
Browse files Browse the repository at this point in the history
  • Loading branch information
luckasRanarison committed Dec 30, 2024
1 parent 87b70e5 commit f0187f6
Show file tree
Hide file tree
Showing 10 changed files with 299 additions and 202 deletions.
2 changes: 1 addition & 1 deletion src/metagen/src/client_py/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ class QueryGraph(QueryGraphBase):
node = selection_to_nodes(
{{"{node_name}": {args_selection}}},
{{"{node_name}": NodeDescs.{meta_method}}},
"$q"
["$q"]
)[0]
return {node_type}(node.node_name, node.instance_name, node.args, node.sub_nodes, node.files)
"#
Expand Down
24 changes: 14 additions & 10 deletions src/metagen/src/client_py/static/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
def selection_to_nodes(
selection: "SelectionErased",
metas: typing.Dict[str, "NodeMetaFn"],
parent_path: str,
parent_path: typing.List[str],
) -> typing.List["SelectNode[typing.Any]"]:
out = []
flags = selection.get("_")
Expand Down Expand Up @@ -50,7 +50,7 @@ def selection_to_nodes(
continue
if isinstance(instance_selection, Alias):
raise Exception(
f"nested Alias node discovered at {parent_path}.{instance_name}"
f"nested Alias node discovered at {'.'.join(parent_path)}.{instance_name}"
)

instance_args: typing.Optional[NodeArgs] = None
Expand All @@ -63,7 +63,7 @@ def selection_to_nodes(
# arg types are always TypedDicts
if not isinstance(arg, dict):
raise Exception(
f"node at {parent_path}.{instance_name} is a node that "
f"node at {'.'.join(parent_path)}.{instance_name} is a node that "
+ "requires arguments "
+ f"but detected argument is typeof {type(arg)}"
)
Expand All @@ -75,7 +75,7 @@ def selection_to_nodes(
ty_name = expected_args.pop(key)
if ty_name is None:
raise Exception(
f"unexpected argument ${key} at {parent_path}.{instance_name}"
f"unexpected argument ${key} at {'.'.join(parent_path)}.{instance_name}"
)
instance_args[key] = NodeArgValue(ty_name, val)

Expand All @@ -88,7 +88,7 @@ def selection_to_nodes(
if meta.arg_types is not None:
if not isinstance(sub_selections, tuple):
raise Exception(
f"node at {parent_path}.{instance_name} is a composite "
f"node at {'.'.join(parent_path)}.{instance_name} is a composite "
+ "that requires an argument object "
+ f"but selection is typeof {type(sub_selections)}"
)
Expand All @@ -97,7 +97,7 @@ def selection_to_nodes(
# we got a tuple selection when this shouldn't be the case
elif isinstance(sub_selections, tuple):
raise Exception(
f"node at {parent_path}.{instance_name} "
f"node at {'.'.join(parent_path)}.{instance_name} "
+ "is a composite that takes no arguments "
+ f"but selection is typeof {type(instance_selection)}",
)
Expand All @@ -109,7 +109,7 @@ def selection_to_nodes(
# selection types are always TypedDicts as well
if not isinstance(sub_selections, dict):
raise Exception(
f"node at {parent_path}.{instance_name} "
f"node at {'.'.join(parent_path)}.{instance_name} "
+ "is a no argument composite but first element of "
+ f"selection is typeof {type(instance_selection)}",
)
Expand All @@ -119,10 +119,11 @@ def selection_to_nodes(
raise Exception(
"unreachable: union/either NodeMetas can't have subnodes"
)
parent_path.append(instance_name)
sub_nodes = selection_to_nodes(
typing.cast("SelectionErased", sub_selections),
meta.sub_nodes,
f"{parent_path}.{instance_name}",
parent_path,
)
else:
assert meta.variants is not None
Expand All @@ -135,11 +136,13 @@ def selection_to_nodes(
continue

variant_select = sub_selections.pop(variant_ty, None)
parent_path.append(instance_name)
parent_path.append(f"variant({variant_ty})")
nodes = (
selection_to_nodes(
typing.cast("SelectionErased", variant_select),
variant_meta.sub_nodes,
f"{parent_path}.{instance_name}.variant({variant_ty})",
parent_path,
)
if variant_select is not None
else []
Expand All @@ -161,7 +164,7 @@ def selection_to_nodes(

if len(sub_selections) > 0:
raise Exception(
f"node at {parent_path}.{instance_name} "
f"node at {'.'.join(parent_path)}.{instance_name} "
+ "has none of the variants called "
+ str(sub_selections.keys()),
)
Expand All @@ -172,6 +175,7 @@ def selection_to_nodes(
)
out.append(node)

parent_path.pop()
found_nodes.discard("_")
if len(found_nodes) > 0:
raise Exception(
Expand Down
2 changes: 1 addition & 1 deletion src/metagen/src/client_ts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export class QueryGraph extends _QueryGraphBase {{
const inner = _selectionToNodeSet(
{{ "{node_name}": {args_selection} }},
[["{node_name}", nodeMetas.{meta_method}]],
"$q",
["$q"],
)[0];
return new {node_type}(inner) as {node_type}<{out_ty_name}>;
}}"#
Expand Down
31 changes: 22 additions & 9 deletions src/metagen/src/client_ts/static/mod.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function _selectionToNodeSet(
selection: Selection,
metas: [string, () => NodeMeta][],
parentPath: string,
parentPath: string[],
): SelectNode<unknown>[] {
const out = [] as SelectNode[];
const selectAll = selection._ == "selectAll";
Expand Down Expand Up @@ -33,7 +33,7 @@ function _selectionToNodeSet(
}
if (instanceSelection instanceof Alias) {
throw new Error(
`nested Alias discovered at ${parentPath}.${instanceName}`,
`nested Alias discovered at ${parentPath.join(".")}.${instanceName}`,
);
}
const node: SelectNode = { instanceName, nodeName, files: inputFiles };
Expand All @@ -47,7 +47,7 @@ function _selectionToNodeSet(
// TODO: consider bringing in Zod (after hoisting impl into common lib)
if (typeof arg != "object" || arg === null) {
throw new Error(
`node at ${parentPath}.${instanceName} is a node ` +
`node at ${parentPath.join(".")}.${instanceName} is a node ` +
`that requires arguments object but detected argument ` +
`is typeof ${typeof arg}`,
);
Expand All @@ -61,7 +61,7 @@ function _selectionToNodeSet(
// Selection as arg
if (!typeName) {
throw new Error(
`unexpected argument ${key} at ${parentPath}.${instanceName}`,
`unexpected argument ${key} at ${parentPath.join(".")}.${instanceName}`,
);
}
expectedArguments.delete(key);
Expand All @@ -75,15 +75,15 @@ function _selectionToNodeSet(
if (argumentTypes) {
if (!Array.isArray(subSelections)) {
throw new Error(
`node at ${parentPath}.${instanceName} ` +
`node at ${parentPath.join(".")}.${instanceName} ` +
`is a composite that takes an argument ` +
`but selection is typeof ${typeof subSelections}`,
);
}
subSelections = subSelections[1];
} else if (Array.isArray(subSelections)) {
throw new Error(
`node at ${parentPath}.${instanceName} ` +
`node at ${parentPath.join(".")}.${instanceName} ` +
`is a composite that takes no arguments ` +
`but selection is typeof ${typeof subSelections}`,
);
Expand All @@ -95,7 +95,7 @@ function _selectionToNodeSet(
}
if (typeof subSelections != "object") {
throw new Error(
`node at ${parentPath}.${nodeName} ` +
`node at ${parentPath.join(".")}.${nodeName} ` +
`is a no argument composite but first element of ` +
`selection is typeof ${typeof nodeSelection}`,
);
Expand All @@ -107,13 +107,24 @@ function _selectionToNodeSet(
"unreachable: union/either NodeMetas can't have subnodes",
);
}

const lastNode = parentPath.at(-1);
// skip recursive fields when using `selectAll`
if (
subSelections?._ === "selectAll" &&
subNodes.find(([node]) => lastNode === node)
) {
continue;
}

parentPath.push(instanceName);
node.subNodes = _selectionToNodeSet(
// assume it's a Selection. If it's an argument
// object, mismatch between the node desc should hopefully
// catch it
subSelections as Selection,
subNodes,
`${parentPath}.${instanceName}`,
parentPath,
);
} else {
const unionSelections = {} as Record<string, SelectNode[]>;
Expand All @@ -125,12 +136,13 @@ function _selectionToNodeSet(
continue;
}
foundVariants.delete(variantTy);
parentPath.push(instanceName, `variant(${variantTy})`);
const variant_select = subSelections[variantTy];
const nodes = variant_select
? _selectionToNodeSet(
variant_select as Selection,
variant_meta.subNodes,
`${parentPath}.${instanceName}.variant(${variantTy})`,
parentPath,
)
: [];
nodes.push({
Expand All @@ -153,6 +165,7 @@ function _selectionToNodeSet(
out.push(node);
}
}
parentPath.pop();
foundNodes.delete("_");
if (foundNodes.size > 0) {
throw new Error(
Expand Down
2 changes: 1 addition & 1 deletion tests/metagen/typegraphs/identities/rs/fdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl Router {
}

pub fn init(&self, args: InitArgs) -> Result<InitResponse, InitError> {
static MT_VERSION: &str = "0.5.0-rc.8";
static MT_VERSION: &str = "0.5.0-rc.9";
if args.metatype_version != MT_VERSION {
return Err(InitError::VersionMismatch(MT_VERSION.into()));
}
Expand Down
70 changes: 30 additions & 40 deletions tests/metagen/typegraphs/sample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,23 @@ export const tg = await typegraph({
const random = new RandomRuntime({ seed: 0 });
const deno = new DenoRuntime();

const post = t.struct({
id: t.uuid({ asId: true, config: { auto: true } }),
slug: t.string(),
title: t.string(),
}, { name: "post" });
const post = t.struct(
{
id: t.uuid({ asId: true, config: { auto: true } }),
slug: t.string(),
title: t.string(),
},
{ name: "post" },
);

const user = t.struct({
id: t.uuid({ asId: true, config: { auto: true } }),
email: t.email(),
posts: t.list(g.ref("post")),
}, { name: "user" });
const user = t.struct(
{
id: t.uuid({ asId: true, config: { auto: true } }),
email: t.email(),
posts: t.list(g.ref("post")),
},
{ name: "user" },
);

const compositeUnion = t.union([post, user]);
const scalarUnion = t.union([t.string(), t.integer()]);
Expand All @@ -44,47 +50,31 @@ export const tg = await typegraph({
getPosts: random.gen(post),

scalarNoArgs: random.gen(t.string()),
scalarArgs: deno.func(
post,
t.string(),
{
code: () => "hello",
effect: fx.update(),
},
),
scalarArgs: deno.func(post, t.string(), {
code: () => "hello",
effect: fx.update(),
}),
compositeNoArgs: deno.func(t.struct({}), post, {
code: genPost,
effect: fx.update(),
}),
compositeArgs: deno.func(
t.struct({ id: t.string() }),
post,
{
code: genPost,
effect: fx.update(),
},
),
scalarUnion: deno.func(
t.struct({ id: t.string() }),
scalarUnion,
{
code: () => "hello",
},
),
compositeArgs: deno.func(t.struct({ id: t.string() }), post, {
code: genPost,
effect: fx.update(),
}),
scalarUnion: deno.func(t.struct({ id: t.string() }), scalarUnion, {
code: () => "hello",
}),
compositeUnion: deno.func(
t.struct({ id: t.string() }),
compositeUnion,
{
code: genPost,
},
),
mixedUnion: deno.func(
t.struct({ id: t.string() }),
mixedUnion,
{
code: () => "hello",
},
),
mixedUnion: deno.func(t.struct({ id: t.string() }), mixedUnion, {
code: () => "hello",
}),
},
Policy.public(),
);
Expand Down
Loading

0 comments on commit f0187f6

Please sign in to comment.