@cosmwasm/ts-codegen 0.16.5 → 0.18.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.
@@ -0,0 +1,77 @@
1
+ import { pascal } from "case";
2
+
3
+ const cleanFor = (str) => {
4
+ /*
5
+ 1. look at first char after _for_
6
+ 2. ONLY if you find capitals after, modify it
7
+ */
8
+ while (/_[a-z]+_[A-Z]/.test(str)) {
9
+ const m = str.match(/(_[a-z]+_)[A-Z]/);
10
+ str = str.replace(m[1], pascal(m[1]));
11
+ }
12
+
13
+ return str;
14
+ };
15
+
16
+ export const cleanse = (obj) => {
17
+ var copy;
18
+ // Handle the 3 simple types, and null or undefined
19
+ if (null == obj || 'object' != typeof obj) return obj;
20
+
21
+ // Handle Date
22
+ if (obj instanceof Date) {
23
+ copy = new Date();
24
+ copy.setTime(obj.getTime());
25
+ return copy;
26
+ }
27
+
28
+ // Handle Array
29
+ if (obj instanceof Array) {
30
+ copy = [];
31
+ for (var i = 0, len = obj.length; i < len; i++) {
32
+ copy[i] = cleanse(obj[i]);
33
+ }
34
+ return copy;
35
+ }
36
+
37
+ // Handle Object
38
+ if (obj instanceof Object || typeof obj === 'object') {
39
+ copy = {};
40
+
41
+ // https://github.com/CosmWasm/cosmwasm-typescript-gen/issues/27
42
+ if (Array.isArray(obj.enum) && obj.enum.length === 0) {
43
+ delete obj.enum;
44
+ if (!obj.type) {
45
+ obj.type = 'string';
46
+ }
47
+ }
48
+
49
+ for (var attr in obj) {
50
+ if (obj.hasOwnProperty(attr)) {
51
+
52
+ if (/_for_/.test(attr)) {
53
+ copy[cleanFor(attr)] = cleanse(obj[attr]);
54
+ } else {
55
+ switch (attr) {
56
+ case 'title':
57
+ case '$ref':
58
+ if (typeof obj[attr] === 'string') {
59
+ copy[attr] = cleanse(cleanFor(obj[attr]));
60
+ } else {
61
+ copy[attr] = cleanse(obj[attr]);
62
+ }
63
+ break;
64
+ default:
65
+ copy[attr] = cleanse(obj[attr]);
66
+ }
67
+ }
68
+
69
+ } else {
70
+ copy[attr] = cleanse(obj[attr]);
71
+ }
72
+ }
73
+ return copy;
74
+ }
75
+
76
+ throw new Error("Unable to copy obj! Its type isn't supported.");
77
+ };
@@ -0,0 +1,8 @@
1
+ import pkg from '../../package.json';
2
+ const version = process.env.NODE_ENV === 'test' ? 'latest' : pkg.version;
3
+ export const header = `/**
4
+ * This file was automatically generated by ${pkg.name}@${version}.
5
+ * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
6
+ * and run the ${pkg.name} generate command to regenerate this file.
7
+ */
8
+ \n`;
@@ -0,0 +1 @@
1
+ export * from './schemas';
@@ -0,0 +1,45 @@
1
+ import babelTraverse from '@babel/traverse';
2
+ import { parse, ParserPlugin } from '@babel/parser';
3
+
4
+ export const parser = (codes) => {
5
+
6
+ const hash = {};
7
+ codes.forEach(code => {
8
+
9
+ const plugins: ParserPlugin[] = [
10
+ 'typescript',
11
+ ];
12
+
13
+ const ast = parse(code, {
14
+ sourceType: 'module',
15
+ plugins
16
+ });
17
+
18
+ const visitor = visitorFn({
19
+ addType(key, node) {
20
+ hash[key] = node;
21
+ }
22
+ })
23
+ babelTraverse(ast, visitor);
24
+ });
25
+
26
+ return hash;
27
+
28
+ }
29
+
30
+ const visitorFn = (parser) => ({
31
+ TSTypeAliasDeclaration(path) {
32
+ parser.addType(path.node.id.name, path.parentPath.node);
33
+ // if (path.node.id.name.endsWith('For_Empty')) {
34
+ // const newName = path.node.id.name.replace(/For_Empty$/, '_for_Empty');
35
+ // path.parentPath.node.declaration.id.name = newName;
36
+ // parser.addType(newName, path.parentPath.node);
37
+ // } else {
38
+ // parser.addType(path.node.id.name, path.parentPath.node);
39
+ // }
40
+ },
41
+ TSInterfaceDeclaration(path) {
42
+ parser.addType(path.node.id.name, path.parentPath.node);
43
+ }
44
+ });
45
+
@@ -0,0 +1,65 @@
1
+ import { filter } from 'fuzzy';
2
+ import { prompt as inquirerer } from 'inquirerer';
3
+
4
+ export const getFuzzySearch = (list) => {
5
+ return (answers, input) => {
6
+ input = input || '';
7
+ return new Promise(function (resolve) {
8
+ setTimeout(function () {
9
+ const fuzzyResult = filter(input, list);
10
+ resolve(
11
+ fuzzyResult.map(function (el) {
12
+ return el.original;
13
+ })
14
+ );
15
+ }, 25);
16
+ });
17
+ };
18
+ };
19
+
20
+ export const getFuzzySearchNames = (nameValueItemList) => {
21
+ const list = nameValueItemList.map(({ name, value }) => name);
22
+ return (answers, input) => {
23
+ input = input || '';
24
+ return new Promise(function (resolve) {
25
+ setTimeout(function () {
26
+ const fuzzyResult = filter(input, list);
27
+ resolve(
28
+ fuzzyResult.map(function (el) {
29
+ return nameValueItemList.find(
30
+ ({ name, value }) => el.original == name
31
+ );
32
+ })
33
+ );
34
+ }, 25);
35
+ });
36
+ };
37
+ };
38
+ const transform = (questions) => {
39
+ return questions.map((q) => {
40
+ if (q.type === 'fuzzy') {
41
+ const choices = q.choices;
42
+ delete q.choices;
43
+ return {
44
+ ...q,
45
+ type: 'autocomplete',
46
+ source: getFuzzySearch(choices)
47
+ };
48
+ } else if (q.type === 'fuzzy:objects') {
49
+ const choices = q.choices;
50
+ delete q.choices;
51
+ return {
52
+ ...q,
53
+ type: 'autocomplete',
54
+ source: getFuzzySearchNames(choices)
55
+ };
56
+ } else {
57
+ return q;
58
+ }
59
+ });
60
+ };
61
+
62
+ export const prompt = async (questions = [], argv = {}) => {
63
+ questions = transform(questions);
64
+ return await inquirerer(questions, argv);
65
+ };
@@ -0,0 +1,102 @@
1
+ import { sync as glob } from 'glob';
2
+ import { readFileSync } from 'fs';
3
+ import { cleanse } from './cleanse';
4
+ import { compile } from '@pyramation/json-schema-to-typescript';
5
+ import { parser } from './parse';
6
+ import { ContractInfo, JSONSchema } from 'wasm-ast-types';
7
+ interface ReadSchemaOpts {
8
+ schemaDir: string;
9
+ clean?: boolean;
10
+ };
11
+
12
+ export const readSchemas = async ({
13
+ schemaDir, clean = true
14
+ }: ReadSchemaOpts): Promise<ContractInfo> => {
15
+ const fn = clean ? cleanse : (str) => str;
16
+ const files = glob(schemaDir + '/**/*.json');
17
+ const schemas = files
18
+ .map(file => JSON.parse(readFileSync(file, 'utf-8')));
19
+
20
+ if (schemas.length > 1) {
21
+ // legacy
22
+ // TODO add console.warn here
23
+ return {
24
+ schemas: fn(schemas)
25
+ };
26
+ }
27
+
28
+ if (schemas.length === 0) {
29
+ throw new Error('Error [too few files]: requires one schema file per contract');
30
+ }
31
+
32
+ if (schemas.length !== 1) {
33
+ throw new Error('Error [too many files]: CosmWasm v1.1 schemas supports one file');
34
+ }
35
+
36
+ const idlObject = schemas[0];
37
+ const {
38
+ contract_name,
39
+ contract_version,
40
+ idl_version,
41
+ responses,
42
+ instantiate,
43
+ execute,
44
+ query,
45
+ migrate,
46
+ sudo
47
+ } = idlObject;
48
+
49
+ if (typeof idl_version !== 'string') {
50
+ // legacy
51
+ return {
52
+ schemas: fn(schemas)
53
+ };
54
+ }
55
+
56
+ // TODO use contract_name, etc.
57
+ return {
58
+ schemas: [
59
+ ...Object.values(fn({
60
+ instantiate,
61
+ execute,
62
+ query,
63
+ migrate,
64
+ sudo
65
+ })).filter(Boolean),
66
+ ...Object.values(fn({ ...responses })).filter(Boolean)
67
+ ],
68
+ responses,
69
+ idlObject
70
+ };
71
+ };
72
+
73
+ export const findQueryMsg = (schemas) => {
74
+ const QueryMsg = schemas.find(schema => schema.title === 'QueryMsg');
75
+ return QueryMsg;
76
+ };
77
+
78
+ export const findExecuteMsg = (schemas) => {
79
+ const ExecuteMsg = schemas.find(schema =>
80
+ schema.title === 'ExecuteMsg' ||
81
+ schema.title === 'ExecuteMsg_for_Empty' || // if cleanse is used, this is never
82
+ schema.title === 'ExecuteMsgForEmpty'
83
+ );
84
+ return ExecuteMsg;
85
+ };
86
+
87
+ export const findAndParseTypes = async (schemas) => {
88
+ const Types = schemas;
89
+ const allTypes = [];
90
+ for (const typ in Types) {
91
+ if (Types[typ].definitions) {
92
+ for (const key of Object.keys(Types[typ].definitions)) {
93
+ // set title
94
+ Types[typ].definitions[key].title = key;
95
+ }
96
+ }
97
+ const result = await compile(Types[typ], Types[typ].title);
98
+ allTypes.push(result);
99
+ }
100
+ const typeHash = parser(allTypes);
101
+ return typeHash;
102
+ };