@metamask/snaps-sdk
Version:
A library containing the core functionality for building MetaMask Snaps
1 lines • 4.07 kB
Source Map (JSON)
{"version":3,"file":"builder.cjs","sourceRoot":"","sources":["../../src/ui/builder.ts"],"names":[],"mappings":";;;AACA,2CAA8D;AA8B9D;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,aAAa,CAI3B,IAAc,EACd,MAAoB,EACpB,OAAa,EAAqB;IAElC,OAAO,CAAC,GAAG,IAA2D,EAAE,EAAE;QACxE,kCAAkC;QAClC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAA,qBAAa,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YAElC,yEAAyE;YACzE,+CAA+C;YAC/C,IAAA,oBAAY,EAAC,IAAI,EAAE,MAAM,EAAE,WAAW,IAAI,YAAY,CAAC,CAAC;YACxD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wCAAwC;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CACtB,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YAC1B,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO;oBACL,GAAG,WAAW;oBACd,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;iBACnB,CAAC;YACJ,CAAC;YAED,OAAO,WAAW,CAAC;QACrB,CAAC,EACD,EAAE,IAAI,EAAE,CACT,CAAC;QAEF,yEAAyE;QACzE,+CAA+C;QAC/C,IAAA,oBAAY,EAAC,IAAI,EAAE,MAAM,EAAE,WAAW,IAAI,YAAY,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AAvCD,sCAuCC","sourcesContent":["import type { Struct } from '@metamask/superstruct';\nimport { assertStruct, isPlainObject } from '@metamask/utils';\n\nimport type { Component } from './components';\nimport type { NodeType } from './nodes';\n\n/**\n * A function that builds a {@link Component}. This infers the proper args type\n * from the given node.\n *\n * @internal\n */\ntype NodeBuilder<Node extends Component, Keys extends (keyof Node)[]> =\n Omit<Node, 'type'> extends Record<string, never>\n ? (...args: []) => Node\n : (...args: [Omit<Node, 'type'>] | NodeArrayType<Node, Keys>) => Node;\n\n/**\n * Map from an array of node keys to the corresponding array type.\n *\n * @example\n * type Node = { type: 'node'; a: string; b: number; c: boolean };\n * type Keys = ['a', 'b', 'c'];\n *\n * type NodeArray = NodeArrayType<Node, Keys>; // [string, number, boolean]\n * @internal\n */\ntype NodeArrayType<Node extends Component, Keys extends (keyof Node)[]> = {\n [Key in keyof Keys]: Node[Keys[Key]];\n};\n\n/**\n * A function that returns a function to \"build\" a {@link Component}. It infers\n * the type of the component from the given struct, and performs validation on\n * the created component.\n *\n * The returned function can handle the node arguments in two ways:\n * 1. As a single object, with the keys corresponding to the node's properties,\n * excluding the `type` property.\n * 2. As an array of arguments, with the order corresponding to the given keys.\n *\n * @param type - The type of the component to build.\n * @param struct - The struct to use to validate the component.\n * @param keys - The keys of the component to use as arguments to the builder.\n * The order of the keys determines the order of the arguments.\n * @returns A function that builds a component of the given type.\n * @internal\n */\nexport function createBuilder<\n Node extends Component,\n Keys extends (keyof Node)[] = [],\n>(\n type: NodeType,\n struct: Struct<Node>,\n keys: Keys = [] as unknown as Keys,\n): NodeBuilder<Node, Keys> {\n return (...args: [Omit<Node, 'type'>] | NodeArrayType<Node, Keys> | []) => {\n // Node passed as a single object.\n if (args.length === 1 && isPlainObject(args[0])) {\n const node = { ...args[0], type };\n\n // The user could be passing invalid values to the builder, so we need to\n // validate them as per the component's struct.\n assertStruct(node, struct, `Invalid ${type} component`);\n return node;\n }\n\n // Node passed as an array of arguments.\n const node = keys.reduce<Partial<Component>>(\n (partialNode, key, index) => {\n if (args[index] !== undefined) {\n return {\n ...partialNode,\n [key]: args[index],\n };\n }\n\n return partialNode;\n },\n { type },\n );\n\n // The user could be passing invalid values to the builder, so we need to\n // validate them as per the component's struct.\n assertStruct(node, struct, `Invalid ${type} component`);\n return node;\n };\n}\n"]}