Skip to content

Commit 3924999

Browse files
committed
Initial Commit of powerbi-models. Has interfaces which are shared between host and iframe code.
1 parent 5869599 commit 3924999

18 files changed

+611
-1
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
coverage
3+
typings
4+
dist
5+
tmp

LICENSE.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
powerbi-models
2+
3+
Copyright (c) Microsoft Corporation
4+
5+
All rights reserved.
6+
7+
MIT License
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,29 @@
11
# powerbi-models
2-
Contains JavaScript & TypeScript object models for Microsoft Power BI JavaScript SDK
2+
3+
Collection of functions to validate PowerBI messages using json schema. Also contains shared interfaces for all messages to ensure host and iframe agree.
4+
5+
## Getting Started
6+
7+
Install
8+
```
9+
npm install --save powerbi-models
10+
```
11+
12+
Import
13+
```
14+
import * as models from 'powerbi-models';
15+
```
16+
17+
Usage
18+
```
19+
let testObject = { x: 1 };
20+
21+
const errors = models.validateLoad(testObject);
22+
23+
if(errors) {
24+
console.warn(errors)
25+
}
26+
27+
...
28+
29+
```

gulpfile.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
var gulp = require('gulp-help')(require('gulp'));
2+
var rename = require('gulp-rename'),
3+
replace = require('gulp-replace'),
4+
uglify = require('gulp-uglify'),
5+
karma = require('karma'),
6+
webpack = require('webpack-stream'),
7+
webpackConfig = require('./webpack.config'),
8+
webpackTestConfig = require('./webpack.test.config'),
9+
runSequence = require('run-sequence'),
10+
argv = require('yargs').argv;
11+
;
12+
13+
gulp.task('build', 'Build for release', function (done) {
14+
return runSequence(
15+
'compile:ts',
16+
'min',
17+
'generatecustomdts',
18+
done
19+
);
20+
});
21+
22+
gulp.task('test', 'Runs all tests', function (done) {
23+
return runSequence(
24+
'compile:spec',
25+
'test:js',
26+
done
27+
);
28+
});
29+
30+
gulp.task('compile:ts', 'Compile source files', function() {
31+
return gulp.src(['typings/**/*.d.ts', './src/**/*.ts'])
32+
.pipe(webpack(webpackConfig))
33+
.pipe(gulp.dest('./dist'));
34+
});
35+
36+
gulp.task('min', 'Minify build files', function () {
37+
return gulp.src(['./dist/models.js'])
38+
.pipe(uglify())
39+
.pipe(rename({
40+
suffix: '.min'
41+
}))
42+
.pipe(gulp.dest('./dist/'));
43+
});
44+
45+
gulp.task('compile:spec', 'Compile spec tests', function () {
46+
return gulp.src(['./test/test.spec.ts'])
47+
.pipe(webpack(webpackTestConfig))
48+
.pipe(gulp.dest('./tmp'));
49+
});
50+
51+
gulp.task('generatecustomdts', 'Generate dts with no exports', function (done) {
52+
return gulp.src(['./dist/*.d.ts'])
53+
.pipe(replace(/export\s/g, ''))
54+
.pipe(rename(function (path) {
55+
path.basename = "httpPostMessage-noexports.d";
56+
}))
57+
.pipe(gulp.dest('dist/'));
58+
});
59+
60+
gulp.task('test:js', 'Run spec tests', function (done) {
61+
new karma.Server.start({
62+
configFile: __dirname + '/karma.conf.js',
63+
singleRun: argv.debug ? false : true,
64+
captureTimeout: argv.timeout || 60000
65+
}, done);
66+
});

karma.conf.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
var argv = require('yargs').argv;
2+
3+
module.exports = function (config) {
4+
config.set({
5+
frameworks: ['jasmine'],
6+
files: [
7+
'./tmp/**/*.js'
8+
],
9+
exclude: [],
10+
reporters: argv.debug ? ['spec'] : ['spec', 'coverage'],
11+
autoWatch: true,
12+
browsers: [argv.chrome ? 'Chrome' : 'PhantomJS'],
13+
plugins: [
14+
'karma-chrome-launcher',
15+
'karma-jasmine',
16+
'karma-spec-reporter',
17+
'karma-phantomjs-launcher',
18+
'karma-coverage'
19+
],
20+
preprocessors: { './tmp/**/*.js': ['coverage'] },
21+
coverageReporter: {
22+
reporters: [
23+
{ type: 'html' },
24+
{ type: 'text-summary' }
25+
]
26+
},
27+
logLevel: argv.debug ? config.LOG_DEBUG : config.LOG_INFO
28+
});
29+
};

