powerbi-visuals-tools 4.3.2 → 5.0.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 (69) hide show
  1. package/Changelog.md +7 -0
  2. package/README.md +1 -1
  3. package/bin/pbiviz.js +55 -36
  4. package/certs/PowerBICustomVisualTest_private.key +26 -26
  5. package/certs/PowerBICustomVisualTest_public.crt +17 -17
  6. package/config.json +27 -34
  7. package/lib/CertificateTools.js +119 -143
  8. package/lib/CommandManager.js +52 -0
  9. package/lib/ConsoleWriter.js +63 -85
  10. package/lib/TemplateFetcher.js +23 -30
  11. package/lib/VisualGenerator.js +42 -56
  12. package/lib/VisualManager.js +193 -0
  13. package/lib/WebPackWrap.js +96 -145
  14. package/lib/utils.js +21 -13
  15. package/lib/webpack.config.js +47 -56
  16. package/package.json +34 -26
  17. package/spec/clean-tests.js +1 -1
  18. package/spec/e2e/pbivizCertSpec.js +14 -13
  19. package/spec/e2e/pbivizInfoSpec.js +7 -10
  20. package/spec/e2e/pbivizNewSpec.js +53 -65
  21. package/spec/e2e/pbivizPackageSpec.js +86 -90
  22. package/spec/e2e/pbivizStartSpec.js +6 -7
  23. package/spec/e2e/pbivizWebpackVerSpec.js +14 -16
  24. package/spec/e2e/{utils.js → testUtils.js} +9 -12
  25. package/spec/helpers/FileSystem.js +18 -18
  26. package/spec/jasmine-runner.js +5 -5
  27. package/src/CertificateTools.ts +431 -0
  28. package/src/CommandManager.ts +78 -0
  29. package/src/ConsoleWriter.ts +206 -0
  30. package/src/TemplateFetcher.ts +122 -0
  31. package/src/VisualGenerator.ts +236 -0
  32. package/src/VisualManager.ts +220 -0
  33. package/src/WebPackWrap.ts +299 -0
  34. package/src/utils.ts +41 -0
  35. package/src/webpack.config.ts +144 -0
  36. package/templates/pbiviz-json-template.js +2 -2
  37. package/templates/pbiviz.json.template +1 -1
  38. package/templates/plugin-ts-template.js +1 -1
  39. package/templates/visuals/default/.eslintignore +5 -0
  40. package/templates/visuals/default/.eslintrc.js +20 -0
  41. package/templates/visuals/default/package.json +9 -8
  42. package/templates/visuals/default/pbiviz.json +3 -2
  43. package/templates/visuals/default/tsconfig.json +2 -2
  44. package/templates/visuals/rhtml/.eslintignore +5 -0
  45. package/templates/visuals/rhtml/.eslintrc.js +20 -0
  46. package/templates/visuals/rhtml/package.json +7 -6
  47. package/templates/visuals/rhtml/pbiviz.json +2 -1
  48. package/templates/visuals/rvisual/.eslintignore +5 -0
  49. package/templates/visuals/rvisual/.eslintrc.js +20 -0
  50. package/templates/visuals/rvisual/package.json +5 -4
  51. package/templates/visuals/slicer/.eslintignore +5 -0
  52. package/templates/visuals/slicer/.eslintrc.js +20 -0
  53. package/templates/visuals/slicer/package.json +8 -7
  54. package/templates/visuals/table/.eslintignore +5 -0
  55. package/templates/visuals/table/.eslintrc.js +20 -0
  56. package/templates/visuals/table/package.json +8 -7
  57. package/templates/visuals/table/tsconfig.json +4 -0
  58. package/tsconfig.json +22 -0
  59. package/bin/pbiviz-info.js +0 -54
  60. package/bin/pbiviz-new.js +0 -82
  61. package/bin/pbiviz-package.js +0 -122
  62. package/bin/pbiviz-start.js +0 -142
  63. package/lib/CommandHelpManager.js +0 -51
  64. package/lib/VisualPackage.js +0 -118
  65. package/templates/visuals/default/tslint.json +0 -9
  66. package/templates/visuals/rhtml/tslint.json +0 -9
  67. package/templates/visuals/rvisual/tslint.json +0 -9
  68. package/templates/visuals/slicer/tslint.json +0 -9
  69. package/templates/visuals/table/tslint.json +0 -9
