UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

1 lines 9.7 kB
{"version":3,"sources":["../../../packages/tools/gulp-ps-code/index.ts"],"names":[],"mappings":"","file":"index.d.ts","sourcesContent":["/* eslint-disable no-console */\r\n'use strict';\r\n\r\nimport Path from 'path';\r\nimport pluginError from 'plugin-error';\r\nimport through2 from 'through2';\r\nimport Vinyl from 'vinyl';\r\nimport * as util from '../utilities';\r\nimport * as PsCode from './ps-code-convert';\r\nimport { Group, Groups, PsCodeConverter } from './ps-code-convert';\r\n\r\nconst PLUGIN_NAME = 'gulp-ps-code';\r\n\r\n/**\r\n * Plugin level function\r\n */\r\nfunction gulpPsCode(options: PsCode.Options) {\r\n //\r\n // (Options):\r\n //\r\n // name of PowerShell module. (required)\r\n // powerShellModuleName: string\r\n //\r\n // name of generated file.\r\n // name: string; default is 'powershell-script.ts'\r\n //\r\n // base path of powershell files.\r\n // basePath: string; default is 'src/resources/scripts'\r\n //\r\n // generated path of powershell files.\r\n // generatedPath: string; default is 'src/generated/scripts'\r\n //\r\n // remove comments at default.\r\n // noComments: boolean;\r\n //\r\n // validate content of PowerShell script.\r\n // - non-ascii code, no comments, unsupported script file name and unofficial verb\r\n // validate: boolean;\r\n //\r\n // JEA data object format.\r\n // jea: boolean\r\n //\r\n // name of resource root. the key name of resjson.\r\n // resourceName: string\r\n //\r\n\r\n // override options settings if not specified.\r\n options = Object.assign(\r\n <PsCode.Options>{\r\n name: 'powershell-scripts.ts',\r\n basePath: 'src\\\\resources\\\\scripts',\r\n generatedPath: 'src\\\\generated\\\\scripts',\r\n noComments: true,\r\n validate: true,\r\n jea: true\r\n },\r\n options || {});\r\n\r\n const groups: Groups = {};\r\n const collection = {};\r\n let lastFile = null;\r\n\r\n return through2.obj(\r\n function (file, enc, cb) {\r\n let error = null;\r\n try {\r\n if (!options.powerShellModuleName) {\r\n throw new Error('gulp-ps-code requires powerShellModuleName option.');\r\n }\r\n\r\n const path = Path.parse(file.path);\r\n if (path.ext === '.ps1') {\r\n let relPath: string = file.path.substring(file.cwd.length + 1);\r\n relPath = relPath.substring(0, relPath.length - path.base.length - 1);\r\n let groupName = PsCodeConverter.defaultGroup;\r\n if (relPath === options.generatedPath) {\r\n groupName = PsCodeConverter.generatedGroup;\r\n } else {\r\n if (relPath !== options.basePath && relPath.indexOf(options.basePath) === 0) {\r\n groupName = relPath.substring(options.basePath.length + 1);\r\n }\r\n }\r\n\r\n let group: Group = groups[groupName];\r\n if (!group) {\r\n group = {};\r\n groups[groupName] = group;\r\n }\r\n\r\n if (collection[path.base]) {\r\n throw new Error('gulp-ps-code requires unique name of ps file, conflicted with ' + path.base);\r\n }\r\n\r\n collection[path.base] = true;\r\n\r\n const data: string = file.contents.toString('utf8');\r\n if (options.validate) {\r\n // validate non-ascii code presence.\r\n const lines = data.split('\\n');\r\n let errorCode = false;\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n for (let j = 0; j < line.length; j++) {\r\n const code = line.charCodeAt(j);\r\n if (code > 0x7f) {\r\n let point = '';\r\n if (j > 0) {\r\n for (let k = 1; k <= j; k++) {\r\n point += ' ';\r\n }\r\n }\r\n\r\n console.error(\r\n `File: ${path.base}, Line: ${i + 1}, Position: ${j + 1}, Char: '${line.charAt(j)}', Code: ${code}`);\r\n console.error(line);\r\n console.error(point + '^----<see>');\r\n errorCode = true;\r\n }\r\n }\r\n }\r\n\r\n if (errorCode) {\r\n throw new Error('File contained non ascii code: ' + path.base);\r\n }\r\n\r\n // validate script file name.\r\n const segments = path.base.split('-');\r\n if (segments.length !== 2) {\r\n console.error('File doesn\\'t follow <Verb>-<Name>.ps1 format to support JEA: ' + path.base);\r\n } else {\r\n // validate script verb.\r\n const found = PsCodeConverter.verbs.find(x => x === segments[0]);\r\n if (!found) {\r\n console.error('File doesn\\'t follow official verb name to support JEA: ' + path.base);\r\n console.error('Try Get-Verb PowerShell command to find official verbs.');\r\n console.error('https://msdn.microsoft.com/en-us/library/ms714428(v=vs.85).aspx');\r\n errorCode = true;\r\n } else {\r\n // validate comments for JEA.\r\n const commentIndex = data.indexOf('{');\r\n const comments: string = commentIndex < 0 ? data : data.substring(0, commentIndex);\r\n const commentsMinimum = comments.indexOf('<#') >= 0\r\n && comments.indexOf('#>') > 0\r\n && comments.indexOf('.SYNOPSIS') > 0\r\n && comments.indexOf('.DESCRIPTION') > 0\r\n && comments.indexOf('.ROLE') > 0;\r\n if (!commentsMinimum) {\r\n console.error(\r\n 'The script file doesn\\'t contain formal PowerShell comment section to support JEA: ' + path.base);\r\n console.error(\r\n 'Requires .SYNOPSIS, .DESCRIPTION and .ROLE comments.');\r\n errorCode = true;\r\n }\r\n\r\n let roleLine = false;\r\n for (const comment of comments.split('\\n')) {\r\n if (roleLine) {\r\n const role = comment.trim();\r\n if (role === '' || role === '#>') {\r\n break;\r\n }\r\n\r\n if (role !== 'Administrators' && role !== 'Readers' && role !== 'Hyper-V-Administrators') {\r\n console.error(\r\n 'The script file contains unsupported JEA ROLE \"' + role + '\": ' + path.base);\r\n errorCode = true;\r\n }\r\n }\r\n\r\n if (comment.indexOf('.ROLE') >= 0) {\r\n roleLine = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (errorCode) {\r\n throw new Error('File cannot support JEA: ' + path.base);\r\n }\r\n }\r\n\r\n group[path.base] = data;\r\n lastFile = file;\r\n }\r\n } catch (e) {\r\n error = (!e.plugin || (e.plugin !== PLUGIN_NAME)) ?\r\n util.extendError(new pluginError({ plugin: PLUGIN_NAME, message: e.message }), e) : e;\r\n }\r\n\r\n return cb(error);\r\n },\r\n function (cb) {\r\n const converter = new PsCode.PsCodeConverter(options);\r\n converter.contentReset();\r\n converter.generate(groups);\r\n const tsFile = new Vinyl({\r\n cwd: lastFile.cwd,\r\n base: lastFile.base,\r\n path: lastFile.base + '/' + options.name,\r\n contents: Buffer.from(converter.content, 'utf8')\r\n });\r\n\r\n this.push(tsFile);\r\n cb();\r\n });\r\n}\r\n\r\nmodule.exports = gulpPsCode;\r\n"]}