powerbi-visuals-tools 5.2.1 → 5.4.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/Changelog.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  This page contains information about changes to the PowerBI Visual Tools (pbiviz).
4
4
 
5
+ ## 5.4.0
6
+ * Updated packages
7
+ * New command `pbiviz lint` to run lint check from tools. It'll use eslintrc file from the root of the visual, if there is no such file, recommended one will be used instead.
8
+
9
+ ## 5.3.0
10
+ * Updated packages
11
+ * Updated to Typescript 5.0 **⚠**
12
+ * New flag `--pbiviz-file` to specify path to pbiviz.json file
13
+
5
14
  ## 5.2.1
6
15
  * Fixed errors output when packaging the visual
7
16
  * Fixed `RHTML` template render error
package/bin/pbiviz.js CHANGED
@@ -34,6 +34,7 @@ import { program, Option } from 'commander';
34
34
 
35
35
  const npmPackage = readJsonFromRoot('package.json');
36
36
  const rootPath = process.cwd();
37
+ const pbivizFile = 'pbiviz.json';
37
38
 
38
39
  const pbiviz = program
39
40
  .version(npmPackage.version)
@@ -68,6 +69,13 @@ pbiviz
68
69
  CommandManager.installCert();
69
70
  });
70
71
 
72
+ pbiviz
73
+ .command('lint')
74
+ .option('--fix', 'Enable autofixing of lint errors')
75
+ .action(options => {
76
+ CommandManager.lint({ ...options, verbose: true }, rootPath);
77
+ });
78
+
71
79
  pbiviz
72
80
  .command('start')
73
81
  .usage('[options]')
@@ -76,6 +84,7 @@ pbiviz
76
84
  .option('--no-stats', "Doesn't generate statistics files")
77
85
  .option('--skip-api', "Skips powerbi-visuals-api verifying")
78
86
  .option('-l, --all-locales', "Keeps all locale files in the package. By default only used inside stringResources folder locales are included.")
87
+ .option('-p, --pbiviz-file <pbiviz-file>', "Path to pbiviz.json file (useful for debugging)", pbivizFile)
79
88
  .action(async (options) => {
80
89
  CommandManager.start(options, rootPath);
81
90
  });
@@ -90,6 +99,8 @@ pbiviz
90
99
  .option('--skip-api', "Skips powerbi-visuals-api verifying")
91
100
  .option('-l, --all-locales', "Keeps all locale files in the package. By default only used inside stringResources folder locales are included.")
92
101
  .option('-v, --verbose', "Enables verbose logging")