@@ -0,0 +1,220 @@
1
+ /*
2
+ * Power BI Visual CLI
3
+ *
4
+ * Copyright (c) Microsoft Corporation
5
+ * All rights reserved.
6
+ * MIT License
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the ""Software""), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+
27
+ "use strict";
28
+
29
+ import webpack, { Compiler, Stats } from "webpack";
30
+ import WebpackDevServer from "webpack-dev-server";
31
+ import childProcess from 'child_process';
32
+ import fs from 'fs-extra';
33
+ import path from 'path';
34
+
35
+ import ConsoleWriter from './ConsoleWriter.js';
36
+ import VisualGenerator from './VisualGenerator.js';
37
+ import { readJsonFromRoot, readJsonFromVisual } from './utils.js';
38
+ import WebpackWrap, { WebpackOptions } from './WebPackWrap.js';
39
+ import TemplateFetcher from "./TemplateFetcher.js";
40
+
41
+ interface GenerateOptions {
42
+ force: boolean;
43
+ template: string;
44
+ }
45
+
46
+ const PBIVIZ_FILE = 'pbiviz.json';
47
+
48
+ /**
49
+ * Represents an instance of a visual package based on file path
50
+ */
51
+ export default class VisualManager {
52
+ public basePath: string;
53
+ public pbivizConfig;
54
+ private webpackConfig;
55
+ private compiler: Compiler;
56
+ private webpackDevServer: WebpackDevServer;
57
+
58
+ constructor(rootPath: string) {
59
+ this.basePath = rootPath;
60
+ }
61
+
62
+ public prepareVisual() {
63
+ if (this.doesPBIVIZExists()) {
64
+ this.pbivizConfig = readJsonFromVisual(PBIVIZ_FILE, this.basePath);
65
+ } else {
66
+ throw new Error(PBIVIZ_FILE + ' not found. You must be in the root of a visual project to run this command.')
67
+ }
68
+ return this;
69
+ }
70
+
71
+ public async initializeWebpack(webpackOptions: WebpackOptions) {
72
+ const webpackWrap = new WebpackWrap();
73
+ this.webpackConfig = await webpackWrap.generateWebpackConfig(this, webpackOptions)
74
+
75
+ this.compiler = webpack(this.webpackConfig);
76
+
77
+ return this;
78
+ }
79
+
80
+ public generatePackage() {
81
+ const callback = (err: Error, stats: Stats) => {
82
+ this.parseCompilationResults(err, stats)
83
+ }
84
+ this.compiler.run(callback);
85
+ }
86
+
87
+ public startWebpackServer(generateDropFiles: boolean = false) {
88
+ ConsoleWriter.blank();
89
+ ConsoleWriter.info('Starting server...');
90
+ try {
91
+ if (generateDropFiles) {
92
+ this.prepareDropFiles();
93
+ }
94
+
95
+ this.webpackDevServer = new WebpackDevServer({
96
+ ...this.webpackConfig.devServer,
97
+ client: false,
98
+ hot: false,
99
+ devMiddleware: {
100
+ writeToDisk: true
101
+ }
102
+ }, this.compiler);
103
+
104
+ (async () => {
105
+ await this.webpackDevServer.start();
106
+ ConsoleWriter.info(`Server listening on port ${this.webpackConfig.devServer.port}`);
107
+ })();
108
+
109
+ process.on('SIGINT', this.stopServer);
110
+ process.on('SIGTERM', this.stopServer);
111
+ } catch (e) {
112
+ ConsoleWriter.error(e.message);
113
+ process.exit(1);
114
+ }
115
+ }
116
+
117
+ public displayInfo() {
118
+ if (this.pbivizConfig) {
119
+ ConsoleWriter.infoTable(this.pbivizConfig);
120
+ } else {
121
+ ConsoleWriter.error('Unable to load visual info. Please ensure the package is valid.');
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Creates a new visual package
127
+ */
128
+ static async createVisual(rootPath: string, visualName: string, generateOptions: GenerateOptions): Promise<VisualManager | void> {
129
+ ConsoleWriter.info('Creating new visual');
130
+ if (generateOptions.force) {
131
+ ConsoleWriter.warning('Running with force flag. Existing files will be overwritten');
132
+ }
133
+
134
+ try {
135
+ const config = readJsonFromRoot('config.json');
136
+ if(config.visualTemplates[generateOptions.template]){
137
+ new TemplateFetcher( generateOptions.template, visualName, undefined )
138
+ .fetch();
139
+ return;
140
+ }
141
+ const newVisualPath = await VisualGenerator.generateVisual(rootPath, visualName, generateOptions)
142
+ await VisualManager.installPackages(newVisualPath).then(() => ConsoleWriter.done('Visual creation complete'))
143
+
144
+ return new VisualManager(newVisualPath);
145
+ } catch (error) {
146
+ ConsoleWriter.error(['Unable to create visual.\n', error]);
147
+ process.exit(1);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Install npm dependencies for visual
153
+ */
154
+ static installPackages(visualPath: string): Promise<void> {
155
+ return new Promise(function (resolve, reject) {
156
+ ConsoleWriter.info('Installing packages...');
157
+ childProcess.exec(`npm install`, { cwd: visualPath },
158
+ (err) => {
159
+ if (err) {
160
+ reject(new Error('Package install failed.'));
161
+ } else {
162
+ ConsoleWriter.info('Installed packages.');
163
+ resolve();
164
+ }
165
+ });
166
+ });
167
+ }
168
+
169
+ private doesPBIVIZExists() {
170
+ return fs.existsSync(PBIVIZ_FILE);
171
+ }
172
+
173
+ private prepareDropFiles() {
174
+ this.webpackConfig.devServer.onBeforeSetupMiddleware = (devServer) => {
175
+ const { headers, publicPath, static: { directory } } = this.webpackConfig.devServer;
176
+ const assets = [ 'visual.js`', 'visual.css', 'pbiviz.json' ]
177
+
178
+ const setHeaders = (res) => {
179
+ Object.getOwnPropertyNames(headers)
180
+ .forEach(property => res.header(property, headers[property]));
181
+ };
182
+ const readFile = (file, res) => {
183
+ fs.readFile(file).then(function (content) {
184
+ res.write(content);
185
+ res.end();
186
+ });
187
+ };
188
+
189
+ assets.forEach(asset => {
190
+ devServer.app.get(`${publicPath}/${asset}`, function (req, res) {
191
+ setHeaders(res);
192
+ readFile(path.join(directory, asset), res);
193
+ });
194
+ });
195
+ };
196
+ }
197
+
198
+ private stopServer() {
199
+ ConsoleWriter.blank();
200
+ ConsoleWriter.info("Stopping server...");
201
+ if (this.webpackDevServer) {
202
+ this.webpackDevServer.close();
203
+ this.webpackDevServer = null;
204
+ }
205
+ }
206
+
207
+ private parseCompilationResults(err: Error, stats: Stats) {
208
+ ConsoleWriter.blank();
209
+ if (err) {
210
+ ConsoleWriter.error(`Package wasn't created. ${JSON.stringify(err)}`);
211
+ }
212
+ if (stats?.compilation.errors.length) {
213
+ stats.compilation.errors.forEach(error => ConsoleWriter.error(error.message));
214
+ ConsoleWriter.error(`Package wasn't created. ${stats.compilation.errors.length} errors found.`);
215
+ }
216
+ if (!err && !stats?.compilation.errors.length) {
217
+ ConsoleWriter.done('Build completed successfully');
218
+ }
219
+ }
220
+ }
@@ -0,0 +1,299 @@
1
+ "use strict";
2
+
3
+ import fs from 'fs-extra';
4
+ import os from 'os';
5
+ import path from 'path';
6
+ import webpack from 'webpack';
7
+ import util from 'util';
8
+ const exec = util.promisify(processExec);
9
+ import { exec as processExec } from 'child_process';
10
+ import ExtraWatchWebpackPlugin from 'extra-watch-webpack-plugin';
11
+ import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
12
+ import { PowerBICustomVisualsWebpackPlugin } from 'powerbi-visuals-webpack-plugin';
13
+ import ConsoleWriter from './ConsoleWriter.js';
14
+ import { resolveCertificate } from "./CertificateTools.js";
15
+ import lodashCloneDeep from 'lodash.clonedeep';
16
+ import { readJsonFromRoot, readJsonFromVisual } from './utils.js'
17
+
18
+ const config = readJsonFromRoot('config.json');
19
+ const npmPackage = readJsonFromRoot('package.json');
20
+
21
+ const visualPlugin = "visualPlugin.ts";
22
+ const encoding = "utf8";
23
+
24
+ export interface WebpackOptions {
25
+ devMode: boolean;
26
+ generateResources: boolean;
27
+ generatePbiviz: boolean;
28
+ minifyJS: boolean;
29
+ minify: boolean;
30
+ stats: boolean;
31
+ compression?: number;
32
+ devtool?: string;
33
+ devServerPort?: number;
34
+ fast?: boolean;
35
+ }
36
+
37
+ export default class WebPackWrap {
38
+ private pbiviz;
39
+ private webpackConfig;
40
+
41
+ static async prepareFoldersAndFiles(visualPackage) {
42
+ const tmpFolder = path.join(visualPackage.basePath, ".tmp");
43
+ const precompileFolder = path.join(visualPackage.basePath, config.build.precompileFolder);
44
+ const dropFolder = path.join(visualPackage.basePath, config.build.dropFolder);
45
+ const packageDropFolder = path.join(visualPackage.basePath, config.package.dropFolder);
46
+ const visualPluginFile = path.join(visualPackage.basePath, config.build.precompileFolder, visualPlugin);
47
+ await fs.ensureDir(tmpFolder);
48
+ await fs.ensureDir(precompileFolder);
49
+ await fs.ensureDir(dropFolder);
50
+ await fs.ensureDir(packageDropFolder);
51
+ await fs.createFile(visualPluginFile);
52
+ }
53
+
54
+ static loadAPIPackage() {
55
+ try {
56
+ return import("file://" + path.join(process.cwd(), "node_modules", "powerbi-visuals-api", "index.js"));
57
+ } catch (ex) {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ async installAPIpackage() {
63
+ const apiVersion = this.pbiviz.apiVersion ? `~${this.pbiviz.apiVersion}` : "latest";
64
+ try {
65
+ ConsoleWriter.info(`Installing API: ${apiVersion}...`);
66
+ const {
67
+ stdout,
68
+ stderr
69
+ } = await exec(`npm install --save powerbi-visuals-api@${apiVersion}`);
70
+ if (stdout) ConsoleWriter.info(stdout);
71
+ if (stderr) ConsoleWriter.warning(stderr);
72
+ return true;
73
+ } catch (ex) {
74
+ if (ex.message.indexOf("No matching version found for powerbi-visuals-api") !== -1) {
75
+ throw new Error(`Error: Invalid API version: ${apiVersion}`);
76
+ }
77
+ ConsoleWriter.error(`npm install powerbi-visuals-api@${apiVersion} failed`);
78
+ return false;
79
+ }
80
+ }
81
+
82
+ enableOptimization() {
83
+ this.webpackConfig.mode = "production";
84
+ this.webpackConfig.optimization = {
85
+ concatenateModules: false,
86
+ minimize: true
87
+ };
88
+ }
89
+
90
+ async configureDevServer(visualPackage, port = 8080) {
91
+ const options = await resolveCertificate();
92
+
93
+ this.webpackConfig.devServer = {
94
+ ...this.webpackConfig.devServer,
95
+ hot: false,
96
+ port,
97
+ static: {
98
+ directory: path.join(visualPackage.basePath, config.build.dropFolder),
99
+ publicPath: config.server.assetsRoute
100
+ },
101
+ server: {
102
+ type: 'https',
103
+ options: {
104
+ key: options.key,
105
+ cert: options.cert,
106
+ pfx: options.pfx,
107
+ passphrase: options.passphrase
108
+ }
109
+ }
110
+ };
111
+ }
112
+
113
+ configureVisualPlugin(options, tsconfig, visualPackage) {
114
+ const visualJSFilePath = tsconfig.compilerOptions.out || tsconfig.compilerOptions.outDir;
115
+ this.webpackConfig.output.path = path.join(visualPackage.basePath, config.build.dropFolder);
116
+ this.webpackConfig.output.filename = "[name]";
117
+ const visualPluginPath = path.join(process.cwd(), config.build.precompileFolder, visualPlugin);
118
+ this.webpackConfig.watchOptions.ignored.push(visualPluginPath)
119
+ if (tsconfig.compilerOptions.out) {
120
+ this.webpackConfig.entry = {
121
+ "visual.js": visualJSFilePath
122
+ };
123
+ } else {
124
+ this.webpackConfig.entry["visual.js"] = [visualPluginPath];
125
+ this.webpackConfig.output.library = `${this.pbiviz.visual.guid}${options.devMode ? "_DEBUG" : ""}`;
126
+ this.webpackConfig.output.libraryTarget = 'var';
127
+ }
128
+ }
129
+
130
+ async getEnvironmentDetails() {
131
+ const env = {
132
+ nodeVersion: process.versions.node,
133
+ osPlatform: await os.platform(),
134
+ osVersion: await os.version ?? "undefined",
135
+ osReleaseVersion: await os.release(),
136
+ toolsVersion: npmPackage.version
137
+ };
138
+ return env;
139
+ }
140
+
141
+ async configureCustomVisualsWebpackPlugin(visualPackage, options, tsconfig) {
142
+ const pluginConfiguration = lodashCloneDeep(visualPackage.pbivizConfig);
143
+ //(?=\D*$) - positive look-ahead to find last version symbols and exclude any non-digit symbols after the version.
144
+ const regexFullVersion = /(?:\d+\.?){1,3}(?=\D*$)/;
145
+ const regexMinorVersion = /\d+(?:\.\d+)?/;
146
+ let apiVersionInstalled;
147
+ try {
148
+ const subprocess = await exec('npm list powerbi-visuals-api version')
149
+ apiVersionInstalled = subprocess.stdout.match(regexFullVersion)[0];
150
+ } catch (err) {
151
+ ConsoleWriter.warning(`"powerbi-visuals-api" is not installed`);
152
+ }
153
+ // if the powerbi-visual-api package wasn't installed
154
+ // install the powerbi-visual-api, with version from apiVersion in pbiviz.json
155
+ // or the latest API, if apiVersion is absent in pbiviz.json
156
+ if (!apiVersionInstalled || !this.pbiviz.apiVersion || this.pbiviz.apiVersion.match(regexMinorVersion)[0] != apiVersionInstalled.match(regexMinorVersion)[0]) {
157
+ ConsoleWriter.warning(`installed "powerbi-visuals-api" version - "${apiVersionInstalled}", is not match with the version specified in pbviz.json - "${this.pbiviz.apiVersion}".`);
158
+ await this.installAPIpackage();
159
+ }
160
+
161
+ // pluginConfiguration.env = await this.getEnvironmentDetails();
162
+
163
+ const api = await WebPackWrap.loadAPIPackage();
164
+ pluginConfiguration.apiVersion = api.version;
165
+ pluginConfiguration.capabilitiesSchema = api.schemas.capabilities;
166
+ pluginConfiguration.pbivizSchema = api.schemas.pbiviz;
167
+ pluginConfiguration.stringResourcesSchema = api.schemas.stringResources;
168
+ pluginConfiguration.dependenciesSchema = api.schemas.dependencies;
169
+
170
+
171
+ pluginConfiguration.customVisualID = `CustomVisual_${this.pbiviz.visual.guid}`.replace(/[^\w\s]/gi, '');
172
+ pluginConfiguration.devMode = (typeof options.devMode === "undefined") ? true : options.devMode;
173
+ pluginConfiguration.generatePbiviz = options.generatePbiviz;
174
+ pluginConfiguration.generateResources = options.generateResources;
175
+ pluginConfiguration.minifyJS = options.minifyJS;
176
+ const dependenciesPath = this.pbiviz.dependencies && path.join(process.cwd(), this.pbiviz.dependencies);
177
+ pluginConfiguration.dependencies = fs.existsSync(dependenciesPath) ? this.pbiviz.dependencies : null;
178
+ pluginConfiguration.modules = typeof tsconfig.compilerOptions.outDir !== "undefined";
179
+ pluginConfiguration.visualSourceLocation = path.posix.relative(config.build.precompileFolder, tsconfig.files[0]).replace(/(\.ts)x|\.ts/, "");
180
+ pluginConfiguration.pluginLocation = path.join(config.build.precompileFolder, "visualPlugin.ts");
181
+ pluginConfiguration.compression = options.compression;
182
+ return pluginConfiguration;
183
+ }
184
+
185
+ async appendPlugins(options, visualPackage, tsconfig) {
186
+ const pluginConfiguration = await this.configureCustomVisualsWebpackPlugin(visualPackage, options, tsconfig);
187
+
188
+ let statsFilename = config.build.stats.split("/").pop();
189
+ const statsLocation = config.build.stats.split("/").slice(0, -1).join(path.sep);
190
+ statsFilename = statsFilename?.split(".").slice(0, -1).join(".");
191
+ statsFilename = `${statsFilename}.${options.devMode ? "dev" : "prod"}.html`;
192
+
193
+ if (options.stats) {
194
+ this.webpackConfig.plugins.push(
195
+ new BundleAnalyzerPlugin({
196
+ reportFilename: path.join(statsLocation, statsFilename),
197
+ openAnalyzer: false,
198
+ analyzerMode: `static`
199
+ })
200
+ );
201
+ }
202
+ this.webpackConfig.plugins.push(
203
+ new PowerBICustomVisualsWebpackPlugin(pluginConfiguration),
204
+ new ExtraWatchWebpackPlugin({
205
+ files: this.pbiviz.capabilities
206
+ })
207
+ );
208
+
209
+ if (options.devtool === "source-map" && this.webpackConfig.devServer.port) {
210
+ this.webpackConfig.plugins.push(
211
+ new webpack.SourceMapDevToolPlugin({
212
+ filename: '[file].map',
213
+ publicPath: `https://localhost:${this.webpackConfig.devServer.port}/assets/`
214
+ })
215
+ );
216
+ }
217
+ }
218
+
219
+ async useLoader({
220
+ fast = false
221
+ }) {
222
+ let tsOptions = {};
223
+ if (fast) {
224
+ tsOptions = {
225
+ transpileOnly: false,
226
+ experimentalWatchApi: false
227
+ };
228
+ }
229
+ this.webpackConfig.module.rules.push({
230
+ test: /(\.ts)x?$/,
231
+ use: [
232
+ {
233
+ loader: 'ts-loader',
234
+ options: tsOptions
235
+ }
236
+ ]
237
+ });
238
+ }
239
+
240
+ async prepareWebPackConfig(visualPackage, options: WebpackOptions, tsconfig) {
241
+ this.webpackConfig = Object.assign({}, await import('./webpack.config.js')).default;
242
+ if (options.minifyJS) {
243
+ this.enableOptimization();
244
+ }
245
+
246
+ if (options.devtool) {
247
+ this.webpackConfig.devtool = options.devtool;
248
+ }
249
+
250
+ await this.appendPlugins(options, visualPackage, tsconfig);
251
+ await this.configureDevServer(visualPackage, options.devServerPort);
252
+ await this.configureVisualPlugin(options, tsconfig, visualPackage);
253
+ await this.useLoader({
254
+ fast: options.fast
255
+ });
256
+
257
+ return this.webpackConfig;
258
+ }
259
+
260
+ async assemblyExternalJSFiles(visualPackage) {
261
+ const externalJSFilesContent = "";
262
+ const externalJSFilesPath = path.join(visualPackage.basePath, config.build.precompileFolder, "externalJS.js");
263
+ await fs.writeFile(
264
+ externalJSFilesPath,
265
+ externalJSFilesContent, {
266
+ encoding: encoding
267
+ });
268
+
269
+ return externalJSFilesPath;
270
+ }
271
+
272
+ async generateWebpackConfig(visualPackage, options: WebpackOptions = {
273
+ devMode: false,
274
+ generateResources: false,
275
+ generatePbiviz: false,
276
+ minifyJS: true,
277
+ minify: true,
278
+ devServerPort: 8080,
279
+ fast: false,
280
+ compression: 0,
281
+ stats: true
282
+ }) {
283
+ const tsconfig = readJsonFromVisual('tsconfig.json');
284
+ this.pbiviz = readJsonFromVisual('pbiviz.json');
285
+
286
+ const capabilitiesPath = this.pbiviz.capabilities;
287
+ visualPackage.pbivizConfig.capabilities = capabilitiesPath;
288
+
289
+ const dependenciesPath = this.pbiviz.dependencies && path.join(process.cwd(), this.pbiviz.dependencies);
290
+ const dependenciesFile = fs.existsSync(dependenciesPath) && JSON.parse(fs.readFileSync(dependenciesPath));
291
+ visualPackage.pbivizConfig.dependencies = typeof dependenciesFile === 'object' ? dependenciesFile : {};
292
+
293
+ await WebPackWrap.prepareFoldersAndFiles(visualPackage);
294
+
295
+ const webpackConfig = await this.prepareWebPackConfig(visualPackage, options, tsconfig);
296
+
297
+ return webpackConfig;
298
+ }
299
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,41 @@
1
+ import fs from 'fs-extra';
2
+ import https from "https";
3
+ import path from "path";
4
+ import os from "os";
5
+
6
+ export function download(url, pathToFile) {
7
+ return new Promise((resolve, reject) => {
8
+ const fileStream = fs.createWriteStream(pathToFile);
9
+ https.get(url, (res) => {
10
+ res.pipe(fileStream);
11
+ fileStream.on('close', () => resolve(fileStream));
12
+ res.on('error', (error) => reject(error));
13
+ })
14
+ .on('error', (error) => reject(error));
15
+ });
16
+ }
17
+
18
+ export function createFolder(folderName): string {
19
+ const folder = path.join("./", folderName);
20
+ fs.ensureDirSync(folder);
21
+ return folder;
22
+ }
23
+
24
+ export function getRootPath(): string {
25
+ const isLinux = os.platform() === "linux"
26
+ const pathToDirectory = import.meta.url.split(isLinux ? "file://" : "file:///")[1];
27
+ return path.join(pathToDirectory, "../..");
28
+ }
29
+
30
+ export function readFileFromRoot(filePath: string) {
31
+ return fs.readFileSync(path.join(getRootPath(), filePath), "utf8")
32
+ }
33
+
34
+ export function readJsonFromRoot(filePath: string) {
35
+ return JSON.parse(readFileFromRoot(filePath));
36
+ }
37
+
38
+ export function readJsonFromVisual(filePath: string, visualPath?: string) {
39
+ return JSON.parse(fs.readFileSync(path.join(visualPath ?? process.cwd(), filePath), "utf8"));
40
+ }
41
+