diff --git a/.clasp.json b/.clasp.json new file mode 100644 index 0000000..e3a512c --- /dev/null +++ b/.clasp.json @@ -0,0 +1 @@ +{"scriptId":"1glvOtH5vy8_QUR4MEtMwvYpZUfzesJryyhmUIDIkW90yOLK0NOsfTRYy","rootDir":"/Users/bukaj/www/google-script-groups-browser","projectId":"redbitcz-groups-viewer"} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ccbe46 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules/ diff --git a/Code.gs b/Code.gs deleted file mode 100644 index f7efc93..0000000 --- a/Code.gs +++ /dev/null @@ -1,209 +0,0 @@ -var COMPANY_NAME = "Socialbakers"; -var COMPANY_GSUITE_DOMAIN = "socialbakers.com"; - -var TYPE_ALL = "all"; -var TYPE_USER = "user"; -var TYPE_GROUP = "group"; -var TYPE_DOMAIN = "domain"; -var TYPE_TRANSLATE = { - USER: TYPE_USER, - GROUP: TYPE_GROUP, - CUSTOMER: TYPE_DOMAIN, -}; -var STATUS_ACTIVE = "ACTIVE"; -var ROLE_OWNER = "owner"; -var ROLE_MANAGER = "manager"; -var ROLE_MEMBER = "member"; -var ROLE_TRANSLATE = { - OWNER: ROLE_OWNER, - MANAGER: ROLE_MANAGER, - MEMBER: ROLE_MEMBER, -}; -var WEB_ARCHIV_URL = "https://groups.google.com/a/" + COMPANY_GSUITE_DOMAIN + "/group/%s"; - -function doGet() { - return HtmlService.createHtmlOutputFromFile('UI') - .setTitle(COMPANY_NAME + ' Google Groups Directory') - .addMetaTag('viewport', 'width=device-width, initial-scale=1'); -} - -function search(id, type) { - if(type==TYPE_ALL) { - return getAllGroupsResponse(id, type); - } - - var email = completeEmail(id); - var entity = searchEntity(email, type); - - if(!entity) { - return getErrorResponse("Email address '" + email + "' doesn't exist on the domain."); - } - - if(entity.type == TYPE_GROUP) { - return getGroupMembersResponse(email, entity.object); - } - - if(entity.type == TYPE_USER) { - return getUserGroupsResponse(email, entity.object); - } -} - -function getAllGroupsResponse(id, type) { - var groups = fetchGroups({customer:'my_customer'}); - return { - status: true, - type: TYPE_ALL, - groups: groups, - }; -} - -function getUserGroupsResponse(id, user) { - var groups = fetchGroups({userKey:id}); - return { - status: true, - type: TYPE_USER, - groups: groups, - user: user, - }; -} - -function fetchGroups(filter) { - var groups = []; - var pageToken = null; - do { - var result = AdminDirectory.Groups.list(filter); - filter.pageToken = result.nextPageToken; - if(result.groups) { - groups = groups.concat(result.groups.map(function(group) { - return { - email: group.email, - name: group.name, - description: group.description, - aliases: group.aliases, - }; - })); - } - } - while(result.nextPageToken); - - return groups; -} - -function getGroupMembersResponse(id, group) { - var members = fetchMembers(id); - return { - status: true, - type: TYPE_GROUP, - members: members, - group: group, - }; -} - -function fetchMembers(email) { - var userEmail = Session.getActiveUser().getEmail(); - var members = { - owner: [], - manager: [], - member: [], - }; - var pageToken = null; - do { - var result = AdminDirectory.Members.list(email, {pageToken:pageToken}); - pageToken = result.nextPageToken; - result.members.forEach(function(member){ - var role = ROLE_TRANSLATE[member.role]; - var type = TYPE_TRANSLATE[member.type]; - var email= member.email ? member.email : null; - - members[role].push({ - email: email, - type: type, - role: role, - status: member.status == STATUS_ACTIVE, - me: email == userEmail, - }); - }); - } - while(result.nextPageToken); - return members; -} - -function getErrorResponse(error) { - return { - status: false, - type: null, - error: error, - } -} - -function getGroupInfo(groupKey) { - var group = AdminDirectory.Groups.get(groupKey); - return { - name: group.name, - email: group.email, - description: group.description, - aliases: group.aliases, - webUrl: WEB_ARCHIV_URL.replace('%s', cropUsername(group.email)), - }; -} - - -function getUserInfo(userKey) { - var user = AdminDirectory.Users.get(userKey); - return { - name: user.name, - email: user.primaryEmail, - photo: user.thumbnailPhotoUrl, - aliases: user.aliases, - active: ! user.suspended, - }; -} - - -function completeEmail(shortEmail) { - if (shortEmail.indexOf('@') == -1) { - var currentUser = Session.getEffectiveUser().getEmail(); - var domain = currentUser.substring(currentUser.indexOf('@')); - return shortEmail + domain; - } - return shortEmail; -} - -function cropUsername(email) { - return email.substring(0, email.indexOf('@')); -} - -function searchEntity(id, type) { - try { - var entity = { - type: type, - object: null, - }; - - if(type==TYPE_GROUP) { - entity.object = getGroupInfo(id); - } - else if(type==TYPE_USER) { - entity.object = getUserInfo(id); - } - else { - try { - entity.object = getGroupInfo(id); - entity.type=TYPE_GROUP; - } - catch(error){ - entity.object = getUserInfo(id); - entity.type=TYPE_USER; - } - } - return entity; - } - catch(error){ - Logger.log(error); - return false; - } -} - -function getUrl(){ - return ScriptApp.getService().getUrl(); -} diff --git a/Code.ts b/Code.ts new file mode 100644 index 0000000..f2696ff --- /dev/null +++ b/Code.ts @@ -0,0 +1,208 @@ +import HtmlOutput = GoogleAppsScript.HTML.HtmlOutput; + +const COMPANY_NAME = "Acme"; +const COMPANY_GSUITE_DOMAIN = "acme.com"; + +const TYPE_ALL = "all"; +const TYPE_USER = "user"; +const TYPE_GROUP = "group"; +const TYPE_DOMAIN = "domain"; +const TYPE_TRANSLATE = { + USER: TYPE_USER, + GROUP: TYPE_GROUP, + CUSTOMER: TYPE_DOMAIN, +}; +const STATUS_ACTIVE = "ACTIVE"; +const ROLE_OWNER = "owner"; +const ROLE_MANAGER = "manager"; +const ROLE_MEMBER = "member"; +const ROLE_TRANSLATE = { + OWNER: ROLE_OWNER, + MANAGER: ROLE_MANAGER, + MEMBER: ROLE_MEMBER, +}; +const WEB_ARCHIV_URL = "https://groups.google.com/a/" + COMPANY_GSUITE_DOMAIN + "/group/%s"; + +function doGet(): HtmlOutput { + return HtmlService.createHtmlOutputFromFile('Index') + .setTitle(COMPANY_NAME + ' Google Groups Directory') + .setFaviconUrl('https://jakubboucek.github.io/google-script-groups-browser/assets/favicon.ico') + .addMetaTag('viewport', 'width=device-width, initial-scale=1'); +} + +function search(id, type) { + if (type == TYPE_ALL) { + return getAllGroupsResponse(id, type); + } + + var email = completeEmail(id); + var entity = searchEntity(email, type); + + if (!entity) { + return getErrorResponse("Email address '" + email + "' doesn't exist on the domain."); + } + + if (entity.type == TYPE_GROUP) { + return getGroupMembersResponse(email, entity.object); + } + + if (entity.type == TYPE_USER) { + return getUserGroupsResponse(email, entity.object); + } +} + +function getAllGroupsResponse(id, type) { + var groups = fetchGroups({customer: 'my_customer'}); + return { + status: true, + type: TYPE_ALL, + groups: groups, + }; +} + +function getUserGroupsResponse(id, user) { + var groups = fetchGroups({userKey: id}); + return { + status: true, + type: TYPE_USER, + groups: groups, + user: user, + }; +} + +function fetchGroups(filter) { + var groups = []; + var pageToken = null; + do { + var result = AdminDirectory.Groups.list(filter); + filter.pageToken = result.nextPageToken; + if (result.groups) { + groups = groups.concat(result.groups.map(function (group) { + return { + email: group.email, + name: group.name, + description: group.description, + aliases: group.aliases, + }; + })); + } + } + while (result.nextPageToken); + + return groups; +} + +function getGroupMembersResponse(id, group) { + var members = fetchMembers(id); + return { + status: true, + type: TYPE_GROUP, + members: members, + group: group, + }; +} + +function fetchMembers(email) { + var userEmail = Session.getActiveUser().getEmail(); + var members = { + owner: [], + manager: [], + member: [], + }; + var pageToken = null; + do { + var result = AdminDirectory.Members.list(email, {pageToken: pageToken}); + pageToken = result.nextPageToken; + result.members.forEach(function (member) { + var role = ROLE_TRANSLATE[member.role]; + var type = TYPE_TRANSLATE[member.type]; + var email = member.email ? member.email : null; + + members[role].push({ + email: email, + type: type, + role: role, + status: member.status == STATUS_ACTIVE, + me: email == userEmail, + }); + }); + } + while (result.nextPageToken); + return members; +} + +function getErrorResponse(error) { + return { + status: false, + type: null, + error: error, + } +} + +function getGroupInfo(groupKey) { + var group = AdminDirectory.Groups.get(groupKey); + return { + name: group.name, + email: group.email, + description: group.description, + aliases: group.aliases, + webUrl: WEB_ARCHIV_URL.replace('%s', cropUsername(group.email)), + }; +} + + +function getUserInfo(userKey) { + var user = AdminDirectory.Users.get(userKey); + return { + name: user.name, + email: user.primaryEmail, + photo: user.thumbnailPhotoUrl, + aliases: user.aliases, + active: !user.suspended, + }; +} + + +function completeEmail(shortEmail) { + if (shortEmail.indexOf('@') == -1) { + var currentUser = Session.getEffectiveUser().getEmail(); + var domain = currentUser.substring(currentUser.indexOf('@')); + return shortEmail + domain; + } + return shortEmail; +} + +function cropUsername(email) { + return email.substring(0, email.indexOf('@')); +} + +function searchEntity(id, type) { + try { + var entity = { + type: type, + object: null, + }; + + if (type == TYPE_GROUP) { + entity.object = getGroupInfo(id); + } else if (type == TYPE_USER) { + entity.object = getUserInfo(id); + } else { + try { + entity.object = getGroupInfo(id); + entity.type = TYPE_GROUP; + } catch (error) { + entity.object = getUserInfo(id); + entity.type = TYPE_USER; + } + } + return entity; + } catch (error) { + Logger.log(error); + return false; + } +} + +function getUrl() { + return ScriptApp.getService().getUrl(); +} diff --git a/Index.html b/Index.html index 51a17c6..d86d320 100644 --- a/Index.html +++ b/Index.html @@ -1,452 +1,502 @@ - + - + - - - - + + + + - - - - - -
-
+ + + +
+
-

