Skip to content

Commit

Permalink
feat: export only changed names
Browse files Browse the repository at this point in the history
  • Loading branch information
voliva committed Apr 29, 2024
1 parent 5dfba33 commit 47c8436
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 239 deletions.
File renamed without changes.
23 changes: 2 additions & 21 deletions src/CommonTypes.tsx → src/CommonTypes/CommonTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@ import { Components, Virtuoso, VirtuosoHandle } from "react-virtuoso"
import { firstValueFrom } from "rxjs"
import { twMerge } from "tailwind-merge"
import { CommonType } from "./CommonType"
import {
commonTypeNames$,
commonTypes$,
newKnownTypes$,
setSearch,
} from "./commonTypes.state"
import { ExportKnownTypes } from "./Export"
import { commonTypeNames$, commonTypes$, setSearch } from "./commonTypes.state"

export function CommonTypes({ className }: { className?: string }) {
const commonTypes = useStateObservable(commonTypes$)
Expand Down Expand Up @@ -86,18 +82,3 @@ const Item: Components["Item"] = forwardRef(
/>
),
)

const ExportKnownTypes = () => {
const newKnownTypes = useStateObservable(newKnownTypes$)

return (
<div className="p-2 max-h-96 flex flex-col gap-2">
<p>Here are the known types object for the selected chains</p>
<pre className="overflow-auto border rounded p-2">
<code className="select-all">
{JSON.stringify(newKnownTypes, null, 2)}
</code>
</pre>
</div>
)
}
102 changes: 102 additions & 0 deletions src/CommonTypes/Export.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { state, useStateObservable } from "@react-rxjs/core"
import { combineKeys, createSignal } from "@react-rxjs/utils"
import { combineLatest, map, scan } from "rxjs"
import { selectedChains$ } from "../ChainPicker"
import {
chainTypes$,
commonTypeNames$,
getCurrentKnownType,
} from "./commonTypes.state"
import { Checkbox } from "@radix-ui/themes"

type RepositoryEntry = {
name: string
chains: string
paths: string[]
type: string
}
const allNewKnownTypes$ = state(
combineLatest({
chains: combineKeys(selectedChains$, chainTypes$),
names: commonTypeNames$,
}).pipe(
map(({ chains, names }) => {
const result: Record<string, RepositoryEntry> = {}

Object.entries(names).forEach(([checksum, name]) => {
if (!name) return

const chainsWithType = Array.from(chains.keys()).filter(
(chain) => checksum in chains.get(chain)!,
)
if (chainsWithType.length === 0) return

const paths = Array.from(
new Set(
chainsWithType.flatMap((chain) =>
chains
.get(chain)!
[checksum].map((type) => type.entry.path.join(".")),
),
),
)

const selectedChain = chains.get(chainsWithType[0])!
const chainType = selectedChain[checksum][0]
const type = `Enum(${Object.keys(chainType.value).join(", ")})`

result[checksum] = {
name,
chains: chainsWithType.join(", "),
paths,
type,
}
})

return result
}),
),
{},
)

const [toggleOnlyChanges$, toggleOnlyChanges] = createSignal()
const onlyChanges$ = state(
toggleOnlyChanges$.pipe(scan((acc) => !acc, true)),
true,
)

const newKnownTypes$ = state(
combineLatest([allNewKnownTypes$, onlyChanges$]).pipe(
map(([allNewKnownTypes, onlyChanges]) =>
onlyChanges
? Object.fromEntries(
Object.entries(allNewKnownTypes).filter(
([checksum, entry]) =>
entry.name !== getCurrentKnownType(checksum),
),
)
: allNewKnownTypes,
),
),
{},
)

export const ExportKnownTypes = () => {
const onlyChanges = useStateObservable(onlyChanges$)
const newKnownTypes = useStateObservable(newKnownTypes$)

return (
<div className="p-2 max-h-[50vh] flex flex-col gap-2">
<p>Here are the known types object for the selected chains</p>
<label className="flex items-center gap-1 px-2 py-1 border rounded self-start select-none cursor-pointer">
<Checkbox checked={onlyChanges} onCheckedChange={toggleOnlyChanges} />
Only changed names
</label>
<pre className="overflow-auto border rounded p-2 text-xs">
<code className="select-all">
{JSON.stringify(newKnownTypes, null, 2)}
</code>
</pre>
</div>
)
}
165 changes: 165 additions & 0 deletions src/CommonTypes/commonTypes.state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { knownTypesRepository } from "@polkadot-api/codegen"
import {
LookupEntry,
getChecksumBuilder,
getLookupFn,
} from "@polkadot-api/metadata-builders"
import { V14, V15 } from "@polkadot-api/substrate-bindings"
import { state, withDefault } from "@react-rxjs/core"
import { combineKeys, createSignal, mergeWithKey } from "@react-rxjs/utils"
import {
EMPTY,
catchError,
combineLatest,
distinctUntilChanged,
map,
scan,
} from "rxjs"
import { selectedChains$ } from "../ChainPicker"
import { metadatas } from "../api/metadatas"

