Upgraded Vue SFC sample to the latest SPFx drop. Updated dependency versions. Fixed build issues.

This commit is contained in:
Sergei Sergeev 2020-04-28 00:18:08 +03:00
parent 426b91707d
commit 231f87f714
17 changed files with 9580 additions and 9614 deletions

View File

@ -19,7 +19,7 @@ Sample Todo web part demonstrating how you can utilize [Vue](https://vuejs.org/v
## Used SharePoint Framework Version ## Used SharePoint Framework Version
![1.4.0](https://img.shields.io/badge/drop-1.4.0-green.svg) ![1.10.0](https://img.shields.io/badge/drop-1.10.0-green.svg)
## Applies to ## Applies to
@ -42,6 +42,7 @@ Version|Date|Comments
0.0.4|October 7, 2017|Updated packages to latest versions, misc fixing 0.0.4|October 7, 2017|Updated packages to latest versions, misc fixing
0.0.5|November 15, 2017|Added data provider that demonstrates the CRUD operations 0.0.5|November 15, 2017|Added data provider that demonstrates the CRUD operations
0.0.6|December 11, 2018|Updated sample to SPFx 1.4 and Vue 2.5.x 0.0.6|December 11, 2018|Updated sample to SPFx 1.4 and Vue 2.5.x
0.0.7|April 28, 2020|Updated sample to SPFx 1.10 and Vue 2.6.x, fixed issues with batch loader
## Disclaimer ## Disclaimer

View File

@ -1,5 +1,5 @@
{ {
"$schema": "https://dev.office.com/json-schemas/spfx-build/config.2.0.schema.json", "$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0", "version": "2.0",
"bundles": { "bundles": {
"to-do-bundle": { "to-do-bundle": {
@ -14,4 +14,4 @@
"localizedResources": { "localizedResources": {
"toDoStrings": "lib/webparts/toDo/loc/{locale}.js" "toDoStrings": "lib/webparts/toDo/loc/{locale}.js"
} }
} }

View File

@ -1,3 +1,4 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "temp/deploy" "deployCdnPath": "temp/deploy"
} }

View File

@ -1,8 +1,10 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": { "solution": {
"name": "vue-todo-client-side-solution", "name": "vue-todo-client-side-solution",
"id": "93e1bc8f-a063-4617-aa40-837e3b39f958", "id": "93e1bc8f-a063-4617-aa40-837e3b39f958",
"version": "1.0.0.0" "version": "1.0.0.0",
"isDomainIsolated": false
}, },
"paths": { "paths": {
"zippedPackage": "solution/vue-todo.sppkg" "zippedPackage": "solution/vue-todo.sppkg"

View File

@ -1,4 +1,5 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
"port": 4321, "port": 4321,
"initialPage": "https://localhost:5432/workbench", "initialPage": "https://localhost:5432/workbench",
"https": true, "https": true,

View File

@ -1,46 +0,0 @@
{
// Display errors as warnings
"displayAsWarning": true,
// The TSLint task may have been configured with several custom lint rules
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
// project). If true, this flag will deactivate any of these rules.
"removeExistingRules": true,
// When true, the TSLint task is configured with some default TSLint "rules.":
"useDefaultConfigAsBase": false,
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
// which are active, other than the list of rules below.
"lintConfig": {
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-case": true,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-unused-imports": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"valid-typeof": true,
"variable-name": false,
"whitespace": false,
"prefer-const": false
}
}
}

View File

@ -1,3 +1,4 @@
{ {
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
"cdnBasePath": "<!-- PATH TO CDN -->" "cdnBasePath": "<!-- PATH TO CDN -->"
} }

View File

@ -3,41 +3,47 @@
const gulp = require('gulp'); const gulp = require('gulp');
const build = require('@microsoft/sp-build-web'); const build = require('@microsoft/sp-build-web');
var merge = require('webpack-merge'); var merge = require('webpack-merge');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
build.sass.setConfig({ build.sass.setConfig({
sassMatch: [] sassMatch: []
}); });
build.configureWebpack.setConfig({ build.configureWebpack.mergeConfig({
additionalConfiguration: function (config) { additionalConfiguration: (generatedConfiguration) => {
var vueConfig = {
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
esModule: true
}
}]
}]
},
};
return merge(config, vueConfig); generatedConfiguration.plugins.push(new VueLoaderPlugin());
} generatedConfiguration.resolve.alias = {
'vue$': 'vue/dist/vue.esm.js'
};
generatedConfiguration.module.rules.push({
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
esModule: true
}
}]
});
generatedConfiguration.module.rules.push({
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
});
return generatedConfiguration;
}
}); });
let copyOtherFiles = build.subTask('copy-other-files', function(gulp, buildOptions, done){ let copyOtherFiles = build.subTask('copy-other-files', function (gulp, buildOptions, done) {
return gulp.src(['src/**/*.vue', 'src/**/*.scss']) return gulp.src(['src/**/*.vue', 'src/**/*.scss'])
.pipe(gulp.dest(buildOptions.libFolder)) .pipe(gulp.dest(buildOptions.libFolder))
}); });
build.task('copy-other-files', copyOtherFiles); build.task('copy-other-files', copyOtherFiles);
build.rig.addPostTypescriptTask(copyOtherFiles); build.rig.addPostTypescriptTask(copyOtherFiles);

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +1,39 @@
{ {
"name": "vue-todo", "name": "vue-todo",
"version": "0.0.6", "version": "0.0.7",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
}, },
"main": "lib/index.js",
"dependencies": { "dependencies": {
"@microsoft/sp-core-library": "~1.4.0", "@microsoft/sp-core-library": "1.10.0",
"@microsoft/sp-lodash-subset": "~1.4.0", "@microsoft/sp-lodash-subset": "1.10.0",
"@microsoft/sp-office-ui-fabric-core": "~1.4.0", "@microsoft/sp-office-ui-fabric-core": "1.10.0",
"@microsoft/sp-webpart-base": "~1.4.0", "@microsoft/sp-property-pane": "1.10.0",
"@types/webpack-env": ">=1.12.1 <1.14.0", "@microsoft/sp-webpart-base": "1.10.0",
"vue": "^2.5.13", "@types/es6-promise": "0.0.33",
"vue-class-component": "^6.1.2", "@types/webpack-env": "1.13.1",
"vue-property-decorator": "^6.0.0", "vue": "^2.6.11",
"vue-template-compiler": "^2.5.13", "vue-class-component": "^7.2.3",
"minimist": ">=1.2.3", "vue-property-decorator": "^8.4.2",
"acorn": ">=5.7.4" "vue-template-compiler": "^2.6.11"
}, },
"devDependencies": { "devDependencies": {
"@microsoft/sp-build-web": "~1.4.0", "@microsoft/rush-stack-compiler-3.3": "0.3.5",
"@microsoft/sp-module-interfaces": "~1.4.0", "@microsoft/sp-build-web": "1.10.0",
"@microsoft/sp-webpart-workbench": "~1.4.0", "@microsoft/sp-module-interfaces": "1.10.0",
"@types/chai": ">=3.4.34 <3.6.0", "@microsoft/sp-tslint-rules": "1.10.0",
"@types/mocha": ">=2.2.33 <2.6.0", "@microsoft/sp-webpart-workbench": "1.10.0",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2", "ajv": "~5.2.2",
"css-loader": "^3.5.3",
"gulp": "~3.9.1", "gulp": "~3.9.1",
"webpack-merge": "^4.1.1", "node-sass": "~4.14.0",
"node-sass": "~4.5.3", "sass-loader": "~8.0.2",
"sass-loader": "~6.0.6", "tslint-microsoft-contrib": "5.0.0",
"vue-loader": "^13.7.0" "vue-loader": "^15.9.1"
}, },
"scripts": { "scripts": {
"build": "gulp bundle", "build": "gulp bundle",

View File

@ -1,7 +1,7 @@
import { ITaskList } from '../models/ICommonObjects'; import { ITaskList } from '../models/ICommonObjects';
import { import {
IPropertyPaneDropdownOption, IPropertyPaneDropdownOption,
} from '@microsoft/sp-webpart-base'; } from '@microsoft/sp-property-pane';
export class Utils { export class Utils {
@ -27,4 +27,4 @@ export class Utils {
} }
return result; return result;
} }
} }

