@devexpress/analytics-core-cli 26.1.3 → 26.1.4-build-26177-1912

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/README.md CHANGED
@@ -1,25 +1,25 @@
1
- ## About
2
-
3
- The DevExpress analytics-core-cli package is a toolkit designed to help developers handle the devexpress-reporting and devexpress-dashboards packages. The toolset will be supplemented as needed.
4
-
5
- ## Usage
6
-
7
- ### Process custom Knockout HTML templates to make the script-src 'unsafe-eval' directive unnecessary
8
-
9
- The 'processBindings' tool processes your custom Knockout HTML templates and generates a file with the code that calls the `addToBindingsCache` function to add your templates to the cache.
10
- To process custom templates, execute the following command:
11
-
12
- ```
13
- node node_modules/@devexpress/analytics-core-cli/utils/processBindings <templates folder path> <result file path>
14
- ```
15
-
16
- Command parameters are as follows:
17
-
18
- `templates folder path` - A folder that contains template files (.HTML, .CSHTML). Nested folders are processed recursively.
19
- `result file path` - Path to the file being created
20
-
21
- For more information, review the following help topic: [Content Security Policy](https://docs.devexpress.com/XtraReports/404141/web-reporting/web-reporting-application-security/content-security-policy).
22
-
23
- ## License
24
-
1
+ ## About
2
+
3
+ The DevExpress analytics-core-cli package is a toolkit designed to help developers handle the devexpress-reporting and devexpress-dashboards packages. The toolset will be supplemented as needed.
4
+
5
+ ## Usage
6
+
7
+ ### Process custom Knockout HTML templates to make the script-src 'unsafe-eval' directive unnecessary
8
+
9
+ The 'processBindings' tool processes your custom Knockout HTML templates and generates a file with the code that calls the `addToBindingsCache` function to add your templates to the cache.
10
+ To process custom templates, execute the following command:
11
+
12
+ ```
13
+ node node_modules/@devexpress/analytics-core-cli/utils/processBindings <templates folder path> <result file path>
14
+ ```
15
+
16
+ Command parameters are as follows:
17
+
18
+ `templates folder path` - A folder that contains template files (.HTML, .CSHTML). Nested folders are processed recursively.
19
+ `result file path` - Path to the file being created
20
+
21
+ For more information, review the following help topic: [Content Security Policy](https://docs.devexpress.com/XtraReports/404141/web-reporting/web-reporting-application-security/content-security-policy).
22
+
23
+ ## License
24
+
25
25
  A commercial license for DevExpress ASP.NET controls is required to use this package. Please visit [this page](https://www.devexpress.com/support/eulas/) for more information about licensing.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devexpress/analytics-core-cli",
3
3
  "private": false,
4
- "version": "26.1.3",
4
+ "version": "26.1.4-build-26177-1912",
5
5
  "homepage": "https://www.devexpress.com/",
6
6
  "bugs": "https://www.devexpress.com/support/",
7
7
  "author": "Developer Express Inc.",
@@ -22,7 +22,7 @@
22
22
  "scope:analytics:core:cli"
23
23
  ]
24
24
  },
25
- "commitSHA": "68b119d12dc7d8c94a4326b8946521d446275039",
25
+ "commitSHA": "11be03e1be8be05885484d89bf95c17aca67547d",
26
26
  "scripts": {
27
27
  "build": "echo done"
28
28
  }
@@ -1,126 +1,126 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const ko = require('knockout');
4
- const processor = require('js-code-parser/executors/processor').ReplaceVariableProcessor;
5
-
6
- function getBinding(value) {
7
- var backBrace = false;
8
- for(var i = 0; i < value.length; i++) {
9
- if(value[i] === '"' && !backBrace) {
10
- return i;
11
- } else if(value[i] === "\\" && !backBrace) {
12
- backBrace = true;
13
- } else if(backBrace) {
14
- backBrace = false;
15
- }
16
- }
17
- }
18
-
19
- function getBindings(htmlContent, prefix) {
20
- var i = htmlContent.indexOf(prefix);
21
- var bindings = [];
22
- while(i !== -1) {
23
- htmlContent = htmlContent.substring(i + prefix.length);
24
- var index = getBinding(htmlContent);
25
- bindings.push(htmlContent.substring(0, index).trim());
26
- htmlContent = htmlContent.substring(index);
27
- i = htmlContent.indexOf(prefix);
28
- }
29
- return bindings;
30
- }
31
-
32
- function getBindingsWithComments(htmlContent, startTag) {
33
- var i = htmlContent.indexOf(startTag);
34
- var bindings = [];
35
- while(i !== -1) {
36
- htmlContent = htmlContent.substring(i + startTag.length);
37
- var index = htmlContent.indexOf('-->')
38
- bindings.push(htmlContent.substring(0, index).trim());
39
- htmlContent = htmlContent.substring(index);
40
- i = htmlContent.indexOf(startTag);
41
- }
42
- return bindings;
43
- }
44
-
45
- function processHtml(content) {
46
- var htmlValue = content
47
- .replace(/\n|\r/g, "")
48
- .replace(/[\s]{4,}/g, " ").trim();
49
-
50
- return {
51
- bindings: [
52
- ...getBindings(htmlValue, 'data-bind="'),
53
- ...getBindings(htmlValue, ' params="'),
54
- ...getBindingsWithComments(htmlValue, "<!--ko"),
55
- ...getBindingsWithComments(htmlValue, "<!-- ko")
56
- ],
57
- dxtBindings: getBindings(htmlValue, 'data-options="')
58
- };
59
- }
60
-
61
- var _cache = {};
62
-
63
- function initCache(cache) {
64
- _cache = cache;
65
- }
66
-
67
- function concatBindings(bindingsArray, createFunctionString, ns) {
68
- return bindingsArray.reduce((arr, x) => {
69
- if(!_cache[x]) {
70
- _cache[x] = true;
71
- var funcString = createFunctionString(x);
72
- var prefix = ns ? 'DevExpress.Analytics.Utils.' : '';
73
- arr.push(`${prefix}addToBindingsCache('${x.replace(/'/g, "\\'").replace(/\\\\'/g, "\\\\\\'")}', ${funcString});`);
74
- }
75
- return arr;
76
- }, []).join('\n');
77
- }
78
-
79
- function collectBindings(fileName, ns) {
80
- var content = fs.readFileSync(fileName).toString();
81
- var processedHtml = processHtml(content);
82
- var koBindings = concatBindings(processedHtml.bindings, x => {
83
- var rewrittenBindings = ko.expressionRewriting.preProcessBindings(x, {valueAccessors: true});
84
- var funcString = `function($context, $element) { return{ ${rewrittenBindings}}}`;
85
- var contextVariables = ["$root", "$index", "$parents", "$parent", "ko", "$data"];
86
- funcString = new processor(['Math', 'Object', 'window'], (name, exists) => {
87
- if(exists || name === 'this') return name;
88
- var replacePrefix = "$context.$data";
89
- if(contextVariables.indexOf(name) !== -1) {
90
- replacePrefix = "$context";
91
- }
92
- return [replacePrefix, name].join('.');
93
- }).process(funcString);
94
- return funcString
95
- }, ns);
96
- var dxtBindings = concatBindings(processedHtml.dxtBindings, x => {
97
- return `function() { return { ${x} } }`;
98
- }, ns);
99
- return [koBindings, dxtBindings].join('\n');
100
- }
101
-
102
- function generateBindingsCode(dirname, ext, addHeader, ns) {
103
- var result = [];
104
- fs.readdirSync(dirname).forEach(function(filename) {
105
- if(filename !== "node_modules") {
106
- var currentFilePath = path.join(dirname, filename)
107
- var stat = fs.lstatSync(currentFilePath);
108
- if(stat.isDirectory()) {
109
- result.push(generateBindingsCode(currentFilePath, ext, false, ns));
110
- } else if(ext.indexOf(path.extname(currentFilePath)) !== -1) {
111
- result.push(collectBindings(currentFilePath, ns));
112
- }
113
- }
114
- })
115
- if(addHeader && !ns) {
116
- return `import { addToBindingsCache } from '@devexpress/analytics-core/analytics-widgets-internal';\n\n${result.join('\n')}`
117
- }
118
- return result.filter(x => !!x).join('\n');
119
- }
120
-
121
- module.exports = {
122
- getBindings,
123
- collectBindings,
124
- initCache,
125
- generateBindingsCode
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const ko = require('knockout');
4
+ const processor = require('js-code-parser/executors/processor').ReplaceVariableProcessor;
5
+
6
+ function getBinding(value) {
7
+ var backBrace = false;
8
+ for(var i = 0; i < value.length; i++) {
9
+ if(value[i] === '"' && !backBrace) {
10
+ return i;
11
+ } else if(value[i] === "\\" && !backBrace) {
12
+ backBrace = true;
13
+ } else if(backBrace) {
14
+ backBrace = false;
15
+ }
16
+ }
17
+ }
18
+
19
+ function getBindings(htmlContent, prefix) {
20
+ var i = htmlContent.indexOf(prefix);
21
+ var bindings = [];
22
+ while(i !== -1) {
23
+ htmlContent = htmlContent.substring(i + prefix.length);
24
+ var index = getBinding(htmlContent);
25
+ bindings.push(htmlContent.substring(0, index).trim());
26
+ htmlContent = htmlContent.substring(index);
27
+ i = htmlContent.indexOf(prefix);
28
+ }
29
+ return bindings;
30
+ }
31
+
32
+ function getBindingsWithComments(htmlContent, startTag) {
33
+ var i = htmlContent.indexOf(startTag);
34
+ var bindings = [];
35
+ while(i !== -1) {
36
+ htmlContent = htmlContent.substring(i + startTag.length);
37
+ var index = htmlContent.indexOf('-->')
38
+ bindings.push(htmlContent.substring(0, index).trim());
39
+ htmlContent = htmlContent.substring(index);
40
+ i = htmlContent.indexOf(startTag);
41
+ }
42
+ return bindings;
43
+ }
44
+
45
+ function processHtml(content) {
46
+ var htmlValue = content
47
+ .replace(/\n|\r/g, "")
48
+ .replace(/[\s]{4,}/g, " ").trim();
49
+
50
+ return {
51
+ bindings: [
52
+ ...getBindings(htmlValue, 'data-bind="'),
53
+ ...getBindings(htmlValue, ' params="'),
54
+ ...getBindingsWithComments(htmlValue, "<!--ko"),
55
+ ...getBindingsWithComments(htmlValue, "<!-- ko")
56
+ ],
57
+ dxtBindings: getBindings(htmlValue, 'data-options="')
58
+ };
59
+ }
60
+
61
+ var _cache = {};
62
+
63
+ function initCache(cache) {
64
+ _cache = cache;
65
+ }
66
+
67
+ function concatBindings(bindingsArray, createFunctionString, ns) {
68
+ return bindingsArray.reduce((arr, x) => {
69
+ if(!_cache[x]) {
70
+ _cache[x] = true;
71
+ var funcString = createFunctionString(x);
72
+ var prefix = ns ? 'DevExpress.Analytics.Utils.' : '';
73
+ arr.push(`${prefix}addToBindingsCache('${x.replace(/'/g, "\\'").replace(/\\\\'/g, "\\\\\\'")}', ${funcString});`);
74
+ }
75
+ return arr;
76
+ }, []).join('\n');
77
+ }
78
+
79
+ function collectBindings(fileName, ns) {
80
+ var content = fs.readFileSync(fileName).toString();
81
+ var processedHtml = processHtml(content);
82
+ var koBindings = concatBindings(processedHtml.bindings, x => {
83
+ var rewrittenBindings = ko.expressionRewriting.preProcessBindings(x, {valueAccessors: true});
84
+ var funcString = `function($context, $element) { return{ ${rewrittenBindings}}}`;
85
+ var contextVariables = ["$root", "$index", "$parents", "$parent", "ko", "$data"];
86
+ funcString = new processor(['Math', 'Object', 'window'], (name, exists) => {
87
+ if(exists || name === 'this') return name;
88
+ var replacePrefix = "$context.$data";
89
+ if(contextVariables.indexOf(name) !== -1) {
90
+ replacePrefix = "$context";
91
+ }
92
+ return [replacePrefix, name].join('.');
93
+ }).process(funcString);
94
+ return funcString
95
+ }, ns);
96
+ var dxtBindings = concatBindings(processedHtml.dxtBindings, x => {
97
+ return `function() { return { ${x} } }`;
98
+ }, ns);
99
+ return [koBindings, dxtBindings].join('\n');
100
+ }
101
+
102
+ function generateBindingsCode(dirname, ext, addHeader, ns) {
103
+ var result = [];
104
+ fs.readdirSync(dirname).forEach(function(filename) {
105
+ if(filename !== "node_modules") {
106
+ var currentFilePath = path.join(dirname, filename)
107
+ var stat = fs.lstatSync(currentFilePath);
108
+ if(stat.isDirectory()) {
109
+ result.push(generateBindingsCode(currentFilePath, ext, false, ns));
110
+ } else if(ext.indexOf(path.extname(currentFilePath)) !== -1) {
111
+ result.push(collectBindings(currentFilePath, ns));
112
+ }
113
+ }
114
+ })
115
+ if(addHeader && !ns) {
116
+ return `import { addToBindingsCache } from '@devexpress/analytics-core/analytics-widgets-internal';\n\n${result.join('\n')}`
117
+ }
118
+ return result.filter(x => !!x).join('\n');
119
+ }
120
+
121
+ module.exports = {
122
+ getBindings,
123
+ collectBindings,
124
+ initCache,
125
+ generateBindingsCode
126
126
  }
@@ -1,21 +1,21 @@
1
- const fs = require('fs');
2
- const generateBindingsCode = require('./_processBindings').generateBindingsCode;
3
- const inquirer = require('inquirer');
4
-
5
- var args = process.argv.slice(2);
6
- var dirname = args[0];
7
- var outputFile = args[1];
8
- var ext = ['.html', '.cshtml'];
9
-
10
- inquirer.prompt([{
11
- type: 'list',
12
- name: 'approach',
13
- message: 'What approach do you use in your JS code?',
14
- choices: ['Modules', 'Namespaces'],
15
- }]).then((answers) => {
16
- if(!outputFile) {
17
- return generateBindingsCode(dirname, ext, true, answers.approach === 'Namespaces');
18
- } else {
19
- fs.writeFileSync(outputFile, generateBindingsCode(dirname, ext, true, answers.approach === 'Namespaces'))
20
- }
1
+ const fs = require('fs');
2
+ const generateBindingsCode = require('./_processBindings').generateBindingsCode;
3
+ const inquirer = require('inquirer');
4
+
5
+ var args = process.argv.slice(2);
6
+ var dirname = args[0];
7
+ var outputFile = args[1];
8
+ var ext = ['.html', '.cshtml'];
9
+
10
+ inquirer.prompt([{
11
+ type: 'list',
12
+ name: 'approach',
13
+ message: 'What approach do you use in your JS code?',
14
+ choices: ['Modules', 'Namespaces'],
15
+ }]).then((answers) => {
16
+ if(!outputFile) {
17
+ return generateBindingsCode(dirname, ext, true, answers.approach === 'Namespaces');
18
+ } else {
19
+ fs.writeFileSync(outputFile, generateBindingsCode(dirname, ext, true, answers.approach === 'Namespaces'))
20
+ }
21
21
  });
@@ -1,57 +1,57 @@
1
- const fs = require("fs"),
2
- path = require("path");
3
-
4
- var defaultThemes = {
5
- "generic": {
6
- colorSchemes: {
7
- "light": { path: "dx-light-style.less" },
8
- "dark": { path: "dx-dark-style.less" },
9
- "carmine": { path: "dx-carmine-style.less" },
10
- "greenmist": { path: "dx-greenmist-style.less" },
11
- "softblue": { path: "dx-softblue-style.less" },
12
- "darkmoon": { path: "dx-darkmoon-style.less" },
13
- "darkviolet": { path: "dx-darkviolet-style.less" },
14
- }
15
- },
16
- "material": {
17
- colorSchemes: {
18
- "blue.light": { path: "dx-material.blue.light-style.less" },
19
- "blue.dark": { path: "dx-material.blue.dark-style.less" },
20
- "lime.light": { path: "dx-material.lime.light-style.less" },
21
- "lime.dark": { path: "dx-material.lime.dark-style.less" },
22
- "orange.light": { path: "dx-material.orange.light-style.less" },
23
- "orange.dark": { path: "dx-material.orange.dark-style.less" },
24
- "purple.light": { path: "dx-material.purple.light-style.less" },
25
- "purple.dark": { path: "dx-material.purple.dark-style.less" },
26
- "teal.light": { path: "dx-material.teal.light-style.less" },
27
- "teal.dark": { path: "dx-material.teal.dark-style.less" }
28
- }
29
- }
30
- };
31
-
32
- function buildTheme(analyticsPath, nodeLess, baseTheme, variables) {
33
- var resolvePath = (lessFileName) => path.resolve(path.join(analyticsPath, "less"), lessFileName)
34
-
35
- var baseTheme = baseTheme || "generic.light";
36
- var themeComponents = baseTheme.split(".");
37
- var themeType = themeComponents[0] || "";
38
- if (themeType === 'generic')
39
- var colorScheme = themeComponents[1] || "";
40
- else if(themeType === 'material')
41
- var colorScheme = [themeComponents[1], themeComponents[2]].join('.');
42
-
43
- var themeFile = resolvePath(defaultThemes[themeType].colorSchemes[colorScheme].path);
44
-
45
- var analyticsVariables = (variables || []).reduce((acc, value) => {
46
- acc[value.key.replace("@", "")] = value.value;
47
- return acc;
48
- }, {});
49
-
50
- return nodeLess.render(fs.readFileSync(themeFile, "utf8"), {
51
- modifyVars: analyticsVariables,
52
- rootpath: resolvePath(""),
53
- paths: [resolvePath("")]
54
- });
55
- }
56
-
57
- module.exports.buildTheme = buildTheme;
1
+ const fs = require("fs"),
2
+ path = require("path");
3
+
4
+ var defaultThemes = {
5
+ "generic": {
6
+ colorSchemes: {
7
+ "light": { path: "dx-light-style.less" },
8
+ "dark": { path: "dx-dark-style.less" },
9
+ "carmine": { path: "dx-carmine-style.less" },
10
+ "greenmist": { path: "dx-greenmist-style.less" },
11
+ "softblue": { path: "dx-softblue-style.less" },
12
+ "darkmoon": { path: "dx-darkmoon-style.less" },
13
+ "darkviolet": { path: "dx-darkviolet-style.less" },
14
+ }
15
+ },
16
+ "material": {
17
+ colorSchemes: {
18
+ "blue.light": { path: "dx-material.blue.light-style.less" },
19
+ "blue.dark": { path: "dx-material.blue.dark-style.less" },
20
+ "lime.light": { path: "dx-material.lime.light-style.less" },
21
+ "lime.dark": { path: "dx-material.lime.dark-style.less" },
22
+ "orange.light": { path: "dx-material.orange.light-style.less" },
23
+ "orange.dark": { path: "dx-material.orange.dark-style.less" },
24
+ "purple.light": { path: "dx-material.purple.light-style.less" },
25
+ "purple.dark": { path: "dx-material.purple.dark-style.less" },
26
+ "teal.light": { path: "dx-material.teal.light-style.less" },
27
+ "teal.dark": { path: "dx-material.teal.dark-style.less" }
28
+ }
29
+ }
30
+ };
31
+
32
+ function buildTheme(analyticsPath, nodeLess, baseTheme, variables) {
33
+ var resolvePath = (lessFileName) => path.resolve(path.join(analyticsPath, "less"), lessFileName)
34
+
35
+ var baseTheme = baseTheme || "generic.light";
36
+ var themeComponents = baseTheme.split(".");
37
+ var themeType = themeComponents[0] || "";
38
+ if (themeType === 'generic')
39
+ var colorScheme = themeComponents[1] || "";
40
+ else if(themeType === 'material')
41
+ var colorScheme = [themeComponents[1], themeComponents[2]].join('.');
42
+
43
+ var themeFile = resolvePath(defaultThemes[themeType].colorSchemes[colorScheme].path);
44
+
45
+ var analyticsVariables = (variables || []).reduce((acc, value) => {
46
+ acc[value.key.replace("@", "")] = value.value;
47
+ return acc;
48
+ }, {});
49
+
50
+ return nodeLess.render(fs.readFileSync(themeFile, "utf8"), {
51
+ modifyVars: analyticsVariables,
52
+ rootpath: resolvePath(""),
53
+ paths: [resolvePath("")]
54
+ });
55
+ }
56
+
57
+ module.exports.buildTheme = buildTheme;
@@ -1,111 +1,111 @@
1
- const ts = require('typescript');
2
- const fs = require('fs');
3
-
4
- function resolveTypingsInFile(filePath, typeReplacements) {
5
- const compilerOptions = {};
6
- const compilerHost = ts.createCompilerHost(compilerOptions);
7
- const program = ts.createProgram([filePath], compilerOptions, compilerHost);
8
-
9
- const sourceFile = program.getSourceFile(filePath);
10
- const renameAllAddIdentifiersToRenamedAdd = (context) => (rootNode) => {
11
- const visit = (node) => {
12
- let newNode = null;
13
- if(ts.isModuleDeclaration(node)) {
14
- const imports = {};
15
- fillImports(node, imports);
16
- newNode = replaceTypes(node, imports, context);
17
- if(typeReplacements)
18
- newNode = processNodeRecoursive(newNode, typeReplacements, context);
19
- } else {
20
- newNode = ts.visitEachChild(node, visit, context);
21
- }
22
- return newNode;
23
- };
24
- return ts.visitNode(rootNode, visit);
25
- };
26
-
27
- const transformationResult = ts.transform(sourceFile, [
28
- renameAllAddIdentifiersToRenamedAdd,
29
- ]);
30
- const updatedSourceFile = transformationResult.transformed[0];
31
- const printer = ts.createPrinter();
32
- const updatedCode = printer.printFile(updatedSourceFile);
33
-
34
- fs.writeFileSync(filePath, updatedCode, 'utf-8');
35
- }
36
-
37
- function processNodeRecoursive(node, typeReplacements, context) {
38
- var typesToReplace = Object.keys(typeReplacements);
39
- if(ts.isModuleDeclaration(node)) {
40
- if(node.body && ts.isModuleBlock(node.body)) {
41
- for(const statement of node.body.statements) {
42
- const typeName = statement.name?.escapedText;
43
- if(typeName && ts.isTypeAliasDeclaration(statement) && typesToReplace.indexOf(typeName) != -1) {
44
- const newTypeString = typeReplacements[typeName];
45
- const newTypeNode = ts.factory.createTypeReferenceNode(newTypeString, []);
46
-
47
- //in case of some artifacts or side effects use createTypeAliasDeclaration from newTypeNode instead of updateTypeAliasDeclaration
48
- const newPropStatement = ts.factory.updateTypeAliasDeclaration(
49
- statement,
50
- statement.modifiers,
51
- statement.name,
52
- statement.typeParameters,
53
- newTypeNode
54
- );
55
-
56
- node.body = ts.factory.updateModuleBlock(node.body, [
57
- ...node.body.statements.filter((x) => x !== statement),
58
- newPropStatement,
59
- ]);
60
- }
61
- }
62
- } else {
63
- node.body = processNodeRecoursive(node.body, typeReplacements, context);
64
- }
65
- }
66
- return node;
67
- }
68
-
69
- function fillImports(node, imports) {
70
- if(ts.isImportEqualsDeclaration(node)) {
71
- let name = node.name.escapedText;
72
- name && ts.forEachChild(node, node => {
73
- if(ts.isQualifiedName(node)) {
74
- let fullName = getFullTypeName(node);
75
- imports[name] = fullName;
76
- }
77
- });
78
- } else {
79
- ts.forEachChild(node, (node) => fillImports(node, imports))
80
- }
81
- }
82
-
83
- function replaceTypes(node, imports, context) {
84
- if(ts.isTypeReferenceNode(node)) {
85
- const typeName = node.typeName?.text;
86
- const updatedTypeName = imports[typeName];
87
- if(updatedTypeName) {
88
- return ts.factory.createTypeReferenceNode(updatedTypeName, node.typeArguments);
89
- }
90
- } else if(ts.isTypeQueryNode(node)) {
91
- const typeName = node.exprName?.escapedText;
92
- const updatedTypeName = imports[typeName];
93
- if(updatedTypeName) {
94
- const exprName = ts.factory.createIdentifier(updatedTypeName);
95
- return ts.factory.createTypeQueryNode(exprName);
96
- }
97
- }
98
- return ts.visitEachChild(node, (node) => replaceTypes(node, imports, context), context);
99
- }
100
-
101
- function getFullTypeName(node) {
102
- if(node.kind === ts.SyntaxKind.Identifier) {
103
- return node.escapedText
104
- } else {
105
- return getFullTypeName(node.left) + '.' + node.right.escapedText;
106
- }
107
- }
108
-
109
- module.exports = {
110
- resolveTypingsInFile: resolveTypingsInFile
111
- }
1
+ const ts = require('typescript');
2
+ const fs = require('fs');
3
+
4
+ function resolveTypingsInFile(filePath, typeReplacements) {
5
+ const compilerOptions = {};
6
+ const compilerHost = ts.createCompilerHost(compilerOptions);
7
+ const program = ts.createProgram([filePath], compilerOptions, compilerHost);
8
+
9
+ const sourceFile = program.getSourceFile(filePath);
10
+ const renameAllAddIdentifiersToRenamedAdd = (context) => (rootNode) => {
11
+ const visit = (node) => {
12
+ let newNode = null;
13
+ if(ts.isModuleDeclaration(node)) {
14
+ const imports = {};
15
+ fillImports(node, imports);
16
+ newNode = replaceTypes(node, imports, context);
17
+ if(typeReplacements)
18
+ newNode = processNodeRecoursive(newNode, typeReplacements, context);
19
+ } else {
20
+ newNode = ts.visitEachChild(node, visit, context);
21
+ }
22
+ return newNode;
23
+ };
24
+ return ts.visitNode(rootNode, visit);
25
+ };
26
+
27
+ const transformationResult = ts.transform(sourceFile, [
28
+ renameAllAddIdentifiersToRenamedAdd,
29
+ ]);
30
+ const updatedSourceFile = transformationResult.transformed[0];
31
+ const printer = ts.createPrinter();
32
+ const updatedCode = printer.printFile(updatedSourceFile);
33
+
34
+ fs.writeFileSync(filePath, updatedCode, 'utf-8');
35
+ }
36
+
37
+ function processNodeRecoursive(node, typeReplacements, context) {
38
+ var typesToReplace = Object.keys(typeReplacements);
39
+ if(ts.isModuleDeclaration(node)) {
40
+ if(node.body && ts.isModuleBlock(node.body)) {
41
+ for(const statement of node.body.statements) {
42
+ const typeName = statement.name?.escapedText;
43
+ if(typeName && ts.isTypeAliasDeclaration(statement) && typesToReplace.indexOf(typeName) != -1) {
44
+ const newTypeString = typeReplacements[typeName];
45
+ const newTypeNode = ts.factory.createTypeReferenceNode(newTypeString, []);
46
+
47
+ //in case of some artifacts or side effects use createTypeAliasDeclaration from newTypeNode instead of updateTypeAliasDeclaration
48
+ const newPropStatement = ts.factory.updateTypeAliasDeclaration(
49
+ statement,
50
+ statement.modifiers,
51
+ statement.name,
52
+ statement.typeParameters,
53
+ newTypeNode
54
+ );
55
+
56
+ node.body = ts.factory.updateModuleBlock(node.body, [
57
+ ...node.body.statements.filter((x) => x !== statement),
58
+ newPropStatement,
59
+ ]);
60
+ }
61
+ }
62
+ } else {
63
+ node.body = processNodeRecoursive(node.body, typeReplacements, context);
64
+ }
65
+ }
66
+ return node;
67
+ }
68
+
69
+ function fillImports(node, imports) {
70
+ if(ts.isImportEqualsDeclaration(node)) {
71
+ let name = node.name.escapedText;
72
+ name && ts.forEachChild(node, node => {
73
+ if(ts.isQualifiedName(node)) {
74
+ let fullName = getFullTypeName(node);
75
+ imports[name] = fullName;
76
+ }
77
+ });
78
+ } else {
79
+ ts.forEachChild(node, (node) => fillImports(node, imports))
80
+ }
81
+ }
82
+
83
+ function replaceTypes(node, imports, context) {
84
+ if(ts.isTypeReferenceNode(node)) {
85
+ const typeName = node.typeName?.text;
86
+ const updatedTypeName = imports[typeName];
87
+ if(updatedTypeName) {
88
+ return ts.factory.createTypeReferenceNode(updatedTypeName, node.typeArguments);
89
+ }
90
+ } else if(ts.isTypeQueryNode(node)) {
91
+ const typeName = node.exprName?.escapedText;
92
+ const updatedTypeName = imports[typeName];
93
+ if(updatedTypeName) {
94
+ const exprName = ts.factory.createIdentifier(updatedTypeName);
95
+ return ts.factory.createTypeQueryNode(exprName);
96
+ }
97
+ }
98
+ return ts.visitEachChild(node, (node) => replaceTypes(node, imports, context), context);
99
+ }
100
+
101
+ function getFullTypeName(node) {
102
+ if(node.kind === ts.SyntaxKind.Identifier) {
103
+ return node.escapedText
104
+ } else {
105
+ return getFullTypeName(node.left) + '.' + node.right.escapedText;
106
+ }
107
+ }
108
+
109
+ module.exports = {
110
+ resolveTypingsInFile: resolveTypingsInFile
111
+ }