export type MetadataEntry =
(V15 | V14)["lookup"] extends Array<infer R> ? R : never
export type EnumEntry = LookupEntry & { type: "enum"; entry: MetadataEntry }
export const chainTypes$ = state(
(chain: string) =>
metadatas[chain].pipe(
catchError(() => EMPTY),
map((metadata) => {
const lookup = getLookupFn(metadata.lookup)
const checksumBuilder = getChecksumBuilder(metadata)

const result: Record<string, EnumEntry[]> = {}
for (let i = 0; i < metadata.lookup.length; i++) {
if (metadata.lookup[i].def.tag !== "variant") continue

const def = lookup(i)
if (def.type !== "enum") continue

const checksum = checksumBuilder.buildDefinition(i)
if (!checksum) {
throw new Error("unreachable")
}

result[checksum] = result[checksum] ?? []
result[checksum].push({ ...def, entry: metadata.lookup[i] })
}

return result
}),
),
{},
)

export const commonTypes$ = state(
combineKeys(selectedChains$, chainTypes$).pipe(
map((chains) => {
const result: Record<
string,
Array<{
chain: string
type: EnumEntry
}>
> = {}

for (let entry of chains.entries()) {
const [chain, types] = entry
for (let checksum of Object.keys(types)) {
result[checksum] = [
...(result[checksum] ?? []),
...types[checksum].map((type) => ({ chain, type })),
]
}
}

return Object.entries(result)
.map(([checksum, types]) => ({
checksum,
types,
}))
.sort((a, b) => b.types.length - a.types.length)
}),
),
[],
)

export const getCurrentKnownType = (checksum: string) => {
const entry = knownTypesRepository[checksum]
if (!entry) return null
return typeof entry === "string" ? entry : entry.name
}

export const [searchChange$, setSearch] = createSignal<string>()
export const search$ = state(searchChange$, "")

export const [nameChange$, setTypeName] = createSignal<{
checksum: string
name: string
}>()
export const commonTypeNames$ = state(
mergeWithKey({
types: combineKeys(selectedChains$, chainTypes$),
name: nameChange$,
}).pipe(
scan((acc: Record<string, string>, value) => {
const result = { ...acc }
if (value.type === "types") {
for (const chain of value.payload.changes) {
if (!value.payload.has(chain)) continue
const checksums = Object.keys(value.payload.get(chain)!)
checksums.forEach((checksum) => {
result[checksum] = result[checksum] ?? getCurrentKnownType(checksum)
})
}
} else {
result[value.payload.checksum] = value.payload.name
}

return result
}, {}),
),
{},
)

export const currentName$ = state(
(checksum: string) =>
commonTypeNames$.pipe(
map((v) => v[checksum] ?? ""),
distinctUntilChanged(),
),
"",
)
export const isHighlighted$ = state(
(checksum: string) =>
combineLatest([currentName$(checksum), search$]).pipe(
map(
([name, search]) =>
search.length &&
(checksum.includes(search) ||
name.toLocaleLowerCase().includes(search)),
),
),
false,
)

const duplicateNames$ = commonTypeNames$.pipeState(
map((names) => {
const inverted: Record<string, string[]> = {}
Object.entries(names).forEach(([checksum, name]) => {
inverted[name] = inverted[name] ?? []
inverted[name].push(checksum)
})
return Object.fromEntries(
Object.entries(inverted).filter(([, checksums]) => checksums.length > 1),
)
}),
withDefault({} as Record<string, string[]>),
)
export const nameDuplicate$ = state(
(name: string) =>
duplicateNames$.pipe(
map((duplicates) => duplicates[name] ?? []),
distinctUntilChanged((a, b) => a.join(",") === b.join(",")),
),
[],
)
1 change: 1 addition & 0 deletions src/CommonTypes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./CommonTypes"
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "@polkadot-api/metadata-builders"
import { state } from "@react-rxjs/core"
import { map } from "rxjs"
import { metadatas } from "./api/metadatas"
import { metadatas } from "../api/metadatas"

type References = { direct: string[]; indirect: string[] }
const emptyReferences: References = { direct: [], indirect: [] }
Expand Down
Loading

0 comments on commit 47c8436

Please sign in to comment.