I need to pass the query as a string. This string actually code, so I do not get the advantage of IDE(type checking, discoverability).
following would be nice.
Do I need to specify full URL to fetch wrapper? would be nice if I specify a wrapper name. May be web3apiClient can derive the uri from registry?
response I got from calling the client results in an error like, ‘No Web3API found at URI: w3://ens/api.helloworld.web3api.eth’. But promise catch is not called(then is invoked). So in my js it is not considered an error?
Regarding your first question, we are moving away from graphql syntax. You’re already able to call client.invoke(...) on the client instead of client.query(...). While the graphql-based query syntax offers the advantage of concurrent queries, I find the invoke syntax offers a better user experience for reasons such as the one you mentioned. I think you’ll like it.
We are also experimenting with other solutions that can offer a more familiar call syntax. One challenge here is cross-language support, including statically-typed languages. For example, if we are to add a new set of methods to the client, then we want to ensure TypeScript picks up changes to the client’s interface. This is not a trivial problem.
As for your second question, you do need to specify the full URI. I recommend creating a constant variable that holds your URI. Then you can just reference your variable.
const uri = "ens/api.helloworld.web3api.eth";
To answer your third question, when an exception is thrown in your wrapper’s WASM module, the error message is propagated to the client and stored as a string in the errors property of the return value of the query method, and in the error property in the return value of invoke. In your case, if you want to throw the exception you can use something like:
Regarding first one,
It might be difficult, ff we plan to add methods to client interface itself
‘’’
client.hello.logMessage(“Message”)
‘’’
But if we could
‘’’
wrapper = client.initWrapper()
wrapper.logMessage(“Message”)
‘’’
initWrapper method can generate a new dynamic object at add fields at runtime and return.
“dynamic object” concept is present in most of the prominent languages(C#, Python, JS, TS). I am not sure what other languages we are targeting.
In order to write this, TS needs prior knowledge of WrapperType. Without that knowledge, the TS transpiler will complain and the IDE won’t know which methods are available on the wrapper object.
We have plans to release a CLI tool that generates code for a class that encapsulates the client and contains a wrapper’s methods. Users will create a manifest file with information such as URI’s and desired namespaces, then run the CLI command w3 app codegen. Once the code is generated, usage will look like this:
const client: Web3ApiClient = new Web3ApiClient();
const app: PolywrapApp = new PolywrapApp(client);
app.foo.query.logMessage({ message: "Message" });
It make sense. Code auto gen is right aproach instead of generating at runtime.
Given that 1) Which wrappers we refer to is available at build/coding time. 2) Generating at runtime involves latency and gc related complications.
Some improvements were just merged and can be used with the new cli app CLI command. You can add the CLI to your project using yarn add -D @web3api/cli 0.0.1-prealpha.67.
I really like this syntax! I can imagine the initWrapper returning errors like “missing plugin ‘foo’”, or “module environment sanitization failed: ‘Error: …’”.
I agree that run-time type-building is very interesting. This would however require run-time reflection of the wrapper modules, which means we’d be downloading more files into the client, and performing an algorithm that’s similar in complexity to full-on schema parsing. I think we should shy away from this, and do build-time stuff instead
Going to cross link with the GitHub issue discussing these types of toolchain improvements: