@cosmwasm/ts-codegen 0.25.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +26 -0
  2. package/main/builder/builder.js +165 -254
  3. package/main/commands/generate.js +3 -0
  4. package/main/generators/msg-builder.js +113 -0
  5. package/main/index.js +14 -0
  6. package/main/plugins/client.js +141 -0
  7. package/main/plugins/index.js +18 -0
  8. package/main/plugins/message-composer.js +128 -0
  9. package/main/plugins/msg-builder.js +139 -0
  10. package/main/plugins/plugin-base.js +126 -0
  11. package/main/plugins/react-query.js +152 -0
  12. package/main/plugins/recoil.js +145 -0
  13. package/main/plugins/types.js +123 -0
  14. package/module/builder/builder.js +63 -109
  15. package/module/commands/generate.js +3 -0
  16. package/module/generators/msg-builder.js +62 -0
  17. package/module/index.js +1 -0
  18. package/module/plugins/client.js +66 -0
  19. package/module/plugins/index.js +1 -0
  20. package/module/plugins/message-composer.js +53 -0
  21. package/module/plugins/msg-builder.js +63 -0
  22. package/module/plugins/plugin-base.js +59 -0
  23. package/module/plugins/react-query.js +77 -0
  24. package/module/plugins/recoil.js +64 -0
  25. package/module/plugins/types.js +45 -0
  26. package/package.json +3 -3
  27. package/src/builder/builder.ts +82 -82
  28. package/src/commands/generate.ts +3 -0
  29. package/src/generators/msg-builder.ts +80 -0
  30. package/src/index.ts +1 -0
  31. package/src/plugins/client.ts +108 -0
  32. package/src/plugins/index.ts +1 -0
  33. package/src/plugins/message-composer.ts +80 -0
  34. package/src/plugins/msg-builder.ts +85 -0
  35. package/src/plugins/plugin-base.ts +112 -0
  36. package/src/plugins/react-query.ts +115 -0
  37. package/src/plugins/recoil.ts +89 -0
  38. package/src/plugins/types.ts +74 -0
  39. package/types/src/builder/builder.d.ts +13 -9
  40. package/types/src/generators/msg-builder.d.ts +5 -0
  41. package/types/src/generators/msg-builder.ts +5 -0
  42. package/types/src/index.d.ts +1 -0
  43. package/types/src/plugins/client.d.ts +12 -0
  44. package/types/src/plugins/index.d.ts +1 -0
  45. package/types/src/plugins/message-composer.d.ts +12 -0
  46. package/types/src/plugins/msg-builder.d.ts +12 -0
  47. package/types/src/plugins/plugin-base.d.ts +47 -0
  48. package/types/src/plugins/react-query.d.ts +12 -0
  49. package/types/src/plugins/recoil.d.ts +13 -0
  50. package/types/src/plugins/types.d.ts +12 -0
@@ -0,0 +1,64 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
+ import { pascal } from 'case';
3
+ import * as w from 'wasm-ast-types';
4
+ import { findAndParseTypes, findQueryMsg } from '../utils';
5
+ import { RenderContext } from 'wasm-ast-types';
6
+ import { BuilderPluginBase } from './plugin-base';
7
+ export class RecoilPlugin extends BuilderPluginBase {
8
+ constructor(...args) {
9
+ super(...args);
10
+
11
+ _defineProperty(this, "utils", {
12
+ selectorFamily: 'recoil'
13
+ });
14
+ }
15
+
16
+ initContext(contract, options) {
17
+ return new RenderContext(contract, options);
18
+ }
19
+
20
+ async doRender(name, context) {
21
+ const {
22
+ enabled
23
+ } = this.option.recoil;
24
+
25
+ if (!enabled) {
26
+ return;
27
+ }
28
+
29
+ const {
30
+ schemas
31
+ } = context.contract;
32
+ const localname = pascal(name) + '.recoil.ts';
33
+ const ContractFile = pascal(name) + '.client';
34
+ const TypesFile = pascal(name) + '.types';
35
+ const QueryMsg = findQueryMsg(schemas);
36
+ const typeHash = await findAndParseTypes(schemas);
37
+ let QueryClient = null;
38
+ let ReadOnlyInstance = null;
39
+ const body = [];
40
+ body.push(w.importStmt(['cosmWasmClient'], './chain'));
41
+ body.push(w.importStmt(Object.keys(typeHash), `./${TypesFile}`)); // query messages
42
+
43
+ if (QueryMsg) {
44
+ QueryClient = pascal(`${name}QueryClient`);
45
+ ReadOnlyInstance = pascal(`${name}ReadOnlyInterface`);
46
+ body.push(w.importStmt([QueryClient], `./${ContractFile}`));
47
+ body.push(w.createRecoilQueryClientType());
48
+ body.push(w.createRecoilQueryClient(context, name, QueryClient));
49
+ [].push.apply(body, w.createRecoilSelectors(context, name, QueryClient, QueryMsg));
50
+ }
51
+
52
+ if (typeHash.hasOwnProperty('Coin')) {
53
+ // @ts-ignore
54
+ delete context.utils.Coin;
55
+ }
56
+
57
+ return [{
58
+ type: 'recoil',
59
+ localname,
60
+ body
61
+ }];
62
+ }
63
+
64
+ }
@@ -0,0 +1,45 @@
1
+ import * as t from '@babel/types';
2
+ import { clean } from '../utils/clean';
3
+ import { pascal } from 'case';
4
+ import { findExecuteMsg, findAndParseTypes } from '../utils';
5
+ import { RenderContext } from 'wasm-ast-types';
6
+ import { BuilderPluginBase } from './plugin-base';
7
+ export class TypesPlugin extends BuilderPluginBase {
8
+ initContext(contract, options) {
9
+ return new RenderContext(contract, options);
10
+ }
11
+
12
+ async doRender(name, context) {
13
+ const {
14
+ enabled
15
+ } = this.option.types;
16
+
17
+ if (!enabled) {
18
+ return;
19
+ }
20
+
21
+ const {
22
+ schemas
23
+ } = context.contract;
24
+ const options = this.option.types;
25
+ const localname = pascal(name) + '.types.ts';
26
+ const ExecuteMsg = findExecuteMsg(schemas);
27
+ const typeHash = await findAndParseTypes(schemas);
28
+ const body = []; // TYPES
29
+
30
+ Object.values(typeHash).forEach(type => {
31
+ body.push(clean(type));
32
+ }); // alias the ExecuteMsg
33
+
34
+ if (options.aliasExecuteMsg && ExecuteMsg) {
35
+ body.push(t.exportNamedDeclaration(t.tsTypeAliasDeclaration(t.identifier(`${name}ExecuteMsg`), null, t.tsTypeReference(t.identifier('ExecuteMsg')))));
36
+ }
37
+
38
+ return [{
39
+ type: 'type',
40
+ localname,
41
+ body
42
+ }];
43
+ }
44
+
45
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmwasm/ts-codegen",
3
- "version": "0.25.2",
3
+ "version": "0.27.0",
4
4
  "description": "@cosmwasm/ts-codegen converts your CosmWasm smart contracts into dev-friendly TypeScript classes so you can focus on shipping code.",
5
5
  "author": "Dan Lynch <pyramation@gmail.com>",
6
6
  "homepage": "https://github.com/cosmwasm/ts-codegen",
@@ -96,7 +96,7 @@
96
96
  "parse-package-name": "1.0.0",
97
97
  "rimraf": "3.0.2",
98
98
  "shelljs": "0.8.5",
99
- "wasm-ast-types": "^0.18.2"
99
+ "wasm-ast-types": "^0.20.0"
100
100
  },
101
- "gitHead": "a980b8040099876a056027f4bb45e83de86fb278"
101
+ "gitHead": "d2edba320c63e2db5fe2db0bfb1f4cd5e44f2188"
102
102
  }
