powerbi-visuals-tools 5.5.1 → 6.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 (38) hide show
  1. package/Changelog.md +10 -0
  2. package/bin/pbiviz.js +3 -5
  3. package/eslint.config.mjs +37 -0
  4. package/lib/CertificateTools.js +1 -2
  5. package/lib/CommandManager.js +14 -16
  6. package/lib/LintValidator.js +7 -40
  7. package/lib/TemplateFetcher.js +1 -1
  8. package/lib/VisualGenerator.js +2 -2
  9. package/lib/VisualManager.js +24 -16
  10. package/lib/WebPackWrap.js +14 -8
  11. package/lib/features/APIVersion.js +2 -2
  12. package/lib/utils.js +16 -6
  13. package/lib/webpack.config.js +1 -1
  14. package/package.json +27 -28
  15. package/templates/visuals/default/eslint.config.mjs +8 -0
  16. package/templates/visuals/default/package.json +9 -9
  17. package/templates/visuals/rhtml/eslint.config.mjs +8 -0
  18. package/templates/visuals/rhtml/package.json +7 -7
  19. package/templates/visuals/rhtml/src/htmlInjectionUtility.ts +1 -1
  20. package/templates/visuals/rhtml/src/visual.ts +0 -2
  21. package/templates/visuals/rvisual/eslint.config.mjs +8 -0
  22. package/templates/visuals/rvisual/package.json +6 -6
  23. package/templates/visuals/slicer/eslint.config.mjs +8 -0
  24. package/templates/visuals/slicer/package.json +9 -9
  25. package/templates/visuals/table/eslint.config.mjs +8 -0
  26. package/templates/visuals/table/package.json +9 -9
  27. package/templates/visuals/table/tsconfig.json +1 -1
  28. package/templates/visuals/_global/tslint.json +0 -79
  29. package/templates/visuals/default/.eslintignore +0 -5
  30. package/templates/visuals/default/.eslintrc.js +0 -20
  31. package/templates/visuals/rhtml/.eslintignore +0 -5
  32. package/templates/visuals/rhtml/.eslintrc.js +0 -20
  33. package/templates/visuals/rvisual/.eslintignore +0 -5
  34. package/templates/visuals/rvisual/.eslintrc.js +0 -20
  35. package/templates/visuals/slicer/.eslintignore +0 -5
  36. package/templates/visuals/slicer/.eslintrc.js +0 -20
  37. package/templates/visuals/table/.eslintignore +0 -5
  38. package/templates/visuals/table/.eslintrc.js +0 -20
package/Changelog.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  This page contains information about changes to the PowerBI Visual Tools (pbiviz).
4
4
 
5
+ ## 6.0.0
6
+ * **Introduced pbiviz.js support.** This feature allows generate configuration dynamically using benefits of JavaScript.
7
+ It allows you to easily use any js logic to build your pbiviz file using environment variables or other parameters.
8
+ * Updated dependencies to the latest versions.
9
+
10
+ ## 5.6.0
11
+ * Updated to ESLint v9
12
+ * Updated to TypeScript v5
13
+ * `--use-default` flag for `pbiviz package` and `pbiviz lint` commands is deprecated. Recommeded config is used by default
14
+
5
15
  ## 5.5.1
6
16
  * Fixed subtotal feature check
7
17
 
package/bin/pbiviz.js CHANGED
@@ -32,7 +32,7 @@ import CommandManager from '../lib/CommandManager.js';
32
32
  import { readJsonFromRoot } from '../lib/utils.js';
33
33
  import { program, Option } from 'commander';
34
34
 
35
- const npmPackage = readJsonFromRoot('package.json');
35
+ const npmPackage = await readJsonFromRoot('package.json');
36
36
  const rootPath = process.cwd();
37
37
  const pbivizFile = 'pbiviz.json';
38
38
 
@@ -72,7 +72,6 @@ pbiviz
72
72
  pbiviz
73
73
  .command('lint')
74
74
  .option('--fix', 'Enable autofixing of lint errors')
75
- .option('--use-default', 'Use recommended eslintrc file')
76
75
  .action(options => {
77
76
  CommandManager.lint({ ...options, verbose: true }, rootPath);
78
77
  });
@@ -85,7 +84,7 @@ pbiviz
85
84
  .option('--no-stats', "Doesn't generate statistics files")
86
85
  .option('--skip-api', "Skips powerbi-visuals-api verifying")
87
86
  .option('-l, --all-locales', "Keeps all locale files in the package. By default only used inside stringResources folder locales are included.")
88
- .option('-p, --pbiviz-file <pbiviz-file>', "Path to pbiviz.json file (useful for debugging)", pbivizFile)
87
+ .option('-f, --pbiviz-file <pbiviz-file>', "Path to visual config file (pbiviz.json / pbiviz.mjs)", pbivizFile)
89
88
  .action(async (options) => {
90
89
  CommandManager.start(options, rootPath);
91
90
  });
@@ -101,8 +100,7 @@ pbiviz
101
100
  .option('-l, --all-locales', "Keeps all locale files in the package. By default only used inside stringResources folder locales are included.")
102
101
  .option('-v, --verbose', "Enables verbose logging")
103
102
  .option('--fix', 'Enable autofixing of lint errors')
