@cosmwasm/ts-codegen
Version:
@cosmwasm/ts-codegen converts your CosmWasm smart contracts into dev-friendly TypeScript classes so you can focus on shipping code.
167 lines (166 loc) • 6.55 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TSBuilder = void 0;
const generator_1 = __importDefault(require("@babel/generator"));
const t = __importStar(require("@babel/types"));
const ts_codegen_ast_1 = require("@cosmwasm/ts-codegen-ast");
const case_1 = require("case");
const deepmerge_1 = __importDefault(require("deepmerge"));
const fs_1 = require("fs");
const mkdirp_1 = require("mkdirp");
const path_1 = require("path");
const path_2 = require("path");
const bundler_1 = require("../bundler");
const create_helpers_1 = require("../helpers/create-helpers");
const client_1 = require("../plugins/client");
const message_builder_1 = require("../plugins/message-builder");
const message_composer_1 = require("../plugins/message-composer");
const provider_1 = require("../plugins/provider");
const provider_bundle_1 = require("../plugins/provider-bundle");
const react_query_1 = require("../plugins/react-query");
const recoil_1 = require("../plugins/recoil");
const types_1 = require("../plugins/types");
const utils_1 = require("../utils");
const contracts_1 = require("../utils/contracts");
const header_1 = require("../utils/header");
const defaultOpts = {
bundle: {
enabled: true,
scope: 'contracts',
bundleFile: 'bundle.ts'
},
useShorthandCtor: true
};
;
;
;
function getContract(contractOpt) {
if (typeof contractOpt === 'string') {
const name = (0, path_2.basename)(contractOpt);
const contractName = (0, case_1.pascal)(name);
return {
name: contractName,
dir: contractOpt
};
}
return {
name: (0, case_1.pascal)(contractOpt.name),
dir: contractOpt.dir
};
}
class TSBuilder {
contracts;
outPath;
options;
plugins = [];
builderContext = new ts_codegen_ast_1.BuilderContext();
files = [];
loadDefaultPlugins() {
this.plugins.push(new types_1.TypesPlugin(this.options), new client_1.ClientPlugin(this.options), new message_composer_1.MessageComposerPlugin(this.options), new react_query_1.ReactQueryPlugin(this.options), new recoil_1.RecoilPlugin(this.options), new message_builder_1.MessageBuilderPlugin(this.options), new provider_1.ContractsContextProviderPlugin(this.options), new provider_bundle_1.ContractsProviderBundlePlugin(this.options));
}
constructor({ contracts, outPath, options, plugins }) {
this.contracts = contracts;
this.outPath = outPath;
this.options = (0, deepmerge_1.default)((0, deepmerge_1.default)(ts_codegen_ast_1.defaultOptions, defaultOpts), options ?? {});
this.loadDefaultPlugins();
if (plugins && plugins.length) {
this.plugins.push(...plugins);
}
this.plugins.forEach(plugin => plugin.setBuilder(this));
}
async build() {
await this.process();
await this.after();
}
// lifecycle functions
async process() {
for (const contractOpt of this.contracts) {
const contract = getContract(contractOpt);
//resolve contract schema.
const contractInfo = await (0, utils_1.readSchemas)({
schemaDir: contract.dir
});
//lifecycle and plugins.
await this.render('main', contract.name, contractInfo);
}
}
async render(lifecycle, name, contractInfo) {
const plugins = lifecycle
? this.plugins.filter((p) => p.lifecycle === lifecycle)
: this.plugins;
for (const plugin of plugins) {
let files = await plugin.render(this.outPath, name, contractInfo ?? (0, contracts_1.createDefaultContractInfo)());
if (files && files.length) {
this.files.push(...files);
}
}
}
async after() {
await this.render('after');
const helpers = (0, create_helpers_1.createHelpers)({
outPath: this.outPath,
contracts: this.contracts,
options: this.options,
plugins: this.plugins,
}, this.builderContext);
if (helpers && helpers.length) {
this.files.push(...helpers);
}
if (this.options.bundle.enabled) {
this.bundle();
}
}
async bundle() {
const allFiles = this.files;
const bundleFile = this.options.bundle.bundleFile;
const bundlePath = (0, path_1.join)(this.options?.bundle?.bundlePath ?? this.outPath, bundleFile);
const bundleVariables = {};
const importPaths = [];
allFiles.forEach(file => {
(0, bundler_1.createFileBundle)(`${this.options.bundle.scope}.${file.contract}`, file.filename, bundlePath, importPaths, bundleVariables);
});
const ast = (0, bundler_1.recursiveModuleBundle)(bundleVariables);
const nodes = [
...importPaths,
...ast
];
// @ts-ignore
let code = (0, generator_1.default)(t.program(
// @ts-ignore
nodes)).code;
if (this.options?.bundle?.bundlePath) {
(0, mkdirp_1.sync)(this.options?.bundle?.bundlePath);
}
(0, mkdirp_1.sync)(this.outPath);
if (code.trim() === '')
code = 'export {};';
(0, fs_1.writeFileSync)(bundlePath, header_1.header + code);
}
}
exports.TSBuilder = TSBuilder;