@@ -1,18 +1,13 @@
1
- import { RenderOptions, defaultOptions } from "wasm-ast-types";
1
+ import { RenderOptions, defaultOptions, RenderContext, ContractInfo, MessageComposerOptions} from "wasm-ast-types";
2
2
 
3
3
  import { header } from '../utils/header';
4
4
  import { join } from "path";
5
5
  import { writeFileSync } from 'fs';
6
6
  import { sync as mkdirp } from "mkdirp";
7
7
 
8
- import generateMessageComposer from '../generators/message-composer';
9
- import generateTypes from '../generators/types';
10
- import generateReactQuery from '../generators/react-query';
11
- import generateRecoil from '../generators/recoil';
12
- import generateClient from '../generators/client';
13
-
14
8
  import { basename } from 'path';
15
9
  import { readSchemas } from '../utils';
10
+ import { IBuilderPlugin } from '../plugins';
16
11
 
17
12
  import deepmerge from 'deepmerge';
18
13
  import { pascal } from "case";
@@ -20,6 +15,12 @@ import { createFileBundle, recursiveModuleBundle } from "../bundler";
20
15
 
21
16
  import generate from '@babel/generator';
22
17
  import * as t from '@babel/types';
18
+ import { ReactQueryPlugin } from "../plugins/react-query";
19
+ import { RecoilPlugin } from "../plugins/recoil";
20
+ import { MsgBuilderPlugin } from "../plugins/msg-builder";
21
+ import { MessageComposerPlugin } from "../plugins/message-composer";
22
+ import { ClientPlugin } from "../plugins/client";
23
+ import { TypesPlugin } from "../plugins/types";
23
24
 
