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

feat: node support in codegen server #762

Merged
merged 1 commit into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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