@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.
- package/main/commands/install.js +1 -1
- package/module/commands/install.js +1 -1
- package/package.json +6 -4
- package/src/builder/builder.ts +194 -0
- package/src/builder/index.ts +1 -0
- package/src/bundler/bundler.ts +67 -0
- package/src/bundler/index.ts +1 -0
- package/src/cli.js +21 -0
- package/src/cmds.js +12 -0
- package/src/commands/create-boilerplate.ts +139 -0
- package/src/commands/generate.ts +156 -0
- package/src/commands/install.ts +118 -0
- package/src/file.js +20 -0
- package/src/generators/client.ts +108 -0
- package/src/generators/message-composer.ts +86 -0
- package/src/generators/react-query.ts +102 -0
- package/src/generators/recoil.ts +92 -0
- package/src/generators/types.ts +72 -0
- package/src/index.ts +16 -0
- package/src/ts-codegen.js +7 -0
- package/src/utils/clean.ts +45 -0
- package/src/utils/cleanse.ts +77 -0
- package/src/utils/header.ts +8 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/parse.ts +45 -0
- package/src/utils/prompt.js +65 -0
- package/src/utils/schemas.ts +102 -0
@@ -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
|
+
};
|