24
25
  const defaultOpts: TSBuilderOptions = {
25
26
  bundle: {
@@ -33,20 +34,25 @@ export interface TSBuilderInput {
33
34
  contracts: Array<ContractFile | string>;
34
35
  outPath: string;
35
36
  options?: TSBuilderOptions;
37
+ plugins?: IBuilderPlugin[];
36
38
  };
37
39
 
38
40
  export interface BundleOptions {
39
41
  enabled?: boolean;
40
42
  scope?: string;
41
43
  bundleFile?: string;
44
+ bundlePath?: string;
42
45
  };
43
46
 
44
47
  export type TSBuilderOptions = {
45
48
  bundle?: BundleOptions;
46
49
  } & RenderOptions;
47
50
 
51
+ export type BuilderFileType = 'type' | 'client' | 'recoil' | 'react-query' | 'message-composer' | 'msg-builder' | 'plugin';
52
+
48
53
  export interface BuilderFile {
49
- type: 'type' | 'client' | 'recoil' | 'react-query' | 'message-composer';
54
+ type: BuilderFileType;
55
+ pluginType?: string;
50
56
  contract: string;
51
57
  localname: string;
52
58
  filename: string;
@@ -56,14 +62,42 @@ export interface ContractFile {
56
62
  name: string;
57
63
  dir: string;
58
64
  }
65
+
66
+ function getContract(contractOpt): ContractFile {
67
+ if (typeof contractOpt === 'string') {
68
+ const name = basename(contractOpt);
69
+ const contractName = pascal(name);
70
+ return {
71
+ name: contractName,
72
+ dir: contractOpt
73
+ }
74
+ }
75
+ return {
76
+ name: pascal(contractOpt.name),
77
+ dir: contractOpt.dir
78
+ };
79
+ }
80
+
59
81
  export class TSBuilder {
60
82
  contracts: Array<ContractFile | string>;
61
83
  outPath: string;
62
84
  options?: TSBuilderOptions;
85
+ plugins: IBuilderPlugin[] = [];
63
86
 
64
87
  protected files: BuilderFile[] = [];
65
88
 
66
- constructor({ contracts, outPath, options }: TSBuilderInput) {
89
+ loadDefaultPlugins() {
90
+ [].push.apply(this.plugins, [
91
+ new TypesPlugin(this.options),
92
+ new ClientPlugin(this.options),
93
+ new MessageComposerPlugin(this.options),
94
+ new ReactQueryPlugin(this.options),
95
+ new RecoilPlugin(this.options),
96
+ new MsgBuilderPlugin(this.options),
97
+ ]);
98
+ }
99
+
100
+ constructor({ contracts, outPath, options, plugins }: TSBuilderInput) {
67
101
  this.contracts = contracts;
68
102
  this.outPath = outPath;
69
103
  this.options = deepmerge(
@@ -73,85 +107,43 @@ export class TSBuilder {
73
107
  ),
74
108
  options ?? {}
75
109
  );
76
- }
77
110
 
78
- getContracts(): ContractFile[] {
79
- return this.contracts.map(contractOpt => {
80
- if (typeof contractOpt === 'string') {
81
- const name = basename(contractOpt);
82
- const contractName = pascal(name);
83
- return {
84
- name: contractName,
85
- dir: contractOpt
86
- }
87
- }
88
- return {
89
- name: pascal(contractOpt.name),
90
- dir: contractOpt.dir
91
- };
92
- });
93
- }
94
-
95
- async renderTypes(contract: ContractFile) {
96
- const { enabled, ...options } = this.options.types;
97
- if (!enabled) return;
98
- const contractInfo = await readSchemas({
99
- schemaDir: contract.dir
100
- });
101
- const files = await generateTypes(contract.name, contractInfo, this.outPath, options);
102
- [].push.apply(this.files, files);
103
- }
111
+ this.loadDefaultPlugins();
104
112
 
105
- async renderClient(contract: ContractFile) {
106
- const { enabled, ...options } = this.options.client;
107
- if (!enabled) return;
108
- const contractInfo = await readSchemas({
109
- schemaDir: contract.dir
110
- });
111
- const files = await generateClient(contract.name, contractInfo, this.outPath, options);
112
- [].push.apply(this.files, files);
113
+ if (plugins && plugins.length) {
114
+ [].push.apply(this.plugins, plugins);
115
+ }
113
116
  }
114
117
 
115
- async renderRecoil(contract: ContractFile) {
116
- const { enabled, ...options } = this.options.recoil;
117
- if (!enabled) return;
118
- const contractInfo = await readSchemas({
119
- schemaDir: contract.dir
120
- });
121
- const files = await generateRecoil(contract.name, contractInfo, this.outPath, options);
122
- [].push.apply(this.files, files);
118
+ async build() {
119
+ await this.process();
120
+ await this.after();
123
121
  }
124
122
 
125
- async renderReactQuery(contract: ContractFile) {
126
- const { enabled, ...options } = this.options.reactQuery;
127
- if (!enabled) return;
128
- const contractInfo = await readSchemas({
129
- schemaDir: contract.dir
130
- });
131
- const files = await generateReactQuery(contract.name, contractInfo, this.outPath, options);
132
- [].push.apply(this.files, files);
123
+ // lifecycle functions
124
+ private async process(){
125
+ for (const contractOpt of this.contracts) {
126
+ const contract = getContract(contractOpt);
127
+ //resolve contract schema.
128
+ const contractInfo = await readSchemas({
129
+ schemaDir: contract.dir
130
+ });
131
+
132
+ //lifecycle and plugins.
133
+ await this.render(contract.name, contractInfo);
134
+ }
133
135
  }
134
136
 
135
- async renderMessageComposer(contract: ContractFile) {
136
- const { enabled, ...options } = this.options.messageComposer;
137
- if (!enabled) return;
138
- const contractInfo = await readSchemas({
139
- schemaDir: contract.dir
140
- });
141
- const files = await generateMessageComposer(contract.name, contractInfo, this.outPath, options);
142
- [].push.apply(this.files, files);
137
+ private async render(name: string, contractInfo: ContractInfo){
138
+ for (const plugin of this.plugins) {
139
+ let files = await plugin.render(name, contractInfo, this.outPath);
140
+ if(files && files.length){
141
+ [].push.apply(this.files, files);
142
+ }
143
+ }
143
144
  }
144
145
 
145
- async build() {
146
- const contracts = this.getContracts();
147
- for (let c = 0; c < contracts.length; c++) {
148
- const contract = contracts[c];
149
- await this.renderTypes(contract);
150
- await this.renderClient(contract);
151
- await this.renderMessageComposer(contract);
152
- await this.renderReactQuery(contract);
153
- await this.renderRecoil(contract);
154
- }
146
+ private async after(){
155
147
  if (this.options.bundle.enabled) {
156
148
  this.bundle();
157
149
  }
@@ -162,14 +154,18 @@ export class TSBuilder {
162
154
  const allFiles = this.files;
163
155
 
164
156
  const bundleFile = this.options.bundle.bundleFile;
157
+ const bundlePath = join(
158
+ this.options?.bundle?.bundlePath ?? this.outPath,
159
+ bundleFile
160
+ );
165
161
  const bundleVariables = {};
166
162
  const importPaths = [];
167
163
 
168
164
  allFiles.forEach(file => {
169
165
  createFileBundle(
170
166
  `${this.options.bundle.scope}.${file.contract}`,
171
- file.localname,
172
- bundleFile,
167
+ file.filename,
168
+ bundlePath,
173
169
  importPaths,
174
170
  bundleVariables
175
171
  );
@@ -184,11 +180,15 @@ export class TSBuilder {
184
180
  ]
185
181
  )).code;
186
182
 
183
+ if(this.options?.bundle?.bundlePath){
184
+ mkdirp(this.options?.bundle?.bundlePath);
185
+ }
186
+
187
187
  mkdirp(this.outPath);
188
188
 
189
189
  if (code.trim() === '') code = 'export {};'
190
190
 
191
- writeFileSync(join(this.outPath, bundleFile), header + code);
191
+ writeFileSync(bundlePath, header + code);
192
192
 
193
193
  }
194
- }
194
+ }
@@ -151,6 +151,9 @@ export default async (argv) => {
151
151
  messageComposer: {
152
152
  enabled: plugin.includes('message-composer')
153
153
  },
154
+ msgBuilder: {
155
+ enabled: plugin.includes('msg-builder')
156
+ },
154
157
  bundle: {
155
158
  enabled: bundle,
156
159
  scope: bundleScope,
@@ -0,0 +1,80 @@
1
+ import { pascal } from "case";
2
+ import { header } from "../utils/header";
3
+ import { join } from "path";
4
+ import { sync as mkdirp } from "mkdirp";
5
+ import * as w from "wasm-ast-types";
6
+ import * as t from "@babel/types";
7
+ import { writeFileSync } from "fs";
8
+ import generate from "@babel/generator";
9
+ import { ContractInfo, getMessageProperties } from "wasm-ast-types";
10
+ import { findAndParseTypes, findExecuteMsg, findQueryMsg } from '../utils';
11
+ import { RenderContext, MsgBuilderOptions } from 'wasm-ast-types';
12
+ import { BuilderFile } from "../builder";
13
+ import babelTraverse from '@babel/traverse';
14
+ import { parse as babelParse } from '@babel/parser'
15
+
16
+ export default async (
17
+ name: string,
18
+ contractInfo: ContractInfo,
19
+ outPath: string,
20
+ msgBuilderOptions?: MsgBuilderOptions
21
+ ): Promise<BuilderFile[]> => {
22
+ const { schemas } = contractInfo;
23
+ const context = new RenderContext(contractInfo, {
24
+ msgBuilder: msgBuilderOptions ?? {},
25
+ });
26
+
27
+ const localname = pascal(name) + ".msg-builder.ts";
28
+ const TypesFile = pascal(name) + ".types";
29
+ const ExecuteMsg = findExecuteMsg(schemas);
30
+ const typeHash = await findAndParseTypes(schemas);
31
+
32
+ const body = [];
33
+
34
+ body.push(w.importStmt(Object.keys(typeHash), `./${TypesFile}`));
35
+ body.push(w.importStmt(["CamelCasedProperties"], "type-fest"));
36
+
37
+ // execute messages
38
+ if (ExecuteMsg) {
39
+ const children = getMessageProperties(ExecuteMsg);
40
+ if (children.length > 0) {
41
+ const className = pascal(`${name}ExecuteMsgBuilder`);
42
+
43
+ body.push(
44
+ w.createMsgBuilderClass(context, className, ExecuteMsg)
45
+ );
46
+ }
47
+ }
48
+
49
+ const QueryMsg = findQueryMsg(schemas);
50
+ // query messages
51
+ if (QueryMsg) {
52
+ const children = getMessageProperties(QueryMsg);
53
+ if (children.length > 0) {
54
+ const className = pascal(`${name}QueryMsgBuilder`);
55
+
56
+ body.push(
57
+ w.createMsgBuilderClass(context, className, QueryMsg)
58
+ );
59
+ }
60
+ }
61
+
62
+ if (typeHash.hasOwnProperty("Coin")) {
63
+ // @ts-ignore
64
+ delete context.utils.Coin;
65
+ }
66
+ const imports = context.getImports();
67
+ const code = header + generate(t.program([...imports, ...body])).code;
68
+
69
+ mkdirp(outPath);
70
+ writeFileSync(join(outPath, localname), code);
71
+
72
+ return [
73
+ {
74
+ type: "msg-builder",
75
+ contract: name,
76
+ localname,
77
+ filename: join(outPath, localname),
78
+ },
79
+ ];
80
+ };
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export { default as generateRecoil } from './generators/recoil';
9
9
  export * from './utils';
10
10
  export * from './builder';
11
11
  export * from './bundler';
12
+ export * from './plugins';
12
13
 
13
14
  export default async (input: TSBuilderInput) => {
14
15
  const builder = new TSBuilder(input);
@@ -0,0 +1,108 @@
1
+ import { pascal } from 'case';
2
+ import * as w from 'wasm-ast-types';
3
+ import { findExecuteMsg, findAndParseTypes, findQueryMsg } from '../utils';
4
+ import {
5
+ RenderContext,
6
+ ContractInfo,
7
+ RenderContextBase,
8
+ getMessageProperties,
9
+ RenderOptions
10
+ } from 'wasm-ast-types';
11
+ import { BuilderFileType } from '../builder';
12
+ import { BuilderPluginBase } from './plugin-base';
13
+
14
+ export class ClientPlugin extends BuilderPluginBase<RenderOptions> {
15
+ initContext(
16
+ contract: ContractInfo,
17
+ options?: RenderOptions
18
+ ): RenderContextBase<RenderOptions> {
19
+ return new RenderContext(contract, options);
20
+ }
21
+
22
+ async doRender(
23
+ name: string,
24
+ context: RenderContext
25
+ ): Promise<
26
+ {
27
+ type: BuilderFileType;
28
+ pluginType?: string;
29
+ localname: string;
30
+ body: any[];
31
+ }[]
32
+ > {
33
+ const { enabled } = this.option.client;
34
+
35
+ if (!enabled) {
36
+ return;
37
+ }
38
+
39
+ const { schemas } = context.contract;
40
+
41
+ const localname = pascal(name) + '.client.ts';
42
+ const TypesFile = pascal(name) + '.types';
43
+ const QueryMsg = findQueryMsg(schemas);
44
+ const ExecuteMsg = findExecuteMsg(schemas);
45
+ const typeHash = await findAndParseTypes(schemas);
46
+
47
+ let Client = null;
48
+ let Instance = null;
49
+ let QueryClient = null;
50
+ let ReadOnlyInstance = null;
51
+
52
+ const body = [];
53
+
54
+ body.push(w.importStmt(Object.keys(typeHash), `./${TypesFile}`));
55
+
56
+ // query messages
57
+ if (QueryMsg) {
58
+ QueryClient = pascal(`${name}QueryClient`);
59
+ ReadOnlyInstance = pascal(`${name}ReadOnlyInterface`);
60
+
61
+ body.push(w.createQueryInterface(context, ReadOnlyInstance, QueryMsg));
62
+ body.push(
63
+ w.createQueryClass(context, QueryClient, ReadOnlyInstance, QueryMsg)
64
+ );
65
+ }
66
+
67
+ // execute messages
68
+ if (ExecuteMsg) {
69
+ const children = getMessageProperties(ExecuteMsg);
70
+ if (children.length > 0) {
71
+ Client = pascal(`${name}Client`);
72
+ Instance = pascal(`${name}Interface`);
73
+
74
+ body.push(
75
+ w.createExecuteInterface(
76
+ context,
77
+ Instance,
78
+ this.option.client.execExtendsQuery ? ReadOnlyInstance : null,
79
+ ExecuteMsg
80
+ )
81
+ );
82
+
83
+ body.push(
84
+ w.createExecuteClass(
85
+ context,
86
+ Client,
87
+ Instance,
88
+ this.option.client.execExtendsQuery ? QueryClient : null,
89
+ ExecuteMsg
90
+ )
91
+ );
92
+ }
93
+ }
94
+
95
+ if (typeHash.hasOwnProperty('Coin')) {
96
+ // @ts-ignore
97
+ delete context.utils.Coin;
98
+ }
99
+
100
+ return [
101
+ {
102
+ type: 'client',
103
+ localname,
104
+ body
105
+ }
106
+ ];
107
+ }
108
+ }
@@ -0,0 +1 @@
1
+ export * from "./plugin-base"
@@ -0,0 +1,80 @@
1
+ import { pascal } from 'case';
2
+ import * as w from 'wasm-ast-types';
3
+ import { findAndParseTypes, findExecuteMsg } from '../utils';
4
+ import {
5
+ MessageComposerOptions,
6
+ getMessageProperties,
7
+ ContractInfo,
8
+ RenderContextBase,
9
+ RenderContext,
10
+ RenderOptions
11
+ } from 'wasm-ast-types';
12
+ import { BuilderFileType } from '../builder';
13
+ import { BuilderPluginBase } from './plugin-base';
14
+
15
+ export class MessageComposerPlugin extends BuilderPluginBase<RenderOptions> {
16
+ initContext(
17
+ contract: ContractInfo,
18
+ options?: RenderOptions
19
+ ): RenderContextBase<RenderOptions> {
20
+ return new RenderContext(contract, options);
21
+ }
22
+
23
+ async doRender(
24
+ name: string,
25
+ context: RenderContext
26
+ ): Promise<
27
+ {
28
+ type: BuilderFileType;
29
+ pluginType?: string;
30
+ localname: string;
31
+ body: any[];
32
+ }[]
33
+ > {
34
+ const { enabled } = this.option.messageComposer;
35
+
36
+ if (!enabled) {
37
+ return;
38
+ }
39
+
40
+ const { schemas } = context.contract;
41
+
42
+ const localname = pascal(name) + '.message-composer.ts';
43
+ const TypesFile = pascal(name) + '.types';
44
+ const ExecuteMsg = findExecuteMsg(schemas);
45
+ const typeHash = await findAndParseTypes(schemas);
46
+
47
+ const body = [];
48
+
49
+ body.push(w.importStmt(Object.keys(typeHash), `./${TypesFile}`));
50
+
51
+ // execute messages
52
+ if (ExecuteMsg) {
53
+ const children = getMessageProperties(ExecuteMsg);
54
+ if (children.length > 0) {
55
+ const TheClass = pascal(`${name}MessageComposer`);
56
+ const Interface = pascal(`${name}Message`);
57
+
58
+ body.push(
59
+ w.createMessageComposerInterface(context, Interface, ExecuteMsg)
60
+ );
61
+ body.push(
62
+ w.createMessageComposerClass(context, TheClass, Interface, ExecuteMsg)
63
+ );
64
+ }
65
+ }
66
+
67
+ if (typeHash.hasOwnProperty('Coin')) {
68
+ // @ts-ignore
69
+ delete context.utils.Coin;
70
+ }
71
+
72
+ return [
73
+ {
74
+ type: 'message-composer',
75
+ localname,
76
+ body
77
+ }
78
+ ];
79
+ }
80
+ }