View File

@ -1,12 +1,10 @@
import { import {
SPHttpClient, SPHttpClient,
SPHttpClientBatch,
SPHttpClientResponse SPHttpClientResponse
} from '@microsoft/sp-http'; } from '@microsoft/sp-http';
import { IWebPartContext } from '@microsoft/sp-webpart-base'; import { IWebPartContext } from '@microsoft/sp-webpart-base';
import ITodoDataProvider from '../dataProviders/ITodoDataProvider'; import ITodoDataProvider from '../dataProviders/ITodoDataProvider';
import { ITodoItem, ITaskList } from '../models/ICommonObjects'; import { ITodoItem, ITaskList } from '../models/ICommonObjects';
import { debounce } from '@microsoft/sp-lodash-subset';
export default class SharePointDataProvider implements ITodoDataProvider { export default class SharePointDataProvider implements ITodoDataProvider {
@ -45,60 +43,13 @@ export default class SharePointDataProvider implements ITodoDataProvider {
} }
public getItems(): Promise<ITodoItem[]> { public getItems(): Promise<ITodoItem[]> {
return this._getItems(this.webPartContext.spHttpClient);
}
public createItem(title: string): Promise<ITodoItem[]> {
const batch: SPHttpClientBatch = this.webPartContext.spHttpClient.beginBatch();
const batchPromises: Promise<{}>[] = [
this._createItem(batch, title),
this._getItemsBatched(batch)
];
return this._resolveBatch(batch, batchPromises);
}
public deleteItem(itemToBeDeleted: ITodoItem): Promise<ITodoItem[]> {
//Approach 1: it is not working here with DELETE
// const batch: SPHttpClientBatch = this.webPartContext.spHttpClient.beginBatch();
// const batchPromises: Promise<{}>[] = [
// this._deleteItem(batch, itemToBeDeleted),
// this._getItemsBatched(batch)
// ];
// return this._resolveBatch(batch, batchPromises);
//Approach 2:
return this._deleteItem2(this.webPartContext.spHttpClient, itemToBeDeleted);
}
public updateItem(itemUpdated: ITodoItem): Promise<ITodoItem[]> {
const batch: SPHttpClientBatch = this.webPartContext.spHttpClient.beginBatch();
const batchPromises: Promise<{}>[] = [
this._updateItem(batch, itemUpdated),
this._getItemsBatched(batch)
];
return this._resolveBatch(batch, batchPromises);
}
private _getItems(requester: SPHttpClient): Promise<ITodoItem[]> {
const queryUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}` + const queryUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}` +
`/_api/web/lists(guid'${this._selectedList.Id}')/items?$select=Id,Title,PercentComplete`; `/_api/web/lists(guid'${this._selectedList.Id}')/items?$select=Id,Title,PercentComplete`;
return requester.get(queryUrl, SPHttpClient.configurations.v1) return this.webPartContext.spHttpClient.get(queryUrl, SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => { .then((response: SPHttpClientResponse) => {
return response.json(); return response.json();
}) })
//Approach 1: Of the property names of ITodoItem are equal to the internal names of the list, this will work
// .then((json: { value: ITodoItem[] }) => {
// debugger;
// return json.value;
// // .map((task: ITodoItem) => { debugger; return task; });
// });
//Approach 2: manually create the ITodoItem object; useful when the properties are different form the internal names of the list
.then((json: any) => { .then((json: any) => {
return json.value.map((item: any) => { return json.value.map((item: any) => {
let newItem: ITodoItem = { let newItem: ITodoItem = {
@ -111,57 +62,26 @@ export default class SharePointDataProvider implements ITodoDataProvider {
}); });
} }
private _getItemsBatched(requester: SPHttpClientBatch): Promise<ITodoItem[]> { public createItem(title: string): Promise<ITodoItem[]> {
const queryUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}` +
`/_api/web/lists(guid'${this._selectedList.Id}')/items?$select=Id,Title,PercentComplete`;
return requester.get(queryUrl, SPHttpClientBatch.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
})
.then((json: { value: ITodoItem[] }) => {
return json.value.map((task: ITodoItem) => {
return task;
});
});
}
private _createItem(batch: SPHttpClientBatch, title: string): Promise<SPHttpClientResponse> {
const body: {} = { const body: {} = {
'@data.type': this._selectedList.ListItemEntityTypeFullName, '@data.type': this._selectedList.ListItemEntityTypeFullName,
'Title': title 'Title': title
}; };
return batch.post( return this._webPartContext.spHttpClient.post(`${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists(guid'${this._selectedList.Id}')/items`, SPHttpClient.configurations.v1, {
`${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists(guid'${this._selectedList.Id}')/items`, body: JSON.stringify(body)
SPHttpClientBatch.configurations.v1, })
{ body: JSON.stringify(body) } .then(() => {
); return this.getItems();
});
} }
private _deleteItem(batch: SPHttpClientBatch, item: ITodoItem): Promise<SPHttpClientResponse> { public deleteItem(itemToBeDeleted: ITodoItem): Promise<ITodoItem[]> {
const itemDeletedUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists(guid'${this._selectedList.Id}')/items(${item.Id})`; const itemDeletedUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists(guid'${this._selectedList.Id}')/items(${itemToBeDeleted.Id})`;
const headers: Headers = new Headers(); const headers: Headers = new Headers();
headers.append('If-Match', '*'); headers.append('If-Match', '*');
return batch.fetch(itemDeletedUrl, return this.webPartContext.spHttpClient.fetch(itemDeletedUrl,
SPHttpClientBatch.configurations.v1,
{
headers,
method: 'DELETE'
}
);
}
private _deleteItem2(requester: SPHttpClient, item: ITodoItem): Promise<ITodoItem[]> {
const itemDeletedUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists(guid'${this._selectedList.Id}')/items(${item.Id})`;
const headers: Headers = new Headers();
headers.append('If-Match', '*');
return requester.fetch(itemDeletedUrl,
SPHttpClient.configurations.v1, SPHttpClient.configurations.v1,
{ {
headers, headers,
@ -174,42 +94,26 @@ export default class SharePointDataProvider implements ITodoDataProvider {
return Promise.reject(new Error(JSON.stringify(response))); return Promise.reject(new Error(JSON.stringify(response)));
} }
}).then(() => { }).then(() => {
return this._getItems(requester); return this.getItems();
}); });
} }
private _updateItem(batch: SPHttpClientBatch, item: ITodoItem): Promise<SPHttpClientResponse> { public updateItem(itemUpdated: ITodoItem): Promise<ITodoItem[]> {
const itemUpdatedUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists(guid'${this._selectedList.Id}')/items(${itemUpdated.Id})`;
const itemUpdatedUrl: string = `${this._webPartContext.pageContext.web.absoluteUrl}/_api/web/lists(guid'${this._selectedList.Id}')/items(${item.Id})`;
const headers: Headers = new Headers(); const headers: Headers = new Headers();
headers.append('If-Match', '*'); headers.append('If-Match', '*');
const body: {} = { const body: {} = {
'@data.type': this._selectedList.ListItemEntityTypeFullName, '@data.type': this._selectedList.ListItemEntityTypeFullName,
'PercentComplete': item.PercentComplete 'PercentComplete': itemUpdated.PercentComplete
}; };
return batch.fetch(itemUpdatedUrl, return this._webPartContext.spHttpClient.fetch(itemUpdatedUrl, SPHttpClient.configurations.v1, {
SPHttpClientBatch.configurations.v1, body: JSON.stringify(body),
{ headers,
body: JSON.stringify(body), method: 'PATCH'
headers, }).then(() => {
method: 'PATCH' return this.getItems();
} });
);
}
private _resolveBatch(batch: SPHttpClientBatch, promises: Promise<{}>[]): Promise<ITodoItem[]> {
return batch.execute()
.then(() => {
return Promise.all(promises);
}).then((values: any) => {
return Promise.resolve(values[values.length - 1]);
// return values[values.length - 1];
}).catch((ex) => {
throw ex;
});
} }
} }

View File

@ -0,0 +1 @@
// A file is required to be in the root of the /src directory by the TypeScript compiler

View File

@ -1,11 +1,11 @@
{ {
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json", "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
"id": "a0e1eddd-ea67-4775-a52b-0141c5807146", "id": "a0e1eddd-ea67-4775-a52b-0141c5807146",
"alias": "ToDoWebPart", "alias": "ToDoWebPart",
"componentType": "WebPart", "componentType": "WebPart",
"version": "0.0.1", "version": "0.0.1",
"manifestVersion": 2, "manifestVersion": 2,
"supportedHosts": ["SharePointWebPart"],
"preconfiguredEntries": [{ "preconfiguredEntries": [{
"groupId": "a0e1eddd-ea67-4775-a52b-0141c5807146", "groupId": "a0e1eddd-ea67-4775-a52b-0141c5807146",

View File

@ -1,15 +1,15 @@
import { Version, Environment, EnvironmentType } from '@microsoft/sp-core-library'; import { Version, Environment, EnvironmentType } from '@microsoft/sp-core-library';
import { import {
BaseClientSideWebPart, BaseClientSideWebPart
IPropertyPaneConfiguration,
PropertyPaneTextField,
PropertyPaneDropdown,
IPropertyPaneField,
PropertyPaneLabel,
IPropertyPaneDropdownOption
} from '@microsoft/sp-webpart-base'; } from '@microsoft/sp-webpart-base';
import { findIndex } from '@microsoft/sp-lodash-subset'; import { findIndex } from '@microsoft/sp-lodash-subset';
import {
IPropertyPaneConfiguration,
IPropertyPaneDropdownOption,
PropertyPaneDropdown
} from "@microsoft/sp-property-pane";
import Vue from 'vue'; import Vue from 'vue';
import TodoComponent from './components/todo/Todo.vue'; import TodoComponent from './components/todo/Todo.vue';
import { ITodoProps } from './components/todo/ITodoProps'; import { ITodoProps } from './components/todo/ITodoProps';
@ -46,9 +46,9 @@ export default class TodoWebPart extends BaseClientSideWebPart<ITodoWebPartProps
this._dataProvider = new SharePointDataProvider(); this._dataProvider = new SharePointDataProvider();
this._dataProvider.webPartContext = this.context; this._dataProvider.webPartContext = this.context;
} }
/* /*
If we have serialized list in the webpart properties, use it If we have serialized list in the webpart properties, use it
*/ */
if (this.properties.SelectedList) { if (this.properties.SelectedList) {
this._dataProvider.selectedList = this.properties.SelectedList; this._dataProvider.selectedList = this.properties.SelectedList;
@ -57,9 +57,9 @@ export default class TodoWebPart extends BaseClientSideWebPart<ITodoWebPartProps
/* /*
Approach 1: Approach 1:
Get the list of tasks lists from the current site and store them in the variable _dropdownOptions Get the list of tasks lists from the current site and store them in the variable _dropdownOptions
_dropdownOptions will be used to populate the property pane dropdown field when pane opens. _dropdownOptions will be used to populate the property pane dropdown field when pane opens.
Approach 2: Approach 2:
Get the list of tasks lists from the current site and load them in the property pane only when the property pane is open. Get the list of tasks lists from the current site and load them in the property pane only when the property pane is open.
For this approach please review the sample: react-custompropertypanecontrols For this approach please review the sample: react-custompropertypanecontrols
@ -131,16 +131,16 @@ export default class TodoWebPart extends BaseClientSideWebPart<ITodoWebPartProps
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void { protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
/* /*
Check the property path to see which property pane feld changed. Check the property path to see which property pane feld changed.
If the property path matches the dropdown, then we set that list as the selected list for the web part. If the property path matches the dropdown, then we set that list as the selected list for the web part.
*/ */
if (propertyPath === 'selectedList') { if (propertyPath === 'selectedList') {
this._setSelectedList(newValue); this._setSelectedList(newValue);
} }
/* /*
Tell property pane to re-render the web part. Tell property pane to re-render the web part.
This is valid for reactive property pane. This is valid for reactive property pane.
*/ */
super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue); super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue);
} }

View File

@ -1,11 +1,23 @@
{ {
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"module": "commonjs", "module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"declaration": true, "declaration": true,
"sourceMap": true, "sourceMap": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"skipLibCheck": true,
"outDir": "lib",
"inlineSources": false,
"strictNullChecks": false,
"noUnusedLocals": false,
"typeRoots": [
"./node_modules/@types",
"./node_modules/@microsoft"
],
"types": [ "types": [
"es6-promise", "es6-promise",
"webpack-env" "webpack-env"
@ -15,5 +27,12 @@
"dom", "dom",
"es2015.collection" "es2015.collection"
] ]
} },
"include": [
"src/**/*.ts", "src/webparts/themed/index.tsx"
],
"exclude": [
"node_modules",
"lib"
]
} }

View File

@ -1,3 +1,30 @@
{ {
"rulesDirectory": "./config" "extends": "@microsoft/sp-tslint-rules/base-tslint.json",
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"variable-name": false,
"whitespace": false
}
} }