package.json

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"name": "powerbi-models",
3+
"version": "0.1.0",
4+
"description": "Collection of functions to validate PowerBI messages using json schema. Also contains shared interfaces for all messages to ensure host and iframe agree.",
5+
"main": "index.js",
6+
"directories": {
7+
"test": "test"
8+
},
9+
"scripts": {
10+
"prepublish": "gulp build",
11+
"test": "gulp test --chrome"
12+
},
13+
"repository": {
14+
"type": "git",
15+
"url": "https://pbix.visualstudio.com/DefaultCollection/PaaS/_git/powerbi-models"
16+
},
17+
"keywords": [
18+
"Microsoft",
19+
"PowerBI",
20+
"message",
21+
"validation",
22+
"json",
23+
"schema"
24+
],
25+
"author": "Microsoft PowerBI Team",
26+
"license": "MIT",
27+
"devDependencies": {
28+
"gulp": "^3.9.1",
29+
"gulp-help": "^1.6.1",
30+
"gulp-rename": "^1.2.2",
31+
"gulp-replace": "^0.5.4",
32+
"gulp-uglify": "^1.5.4",
33+
"jasmine-core": "^2.4.1",
34+
"json-loader": "^0.5.4",
35+
"karma": "^0.13.22",
36+
"karma-chrome-launcher": "^1.0.1",
37+
"karma-coverage": "^1.0.0",
38+
"karma-jasmine": "^1.0.2",
39+
"karma-phantomjs-launcher": "^1.0.0",
40+
"karma-spec-reporter": "0.0.26",
41+
"phantomjs-prebuilt": "^2.1.7",
42+
"run-sequence": "^1.2.1",
43+
"ts-loader": "^0.8.2",
44+
"webpack-stream": "^3.2.0",
45+
"yargs": "^4.7.1"
46+
},
47+
"publishConfig": {
48+
"tag": "beta"
49+
},
50+
"dependencies": {
51+
"jsen": "^0.6.1"
52+
}
53+
}

src/models.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
declare var require: Function;
2+
3+
export const settingsSchema = require('./schemas/settings.json');
4+
export const loadSchema = require('./schemas/load.json');
5+
export const pageTargetSchema = require('./schemas/pageTarget.json');
6+
export const visualTargetSchema = require('./schemas/visualTarget.json');
7+
export const pageSchema = require('./schemas/page.json');
8+
9+
import * as jsen from 'jsen';
10+
11+
interface IValidationError {
12+
path: string;
13+
keyword: string;
14+
message: string;
15+
}
16+
17+
export interface IError {
18+
message: string;
19+
}
20+
21+
function normalizeError(error: IValidationError): IError {
22+
if(!error.message) {
23+
error.message = `${error.path} is invalid. Not meeting ${error.keyword} constraint`;
24+
}
25+
26+
delete error.path;
27+
delete error.keyword;
28+
29+
return error;
30+
}
31+
32+
/**
33+
* Takes in schema and returns function which can be used to validate the schema with better semantics around exposing errors
34+
*/
35+
export function validate(schema: any, options?: any) {
36+
return (x: any): any[] => {
37+
const validate = jsen(schema, options);
38+
const isValid = validate(x);
39+
40+
if(isValid) {
41+
return undefined;
42+
}
43+
else {
44+
return validate.errors
45+
.map(normalizeError);
46+
}
47+
}
48+
}
49+
50+
51+
export interface ISettings {
52+
filter?: any;
53+
filterPaneEnabled?: boolean;
54+
pageName?: string;
55+
pageNavigationEnabled?: boolean;
56+
}
57+
58+
export const validateSettings = validate(settingsSchema);
59+
60+
/**
61+
* TODO: Consider adding type: "report" | "tile" property to indicate what type of object to embed
62+
*
63+
* This would align with goal of having single embed page which adapts to the thing being embedded
64+
* instead of having M x N embed pages where M is type of object (report, tile) and N is authorization
65+
* type (PaaS, SaaS, Anonymous)
66+
*/
67+
export interface ILoadConfiguration {
68+
accessToken: string;
69+
id: string;
70+
settings?: ISettings;
71+
}
72+
73+
export const validateLoad = validate(loadSchema, {
74+
schemas: {
75+
settings: settingsSchema
76+
}
77+
});
78+
79+
export interface IPageTarget {
80+
type: "page";
81+
name: string;
82+
}
83+
84+
export const validatePageTarget = validate(pageTargetSchema);
85+
86+
export interface IVisualTarget {
87+
type: "visual";
88+
id: string;
89+
}
90+
91+
export const validateVisualTarget = validate(visualTargetSchema);
92+
93+
export interface IPage {
94+
name: string;
95+
displayName: string;
96+
}
97+
98+
export const validatePage = validate(pageSchema);

src/schemas/load.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"type": "object",
4+
"properties": {
5+
"accessToken": {
6+
"type": "string",
7+
"messages": {
8+
"type": "accessToken must be a string",
9+
"required": "accessToken is required"
10+
},
11+
"invalidMessage": "accessToken property is invalid"
12+
},
13+
"id": {
14+
"type": "string",
15+
"messages": {
16+
"type": "id must be a string",
17+
"required": "id is required"
18+
}
19+
},
20+
"settings": {
21+
"$ref": "#settings"
22+
}
23+
},
24+
"required": [
25+
"accessToken",
26+
"id"
27+
]
28+
}

src/schemas/page.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"type": "object",
4+
"properties": {
5+
"name": {
6+
"type": "string",
7+
"messages": {
8+
"type": "name must be a string",
9+
"required": "name is required"
10+
}
11+
},
12+
"displayName": {
13+
"type": "string",
14+
"messages": {
15+
"type": "displayName must be a string",
16+
"required": "displayName is required"
17+
}
18+
}
19+
},
20+
"required": [
21+
"name",
22+
"displayName"
23+
]
24+
}

src/schemas/pageTarget.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"type": "object",
4+
"properties": {
5+
"type": {
6+
"type": "string",
7+
"enum": [
8+
"page"
9+
],
10+
"messages": {
11+
"type": "type must be a string",
12+
"enum": "type must be 'page'",
13+
"required": "type is required"
14+
}
15+
},
16+
"name": {
17+
"type": "string",
18+
"messages": {
19+
"type": "name must be a string",
20+
"required": "name is required"
21+
}
22+
}
23+
},
24+
"required": [
25+
"type",
26+
"name"
27+
]
28+
}

0 commit comments

Comments
 (0)