Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

All-in on Codegen DX #226

Closed
harrysolovay opened this issue Sep 16, 2022 · 2 comments · Fixed by #368
Closed

All-in on Codegen DX #226

harrysolovay opened this issue Sep 16, 2022 · 2 comments · Fixed by #368
Assignees

Comments

@harrysolovay
Copy link
Contributor

harrysolovay commented Sep 16, 2022

The following proposal describes a would-be critical shift in the Capi DX. Feedback would be greatly appreciated.


Currently, Capi utilizes Configs for its discovery values and typings. This is true of both the static and dynamic DXs.

class Polkadot extends Config.from<
  PolkadotCallMethods,
  PolkadotSubscriptionMethods,
  PolkadotErrorDetails,
  PolkadotMetadata
>() {
  constructor() {
    super("wss://rpc.polkadot.io", 0);
  }
};
const polkadot = new Polkadot();

The idea is that the types within a given Config will inform the rest of Capi usage. While the narrow typing is worthwhile, the current execution is overly-complex: Config is somewhere in between static and dynamic; it has one foot in both worlds, but fits into neither. Yes, we can generate Configs with FRAME-specific types, but no, this does not result in the optimal static DX.

import * as C from "capi";
import { config } from "./generated.ts";

const value = await chain(config).pallet("SomePallet").entry("SomeEntry").read();

Note: we cannot attach method/storage-specific TSDocs unless microsoft/TypeScript#41165 is addressed.

The one notable advantage to this experience is that it is consistent; if the chain is not known ahead of time, one can apply any to the config's type params. However, I'd argue that the static use case (where target chain is known ahead of time) is far more common. If we optimize for this use case, the experience can be dramatically simplified.

import { SomePallet } from "./generated.ts";

const value = await SomePallet.SomeEntry.read();

Meanwhile, the dynamic use case can be satisfied via direct usage of std effects.

import * as C from "capi";

const value = await C.readEntry(
  C.config("wss://some.chain.io", 0),
  "SomePallet",
  "SomeEntry",
).read();

Note: config creation could be much simpler without the need for a named signature containing RPC, error and FRAME types.

In addition to offering simpler DX, a key benefit of this approach is the ease of adjusting to runtime upgrades. Simply regenerate the bindings and fix type errors.

deno run -A -r https://deno.land/x/capi/codegen.ts \
  --out="polkadot.ts" \
  --src="wss://rpc.polkadot.io"
@kratico
Copy link
Contributor

kratico commented Sep 19, 2022

This would be super nice.

Apollo has something similar https://www.the-guild.dev/graphql/codegen

@kratico
Copy link
Contributor

kratico commented Sep 20, 2022

This is another DX example for inspiration https://trpc.io/

@harrysolovay harrysolovay added this to the Sub0 milestone Oct 19, 2022
@tjjfvi tjjfvi moved this to Properly Done in Capi Nov 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

4 participants