Google Groups Directory

-

Email address (user or group):

-
-
-
-
- -
-
+

Google Groups Directory

+

Email address (user or group):

+
+
+ +
+
+ +
+
+ +
+
+
-
+
-

About User

-
-
-
- - - - - - - - - - -
Name:
E-mail:
Aliases:
+

About User

+
+
+
+ + + + + + + + + + + + + +
Name:
E-mail:
Aliases:
+
-
-

About Group

-
-
- -

Go to the Group
only for members

+

About Group

+
+
+ +

Go to the Group
only for + members

+
+
+ + + + + + + + + + + + + + + + + +
Name:
Description:
E-mail:
Aliases:
+
-
- - - - - - - - - - - - - -
Name:
Description:
E-mail:
Aliases:
-
-
-

Groups

- - - - - -
+

Groups

+ + + + + +
-

Group members

- - - - - - -
+

Group members

+ + + + + + +
-
-
- - - \ No newline at end of file +
+ + + diff --git a/LICENSE b/LICENSE index 278c99e..9251bde 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 Jakub Bouček +Copyright (c) 2021 Jakub Bouček Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/appsscript.json b/appsscript.json new file mode 100644 index 0000000..106538f --- /dev/null +++ b/appsscript.json @@ -0,0 +1,18 @@ +{ + "timeZone": "Europe/Prague", + "dependencies": { + "enabledAdvancedServices": [ + { + "userSymbol": "AdminDirectory", + "version": "directory_v1", + "serviceId": "admin" + } + ] + }, + "exceptionLogging": "STACKDRIVER", + "runtimeVersion": "V8", + "webapp": { + "executeAs": "USER_DEPLOYING", + "access": "MYSELF" + } +} \ No newline at end of file diff --git a/assets/company-logo.svg b/assets/company-logo.svg new file mode 100644 index 0000000..4d027af --- /dev/null +++ b/assets/company-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/domain.svg b/assets/domain.svg new file mode 100644 index 0000000..235ef07 --- /dev/null +++ b/assets/domain.svg @@ -0,0 +1,17 @@ + + + + Crop + Created with Sketch. + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/favicon.ico b/assets/favicon.ico new file mode 100644 index 0000000..6b8f9c3 Binary files /dev/null and b/assets/favicon.ico differ diff --git a/assets/group.svg b/assets/group.svg new file mode 100644 index 0000000..4b7eaa9 --- /dev/null +++ b/assets/group.svg @@ -0,0 +1,12 @@ + + + + Crop + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/assets/loader.css b/assets/loader.css new file mode 100644 index 0000000..194d17d --- /dev/null +++ b/assets/loader.css @@ -0,0 +1,44 @@ +.loader { + margin: 15px auto; + font-size: 3px; + position: relative; + text-indent: -9999em; + border-top: 1.1em solid rgba(89, 89, 89, 0.2); + border-right: 1.1em solid rgba(89, 89, 89, 0.2); + border-bottom: 1.1em solid rgba(89, 89, 89, 0.2); + border-left: 1.1em solid #595959; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} + +.loader, +.loader:after { + border-radius: 50%; + width: 10em; + height: 10em; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/assets/user.svg b/assets/user.svg new file mode 100644 index 0000000..3c30446 --- /dev/null +++ b/assets/user.svg @@ -0,0 +1,12 @@ + + + + Crop + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..34a7c3a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,46 @@ +{ + "name": "google-script-groups-browser", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "@types/google-apps-script": "^1.0.41" + }, + "devDependencies": { + "typescript": "^4.5.3" + } + }, + "node_modules/@types/google-apps-script": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/@types/google-apps-script/-/google-apps-script-1.0.41.tgz", + "integrity": "sha512-Lv8Tila1iNUynITT0H4lR59fcdkZ1JOPQiuthaOoG/agAbWYkZLeaR6yLIeRydFQ2bQqVgOrAXlmu8Ut8uUcOA==" + }, + "node_modules/typescript": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.3.tgz", + "integrity": "sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + } + }, + "dependencies": { + "@types/google-apps-script": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/@types/google-apps-script/-/google-apps-script-1.0.41.tgz", + "integrity": "sha512-Lv8Tila1iNUynITT0H4lR59fcdkZ1JOPQiuthaOoG/agAbWYkZLeaR6yLIeRydFQ2bQqVgOrAXlmu8Ut8uUcOA==" + }, + "typescript": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.3.tgz", + "integrity": "sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f3bef90 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "@types/google-apps-script": "^1.0.41" + }, + "devDependencies": { + "typescript": "^4.5.3" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..21268b7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,101 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES2019", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "lib": ["esnext"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "None", /* Specify what module code is generated. */ + "rootDir": "src", /* Specify the root folder within your source files. */ + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + "resolveJsonModule": true, /* Enable importing .json files */ + "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "lib", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + "isolatedModules": false, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +}