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

Commit

Permalink
feat: node support in codegen server (#762)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjjfvi authored Mar 20, 2023
1 parent 2f67fbd commit ff26fd9
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 35 deletions.
10 changes: 10 additions & 0 deletions _tasks/dnt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ await Promise.all([
package: {
name: "capi",
version: Deno.args[0]!,
type: "module",
description: "Capi is a framework for crafting interactions with Substrate chains",
license: "Apache-2.0",
repository: "github:paritytech/capi",
Expand Down Expand Up @@ -63,6 +64,14 @@ await Promise.all([
name: "@substrate/smoldot-light",
version: "0.7.6",
},
"https://deno.land/x/smoldot@light-js-deno-v0.7.6/client.d.ts": {
name: "@substrate/smoldot-light",
version: "0.7.6",
},
"http://localhost:4646/frame/wss/rpc.polkadot.io/@latest/mod.js": {
name: "@capi/polkadot",
version: "http://localhost:4646/frame/wss/rpc.polkadot.io/@v0.9.39/pkg.tar",
},
// "https://raw.githubusercontent.com/paritytech/capi-crypto-wrappers/14289c5/lib.ts":
// "https://raw.githubusercontent.com/paritytech/capi-crypto-wrappers/14289c5/lib.node.ts",
},
Expand All @@ -73,6 +82,7 @@ await Promise.all([
test: true,
},
webSocket: true,
crypto: true,
},
test: false,
typeCheck: false,
Expand Down
22 changes: 11 additions & 11 deletions codegen/FrameCodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ export const chain = C.Rune.rec({ metadata, connection }).into(C.ChainRune)
files.set(
"chain.d.ts",
`
import * as _codecs from "./codecs.d.ts"
import { connection } from "./connection.d.ts"
import * as C from "./capi.d.ts"
import * as t from "./types/mod.d.ts"
import * as _codecs from "./codecs.js"
import { connection } from "./connection.js"
import * as C from "./capi.js"
import * as t from "./types/mod.js"
export const metadata: ${this.typeCodegen.print(this.metadata)}
Expand All @@ -55,19 +55,19 @@ export const chain: C.ChainRune<${this.chainName}, never>
files.set(
`mod.${ext}`,
`
export * from "./connection.${ext}"
export * from "./chain.${ext}"
export * from "./pallets.${ext}"
export * as types from "./types/mod.${ext}"
export * from "./connection.js"
export * from "./chain.js"
export * from "./pallets.js"
export * as types from "./types/mod.js"
`,
)

files.set(
`pallets.${ext}`,
`
import { chain, ${isTypes ? this.chainName : ""} } from "./chain.${ext}"
import * as C from "./capi.${ext}"
import * as t from "./types/mod.${ext}"
import { chain, ${isTypes ? this.chainName : ""} } from "./chain.js"
import * as C from "./capi.js"
import * as t from "./types/mod.js"
${
Object.values(this.metadata.pallets).map((pallet) => {
Expand Down
12 changes: 6 additions & 6 deletions codegen/TypeCodegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,15 @@ is${variant.tag}(value) {
files.set(
`${["types", ...path].join("/")}${isFolder ? "/mod" : ""}.${ext}`,
`
import * as C from "${rootDir}capi.${ext}"
import * as _codecs from "${rootDir}codecs.${ext}"
import * as t from "${rootDir}types/mod.${ext}"
import * as C from "${rootDir}capi.js"
import * as _codecs from "${rootDir}codecs.js"
import * as t from "${rootDir}types/mod.js"
${
[...groups].map(([name, entries]) => {
const isFolder = this._write(files, [...path, name], entries)
return `
export * as ${name} from ${JSON.stringify(`./${name}${isFolder ? "/mod" : ""}.${ext}`)}`
export * as ${name} from ${JSON.stringify(`./${name}${isFolder ? "/mod" : ""}.js`)}`
}).join("\n")
}
Expand All @@ -237,8 +237,8 @@ ${this.declVisitor.visit(codec)(name, isTypes)}
files.set(
"codecs.d.ts",
`
import * as C from "./capi.d.ts"
import * as t from "./types/mod.d.ts"
import * as C from "./capi.js"
import * as t from "./types/mod.js"
${
[...this.codecCodegen.codecIds.entries()].filter((x) => x[1] != null).map(([codec, id]) => `
Expand Down
2 changes: 1 addition & 1 deletion deps/capi_crypto_wrappers.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "https://raw.githubusercontent.com/paritytech/capi-crypto-wrappers/14289c5/mod.ts"
export * from "https://raw.githubusercontent.com/paritytech/capi-crypto-wrappers/5d55e35/mod.ts"
4 changes: 4 additions & 0 deletions deps/smoldot.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export type {
Client,
ClientOptions,
} from "https://deno.land/x/smoldot@light-js-deno-v0.7.6/client.d.ts"
export * from "https://deno.land/x/smoldot@light-js-deno-v0.7.6/index-deno.js"
1 change: 0 additions & 1 deletion deps/smoldot/client.d.ts

This file was deleted.

1 change: 1 addition & 0 deletions deps/std/archive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "https://deno.land/std@0.180.0/archive/mod.ts"
1 change: 1 addition & 0 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const running = await fetch(`${href}capi_cwd`)

if (!running) {
await serve(handler(env), {
hostname: "[::]",
port: +portStr,
signal,
onError(error) {
Expand Down
10 changes: 10 additions & 0 deletions providers/frame/FrameProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { WeakMemo } from "../../util/mod.ts"
import { normalizeIdent } from "../../util/normalize.ts"
import { tsFormatter } from "../../util/tsFormatter.ts"
import { withSignal } from "../../util/withSignal.ts"
import { generateTar } from "./common.ts"

export abstract class FrameProvider extends Provider {
codegenCtxsPending: Record<string, Promise<FrameCodegen>> = {}
Expand Down Expand Up @@ -40,6 +41,15 @@ export abstract class FrameProvider extends Provider {
async () => `export * from ${JSON.stringify(capiPath)}`,
)
}
if (filePath === "pkg.tar") {
return new Response(
await this.env.cache.getRaw(`${this.cacheKey(pathInfo)}/pkg.tar`, async () => {
const files = await this.codegen(pathInfo)
const chainName = await this.chainName(pathInfo)
return await generateTar(files, chainName, vRuntime)
}),
)
}
return await f.code(this.env.cache, request, async () => {
const codegen = await this.codegen(pathInfo)
const code = codegen.get(filePath)
Expand Down
6 changes: 3 additions & 3 deletions providers/frame/FrameProxyProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ export abstract class FrameProxyProvider extends FrameProvider {
async connectionCode(pathInfo: PathInfo, isTypes: boolean) {
const url = this.staticUrl(pathInfo)
return `
import * as C from "./capi.${isTypes ? "d.ts" : "js"}"
import * as C from "./capi.js"
export const discoveryValue ${isTypes ? ":" : "="} "${url}"
export const discoveryValue ${isTypes ? ":" : "="} "${url}"
export const connection ${
export const connection ${
isTypes
? ": C.ConnectionRune<never>"
: "= C.connection((signal) => C.WsConnection.connect(discoveryValue, signal))"
Expand Down
48 changes: 48 additions & 0 deletions providers/frame/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { ss58 } from "../../crypto/mod.ts"
import * as $ from "../../deps/scale.ts"
import { Tar } from "../../deps/std/archive.ts"
import { Buffer } from "../../deps/std/io.ts"
import { readableStreamFromReader, writableStreamFromWriter } from "../../deps/std/streams.ts"
import { tsFormatter } from "../../util/tsFormatter.ts"

export const DEFAULT_TEST_USER_COUNT = 100_000
const DEFAULT_TEST_USER_INITIAL_FUNDS = 1_000_000_000_000_000_000
Expand Down Expand Up @@ -67,3 +71,47 @@ export async function handleCount(request: Request, cache: { count: number }): P
headers: { "Content-Type": "application/json" },
})
}

export async function generateTar(_files: Map<string, string>, chainName: string, version: string) {
const files = new Map(_files)

files.set("capi.js", `export * from "capi"`)
files.set("capi.d.ts", `export * from "capi"`)
files.set(
"package.json",
JSON.stringify(
{
name: packageName(chainName),
version,
type: "module",
main: "./mod.js",
peerDependencies: {
capi: "*",
},
},
null,
2,
),
)

const tar = new Tar()
for (const [name, content] of files) {
const formatted = /\.(js|ts)$/.test(name) ? tsFormatter.formatText(name, content) : content
const data = new TextEncoder().encode(formatted)
tar.append(`package/${name}`, {
contentSize: data.length,
reader: new Buffer(data),
})
}

const buffer = new Buffer()

await readableStreamFromReader(tar.getReader())
.pipeTo(writableStreamFromWriter(buffer))

return buffer.bytes()
}

function packageName(chainName: string) {
return `@capi/` + chainName.replace(/([a-z])(?=[A-Z])/g, (x) => `${x}-`).toLowerCase()
}
2 changes: 1 addition & 1 deletion rpc/smoldot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Deno.test({
await assertRejects(
async () => {
const connection = new SmoldotConnection({ relayChainSpec: "" })
return connection.smoldotChainPending
return connection["smoldotChainPending"]
},
AddChainError,
)
Expand Down
6 changes: 3 additions & 3 deletions rpc/smoldot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { start } from "../deps/smoldot.ts"
import { Client, ClientOptions } from "../deps/smoldot/client.d.ts"
import { Client, ClientOptions, start } from "../deps/smoldot.ts"
import { deferred } from "../deps/std/async.ts"
import { Connection } from "./Connection.ts"
import { RpcEgressMessage } from "./rpc_messages.ts"
Expand All @@ -14,7 +13,8 @@ export interface SmoldotRpcConnProps {
let client: undefined | Client

export class SmoldotConnection extends Connection {
smoldotChainPending
// private so that the types don't need to be referenced when packaged
private smoldotChainPending
listening
stopListening

Expand Down
9 changes: 3 additions & 6 deletions rune/ValueRune.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@ type Access<T, K extends keyof T, _K = NonIndexSignatureKeys<T>> = [
>,
][0]

type GetPath<T, P> = P extends [infer K, ...infer Q] ? GetPath<
// @ts-ignore: we assume it's a valid key
T[K],
Q
>
: T
/** @ts-ignore: assume it's a valid key */
type GetPath<T, P> = P extends [infer K, ...infer Q] ? GetPath<T[K], Q> : T

type EnsurePath<T, P> = never extends P ? P extends [infer K, ...infer Q] ?
| [K & keyof T, ...EnsurePath<T[K & keyof T], Q>]
| [keyof T, ...PropertyKey[]]
Expand Down
8 changes: 5 additions & 3 deletions util/notifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { Deferred, deferred } from "../deps/std/async.ts"

export class Notifier implements PromiseLike<void> {
private _next: Deferred<void> = null!
// dprint-ignore (doesn't respect instantiation expression)
then<T1 = void, T2 = never>(...args: Parameters<typeof Notifier.prototype._next.then<T1, T2>>) {
return (this._next ??= deferred()).then(...args)
then<T1 = void, T2 = never>(
onfulfilled?: ((value: void) => T1 | PromiseLike<T1>) | null | undefined,
onrejected?: ((reason: any) => T2 | PromiseLike<T2>) | null | undefined,
) {
return (this._next ??= deferred()).then(onfulfilled, onrejected)
}
emit() {
this._next?.resolve()
Expand Down

0 comments on commit ff26fd9

Please sign in to comment.