102
+ .option('--fix', 'Enable autofixing of lint errors')
103
+ .option('-p, --pbiviz-file <pbiviz-file>', "Path to pbiviz.json file (useful for debugging)", pbivizFile)
93
104
  .addOption(new Option('-c, --compression <compressionLevel>', "Enables compression of visual package")
94
105
  .choices(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
95
106
  .default('6')
@@ -1,28 +1,28 @@
1
1
  -----BEGIN PRIVATE KEY-----
2
- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvQtw8yna8GmTx
3
- LH4StfsKNJaF2yr82la9rp46f3tqTzfeuBXdijxYq1CkibiKVrSIoRenLmJO+zbN
4
- 6j0SJNdmoRCnleHPUjxjiwVdPOWAS/JuNy4PYzOAf2j/3ZZbbkXCV/cKmRUXPCYN
5
- uEJRDIXG8FkJ6DWryAhvbCRLsiQnEFzMlCo6/xin5BsYPTvAChjPqp6DYzMtd0jm
6
- V7tUy9SDcmwYTC3LjgwiJIZ9fPPB0ZNF6qEPSqWlztS5WA8hOjapkeSSbeRtZSzr
7
- OMCB5Wf4ZacDaZ3uBySrCykUDRAQdWoYh1aSKGk54gI+Ho8FTqlgeBCtJKkCLmX9
8
- CPJiwfB/AgMBAAECggEAJ9YyOk0o9POo6xraY0VjFPxEFJPvLv8wBTh6NcDBXDY6
9
- dFDyg2NG+T6je2rke+leasn3FuSXqu02FVL/Y67lGSpWH0mVxKqkGFpCs2FCp0lc
10
- Bwpa2VuKmtQbGUGUSh8EEzssZ4fJP/lHiwnNZR/MDp6WFobmIDA9Hpp9m4kX55rT
11
- oQKaTUq+Drcdj22jB8EgHH0ZJG6Op52pUIij1dyCYqW6zuapz0BhTfltxfCH8qVs
12
- lCA2eNMGIDtK0Y6K+Hp2EHiGlsVf+SKOFnw/DT2o+KI9/8omKEYwhki6Q13K2P/g
13
- 3nmUoi5TCXeOq8GiotSQ40B0oY3WwimCi3/XKd/ZNQKBgQDKgA/HocTruY8ePhAk
14
- 39OAzRypHpkyMRQvWZ+i3XRgdSammM+hZWvlevL6M1nd1d6dqUKqHyM1f917k2VL
15
- mgLgv9IAVDZiqCzxmVbXbrT2OBMkqZk3Ti9V5R6KazROgW8K31t09qSO41zHIksG
16
- Efq8cIFkRzk8RWJxsZyGzBEPdQKBgQDdkIGuhCPjisiSKCsAhz4Y8uvDEPKK18tW
17
- jc+opn3z4IM0B/9836E8IxzCGU78vgPdp6QdCYLN5d519j6TdfAEHv8bQanADuI7
18
- oOT8aJikt7eoxJVcpB286NcjLGGxaq7MV/N4BoLYA1EC2yLCwyMOOD9VrDDL1P9c
19
- QbCmx46VowKBgCR+jdl5gwbEi1F09+3dVL26uXaVKCDOjYe3DDkK1iVoF44grhK1
20
- N4vE67NBu+lp2NPrJDOKpwrGP4E84B2O5QPiLhOXGbIQAwGLlAYBUqWpF3IdCprY
21
- AVnmj+l8RpH7a6q29EGRDbkeqqLMwF6YsOpzEC6lU2BUVNiOnNoCPvTdAoGAeaO4
22
- TqNlQKsU6oj68tNNGE1lejZ3sho/HEnG1ARz6cw8u/gYH+p2jpmIVFeoscFwReSf
23
- iQGLupaUx5ZlTHfXSavqyoAGPdbuBWaT0K9r/iKOxi0HA1Fmsivy0PCwwcKcLLus
24
- gxywAP/xHexI7TxMpqXiv5pFP+K0P2YhIa81bJkCgYEAqGWeJIS1/bdiXkLA14Ta
25
- yS5Q0xbx7dg8JzUIfCAiGvkx0ZTydX0TMZPcGV/wf26Q2BtRfuY8XcSs3kfsjdyo
26
- BxtxANgcE7wRYGn0hiDf4dlkkk2xTwir91L/xOwpJzgosJO1xNz+B4AG60jeF6+p
27
- M0X894SsVFIfKBjTiWryPo0=
2
+ MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqaqvXFqI+mio3
3
+ 6RG/XZx7RbFnD2hadofIowpXFhcC80CporiCAR258sIxOrU3EK+XImV1yuTgGEZe
4
+ hISwunShZhgijN8LPhsITt3CVJosHEzqS0K2dnSn4IxBlUiYptilcaBZxLbGoMd2
5
+ ERG6ACjaFKNY178MCHK7eeyJl2L+r1gw6QNz9esBg0KRuqsE8ag//JFK7g3ETeG4
6
+ 9fRD6xNaIANQFNV7qjgMiIjMdhHG5zdD1luM7RBva2G5AWU8eDfdK44dLgL/3l5j
7
+ s0CmN8gkVKVnmuZpW8aoGR3z0BblKn/NyYqkUKtAPEc0dK60EZ++DRj7fp1Ao+uX
8
+ E+0sfgFLAgMBAAECggEATFkH7Y/dVjCZM30+jz5wKaYaiXKUrNqnkJLCwitKWe8D
9
+ DDyzbsLzP2hr6cREhYv7LrmhPPmOOnuFozi5fbe7IsfrjicQkifb0ogKv9JJU/PF
10
+ 3b2kALznHIL0MzmfUYyGSPC0ByOjQy+qzNFu4KbLppBSci4OEGUEictg1m+1USYg
11
+ JBcAj7f2DCKXJK/M0tDXYRcAz8ydkO7VlG+OgWVwB0otqd73ZlTe7GV+kc8haxdM
12
+ Be6KXMdtjn7Hoq/Y3Ri2jhfWc9hl+Q0Kpp7ce1cd4NLBaJpYTnMNyPeNWqd6iFJ8
13
+ vK68H9Rz/eQI3pAQGrc15pjRvMUaBLpUxhgjq7jVuQKBgQDLe664oY0YuTlZqX96
14
+ ILHjc+tLPZ7Q89cwJpCBrtWU1yBHcoGsWd2s8qal4AbmKmKONqS+rxkOxabInqmn
15
+ IHeCsjk7zA3sS4GykXvb2n1BDoJG0a20PwWP1IgiFPX80B+zK1Cf0pZZOpCtJwTv
16
+ HZ8AeCV1NUtCmTriUGlv4d69hQKBgQDWZkIOJgMJivmjyfEVVYMxAoX4YmmVVYNJ
17
+ xydwL143UHhjcfnuA6emnbgu+ikg1S1UUVz2GC/DSanmMVJrUFRYBhrr4SpTkXxV
18
+ KCEiE23KF3bRQ6Es5GOxF+3xjdhAdxZ0yewCqTJW9EIV/020El5saGZcB1wFiAcD
19
+ JsxxhaDUjwKBgGHuK5+2OIbelghd9/kaBSMXpfU3OdkMkdMdrEyNjUMt6d4Y8Om2
20
+ 8mYK/kM0t31MhtQ03kLbWG7wlx1UpwfFK19eUQdDZKwFhu0e8YJU/BU0W2SkAzqN
21
+ XirjuYTVm7HJpIgBX7Mbkbpt4jVDYy+FjQGX0UdAl/D8eAd1ddkf1qhVAoGARWtu
22
+ z+325cwd8K6eZO3/QIs0nawfy76Yd/cICgcMVpSzpl9tMWf1jLlcvbk6P+tGdhqy
23
+ IuzJ6k2buXEW4rBr3uR7Kw0JC237+Aa6U7I+xkS6sB9ZvJNmxByfaqsm7hihKMeI
24
+ p4PpTMZh74Vuv3ODJ07Wdc3cOd5Fhvu1DrzZynkCgYAC4lQ86RLm9PieDqB4tLxN
25
+ D3uHbeu2IMCxvXKNqFzW2tm4JJ1tinnIiIT19s0/wW/R+AiPR0w/wKNZyHjshpwU
26
+ X+3YFoS8VhQ7w2pvpDCgH/4mjWdhXA+DSKjjdtYTBscWg1BxrbIvdS+7cVxBZpc+
27
+ RDKo/x/i0I8QaRM7AIA+5w==
28
28
  -----END PRIVATE KEY-----
@@ -1,19 +1,19 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- MIIDCTCCAfGgAwIBAgIUbO099tIl8366tDaIzBrkvev3/n8wDQYJKoZIhvcNAQEL
3
- BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMTAxODEwNTQxOVoXDTI0MTAx
4
- NzEwNTQxOVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
5
- AAOCAQ8AMIIBCgKCAQEAr0LcPMp2vBpk8Sx+ErX7CjSWhdsq/NpWva6eOn97ak83
6
- 3rgV3Yo8WKtQpIm4ila0iKEXpy5iTvs2zeo9EiTXZqEQp5Xhz1I8Y4sFXTzlgEvy
7
- bjcuD2MzgH9o/92WW25Fwlf3CpkVFzwmDbhCUQyFxvBZCeg1q8gIb2wkS7IkJxBc
8
- zJQqOv8Yp+QbGD07wAoYz6qeg2MzLXdI5le7VMvUg3JsGEwty44MIiSGfXzzwdGT
9
- ReqhD0qlpc7UuVgPITo2qZHkkm3kbWUs6zjAgeVn+GWnA2md7gckqwspFA0QEHVq
10
- GIdWkihpOeICPh6PBU6pYHgQrSSpAi5l/QjyYsHwfwIDAQABo1MwUTAdBgNVHQ4E
11
- FgQUTZThWkGh0xJl6wLqh3Gi3LHMDMswHwYDVR0jBBgwFoAUTZThWkGh0xJl6wLq
12
- h3Gi3LHMDMswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAetcv
13
- u9yB2CRVi12FKnegu6QGk+6p9ywu4nMQqEznYHzc7h8AknihmNNl2wOLNCffXvFg
14
- PhasNt/KCeyOWmpzlExzlX0w7MoNWqGBZdAhvm26yXmyOaZ2rUc9FuOLWJy9vVT8
15
- CKBdKXGrMbGEta5qpjmnzJ84jWCWX1ChRXPyXtnh2lBJ3xvYZ26MEln6skPC6Iuk
16
- DBKF3MJ0RNoU3KaBaVDVh6d6QUkSqQm+t5GAeqEHx8elyzLtypUuodYnG4p4poZ3
17
- UUlf1XA6m8NsLNl2/1XYxwH6/cOZ8/zPcaFAREChc7lEqC/QOAz+nOH4aS2dJS+l
18
- Q93CnBuVNOscbCHHrg==
2
+ MIIDCTCCAfGgAwIBAgIUeq2Fm/qpDWxqCJIBOMUUXdjfeckwDQYJKoZIhvcNAQEL
3
+ BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDEwOTA5MjUzOFoXDTI1MDEw
4
+ ODA5MjUzOFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
5
+ AAOCAQ8AMIIBCgKCAQEAqmqr1xaiPpoqN+kRv12ce0WxZw9oWnaHyKMKVxYXAvNA
6
+ qaK4ggEdufLCMTq1NxCvlyJldcrk4BhGXoSEsLp0oWYYIozfCz4bCE7dwlSaLBxM
7
+ 6ktCtnZ0p+CMQZVImKbYpXGgWcS2xqDHdhERugAo2hSjWNe/DAhyu3nsiZdi/q9Y
8
+ MOkDc/XrAYNCkbqrBPGoP/yRSu4NxE3huPX0Q+sTWiADUBTVe6o4DIiIzHYRxuc3
9
+ Q9ZbjO0Qb2thuQFlPHg33SuOHS4C/95eY7NApjfIJFSlZ5rmaVvGqBkd89AW5Sp/
10
+ zcmKpFCrQDxHNHSutBGfvg0Y+36dQKPrlxPtLH4BSwIDAQABo1MwUTAdBgNVHQ4E
11
+ FgQUoj3zAbgUkWNA9WBuwsKOb7DE0ugwHwYDVR0jBBgwFoAUoj3zAbgUkWNA9WBu
12
+ wsKOb7DE0ugwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAlLRz
13
+ QJn/I8pSUfIh0ZpZOmHz3CZgXkblpPlCy+85Zkf6W0QLaxx0GR5PTN6VI0NXkK9j
14
+ hGjfPAF74Ds3nhvNCrgJTzJ+EkJ8qOly3U1ohtucEOUSK6aZxTmCaP1l99acHiUR
15
+ Tx1FQTWCtrivR8D2IpfvYtS0A+jOUVYHcQnMIo9IpZ0BmEEKFZahf8hZDy/ciCTr
16
+ Uc0VkwuzR6qiSpqf5MDhZip6vfIoe48T/sFKGd4/PLMmpiY8t0aG5eTimvK4L3Dl
17
+ dZuPPKAjvPwueIa3jl+JJDZbajsHxE0Ns3qmmdngGYMZdMorrGMiyc/Shf0hdZ+8
18
+ DbU8rV24AD5YqTLHtA==
19
19
  -----END CERTIFICATE-----
package/config.json CHANGED
@@ -16,7 +16,6 @@
16
16
  },
17
17
  "package": { "dropFolder": "dist" },
18
18
  "server": {
19
- "root": "webRoot",
20
19
  "assetsRoute": "/assets",
21
20
  "privateKey": "certs/PowerBICustomVisualTest_private.key",
22
21
  "certificate": "certs/PowerBICustomVisualTest_public.crt",
@@ -13,15 +13,22 @@ export default class CommandManager {
13
13
  devServerPort: options.port,
14
14
  stats: options.stats,
15
15
  skipApiCheck: options.skipApi,
16
- allLocales: options.allLocales
16
+ allLocales: options.allLocales,
17
+ pbivizFile: options.pbivizFile,
17
18
  };
18
19
  const visualManager = new VisualManager(rootPath);
19
20
  await visualManager
20
- .prepareVisual()
21
+ .prepareVisual(options.pbivizFile)
21
22
  .validateVisual()
22
23
  .initializeWebpack(webpackOptions);
23
24
  visualManager.startWebpackServer(options.drop);
24
25
  }
26
+ static async lint(options, rootPath) {
27
+ const visualManager = new VisualManager(rootPath);
28
+ await visualManager
29
+ .prepareVisual()
30
+ .runLintValidation(options);
31
+ }
25
32
  static async package(options, rootPath) {
26
33
  if (!options.pbiviz && !options.resources) {
27
34
  ConsoleWriter.error('Nothing to build. Cannot use --no-pbiviz without --resources');
@@ -36,11 +43,16 @@ export default class CommandManager {
36
43
  compression: options.compression,
37
44
  stats: options.stats,
38
45
  skipApiCheck: options.skipApi,
39
- allLocales: options.allLocales
46
+ allLocales: options.allLocales,
47
+ pbivizFile: options.pbivizFile,
40
48
  };
41
- new VisualManager(rootPath)
42
- .prepareVisual()
43
- .validateVisual(options.verbose)
49
+ const lintOptions = {
50
+ verbose: options.verbose,
51
+ fix: options.fix,
52
+ };
53
+ const visual = new VisualManager(rootPath).prepareVisual(options.pbivizFile);
54
+ await visual.runLintValidation(lintOptions);
55
+ visual.validateVisual(options.verbose)
44
56
  .initializeWebpack(webpackOptions)
45
57
  .then(visualManager => visualManager.generatePackage(options.verbose));
46
58
  }
@@ -0,0 +1,78 @@
1
+ import { ESLint } from "eslint";
2
+ import ConsoleWriter from "./ConsoleWriter.js";
3
+ import { fileExists, getRootPath } from "./utils.js";
4
+ export class LintValidator {
5
+ visualPath;
6
+ rootPath;
7
+ config;
8
+ defaultConfig;
9
+ linterInstance;
10
+ constructor(fix = false) {
11
+ this.visualPath = process.cwd();
12
+ this.rootPath = getRootPath();
13
+ this.prepareConfig(fix);
14
+ this.linterInstance = new ESLint(this.config);
15
+ }
16
+ /**
17
+ * Runs lint validation in the visual folder
18
+ */
19
+ async runLintValidation({ verbose, fix }) {
20
+ ConsoleWriter.info("Running lint check...");
21
+ // By default it will lint all files in the src of current working directory, but some files can be excluded in .eslintignore
22
+ const results = await this.linterInstance.lintFiles("src/**/*");
23
+ if (fix) {
24
+ await this.fixErrors(results);
25
+ }
26
+ await this.outputResults(results, verbose);
27
+ ConsoleWriter.info("Lint check completed.");
28
+ }
29
+ async fixErrors(results) {
30
+ ConsoleWriter.info("Lint fixing errors...");
31
+ await ESLint.outputFixes(results);
32
+ }
33
+ async outputResults(results, verbose) {
34
+ if (verbose) {
35
+ const formatter = await this.linterInstance.loadFormatter("stylish");
36
+ const formattedResults = await formatter.format(results);
37
+ console.log(formattedResults);
38
+ }
39
+ else {
40
+ const filteredResults = ESLint.getErrorResults(results);
41
+ // get total amount of errors and warnings in all elements of filteredResults
42
+ const totalErrors = filteredResults.reduce((acc, curr) => acc + curr.errorCount, 0);
43
+ const totalWarnings = filteredResults.reduce((acc, curr) => acc + curr.warningCount, 0);
44
+ if (totalErrors > 0 || totalWarnings > 0) {
45
+ ConsoleWriter.error(`Linter found ${totalErrors} errors and ${totalWarnings} warnings. Run with --verbose flag to see details.`);
46
+ }
47
+ }
48
+ }
49
+ prepareConfig(fix) {
50
+ this.defaultConfig = {
51
+ overrideConfig: {
52
+ env: {
53
+ browser: true,
54
+ es6: true,
55
+ es2022: true
56
+ },
57
+ plugins: [
58
+ "powerbi-visuals"
59
+ ],
60
+ extends: [
61
+ "plugin:powerbi-visuals/recommended"
62
+ ]
63
+ },
64
+ extensions: [".ts", ".tsx"],
65
+ resolvePluginsRelativeTo: this.rootPath,
66
+ useEslintrc: false,
67
+ fix
68
+ };
69
+ const eslintrcExtensions = ['.json', '.js', '.ts'];
70
+ if (eslintrcExtensions.some(el => fileExists(this.visualPath, `.eslintrc${el}`))) {
71
+ this.config = { fix };
72
+ }
73
+ else {
74
+ ConsoleWriter.warning("No .eslintrc file found in the visual folder. Using default config.");
75
+ this.config = this.defaultConfig;
76
+ }
77
+ }
78
+ }
package/lib/Visual.js CHANGED
@@ -4,21 +4,16 @@ export class Visual {
4
4
  visualFeatureType;
5
5
  capabilities;
6
6
  config;
7
- packageJSON;
8
7
  visualVersion;
9
- constructor(capabilities, config, packageJson) {
8
+ constructor(capabilities, config) {
10
9
  this.capabilities = capabilities;
11
10
  this.config = config;
12
11
  this.visualFeatureType = this.getVisualFeatureType();
13
- this.packageJSON = packageJson;
14
12
  this.visualVersion = config.visual.version;
15
13
  }
16
14
  doesAPIVersionMatch(minAPIversion) {
17
15
  return compareVersions(this.config.apiVersion ?? minAPIversion, minAPIversion) !== -1;
18
16
  }
19
- doesESLlintSupported() {
20
- return Object.entries(this.packageJSON.scripts).some(([, value]) => value.includes("eslint"));
21
- }
22
17
  isVisualVersionValid(length) {
23
18
  return this.visualVersion.split(".").length === length;
24
19
  }
@@ -38,6 +38,7 @@ import { Visual } from "./Visual.js";
38
38
  import { FeatureManager, Status } from "./FeatureManager.js";
39
39
  import { Severity, Stage } from "./features/FeatureTypes.js";
40
40
  import TemplateFetcher from "./TemplateFetcher.js";
41
+ import { LintValidator } from "./LintValidator.js";
41
42
  const globalConfig = readJsonFromRoot('config.json');
42
43
  const PBIVIZ_FILE = 'pbiviz.json';
43
44
  /**
@@ -56,21 +57,24 @@ export default class VisualManager {
56
57
  constructor(rootPath) {
57
58
  this.basePath = rootPath;
58
59
  }
59
- prepareVisual() {
60
- if (this.doesPBIVIZExists()) {
61
- this.pbivizConfig = readJsonFromVisual(PBIVIZ_FILE, this.basePath);
60
+ prepareVisual(pbivizFile = PBIVIZ_FILE) {
61
+ if (this.doesPBIVIZExists(pbivizFile)) {
62
+ this.pbivizConfig = readJsonFromVisual(pbivizFile, this.basePath);
62
63
  this.createVisualInstance();
63
64
  }
64
65
  else {
65
- ConsoleWriter.error(PBIVIZ_FILE + ' not found. You must be in the root of a visual project to run this command.');
66
+ ConsoleWriter.error(pbivizFile + ' not found. You must be in the root of a visual project to run this command.');
66
67
  process.exit(1);
67
68
  }
68
69
  return this;
69
70
  }
71
+ runLintValidation(options) {
72
+ const linter = new LintValidator(options.fix);
73
+ linter.runLintValidation(options);
74
+ }
70
75
  createVisualInstance() {
71
76
  this.capabilities = readJsonFromVisual("capabilities.json", this.basePath);
72
- const packageJSON = readJsonFromVisual("package.json", this.basePath);
73
- this.visual = new Visual(this.capabilities, this.pbivizConfig, packageJSON);
77
+ this.visual = new Visual(this.capabilities, this.pbivizConfig);
74
78
  }
75
79
  async initializeWebpack(webpackOptions) {
76
80
  const webpackWrap = new WebpackWrap();
@@ -87,6 +91,9 @@ export default class VisualManager {
87
91
  };
88
92
  this.compiler.run(callback);
89
93
  }
94
+ /**
95
+ * Starts webpack server
96
+ */
90
97
  startWebpackServer(generateDropFiles = false) {
91
98
  ConsoleWriter.blank();
92
99
  ConsoleWriter.info('Starting server...');
@@ -114,6 +121,9 @@ export default class VisualManager {
114
121
  process.exit(1);
115
122
  }
116
123
  }
124
+ /**
125
+ * Validates the visual code
126
+ */
117
127
  validateVisual(verbose = false) {
118
128
  this.featureManager = new FeatureManager();
119
129
  const { status, logs } = this.featureManager.validate(Stage.PreBuild, this.visual);
@@ -123,11 +133,17 @@ export default class VisualManager {
123
133
  }
124
134
  return this;
125
135
  }
136
+ /**
137
+ * Validates the visual package
138
+ */
126
139
  validatePackage() {
127
140
  const featureManager = new FeatureManager();
128
141
  const { logs } = featureManager.validate(Stage.PostBuild, this.package);
129
142
  return logs;
130
143
  }
144
+ /**
145
+ * Outputs the results of the validation
146
+ */
131
147
  outputResults({ errors, deprecation, warnings, info }, verbose) {
132
148
  const headerMessage = {
133
149
  error: `Visual doesn't support some features required for all custom visuals:`,
@@ -144,6 +160,9 @@ export default class VisualManager {
144
160
  const infoLogs = (!info.length || verbose) ? info : [verboseSuggestion];
145
161
  this.outputLogsWithHeadMessage(headerInfoMessage, infoLogs, Severity.Info);
146
162
  }
163
+ /**
164
+ * Displays visual info
165
+ */
147
166
  displayInfo() {
148
167
  if (this.pbivizConfig) {
149
168
  ConsoleWriter.infoTable(this.pbivizConfig);
@@ -153,7 +172,7 @@ export default class VisualManager {
153
172
  }
154
173
  }
155
174
  /**
156
- * Creates a new visual package
175
+ * Creates a new visual
157
176
  */
158
177
  static async createVisual(rootPath, visualName, generateOptions) {
159
178
  ConsoleWriter.info('Creating new visual');
@@ -193,8 +212,8 @@ export default class VisualManager {
193
212
  });
194
213
  });
195
214
  }
196
- doesPBIVIZExists() {
197
- return fs.existsSync(PBIVIZ_FILE);
215
+ doesPBIVIZExists(pbivizFile) {
216
+ return fs.existsSync(pbivizFile);
198
217
  }
199
218
  prepareDropFiles() {
200
219
  this.webpackConfig.devServer.onBeforeSetupMiddleware = (devServer) => {
@@ -241,10 +241,11 @@ export default class WebPackWrap {
241
241
  compression: 0,
242
242
  stats: true,
243
243
  skipApiCheck: false,
244
- allLocales: false
244
+ allLocales: false,
245
+ pbivizFile: 'pbiviz.json',
245
246
  }) {
246
247
  const tsconfig = readJsonFromVisual('tsconfig.json');
247
- this.pbiviz = readJsonFromVisual('pbiviz.json');
248
+ this.pbiviz = readJsonFromVisual(options.pbivizFile);
248
249
  const capabilitiesPath = this.pbiviz.capabilities;
249
250
  visualPackage.pbivizConfig.capabilities = capabilitiesPath;
250
251
  const dependenciesPath = this.pbiviz.dependencies && path.join(process.cwd(), this.pbiviz.dependencies);
@@ -24,6 +24,5 @@ import Tooltips from './Tooltips.js';
24
24
  import TotalSubTotal from './TotalSubTotal.js';
25
25
  import WarningIcon from './WarningIcon.js';
26
26
  import APIVersion from './APIVersion.js';
27
- import ESLint from './ESLint.js';
28
27
  import VisualVersion from './VisualVersion.js';
29
- export { AdvancedEditMode, AllowInteractions, AnalyticsPane, Bookmarks, ColorPalette, ConditionalFormatting, ContextMenu, DrillDown, FetchMoreData, FileDownload, FormatPane, HighContrast, HighlightData, KeyboardNavigation, LandingPage, LaunchURL, Localizations, LocalStorage, ModalDialog, RenderingEvents, SelectionAcrossVisuals, SyncSlicer, Tooltips, TotalSubTotal, WarningIcon, APIVersion, ESLint, VisualVersion };
28
+ export { AdvancedEditMode, AllowInteractions, AnalyticsPane, Bookmarks, ColorPalette, ConditionalFormatting, ContextMenu, DrillDown, FetchMoreData, FileDownload, FormatPane, HighContrast, HighlightData, KeyboardNavigation, LandingPage, LaunchURL, Localizations, LocalStorage, ModalDialog, RenderingEvents, SelectionAcrossVisuals, SyncSlicer, Tooltips, TotalSubTotal, WarningIcon, APIVersion, VisualVersion };
package/lib/utils.js CHANGED
@@ -31,3 +31,6 @@ export function readJsonFromRoot(filePath) {
31
31
  export function readJsonFromVisual(filePath, visualPath) {
32
32
  return JSON.parse(fs.readFileSync(path.join(visualPath ?? process.cwd(), filePath), "utf8"));
33
33
  }
34
+ export function fileExists(pathToFile, fileName) {
35
+ return fs.existsSync(path.join(pathToFile, fileName));
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powerbi-visuals-tools",
3
- "version": "5.2.1",
3
+ "version": "5.4.0",
4
4
  "description": "Command line tool for creating and publishing visuals for Power BI",
5
5
  "main": "./bin/pbiviz.js",
6
6
  "type": "module",
@@ -29,28 +29,28 @@
29
29
  },
30
30
  "homepage": "https://github.com/Microsoft/PowerBI-visuals-tools#readme",
31
31
  "dependencies": {
32
- "@typescript-eslint/parser": "^6.7.5",
32
+ "@typescript-eslint/parser": "^6.17.0",
33
33
  "assert": "^2.1.0",
34
- "async": "^3.2.4",
34
+ "async": "^3.2.5",
35
35
  "browserify-zlib": "^0.2.0",
36
36
  "buffer": "^6.0.3",
37
37
  "chalk": "^5.3.0",
38
- "commander": "^11.0.0",
38
+ "commander": "^11.1.0",
39
39
  "compare-versions": "^6.1.0",
40
40
  "console-browserify": "^1.2.0",
41
41
  "constants-browserify": "^1.0.0",
42
42
  "crypto-browserify": "^3.12.0",
43
43
  "css-loader": "^6.8.1",
44
- "domain-browser": "^4.22.0",
44
+ "domain-browser": "^5.7.0",
45
45
  "events": "^3.3.0",
46
46
  "extra-watch-webpack-plugin": "^1.0.3",
47
- "fs-extra": "^11.1.1",
47
+ "fs-extra": "^11.2.0",
48
48
  "https-browserify": "^1.0.0",
49
49
  "inline-source-map": "^0.6.2",
50
50
  "json-loader": "0.5.7",
51
51
  "jszip": "^3.10.1",
52
52
  "less": "^4.2.0",
53
- "less-loader": "^11.1.3",
53
+ "less-loader": "^11.1.4",
54
54
  "lodash.clonedeep": "4.5.0",
55
55
  "lodash.defaults": "4.2.0",
56
56
  "lodash.isequal": "4.5.0",
@@ -58,29 +58,29 @@
58
58
  "mini-css-extract-plugin": "^2.7.6",
59
59
  "os-browserify": "^0.3.0",
60
60
  "path-browserify": "^1.0.1",
61
- "powerbi-visuals-webpack-plugin": "4.0.1",
61
+ "powerbi-visuals-webpack-plugin": "4.1.0",
62
62
  "process": "^0.11.10",
63
- "punycode": "^2.3.0",
63
+ "punycode": "^2.3.1",
64
64
  "querystring-es3": "^0.2.1",
65
- "readable-stream": "^4.4.2",
65
+ "readable-stream": "^4.5.2",
66
66
  "stream-browserify": "^3.0.0",
67
67
  "stream-http": "^3.2.0",
68
68
  "string_decoder": "^1.3.0",
69
- "terser-webpack-plugin": "^5.3.9",
69
+ "terser-webpack-plugin": "^5.3.10",
70
70
  "timers-browserify": "^2.0.12",
71
- "ts-loader": "^9.5.0",
71
+ "ts-loader": "^9.5.1",
72
72
  "tty-browserify": "^0.0.1",
73
73
  "typescript": "^4.9.5",
74
74
  "url": "^0.11.3",
75
75
  "util": "^0.12.5",
76
76
  "vm-browserify": "^1.1.2",
77
- "webpack": "^5.88.2",
78
- "webpack-bundle-analyzer": "4.9.1",
77
+ "webpack": "^5.89.0",
78
+ "webpack-bundle-analyzer": "4.10.1",
79
79
  "webpack-dev-server": "^4.15.1"
80
80
  },
81
81
  "devDependencies": {
82
- "@typescript-eslint/eslint-plugin": "^6.7.5",
83
- "eslint": "^8.51.0",
82
+ "@typescript-eslint/eslint-plugin": "^6.17.0",
83
+ "eslint": "^8.56.0",
84
84
  "eslint-plugin-powerbi-visuals": "^0.8.1",
85
85
  "jasmine": "5.1.0",
86
86
  "jasmine-spec-reporter": "7.0.0",
@@ -6,8 +6,7 @@
6
6
  "type": "chrome",
7
7
  "request": "attach",
8
8
  "port": 9222,
9
- "sourceMaps": true,
10
- "webRoot": "${cwd}/"
9
+ "sourceMaps": true
11
10
  }
12
11
  ]
13
12
  }
@@ -1,12 +0,0 @@
1
- import { Severity, Stage, VisualFeatureType } from "./FeatureTypes.js";
2
- export default class ESLint {
3
- static featureName = "ESLint";
4
- static documentationLink = "https://github.com/microsoft/eslint-plugin-powerbi-visuals";
5
- static severity = Severity.Warning;
6
- static stage = Stage.PreBuild;
7
- static visualFeatureType = VisualFeatureType.All;
8
- static errorMessage = `${this.featureName} - ${this.documentationLink}`;
9
- static isSupported(visual) {
10
- return visual.doesESLlintSupported();
11
- }
12
- }
Binary file
@@ -1,34 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>PowerBI Custom Visual</title>
5
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
6
- <script src="/assets/visual.js"></script>
7
- <link rel="stylesheet" href="/assets/visual.css">
8
- </head>
9
- <body>
10
- <div id="visual" style="width: 500px; height: 500px; background: white; margin: 0;"></div>
11
-
12
-
13
- <script>
14
- var plugin, plugins = powerbi.visuals.plugins;
15
-
16
- for(var key in plugins) {
17
- plugin = plugins[key];
18
- }
19
- console.log('plugin', plugin.name);
20
- var visual = plugin.create();
21
- console.log('visual', visual);
22
- visual.init({
23
- element: $('#visual'),
24
- viewport: {
25
- width:500,
26
- height:500
27
- }
28
- });
29
- setInterval(function(){
30
- visual.update({dataView:Math.round(Math.random()*1000)})
31
- },500)
32
- </script>
33
- </body>
34
- </html>