104
- .option('--use-default', 'Use recommended eslintrc file')
105
- .option('-p, --pbiviz-file <pbiviz-file>', "Path to pbiviz.json file (useful for debugging)", pbivizFile)
103
+ .option('-p, --pbiviz-file <pbiviz-file>', "Path to visual config file (pbiviz.json / pbiviz.mjs)", pbivizFile)
106
104
  .addOption(new Option('-c, --compression <compressionLevel>', "Enables compression of visual package")
107
105
  .choices(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
108
106
  .default('6')
@@ -0,0 +1,37 @@
1
+ import typescriptEslint from "@typescript-eslint/eslint-plugin";
2
+ import globals from "globals";
3
+ import tsParser from "@typescript-eslint/parser";
4
+
5
+ export default [
6
+ {
7
+ files: ["*.ts", "*tsx"],
8
+ ignores: [
9
+ "node_modules/",
10
+ "dist/",
11
+ "templates/",
12
+ "spec/*/**",
13
+ "**/lib/",
14
+ "bin/",
15
+ "eslint.config.mjs",
16
+ ],
17
+ plugins: {
18
+ "@typescript-eslint": typescriptEslint,
19
+ },
20
+ languageOptions: {
21
+ globals: {
22
+ ...globals.node,
23
+ },
24
+ parser: tsParser,
25
+ ecmaVersion: 2023,
26
+ sourceType: "module",
27
+ parserOptions: {
28
+ project: "tsconfig.json",
29
+ tsconfigRootDir: ".",
30
+ },
31
+ },
32
+ rules: {
33
+ "no-unused-vars": "off",
34
+ "@typescript-eslint/no-unused-vars": "error",
35
+ },
36
+ }
37
+ ];
@@ -1,4 +1,3 @@
1
- /* eslint-disable no-case-declarations */
2
1
  /*
3
2
  * Power BI Visual CLI
4
3
  *
@@ -33,7 +32,7 @@ import crypto from "crypto";
33
32
  import { readJsonFromRoot } from './utils.js';
34
33
  import ConsoleWriter from './ConsoleWriter.js';
35
34
  const certSafePeriod = 1000 * 60 * 60 * 24; // 24 hours
36
- const config = readJsonFromRoot('config.json');
35
+ const config = await readJsonFromRoot('config.json');
37
36
  const pathToCertFolder = path.join(os.homedir(), config.server.certificateFolder);
38
37
  const secretFilesPath = {
39
38
  certPath: path.join(pathToCertFolder, config.server.certificate),
@@ -17,17 +17,15 @@ export default class CommandManager {
17
17
  pbivizFile: options.pbivizFile,
18
18
  };
19
19
  const visualManager = new VisualManager(rootPath);
20
- await visualManager
21
- .prepareVisual(options.pbivizFile)
22
- .validateVisual()
23
- .initializeWebpack(webpackOptions);
20
+ await visualManager.prepareVisual(options.pbivizFile);
21
+ await visualManager.validateVisual();
22
+ await visualManager.initializeWebpack(webpackOptions);
24
23
  visualManager.startWebpackServer(options.drop);
25
24
  }
26
25
  static async lint(options, rootPath) {
27
26
  const visualManager = new VisualManager(rootPath);
28
- await visualManager
29
- .prepareVisual()
30
- .runLintValidation(options);
27
+ await visualManager.prepareVisual();
28
+ await visualManager.runLintValidation(options);
31
29
  }
32
30
  static async package(options, rootPath) {
33
31
  if (!options.pbiviz && !options.resources) {
@@ -49,13 +47,13 @@ export default class CommandManager {
49
47
  const lintOptions = {
50
48
  verbose: options.verbose,
51
49
  fix: options.fix,
52
- useDefault: options.useDefault
53
50
  };
54
- const visual = new VisualManager(rootPath).prepareVisual(options.pbivizFile);
51
+ const visualManager = new VisualManager(rootPath);
52
+ const visual = await visualManager.prepareVisual(options.pbivizFile);
55
53
  await visual.runLintValidation(lintOptions);
56
- visual.validateVisual(options.verbose)
57
- .initializeWebpack(webpackOptions)
58
- .then(visualManager => visualManager.generatePackage(options.verbose));
54
+ await visual.validateVisual(options.verbose);
55
+ await visual.initializeWebpack(webpackOptions)
56
+ .then(manager => manager.generatePackage(options.verbose));
59
57
  }
60
58
  static new({ force, template }, name, rootPath) {
61
59
  const generateOptions = {
@@ -64,10 +62,10 @@ export default class CommandManager {
64
62
  };
65
63
  VisualManager.createVisual(rootPath, name, generateOptions);
66
64
  }
67
- static info(rootPath) {
68
- new VisualManager(rootPath)
69
- .prepareVisual()
70
- .displayInfo();
65
+ static async info(rootPath) {
66
+ const visualManager = new VisualManager(rootPath);
67
+ await visualManager.prepareVisual();
68
+ await visualManager.displayInfo();
71
69
  }
72
70
  static async installCert() {
73
71
  await createCertificate();
@@ -1,21 +1,18 @@
1
1
  import { ESLint } from "eslint";
2
- import path from 'path';
3
- import fs from 'fs-extra';
2
+ import powerbiPlugin from 'eslint-plugin-powerbi-visuals';
4
3
  import ConsoleWriter from "./ConsoleWriter.js";
5
4
  import { getRootPath } from "./utils.js";
6
5
  export class LintValidator {
7
6
  visualPath;
8
7
  rootPath;
9
8
  isVerboseMode;
10
- useDefault;
11
9
  shouldFix;
12
10
  config;
13
11
  linterInstance;
14
- constructor({ verbose, fix, useDefault }) {
12
+ constructor({ verbose, fix }) {
15
13
  this.visualPath = process.cwd();
16
14
  this.rootPath = getRootPath();
17
15
  this.isVerboseMode = verbose;
18
- this.useDefault = useDefault;
19
16
  this.shouldFix = fix;
20
17
  this.prepareConfig();
21
18
  this.linterInstance = new ESLint(this.config);
@@ -25,7 +22,7 @@ export class LintValidator {
25
22
  */
26
23
  async runLintValidation() {
27
24
  ConsoleWriter.info("Running lint check...");
28
- // By default it will lint all files in the src of current working directory, but some files can be excluded in .eslintignore
25
+ // By default it will lint all files in the src of current working directory
29
26
  const results = await this.linterInstance.lintFiles("src/");
30
27
  if (this.shouldFix) {
31
28
  await this.fixErrors(results);
@@ -54,41 +51,11 @@ export class LintValidator {
54
51
  }
55
52
  }
56
53
  prepareConfig() {
57
- const requiredConfig = {
58
- extensions: [".js", ".jsx", ".ts", ".tsx"],
54
+ ConsoleWriter.warning("Using recommended eslint config.");
55
+ this.config = {
56
+ overrideConfig: powerbiPlugin.configs.recommended,
57
+ overrideConfigFile: true,
59
58
  fix: this.shouldFix,
60
- resolvePluginsRelativeTo: this.getPluginPath()
61
59
  };
62
- const eslintrcExtensions = ['.json', '.js', '.cjs', '.ts', ''];
63
- if (!this.useDefault && eslintrcExtensions.some(el => fs.existsSync(path.join(this.visualPath, `.eslintrc${el}`)))) {
64
- this.config = requiredConfig;
65
- }
66
- else {
67
- ConsoleWriter.warning("Using recommended eslint config.");
68
- this.config = {
69
- ...requiredConfig,
70
- overrideConfig: {
71
- env: {
72
- browser: true,
73
- es6: true,
74
- es2022: true
75
- },
76
- plugins: [
77
- "powerbi-visuals"
78
- ],
79
- extends: [
80
- "plugin:powerbi-visuals/recommended"
81
- ]
82
- },
83
- useEslintrc: false,
84
- };
85
- }
86
- }
87
- getPluginPath() {
88
- const pluginPaths = [
89
- path.resolve(this.visualPath, "node_modules", "eslint-plugin-powerbi-visuals"),
90
- path.resolve(this.rootPath, "node_modules", "eslint-plugin-powerbi-visuals")
91
- ];
92
- return pluginPaths.find(fs.existsSync);
93
60
  }
94
61
  }
@@ -5,7 +5,7 @@ import VisualGenerator from "./VisualGenerator.js";
5
5
  import { exec } from 'child_process';
6
6
  import fs from 'fs-extra';
7
7
  import path from 'path';
8
- const config = readJsonFromRoot('config.json');
8
+ const config = await readJsonFromRoot('config.json');
9
9
  export default class TemplateFetcher {
10
10
  templateName;
11
11
  visualName;
@@ -31,7 +31,7 @@ import fs from 'fs-extra';
31
31
  import lodashDefaults from 'lodash.defaults';
32
32
  import path from 'path';
33
33
  import template from '../templates/pbiviz-json-template.js';
34
- const config = readJsonFromRoot('config.json');
34
+ const config = await readJsonFromRoot('config.json');
35
35
  const VISUAL_TEMPLATES_PATH = path.join(getRootPath(), config.templates.visuals);
36
36
  const API_VERSION = config.generate.apiVersion;
37
37
  const minAPIversion = config.constants.minAPIversion;
@@ -191,7 +191,7 @@ export default class VisualGenerator {
191
191
  */
192
192
  static checkVisualName(name) {
193
193
  const regexES3ReservedWord = /^(?:do|if|in|for|int|new|try|var|byte|case|char|else|enum|goto|long|null|this|true|void|with|break|catch|class|const|false|final|float|short|super|throw|while|delete|double|export|import|native|public|return|static|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|interface|protected|transient|implements|instanceof|synchronized)$/;
194
- const regexNumber = /^(?![+-])([0-9\+\-\.]+)/; // eslint-disable-line no-useless-escape
194
+ const regexNumber = /^(?![+-])([0-9\+\-\.]+)/;
195
195
  const regexZeroWidth = /\u200c|\u200d/;
196
196
  const regexpWrongSymbols = /^[a-zA-Z0-9]+$/;
197
197
  const valueAsUnescapedString = name.replace(/\\u([a-fA-F0-9]{4})|\\u\{([0-9a-fA-F]{1,})\}/g, ($0, $1, $2) => {
@@ -39,7 +39,7 @@ import { FeatureManager, Status } from "./FeatureManager.js";
39
39
  import { Severity, Stage } from "./features/FeatureTypes.js";
40
40
  import TemplateFetcher from "./TemplateFetcher.js";
41
41
  import { LintValidator } from "./LintValidator.js";
42
- const globalConfig = readJsonFromRoot('config.json');
42
+ const globalConfig = await readJsonFromRoot('config.json');
43
43
  const PBIVIZ_FILE = 'pbiviz.json';
44
44
  /**
45
45
  * Represents an instance of a visual package based on file path
@@ -57,10 +57,10 @@ export default class VisualManager {
57
57
  constructor(rootPath) {
58
58
  this.basePath = rootPath;
59
59
  }
60
- prepareVisual(pbivizFile = PBIVIZ_FILE) {
61
- if (this.doesPBIVIZExists(pbivizFile)) {
62
- this.pbivizConfig = readJsonFromVisual(pbivizFile, this.basePath);
63
- this.createVisualInstance();
60
+ async prepareVisual(pbivizFile = PBIVIZ_FILE) {
61
+ this.pbivizConfig = await readJsonFromVisual(pbivizFile, this.basePath);
62
+ if (this.pbivizConfig) {
63
+ await this.createVisualInstance();
64
64
  }
65
65
  else {
66
66
  ConsoleWriter.error(pbivizFile + ' not found. You must be in the root of a visual project to run this command.');
@@ -80,8 +80,8 @@ export default class VisualManager {
80
80
  }
81
81
  }
82
82
  }
83
- createVisualInstance() {
84
- this.capabilities = readJsonFromVisual("capabilities.json", this.basePath);
83
+ async createVisualInstance() {
84
+ this.capabilities = await readJsonFromVisual("capabilities.json", this.basePath);
85
85
  this.visual = new Visual(this.capabilities, this.pbivizConfig);
86
86
  }
87
87
  async initializeWebpack(webpackOptions) {
@@ -188,7 +188,7 @@ export default class VisualManager {
188
188
  ConsoleWriter.warning('Running with force flag. Existing files will be overwritten');
189
189
  }
190
190
  try {
191
- const config = readJsonFromRoot('config.json');
191
+ const config = await readJsonFromRoot('config.json');
192
192
  if (config.visualTemplates[generateOptions.template]) {
193
193
  new TemplateFetcher(generateOptions.template, visualName, undefined)
194
194
  .fetch();
@@ -224,32 +224,40 @@ export default class VisualManager {
224
224
  return fs.existsSync(pbivizFile);
225
225
  }
226
226
  prepareDropFiles() {
227
- this.webpackConfig.devServer.onBeforeSetupMiddleware = (devServer) => {
227
+ this.webpackConfig.devServer.setupMiddlewares = (middlewares, devServer) => {
228
228
  const { headers, publicPath, static: { directory } } = this.webpackConfig.devServer;
229
229
  const assets = ['visual.js`', 'visual.css', 'pbiviz.json'];
230
230
  const setHeaders = (res) => {
231
231
  Object.getOwnPropertyNames(headers)
232
232
  .forEach(property => res.header(property, headers[property]));
233
233
  };
234
- const readFile = (file, res) => {
235
- fs.readFile(file).then(function (content) {
236
- res.write(content);
237
- res.end();
234
+ const readFile = (file, res, name) => {
235
+ middlewares.unshift({
236
+ name,
237
+ middleware: (req, middlewareRes) => {
238
+ fs.readFile(file).then(function (content) {
239
+ middlewareRes.write(content);
240
+ console.log(`Serving ${name} to `);
241
+ middlewareRes.end();
242
+ });
243
+ },
238
244
  });
245
+ res.end();
239
246
  };
240
247
  assets.forEach(asset => {
241
248
  devServer.app.get(`${publicPath}/${asset}`, function (req, res) {
242
249
  setHeaders(res);
243
- readFile(path.join(directory, asset), res);
250
+ readFile(path.join(directory, asset), res, asset);
244
251
  });
245
252
  });
253
+ return middlewares;
246
254
  };
247
255
  }
248
- stopServer() {
256
+ async stopServer() {
249
257
  ConsoleWriter.blank();
250
258
  ConsoleWriter.info("Stopping server...");
251
259
  if (this.webpackDevServer) {
252
- this.webpackDevServer.close();
260
+ await this.webpackDevServer.stop();
253
261
  this.webpackDevServer = null;
254
262
  }
255
263
  }
@@ -13,8 +13,8 @@ import { PowerBICustomVisualsWebpackPlugin, LocalizationLoader } from 'powerbi-v
13
13
  import ConsoleWriter from './ConsoleWriter.js';
14
14
  import { resolveCertificate } from "./CertificateTools.js";
15
15
  import { readJsonFromRoot, readJsonFromVisual } from './utils.js';
16
- const config = readJsonFromRoot('config.json');
17
- const npmPackage = readJsonFromRoot('package.json');
16
+ const config = await readJsonFromRoot('config.json');
17
+ const npmPackage = await readJsonFromRoot('package.json');
18
18
  const visualPlugin = "visualPlugin.ts";
19
19
  const encoding = "utf8";
20
20
  export default class WebPackWrap {
@@ -123,7 +123,7 @@ export default class WebPackWrap {
123
123
  await this.configureAPIVersion();
124
124
  }
125
125
  const api = await WebPackWrap.loadAPIPackage();
126
- const dependenciesPath = this.pbiviz.dependencies && path.join(process.cwd(), this.pbiviz.dependencies);
126
+ const dependenciesPath = typeof this.pbiviz.dependencies === "string" && path.join(process.cwd(), this.pbiviz.dependencies);
127
127
  let pluginConfiguration = {
128
128
  ...lodashCloneDeep(visualPackage.pbivizConfig),
129
129
  apiVersion: api.version,
@@ -149,8 +149,14 @@ export default class WebPackWrap {
149
149
  const regexFullVersion = /(?<=powerbi-visuals-api@)((?:\d+\.?){1,3})/g;
150
150
  //get only first 2 parts of version
151
151
  const regexMajorVersion = /\d+(?:\.\d+)?/;
152
- const listResults = (await exec('npm list powerbi-visuals-api version')).stdout;
153
- const installedAPIVersion = listResults.match(regexFullVersion)[0] ?? "not found";
152
+ let listResults;
153
+ try {
154
+ listResults = (await exec('npm list powerbi-visuals-api version')).stdout;
155
+ }
156
+ catch (error) {
157
+ listResults = error.stdout;
158
+ }
159
+ const installedAPIVersion = listResults.match(regexFullVersion)?.[0] ?? "not found";
154
160
  const doesAPIExist = fs.pathExistsSync(path.join(process.cwd(), "node_modules", "powerbi-visuals-api"));
155
161
  // if the powerbi-visual-api package wasn't installed install the powerbi-visual-api,
156
162
  // with version from apiVersion in pbiviz.json or the latest API, if apiVersion is absent in pbiviz.json
@@ -200,7 +206,7 @@ export default class WebPackWrap {
200
206
  });
201
207
  if (!includeAllLocales) {
202
208
  this.webpackConfig.module.rules.push({
203
- test: /powerbiGlobalizeLocales\.js$/,
209
+ test: /powerbiGlobalizeLocales\.js$/, // path to file with all locales declared in formattingutils
204
210
  loader: LocalizationLoader
205
211
  });
206
212
  }
@@ -244,8 +250,8 @@ export default class WebPackWrap {
244
250
  allLocales: false,
245
251
  pbivizFile: 'pbiviz.json',
246
252
  }) {
247
- const tsconfig = readJsonFromVisual('tsconfig.json');
248
- this.pbiviz = readJsonFromVisual(options.pbivizFile);
253
+ const tsconfig = await readJsonFromVisual('tsconfig.json');
254
+ this.pbiviz = await readJsonFromVisual(options.pbivizFile);
249
255
  const capabilitiesPath = this.pbiviz.capabilities;
250
256
  visualPackage.pbivizConfig.capabilities = capabilitiesPath;
251
257
  const dependenciesPath = this.pbiviz.dependencies && path.join(process.cwd(), this.pbiviz.dependencies);
@@ -7,8 +7,8 @@ export default class APIVersion {
7
7
  static visualFeatureType = VisualFeatureType.NonSlicer;
8
8
  static minAPIversion;
9
9
  static errorMessage;
10
- static isSupported(visual) {
11
- const globalConfig = readJsonFromRoot('config.json');
10
+ static async isSupported(visual) {
11
+ const globalConfig = await readJsonFromRoot('config.json');
12
12
  this.minAPIversion = globalConfig.constants.minAPIversion;
13
13
  this.errorMessage = `API version must be at least ${this.minAPIversion}.`;
14
14
  return visual.doesAPIVersionMatch(this.minAPIversion);
package/lib/utils.js CHANGED
@@ -22,12 +22,22 @@ export function getRootPath() {
22
22
  const pathToDirectory = fileURLToPath(import.meta.url);
23
23
  return path.join(pathToDirectory, "..", "..");
24
24
  }
25
- function readFileFromRoot(filePath) {
26
- return fs.readFileSync(path.join(getRootPath(), filePath), "utf8");
25
+ export function getJsPath(filePath) {
26
+ return filePath.replace(/\.json$/, '.mjs');
27
27
  }
28
- export function readJsonFromRoot(filePath) {
29
- return JSON.parse(readFileFromRoot(filePath));
28
+ async function safelyImport(filePath) {
29
+ return fs.existsSync(filePath) && (await import(`file://${filePath}`)).default;
30
30
  }
31
- export function readJsonFromVisual(filePath, visualPath) {
32
- return JSON.parse(fs.readFileSync(path.join(visualPath ?? process.cwd(), filePath), "utf8"));
31
+ function safelyParse(filePath) {
32
+ return fs.existsSync(filePath) && JSON.parse(fs.readFileSync(filePath, "utf-8"));
33
+ }
34
+ export async function readJsonFromRoot(jsonFilename) {
35
+ const jsonPath = path.join(getRootPath(), jsonFilename);
36
+ const jsPath = getJsPath(jsonPath);
37
+ return (await safelyImport(jsPath)) || safelyParse(jsonPath);
38
+ }
39
+ export async function readJsonFromVisual(filePath, visualPath) {
40
+ const jsonPath = path.join(visualPath ?? process.cwd(), filePath);
41
+ const jsPath = getJsPath(jsonPath);
42
+ return (await safelyImport(jsPath)) || safelyParse(jsonPath);
33
43
  }
@@ -3,7 +3,7 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin";
3
3
  import TerserPlugin from "terser-webpack-plugin";
4
4
  import path from "path";
5
5
  import webpack from "webpack";
6
- const config = readJsonFromRoot("/config.json");
6
+ const config = await readJsonFromRoot("/config.json");
7
7
  const rootPath = getRootPath();
8
8
  const webpackConfig = {
9
9
  entry: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powerbi-visuals-tools",
3
- "version": "5.5.1",
3
+ "version": "6.0.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",
@@ -8,12 +8,11 @@
8
8
  "build": "tsc",
9
9
  "pbiviz": "node ./bin/pbiviz.js",
10
10
  "start": "npm run pbiviz start",
11
- "test": "npm run build && npm run clean-tests && npm run lint && npm run jasmine",
11
+ "test": "npm run build && npm run lint && npm run jasmine",
12
12
  "jasmine": "node spec/jasmine-runner.js",
13
13
  "jasmine-inspect": "node --inspect spec/jasmine-runner.js",
14
- "lint": "npx eslint . --ext .ts,.tsx",
15
- "clean-tests": "node spec/clean-tests.js",
16
- "debug-tests": "npm run clean-tests && npm run lint && npm run jasmine-inspect"
14
+ "lint": "npx eslint .",
15
+ "debug-tests": "npm run lint && npm run jasmine-inspect"
17
16
  },
18
17
  "bin": {
19
18
  "pbiviz": "./bin/pbiviz.js"
@@ -29,64 +28,64 @@
29
28
  },
30
29
  "homepage": "https://github.com/Microsoft/PowerBI-visuals-tools#readme",
31
30
  "dependencies": {
32
- "@typescript-eslint/parser": "^7.12.0",
31
+ "@typescript-eslint/parser": "^8.26.0",
33
32
  "assert": "^2.1.0",
34
- "async": "^3.2.5",
33
+ "async": "^3.2.6",
35
34
  "browserify-zlib": "^0.2.0",
36
35
  "buffer": "^6.0.3",
37
- "chalk": "^5.3.0",
38
- "commander": "^11.1.0",
39
- "compare-versions": "^6.1.0",
36
+ "chalk": "^5.4.1",
37
+ "commander": "^13.1.0",
38
+ "compare-versions": "^6.1.1",
40
39
  "console-browserify": "^1.2.0",
41
40
  "constants-browserify": "^1.0.0",
42
- "crypto-browserify": "^3.12.0",
43
- "css-loader": "^6.11.0",
41
+ "crypto-browserify": "^3.12.1",
42
+ "css-loader": "^7.1.2",
44
43
  "domain-browser": "^5.7.0",
45
44
  "events": "^3.3.0",
46
45
  "extra-watch-webpack-plugin": "^1.0.3",
47
- "fs-extra": "^11.2.0",
46
+ "fs-extra": "^11.3.0",
48
47
  "https-browserify": "^1.0.0",
49
48
  "inline-source-map": "^0.6.3",
50
49
  "json-loader": "0.5.7",
51
50
  "jszip": "^3.10.1",
52
- "less": "^4.2.0",
51
+ "less": "^4.2.2",
53
52
  "less-loader": "^12.2.0",
54
53
  "lodash.clonedeep": "4.5.0",
55
54
  "lodash.defaults": "4.2.0",
56
55
  "lodash.isequal": "4.5.0",
57
56
  "lodash.ismatch": "^4.4.0",
58
- "mini-css-extract-plugin": "^2.9.0",
57
+ "mini-css-extract-plugin": "^2.9.2",
59
58
  "os-browserify": "^0.3.0",
60
59
  "path-browserify": "^1.0.1",
61
60
  "powerbi-visuals-webpack-plugin": "4.1.0",
61
+ "eslint-plugin-powerbi-visuals": "^1.0.0",
62
62
  "process": "^0.11.10",
63
63
  "punycode": "^2.3.1",
64
64
  "querystring-es3": "^0.2.1",
65
- "readable-stream": "^4.5.2",
65
+ "readable-stream": "^4.7.0",
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.10",
69
+ "terser-webpack-plugin": "^5.3.14",
70
70
  "timers-browserify": "^2.0.12",
71
- "ts-loader": "^9.5.1",
71
+ "ts-loader": "^9.5.2",
72
72
  "tty-browserify": "^0.0.1",
73
- "typescript": "^4.9.5",
74
- "url": "^0.11.3",
73
+ "typescript": "^5.8.2",
74
+ "url": "^0.11.4",
75
75
  "util": "^0.12.5",
76
76
  "vm-browserify": "^1.1.2",
77
- "webpack": "^5.91.0",
77
+ "webpack": "^5.98.0",
78
78
  "webpack-bundle-analyzer": "4.10.2",
79
- "webpack-dev-server": "^4.15.2"
79
+ "webpack-dev-server": "^5.2.0"
80
80
  },
81
81
  "devDependencies": {
82
- "@typescript-eslint/eslint-plugin": "^7.12.0",
83
- "eslint": "^8.57.0",
84
- "eslint-plugin-powerbi-visuals": "^0.8.1",
85
- "jasmine": "5.1.0",
82
+ "@typescript-eslint/eslint-plugin": "^8.26.0",
83
+ "eslint": "^9.22.0",
84
+ "jasmine": "5.3.1",
86
85
  "jasmine-spec-reporter": "7.0.0",
87
- "semver": "7.6.2",
86
+ "semver": "7.7.1",
88
87
  "tree-kill": "1.2.2",
89
- "webpack-cli": "^5.1.4"
88
+ "webpack-cli": "^6.0.1"
90
89
  },
91
90
  "optionalDependencies": {
92
91
  "fsevents": "*"
@@ -0,0 +1,8 @@
1
+ import powerbiVisualsConfigs from "eslint-plugin-powerbi-visuals";
2
+
3
+ export default [
4
+ powerbiVisualsConfigs.configs.recommended,
5
+ {
6
+ ignores: ["node_modules/**", "dist/**", ".vscode/**", ".tmp/**"],
7
+ },
8
+ ];
@@ -11,18 +11,18 @@
11
11
  "pbiviz": "pbiviz",
12
12
  "start": "pbiviz start",
13
13
  "package": "pbiviz package",
14
- "lint": "npx eslint . --ext .js,.jsx,.ts,.tsx"
14
+ "lint": "npx eslint ."
15
15
  },
16
16
  "dependencies": {
17
- "@types/d3": "7.4.0",
18
- "d3": "7.8.5",
19
- "powerbi-visuals-api": "5.4.0",
20
- "powerbi-visuals-utils-formattingmodel": "6.0.0"
17
+ "@types/d3": "7.4.3",
18
+ "d3": "7.9.0",
19
+ "powerbi-visuals-api": "5.11.0",
20
+ "powerbi-visuals-utils-formattingmodel": "6.0.4"
21
21
  },
22
22
  "devDependencies": {
23
- "@typescript-eslint/eslint-plugin": "^5.59.11",
24
- "eslint": "^8.42.0",
25
- "eslint-plugin-powerbi-visuals": "^0.8.1",
26
- "typescript": "4.9.3"
23
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
24
+ "eslint": "^9.11.1",
25
+ "eslint-plugin-powerbi-visuals": "^1.0.0",
26
+ "typescript": "5.5.4"
27
27
  }
28
28
  }
@@ -0,0 +1,8 @@
1
+ import powerbiVisualsConfigs from "eslint-plugin-powerbi-visuals";
2
+
3
+ export default [
4
+ powerbiVisualsConfigs.configs.recommended,
5
+ {
6
+ ignores: ["node_modules/**", "dist/**", ".vscode/**", ".tmp/**"],
7
+ },
8
+ ];
@@ -4,17 +4,17 @@
4
4
  "powerbi-visuals-utils-formattingmodel": "6.0.0"
5
5
  },
6
6
  "devDependencies": {
7
- "powerbi-visuals-api": "5.4.0",
8
- "ts-loader": "9.4.3",
9
- "@typescript-eslint/eslint-plugin": "^5.59.11",
10
- "eslint": "^8.42.0",
11
- "eslint-plugin-powerbi-visuals": "^0.8.1",
12
- "typescript": "5.1.3"
7
+ "powerbi-visuals-api": "5.11.0",
8
+ "ts-loader": "9.5.1",
9
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
10
+ "eslint": "^9.11.1",
11
+ "eslint-plugin-powerbi-visuals": "^1.0.0",
12
+ "typescript": "5.5.4"
13
13
  },
14
14
  "scripts": {
15
15
  "pbiviz": "pbiviz",
16
16
  "start": "pbiviz start",
17
17
  "package": "pbiviz package",
18
- "lint": "npx eslint . --ext .js,.jsx,.ts,.tsx"
18
+ "lint": "npx eslint ."
19
19
  }
20
20
  }
@@ -39,7 +39,7 @@ function createScriptNode(refNode: Element): HTMLElement {
39
39
  };
40
40
  }
41
41
  }
42
- // tslint:disable-next-line
42
+
43
43
  script.innerHTML = refNode.innerHTML;
44
44
  return script;
45
45
  }
@@ -128,7 +128,6 @@ export class Visual implements IVisual {
128
128
  }
129
129
 
130
130
  public onResizing(finalViewport: IViewport): void {
131
- // tslint:disable-next-line
132
131
  /* add code to handle resizing of the view port */
133
132
  }
134
133
 
@@ -146,7 +145,6 @@ export class Visual implements IVisual {
146
145
  // create 'virtual' HTML, so parsing is easier
147
146
  let el: HTMLHtmlElement = document.createElement("html");
148
147
  try {
149
- // tslint:disable-next-line
150
148
  el.innerHTML = window.atob(payloadBase64);
151
149
  } catch (err) {
152
150
  return;
@@ -0,0 +1,8 @@
1
+ import powerbiVisualsConfigs from "eslint-plugin-powerbi-visuals";
2
+
3
+ export default [
4
+ powerbiVisualsConfigs.configs.recommended,
5
+ {
6
+ ignores: ["node_modules/**", "dist/**", ".vscode/**", ".tmp/**"],
7
+ },
8
+ ];
@@ -4,16 +4,16 @@
4
4
  "powerbi-visuals-utils-formattingmodel": "6.0.0"
5
5
  },
6
6
  "devDependencies": {
7
- "powerbi-visuals-api": "5.4.0",
8
- "@typescript-eslint/eslint-plugin": "^5.59.11",
9
- "eslint": "^8.42.0",
10
- "eslint-plugin-powerbi-visuals": "^0.8.1",
11
- "typescript": "4.9.3"
7
+ "powerbi-visuals-api": "5.11.0",
8
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
9
+ "eslint": "^9.11.1",
10
+ "eslint-plugin-powerbi-visuals": "^1.0.0",
11
+ "typescript": "5.5.4"
12
12
  },
13
13
  "scripts": {
14
14
  "pbiviz": "pbiviz",
15
15
  "start": "pbiviz start",
16
16
  "package": "pbiviz package",
17
- "lint": "tslint -c tslint.json -p tsconfig.json"
17
+ "lint": "eslint ."
18
18
  }
19
19
  }
@@ -0,0 +1,8 @@
1
+ import powerbiVisualsConfigs from "eslint-plugin-powerbi-visuals";
2
+
3
+ export default [
4
+ powerbiVisualsConfigs.configs.recommended,
5
+ {
6
+ ignores: ["node_modules/**", "dist/**", ".vscode/**", ".tmp/**"],
7
+ },
8
+ ];
@@ -4,18 +4,18 @@
4
4
  "pbiviz": "pbiviz",
5
5
  "start": "pbiviz start",
6
6
  "package": "pbiviz package",
7
- "lint": "npx eslint . --ext .js,.jsx,.ts,.tsx"
7
+ "lint": "npx eslint ."
8
8
  },
9
9
  "dependencies": {
10
- "d3": "7.8.5",
11
- "powerbi-visuals-utils-formattingmodel": "6.0.0"
10
+ "d3": "7.9.0",
11
+ "powerbi-visuals-utils-formattingmodel": "6.0.4"
12
12
  },
13
13
  "devDependencies": {
14
- "@types/d3": "7.4.0",
15
- "powerbi-visuals-api": "5.4.0",
16
- "@typescript-eslint/eslint-plugin": "^5.59.11",
17
- "eslint": "^8.42.0",
18
- "eslint-plugin-powerbi-visuals": "^0.8.1",
19
- "typescript": "4.9.3"
14
+ "@types/d3": "7.4.3",
15
+ "powerbi-visuals-api": "5.11.0",
16
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
17
+ "eslint": "^9.11.1",
18
+ "eslint-plugin-powerbi-visuals": "^1.0.0",
19
+ "typescript": "5.5.4"
20
20
  }
21
21
  }
@@ -0,0 +1,8 @@
1
+ import powerbiVisualsConfigs from "eslint-plugin-powerbi-visuals";
2
+
3
+ export default [
4
+ powerbiVisualsConfigs.configs.recommended,
5
+ {
6
+ ignores: ["node_modules/**", "dist/**", ".vscode/**", ".tmp/**"],
7
+ },
8
+ ];
@@ -4,18 +4,18 @@
4
4
  "pbiviz": "pbiviz",
5
5
  "start": "pbiviz start",
6
6
  "package": "pbiviz package",
7
- "lint": "npx eslint . --ext .js,.jsx,.ts,.tsx"
7
+ "lint": "npx eslint ."
8
8
  },
9
9
  "dependencies": {
10
- "d3": "7.8.5",
11
- "powerbi-visuals-utils-formattingmodel": "6.0.0"
10
+ "d3": "7.9.0",
11
+ "powerbi-visuals-utils-formattingmodel": "6.0.4"
12
12
  },
13
13
  "devDependencies": {
14
- "powerbi-visuals-api": "5.4.0",
15
- "@types/d3": "7.4.0",
16
- "@typescript-eslint/eslint-plugin": "^5.59.11",
17
- "eslint": "^8.42.0",
18
- "eslint-plugin-powerbi-visuals": "^0.8.1",
19
- "typescript": "4.9.3"
14
+ "powerbi-visuals-api": "5.11.0",
15
+ "@types/d3": "7.4.3",
16
+ "@typescript-eslint/eslint-plugin": "^8.8.0",
17
+ "eslint": "^9.11.1",
18
+ "eslint-plugin-powerbi-visuals": "^1.0.0",
19
+ "typescript": "5.5.4"
20
20
  }
21
21
  }
@@ -18,6 +18,6 @@
18
18
  ],
19
19
  "exclude": [
20
20
  "node_modules",
21
- "templates",
21
+ "templates"
22
22
  ]
23
23
  }
@@ -1,79 +0,0 @@
1
- {
2
- "rules": {
3
- "class-name": true,
4
- "comment-format": [
5
- true,
6
- "check-space"
7
- ],
8
- "indent": [
9
- true,
10
- "spaces"
11
- ],
12
- "no-duplicate-variable": true,
13
- "no-eval": true,
14
- "no-internal-module": false,
15
- "no-trailing-whitespace": true,
16
- "no-unsafe-finally": true,
17
- "no-var-keyword": true,
18
- "one-line": [
19
- true,
20
- "check-open-brace",
21
- "check-whitespace"
22
- ],
23
- "quotemark": [
24
- false,
25
- "double"
26
- ],
27
- "semicolon": [
28
- true,
29
- "always"
30
- ],
31
- "triple-equals": [
32
- true,
33
- "allow-null-check"
34
- ],
35
- "typedef-whitespace": [
36
- true,
37
- {
38
- "call-signature": "nospace",
39
- "index-signature": "nospace",
40
- "parameter": "nospace",
41
- "property-declaration": "nospace",
42
- "variable-declaration": "nospace"
43
- }
44
- ],
45
- "variable-name": [
46
- true,
47
- "ban-keywords"
48
- ],
49
- "whitespace": [
50
- true,
51
- "check-branch",
52
- "check-decl",
53
- "check-operator",
54
- "check-separator",
55
- "check-type"
56
- ],
57
- "insecure-random": true,
58
- "no-banned-terms": true,
59
- "no-cookies": true,
60
- "no-delete-expression": true,
61
- "no-disable-auto-sanitization": true,
62
- "no-document-domain": true,
63
- "no-document-write": true,
64
- "no-exec-script": true,
65
- "no-function-constructor-with-string-args": true,
66
- "no-http-string": [true, "http://www.example.com/?.*", "http://www.examples.com/?.*"],
67
- "no-inner-html": true,
68
- "no-octal-literal": true,
69
- "no-reserved-keywords": true,
70
- "no-string-based-set-immediate": true,
71
- "no-string-based-set-interval": true,
72
- "no-string-based-set-timeout": true,
73
- "non-literal-require": true,
74
- "possible-timing-attack": true,
75
- "react-anchor-blank-noopener": true,
76
- "react-iframe-missing-sandbox": true,
77
- "react-no-dangerous-html": true
78
- }
79
- }
@@ -1,5 +0,0 @@
1
- assets
2
- style
3
- dist
4
- node_modules
5
- .eslintrc.js
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- env: {
3
- "browser": true,
4
- "es6": true,
5
- "es2017": true
6
- },
7
- root: true,
8
- parser: "@typescript-eslint/parser",
9
- parserOptions: {
10
- project: "tsconfig.json",
11
- tsconfigRootDir: ".",
12
- },
13
- plugins: [
14
- "powerbi-visuals"
15
- ],
16
- extends: [
17
- "plugin:powerbi-visuals/recommended"
18
- ],
19
- rules: {}
20
- };
@@ -1,5 +0,0 @@
1
- assets
2
- style
3
- dist
4
- node_modules
5
- .eslintrc.js
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- env: {
3
- "browser": true,
4
- "es6": true,
5
- "es2017": true
6
- },
7
- root: true,
8
- parser: "@typescript-eslint/parser",
9
- parserOptions: {
10
- project: "tsconfig.json",
11
- tsconfigRootDir: ".",
12
- },
13
- plugins: [
14
- "powerbi-visuals"
15
- ],
16
- extends: [
17
- "plugin:powerbi-visuals/recommended"
18
- ],
19
- rules: {}
20
- };
@@ -1,5 +0,0 @@
1
- assets
2
- style
3
- dist
4
- node_modules
5
- .eslintrc.js
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- env: {
3
- "browser": true,
4
- "es6": true,
5
- "es2017": true
6
- },
7
- root: true,
8
- parser: "@typescript-eslint/parser",
9
- parserOptions: {
10
- project: "tsconfig.json",
11
- tsconfigRootDir: ".",
12
- },
13
- plugins: [
14
- "powerbi-visuals"
15
- ],
16
- extends: [
17
- "plugin:powerbi-visuals/recommended"
18
- ],
19
- rules: {}
20
- };
@@ -1,5 +0,0 @@
1
- assets
2
- style
3
- dist
4
- node_modules
5
- .eslintrc.js
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- env: {
3
- "browser": true,
4
- "es6": true,
5
- "es2017": true
6
- },
7
- root: true,
8
- parser: "@typescript-eslint/parser",
9
- parserOptions: {
10
- project: "tsconfig.json",
11
- tsconfigRootDir: ".",
12
- },
13
- plugins: [
14
- "powerbi-visuals"
15
- ],
16
- extends: [
17
- "plugin:powerbi-visuals/recommended"
18
- ],
19
- rules: {}
20
- };
@@ -1,5 +0,0 @@
1
- assets
2
- style
3
- dist
4
- node_modules
5
- .eslintrc.js
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- env: {
3
- "browser": true,
4
- "es6": true,
5
- "es2017": true
6
- },
7
- root: true,
8
- parser: "@typescript-eslint/parser",
9
- parserOptions: {
10
- project: "tsconfig.json",
11
- tsconfigRootDir: ".",
12
- },
13
- plugins: [
14
- "powerbi-visuals"
15
- ],
16
- extends: [
17
- "plugin:powerbi-visuals/recommended"
18
- ],
19
- rules: {}
20
- };