diff --git a/README.md b/README.md
index e591c87d..28f2e4d1 100644
--- a/README.md
+++ b/README.md
@@ -81,19 +81,25 @@ The following inputs are recommended or required for this action:
The following options allow to instrument TICS Client more specifically:
-| Input | Description | Default |
-| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ |
-| `calc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be calculated. The `GATE` metric is supported for TICS Viewer versions higher than 2022.2.x. | `GATE` |
-| `recalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be recalculated. The `GATE` GATE metric is supported for TICS Viewer versions higher than 2022.2.x. | - |
-| `nocalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be calculated. | - |
-| `norecalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be recalculated. | - |
-| `filelist` | Path to a file containing [a list of files](https://ticsdocumentation.tiobe.com/latest/docs/#doc=user/clientusecases.html%23client-file-list) (newline separated) to run TICS for. This can be an absolute or relative (to workspace) path, and can also be `.` to analyze the whole project. This has to be set when the action is run outside of a pull request. | - |
-| `cdtoken` | A custom client-data token for the purpose of the Client Viewer functionality. This provides a static URL that is updated with every analysis. | - |
-| `branchname` | Name of the branch in TICS. | - |
-| `codetype` | Allows you to pick which specific types of code you want to analyze with the TICS client. Options are `PRODUCTION`, `TESTCODE`, `EXTERNAL` and `GENERATED`. | `PRODUCTION` |
-| `excludeMovedFiles` | Exclude moved files from analysis even if there are modifications in the file. | `false` |
-| `showBlockingAfter` | Show the blocking after violations in the changed files window. Options are `true` or `false`. | `true` |
-| `tmpdir` | Location to store debug information. | - |
+| Input | Description | Default |
+| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- |
+| `calc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be calculated. The `GATE` metric is supported for TICS Viewer versions higher than 2022.2.x. | `GATE` |
+| `recalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be recalculated. The `GATE` GATE metric is supported for TICS Viewer versions higher than 2022.2.x. | - |
+| `nocalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be calculated. | - |
+| `norecalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be recalculated. | - |
+| `filelist` | Path to a file containing [a list of files](https://ticsdocumentation.tiobe.com/latest/docs/#doc=user/clientusecases.html%23client-file-list) (newline separated) to run TICS for. This can be an absolute or relative (to workspace) path, and can also be `.` to analyze the whole project. This has to be set when the action is run outside of a pull request. | - |
+| `cdtoken` | A custom client-data token for the purpose of the Client Viewer functionality. This provides a static URL that is updated with every analysis. | - |
+| `branchname` | Name of the branch in TICS. | - |
+| `codetype` | Allows you to pick which specific types of code you want to analyze with the TICS client. Options are `PRODUCTION`, `TESTCODE`, `EXTERNAL` and `GENERATED`. | `PRODUCTION` |
+| `excludeMovedFiles` | Exclude moved files from analysis even if there are modifications in the file. | `false` |
+| `showAnnotationSeverity` | Show TICS violations with at least the specified severity in the changed files window (will also show up in `outputs.annotations`). Options are `blocking`, `blocking-after` or `issue`. | `blocking-after` |
+| `tmpdir` | Location to store debug information. | - |
+
+#### Deprecated parameters
+
+| Input | Description | Default | Replacement |
+| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------ |
+| `showBlockingAfter` | !Will not be used if `showAnnotationSeverity` is set! Show the blocking after violations in the changed files window. Options are `true` or `false`. | `true` | `showAnnotationSeverity` |
## QServer
@@ -148,15 +154,21 @@ The following inputs are recommended or required for this action:
The following options allow to instrument TICSQServer more specifically:
-| Input | Description | Default |
-| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
-| `calc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be calculated. | `ALL` |
-| `recalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be recalculated. | - |
-| `nocalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be calculated. | - |
-| `norecalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be recalculated. | - |
-| `branchname` | Name of the branch in TICS. | - |
-| `showBlockingAfter` | Show the blocking after violations in the changed files window. Options are `true` or `false`. | `true` |
-| `tmpdir` | Location to store debug information. | - |
+| Input | Description | Default |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
+| `calc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be calculated. | `ALL` |
+| `recalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to be recalculated. | - |
+| `nocalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be calculated. | - |
+| `norecalc` | Comma-separated list of [metrics](https://ticsdocumentation.tiobe.com/latest/docs/index.html#doc=user/clientoptions.html%23MetricAliases) to not be recalculated. | - |
+| `branchname` | Name of the branch in TICS. | - |
+| `showAnnotationSeverity` | Show TICS violations with at least the specified severity in the changed files window (will also show up in `outputs.annotations`). Options are `blocking`, `blocking-after` or `issue`. | `blocking-after` |
+| `tmpdir` | Location to store debug information. | - |
+
+#### Deprecated parameters
+
+| Input | Description | Default | Replacement |
+| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------------------ |
+| `showBlockingAfter` | !Will not be used if `showAnnotationSeverity` is set! Show the blocking after violations in the changed files window. Options are `true` or `false`. | `true` | `showAnnotationSeverity` |
## Other features
@@ -210,14 +222,14 @@ jobs:
It is possible to retrieve all Quality Gate conditions and reported annotations in JSON format. To do this add an id to the step:
```yaml
- - name: TICS GitHub Action
- id: tics-github-action
- uses: tiobe/tics-github-action@v3
- with:
- mode: diagnostic
- viewerUrl: https://domain.com/tiobeweb/TICS/api/cfg?name=config
- ticsAuthToken: ${{ secrets.TICSAUTHTOKEN }}
- installTics: true
+- name: TICS GitHub Action
+ id: tics-github-action
+ uses: tiobe/tics-github-action@v3
+ with:
+ mode: diagnostic
+ viewerUrl: https://domain.com/tiobeweb/TICS/api/cfg?name=config
+ ticsAuthToken: ${{ secrets.TICSAUTHTOKEN }}
+ installTics: true
```
This can then be used in following steps with `{{ steps.tics-github-action.outputs.annotations }}`.
diff --git a/action.yaml b/action.yaml
index d58e59f8..8c9b28da 100644
--- a/action.yaml
+++ b/action.yaml
@@ -82,9 +82,13 @@ inputs:
description: Comma-seperated list of extra secrets to mask in the console output.
required: false
showBlockingAfter:
- description: Show the blocking after violations in the changed files window. Options are `true` or `false` (default is `true`).
+ description: (deprecated) !Will not be used if `showAnnotationSeverity` is set! Show the blocking after TICS violations in the changed files window (will also show up in `outputs.annotations`). Options are `true` or `false` (default is `true`).
required: false
default: true
+ deprecationMessage: This input parameter is deprecated in favor of `showAnnotationSeverity`.
+ showAnnotationSeverity:
+ description: Show TICS violations with at least the specified severity in the changed files window (will also show up in `outputs.annotations`). Options are `blocking`, `blocking-after` or `issue` (default is `blocking-after`).
+ required: false
ticsAuthToken:
description: Authentication token to authorize the plugin when it connects to the TICS Viewer.
required: false
diff --git a/dist/index.js b/dist/index.js
index 5d5ee19b..4b40b142 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -56,7 +56,7 @@ async function decorateAction(analysisResult, analysis) {
await (0, pull_request_1.decoratePullRequest)(analysisResult?.passed ?? false, summaryBody);
}
if (analysisResult && config_1.actionConfig.postAnnotations) {
- (0, annotations_1.postAnnotations)(analysisResult.projectResults);
+ await (0, annotations_1.postAnnotations)(analysisResult.projectResults);
}
}
@@ -509,10 +509,23 @@ function createUnpostableAnnotationsDetails(unpostableAnnotations) {
unpostableAnnotations.forEach(reviewComment => {
const path = reviewComment.path;
const displayCount = reviewComment.displayCount ?? '';
- const icon = reviewComment.blocking?.state === 'after' ? ':warning:' : ':x:';
- const blocking = reviewComment.blocking?.state === 'after' && reviewComment.blocking.after
- ? `Blocking after ${(0, date_fns_1.format)(reviewComment.blocking.after, 'yyyy-MM-dd')}`
- : 'Blocking';
+ let icon = '';
+ let blocking = '';
+ switch (reviewComment.blocking?.state) {
+ case 'no':
+ icon = ':beetle:';
+ blocking = 'Non-Blocking';
+ break;
+ case 'after':
+ icon = ':warning:';
+ blocking = `Blocking after${reviewComment.blocking.after ? ` ${(0, date_fns_1.format)(reviewComment.blocking.after, 'yyyy-MM-dd')}` : ''}`;
+ break;
+ case 'yes':
+ default:
+ icon = ':x:';
+ blocking = 'Blocking';
+ break;
+ }
if (previousPath === '') {
body += `
| ${path} |
`;
}
@@ -874,10 +887,47 @@ async function getAnalysisResult(date) {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.ActionConfiguration = void 0;
+exports.ActionConfiguration = exports.ShowAnnotationSeverity = void 0;
const os_1 = __nccwpck_require__(70857);
const core_1 = __nccwpck_require__(37484);
const logger_1 = __nccwpck_require__(66113);
+class ShowAnnotationSeverity {
+ param;
+ severities;
+ blockingStates;
+ static BLOCKING = new ShowAnnotationSeverity('blocking', ['blocking'], ['yes']);
+ static AFTER = new ShowAnnotationSeverity('blocking-after', ['blocking', 'after'], ['yes', 'after']);
+ static ISSUE = new ShowAnnotationSeverity('issue', ['blocking', 'after', 'issue'], ['yes', 'after', 'no']);
+ constructor(param, severities, blockingStates) {
+ this.param = param;
+ this.severities = severities;
+ this.blockingStates = blockingStates;
+ }
+ static parse(input) {
+ const severity = input.toLowerCase();
+ switch (severity) {
+ case this.BLOCKING.param:
+ return this.BLOCKING;
+ case this.AFTER.param:
+ return this.AFTER;
+ case this.ISSUE.param:
+ return this.ISSUE;
+ }
+ throw Error(`Parameter 'showAnnotationSeverity' should be one of 'blocking', 'blocking-after' or 'issue'. Input given is '${input}'`);
+ }
+ getAnnotationSeverityFilter() {
+ if (this.severities.length > 1) {
+ return `AnnotationSeverity(Set(${this.severities.join(',')}))`;
+ }
+ else {
+ return `AnnotationSeverity(${this.severities[0]})`;
+ }
+ }
+ shouldPostAnnotation(annotation) {
+ return annotation.postable && (annotation.blocking?.state === undefined || this.blockingStates.includes(annotation.blocking.state));
+ }
+}
+exports.ShowAnnotationSeverity = ShowAnnotationSeverity;
class ActionConfiguration {
excludeMovedFiles;
postAnnotations;
@@ -885,7 +935,7 @@ class ActionConfiguration {
pullRequestApproval;
retryConfig;
secretsFilter;
- showBlockingAfter;
+ showAnnotationSeverity;
constructor() {
this.excludeMovedFiles = (0, core_1.getBooleanInput)('excludeMovedFiles');
this.postAnnotations = (0, core_1.getBooleanInput)('postAnnotations');
@@ -893,7 +943,7 @@ class ActionConfiguration {
this.pullRequestApproval = (0, core_1.getBooleanInput)('pullRequestApproval');
this.retryConfig = this.validateAndGetRetryConfig((0, core_1.getInput)('retryCodes'));
this.secretsFilter = this.getSecretsFilter((0, core_1.getInput)('secretsFilter'));
- this.showBlockingAfter = (0, core_1.getBooleanInput)('showBlockingAfter');
+ this.showAnnotationSeverity = this.getAnnotationSeverity((0, core_1.getInput)('showAnnotationSeverity'), (0, core_1.getBooleanInput)('showBlockingAfter'));
}
/**
* Validates if the given input are valid retry codes and returns them.
@@ -938,6 +988,19 @@ class ActionConfiguration {
logger_1.logger.setSecretsFilter(combinedFilters);
return combinedFilters;
}
+ getAnnotationSeverity(input, blockingAfter) {
+ // `showAnnotationSeverity` takes precedent over `blockingAfter`, which is deprecated.
+ if (input !== '') {
+ return ShowAnnotationSeverity.parse(input);
+ }
+ else {
+ // if `showAnnotationSeverity` is not set use the value of `blockingAfter` to set a level.
+ if (!blockingAfter) {
+ return ShowAnnotationSeverity.BLOCKING;
+ }
+ return ShowAnnotationSeverity.AFTER;
+ }
+ }
}
exports.ActionConfiguration = ActionConfiguration;
@@ -1004,7 +1067,10 @@ class GithubConfig {
apiUrl;
owner;
reponame;
- commitSha;
+ // Sha of the (merge) commit
+ sha;
+ // Sha of the (underlying) commit that triggered the flow
+ headSha;
event;
job;
action;
@@ -1020,8 +1086,9 @@ class GithubConfig {
this.apiUrl = github_1.context.apiUrl;
this.owner = github_1.context.repo.owner;
this.reponame = github_1.context.repo.repo;
- this.commitSha = github_1.context.sha;
+ this.sha = github_1.context.sha;
this.event = this.getGithubEvent();
+ this.headSha = this.getHeadSha();
this.job = github_1.context.job.replace(/[\s|_]+/g, '-');
this.action = github_1.context.action.replace('__tiobe_', '');
this.workflow = github_1.context.workflow.replace(/[\s|_]+/g, '-');
@@ -1073,6 +1140,17 @@ class GithubConfig {
return github_event_1.GithubEvent.PUSH;
}
}
+ getHeadSha() {
+ // Should run after getGithubEvent
+ if (this.event.isPullRequest) {
+ const pr = github_1.context.payload.pull_request;
+ logger_1.logger.debug(`Found pull_request.head.sha: ${pr?.head?.sha ?? 'undefined'}`);
+ return pr?.head?.sha;
+ }
+ else {
+ return github_1.context.sha;
+ }
+ }
getCommentIdentifier() {
return [this.workflow, this.job, this.runNumber, this.runAttempt].join('_');
}
@@ -1446,39 +1524,97 @@ async function getPostedReviewComments() {
* Deletes the review comments of previous runs.
* @param postedReviewComments Previously posted review comments.
*/
-function postAnnotations(projectResults) {
+async function postAnnotations(projectResults) {
logger_1.logger.header('Posting annotations.');
- projectResults.forEach(projectResult => {
- projectResult.annotations.forEach(annotation => {
- if (annotation.postable) {
- const title = annotation.msg;
- const body = createReviewCommentBody(annotation);
- if (annotation.blocking?.state === undefined || annotation.blocking.state === 'yes') {
- logger_1.logger.warning(body, {
- file: annotation.path,
- startLine: annotation.line,
- title: title
- });
- }
- else if (annotation.blocking.state === 'after' && config_1.actionConfig.showBlockingAfter) {
- logger_1.logger.notice(body, {
- file: annotation.path,
- startLine: annotation.line,
- title: title
- });
+ if (!config_1.githubConfig.headSha) {
+ logger_1.logger.warning('Commit of underlying commit not found, cannot post annotations');
+ return;
+ }
+ const batchSize = 50;
+ const annotations = projectResults
+ .flatMap(projectResult => projectResult.annotations)
+ .filter(annotation => config_1.actionConfig.showAnnotationSeverity.shouldPostAnnotation(annotation))
+ .map(createGithubAnnotation);
+ if (annotations.length === 0) {
+ logger_1.logger.info('No annotations to post.');
+ return;
+ }
+ let checkRunId = 0;
+ for (let i = 0; i < annotations.length; i += batchSize) {
+ const params = {
+ owner: config_1.githubConfig.owner,
+ repo: config_1.githubConfig.reponame,
+ output: {
+ title: 'TICS annotations',
+ summary: '',
+ annotations: annotations.slice(i, i + batchSize)
+ }
+ };
+ try {
+ if (i === 0) {
+ const pars = {
+ ...params,
+ head_sha: config_1.githubConfig.headSha,
+ name: 'TICS annotations',
+ conclusion: i + batchSize >= annotations.length ? 'success' : undefined,
+ status: i + batchSize >= annotations.length ? undefined : 'in_progress'
+ };
+ logger_1.logger.debug('Creating check run with: ' + JSON.stringify(pars));
+ const response = await octokit_1.octokit.rest.checks.create(pars);
+ checkRunId = response.data.id;
+ }
+ else {
+ const pars = { ...params, check_run_id: checkRunId };
+ if (i + batchSize >= annotations.length) {
+ pars.conclusion = 'success';
}
+ logger_1.logger.debug('Updating check run with: ' + JSON.stringify(pars));
+ await octokit_1.octokit.rest.checks.update(pars);
}
- });
- });
- logger_1.logger.info('Posted all postable annotations (none if there are no violations).');
+ }
+ catch (error) {
+ const message = (0, response_1.handleOctokitError)(error);
+ logger_1.logger.notice(`Could not post (some) annotations: ${message}`);
+ }
+ }
+ logger_1.logger.info('Posted all postable annotations');
}
-function createReviewCommentBody(annotation) {
- let body = '';
- if (annotation.blocking?.state === 'yes') {
- body += `Blocking`;
+function createGithubAnnotation(annotation) {
+ const title = annotation.msg;
+ const body = createReviewCommentBody(annotation);
+ let level;
+ switch (annotation.blocking?.state) {
+ case 'no':
+ case 'after':
+ level = 'notice';
+ break;
+ case 'yes':
+ default:
+ level = 'warning';
+ break;
}
- else if (annotation.blocking?.state === 'after' && annotation.blocking.after) {
- body += `Blocking after: ${(0, date_fns_1.format)(annotation.blocking.after, 'yyyy-MM-dd')}`;
+ return {
+ title: title,
+ message: body,
+ annotation_level: level,
+ path: annotation.path,
+ start_line: annotation.line,
+ end_line: annotation.line
+ };
+}
+function createReviewCommentBody(annotation) {
+ let body;
+ switch (annotation.blocking?.state) {
+ case 'no':
+ body = 'Non-Blocking';
+ break;
+ case 'after':
+ body = `Blocking after${annotation.blocking.after ? ` ${(0, date_fns_1.format)(annotation.blocking.after, 'yyyy-MM-dd')}` : ''}`;
+ break;
+ case 'yes':
+ default:
+ body = 'Blocking';
+ break;
}
const secondLine = [];
if (annotation.level) {
@@ -1755,7 +1891,7 @@ async function getChangedFilesOfCommit() {
const params = {
owner: config_1.githubConfig.owner,
repo: config_1.githubConfig.reponame,
- ref: config_1.githubConfig.commitSha
+ ref: config_1.githubConfig.sha
};
let response = [];
try {
@@ -2530,7 +2666,7 @@ async function buildRunCommand(fileListPath) {
}
}
else if ((0, os_1.platform)() === 'linux') {
- installCommand = `TICS='${config_1.ticsConfig.viewerUrl}';`;
+ installCommand = `TICS='${config_1.ticsConfig.viewerUrl}'`;
}
else {
installCommand = `$env:TICS='${config_1.ticsConfig.viewerUrl}'`;
@@ -2766,7 +2902,7 @@ async function fetchAnnotationsWithApiLinks(apiLinks) {
}
async function fetchAnnotationsByRun(identifier) {
const annotationsUrl = new URL(`${config_1.ticsConfig.baseUrl}/api/public/v1/Annotations?metric=QualityGate()`);
- let filters = `Project(${identifier.project}),AnnotationSeverity(Set(blocking,after))`;
+ let filters = `Project(${identifier.project}),${config_1.actionConfig.showAnnotationSeverity.getAnnotationSeverityFilter()}`;
if (identifier.cdtoken) {
filters += `,ClientData(${identifier.cdtoken})`;
}
@@ -135074,457 +135210,457 @@ function copy (src) {
/***/ 61860:
/***/ ((module) => {
-/******************************************************************************
-Copyright (c) Microsoft Corporation.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-***************************************************************************** */
-/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */
-var __extends;
-var __assign;
-var __rest;
-var __decorate;
-var __param;
-var __esDecorate;
-var __runInitializers;
-var __propKey;
-var __setFunctionName;
-var __metadata;
-var __awaiter;
-var __generator;
-var __exportStar;
-var __values;
-var __read;
-var __spread;
-var __spreadArrays;
-var __spreadArray;
-var __await;
-var __asyncGenerator;
-var __asyncDelegator;
-var __asyncValues;
-var __makeTemplateObject;
-var __importStar;
-var __importDefault;
-var __classPrivateFieldGet;
-var __classPrivateFieldSet;
-var __classPrivateFieldIn;
-var __createBinding;
-var __addDisposableResource;
-var __disposeResources;
-var __rewriteRelativeImportExtension;
-(function (factory) {
- var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {};
- if (typeof define === "function" && define.amd) {
- define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); });
- }
- else if ( true && typeof module.exports === "object") {
- factory(createExporter(root, createExporter(module.exports)));
- }
- else {
- factory(createExporter(root));
- }
- function createExporter(exports, previous) {
- if (exports !== root) {
- if (typeof Object.create === "function") {
- Object.defineProperty(exports, "__esModule", { value: true });
- }
- else {
- exports.__esModule = true;
- }
- }
- return function (id, v) { return exports[id] = previous ? previous(id, v) : v; };
- }
-})
-(function (exporter) {
- var extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
-
- __extends = function (d, b) {
- if (typeof b !== "function" && b !== null)
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- };
-
- __assign = Object.assign || function (t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
- }
- return t;
- };
-
- __rest = function (s, e) {
- var t = {};
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
- t[p] = s[p];
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
- t[p[i]] = s[p[i]];
- }
- return t;
- };
-
- __decorate = function (decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- };
-
- __param = function (paramIndex, decorator) {
- return function (target, key) { decorator(target, key, paramIndex); }
- };
-
- __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
- var _, done = false;
- for (var i = decorators.length - 1; i >= 0; i--) {
- var context = {};
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
- if (kind === "accessor") {
- if (result === void 0) continue;
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
- if (_ = accept(result.get)) descriptor.get = _;
- if (_ = accept(result.set)) descriptor.set = _;
- if (_ = accept(result.init)) initializers.unshift(_);
- }
- else if (_ = accept(result)) {
- if (kind === "field") initializers.unshift(_);
- else descriptor[key] = _;
- }
- }
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
- done = true;
- };
-
- __runInitializers = function (thisArg, initializers, value) {
- var useValue = arguments.length > 2;
- for (var i = 0; i < initializers.length; i++) {
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
- }
- return useValue ? value : void 0;
- };
-
- __propKey = function (x) {
- return typeof x === "symbol" ? x : "".concat(x);
- };
-
- __setFunctionName = function (f, name, prefix) {
- if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
- return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
- };
-
- __metadata = function (metadataKey, metadataValue) {
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
- };
-
- __awaiter = function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
-
- __generator = function (thisArg, body) {
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
- function verb(n) { return function (v) { return step([n, v]); }; }
- function step(op) {
- if (f) throw new TypeError("Generator is already executing.");
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
- if (y = 0, t) op = [op[0] & 2, t.value];
- switch (op[0]) {
- case 0: case 1: t = op; break;
- case 4: _.label++; return { value: op[1], done: false };
- case 5: _.label++; y = op[1]; op = [0]; continue;
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
- default:
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
- if (t[2]) _.ops.pop();
- _.trys.pop(); continue;
- }
- op = body.call(thisArg, _);
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
- }
- };
-
- __exportStar = function(m, o) {
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
- };
-
- __createBinding = Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
- }) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
- });
-
- __values = function (o) {
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
- if (m) return m.call(o);
- if (o && typeof o.length === "number") return {
- next: function () {
- if (o && i >= o.length) o = void 0;
- return { value: o && o[i++], done: !o };
- }
- };
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
- };
-
- __read = function (o, n) {
- var m = typeof Symbol === "function" && o[Symbol.iterator];
- if (!m) return o;
- var i = m.call(o), r, ar = [], e;
- try {
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
- }
- catch (error) { e = { error: error }; }
- finally {
- try {
- if (r && !r.done && (m = i["return"])) m.call(i);
- }
- finally { if (e) throw e.error; }
- }
- return ar;
- };
-
- /** @deprecated */
- __spread = function () {
- for (var ar = [], i = 0; i < arguments.length; i++)
- ar = ar.concat(__read(arguments[i]));
- return ar;
- };
-
- /** @deprecated */
- __spreadArrays = function () {
- for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
- for (var r = Array(s), k = 0, i = 0; i < il; i++)
- for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
- r[k] = a[j];
- return r;
- };
-
- __spreadArray = function (to, from, pack) {
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
- if (ar || !(i in from)) {
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
- ar[i] = from[i];
- }
- }
- return to.concat(ar || Array.prototype.slice.call(from));
- };
-
- __await = function (v) {
- return this instanceof __await ? (this.v = v, this) : new __await(v);
- };
-
- __asyncGenerator = function (thisArg, _arguments, generator) {
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
- return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
- function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
- function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
- function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
- function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
- function fulfill(value) { resume("next", value); }
- function reject(value) { resume("throw", value); }
- function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
- };
-
- __asyncDelegator = function (o) {
- var i, p;
- return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
- function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
- };
-
- __asyncValues = function (o) {
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
- var m = o[Symbol.asyncIterator], i;
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
- };
-
- __makeTemplateObject = function (cooked, raw) {
- if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
- return cooked;
- };
-
- var __setModuleDefault = Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
- }) : function(o, v) {
- o["default"] = v;
- };
-
- var ownKeys = function(o) {
- ownKeys = Object.getOwnPropertyNames || function (o) {
- var ar = [];
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
- return ar;
- };
- return ownKeys(o);
- };
-
- __importStar = function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
- __setModuleDefault(result, mod);
- return result;
- };
-
- __importDefault = function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
-
- __classPrivateFieldGet = function (receiver, state, kind, f) {
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
- };
-
- __classPrivateFieldSet = function (receiver, state, value, kind, f) {
- if (kind === "m") throw new TypeError("Private method is not writable");
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
- };
-
- __classPrivateFieldIn = function (state, receiver) {
- if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
- return typeof state === "function" ? receiver === state : state.has(receiver);
- };
-
- __addDisposableResource = function (env, value, async) {
- if (value !== null && value !== void 0) {
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
- var dispose, inner;
- if (async) {
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
- dispose = value[Symbol.asyncDispose];
- }
- if (dispose === void 0) {
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
- dispose = value[Symbol.dispose];
- if (async) inner = dispose;
- }
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
- env.stack.push({ value: value, dispose: dispose, async: async });
- }
- else if (async) {
- env.stack.push({ async: true });
- }
- return value;
- };
-
- var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
- var e = new Error(message);
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
- };
-
- __disposeResources = function (env) {
- function fail(e) {
- env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
- env.hasError = true;
- }
- var r, s = 0;
- function next() {
- while (r = env.stack.pop()) {
- try {
- if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
- if (r.dispose) {
- var result = r.dispose.call(r.value);
- if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
- }
- else s |= 1;
- }
- catch (e) {
- fail(e);
- }
- }
- if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
- if (env.hasError) throw env.error;
- }
- return next();
- };
-
- __rewriteRelativeImportExtension = function (path, preserveJsx) {
- if (typeof path === "string" && /^\.\.?\//.test(path)) {
- return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
- return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
- });
- }
- return path;
- };
-
- exporter("__extends", __extends);
- exporter("__assign", __assign);
- exporter("__rest", __rest);
- exporter("__decorate", __decorate);
- exporter("__param", __param);
- exporter("__esDecorate", __esDecorate);
- exporter("__runInitializers", __runInitializers);
- exporter("__propKey", __propKey);
- exporter("__setFunctionName", __setFunctionName);
- exporter("__metadata", __metadata);
- exporter("__awaiter", __awaiter);
- exporter("__generator", __generator);
- exporter("__exportStar", __exportStar);
- exporter("__createBinding", __createBinding);
- exporter("__values", __values);
- exporter("__read", __read);
- exporter("__spread", __spread);
- exporter("__spreadArrays", __spreadArrays);
- exporter("__spreadArray", __spreadArray);
- exporter("__await", __await);
- exporter("__asyncGenerator", __asyncGenerator);
- exporter("__asyncDelegator", __asyncDelegator);
- exporter("__asyncValues", __asyncValues);
- exporter("__makeTemplateObject", __makeTemplateObject);
- exporter("__importStar", __importStar);
- exporter("__importDefault", __importDefault);
- exporter("__classPrivateFieldGet", __classPrivateFieldGet);
- exporter("__classPrivateFieldSet", __classPrivateFieldSet);
- exporter("__classPrivateFieldIn", __classPrivateFieldIn);
- exporter("__addDisposableResource", __addDisposableResource);
- exporter("__disposeResources", __disposeResources);
- exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension);
-});
-
-0 && (0);
+/******************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
+/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */
+var __extends;
+var __assign;
+var __rest;
+var __decorate;
+var __param;
+var __esDecorate;
+var __runInitializers;
+var __propKey;
+var __setFunctionName;
+var __metadata;
+var __awaiter;
+var __generator;
+var __exportStar;
+var __values;
+var __read;
+var __spread;
+var __spreadArrays;
+var __spreadArray;
+var __await;
+var __asyncGenerator;
+var __asyncDelegator;
+var __asyncValues;
+var __makeTemplateObject;
+var __importStar;
+var __importDefault;
+var __classPrivateFieldGet;
+var __classPrivateFieldSet;
+var __classPrivateFieldIn;
+var __createBinding;
+var __addDisposableResource;
+var __disposeResources;
+var __rewriteRelativeImportExtension;
+(function (factory) {
+ var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {};
+ if (typeof define === "function" && define.amd) {
+ define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); });
+ }
+ else if ( true && typeof module.exports === "object") {
+ factory(createExporter(root, createExporter(module.exports)));
+ }
+ else {
+ factory(createExporter(root));
+ }
+ function createExporter(exports, previous) {
+ if (exports !== root) {
+ if (typeof Object.create === "function") {
+ Object.defineProperty(exports, "__esModule", { value: true });
+ }
+ else {
+ exports.__esModule = true;
+ }
+ }
+ return function (id, v) { return exports[id] = previous ? previous(id, v) : v; };
+ }
+})
+(function (exporter) {
+ var extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+
+ __extends = function (d, b) {
+ if (typeof b !== "function" && b !== null)
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ };
+
+ __assign = Object.assign || function (t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+ }
+ return t;
+ };
+
+ __rest = function (s, e) {
+ var t = {};
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
+ t[p] = s[p];
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
+ t[p[i]] = s[p[i]];
+ }
+ return t;
+ };
+
+ __decorate = function (decorators, target, key, desc) {
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
+ };
+
+ __param = function (paramIndex, decorator) {
+ return function (target, key) { decorator(target, key, paramIndex); }
+ };
+
+ __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
+ var _, done = false;
+ for (var i = decorators.length - 1; i >= 0; i--) {
+ var context = {};
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
+ if (kind === "accessor") {
+ if (result === void 0) continue;
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
+ if (_ = accept(result.get)) descriptor.get = _;
+ if (_ = accept(result.set)) descriptor.set = _;
+ if (_ = accept(result.init)) initializers.unshift(_);
+ }
+ else if (_ = accept(result)) {
+ if (kind === "field") initializers.unshift(_);
+ else descriptor[key] = _;
+ }
+ }
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
+ done = true;
+ };
+
+ __runInitializers = function (thisArg, initializers, value) {
+ var useValue = arguments.length > 2;
+ for (var i = 0; i < initializers.length; i++) {
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
+ }
+ return useValue ? value : void 0;
+ };
+
+ __propKey = function (x) {
+ return typeof x === "symbol" ? x : "".concat(x);
+ };
+
+ __setFunctionName = function (f, name, prefix) {
+ if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
+ return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
+ };
+
+ __metadata = function (metadataKey, metadataValue) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
+ };
+
+ __awaiter = function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+ };
+
+ __generator = function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+ };
+
+ __exportStar = function(m, o) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
+ };
+
+ __createBinding = Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+ }) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+ });
+
+ __values = function (o) {
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
+ if (m) return m.call(o);
+ if (o && typeof o.length === "number") return {
+ next: function () {
+ if (o && i >= o.length) o = void 0;
+ return { value: o && o[i++], done: !o };
+ }
+ };
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
+ };
+
+ __read = function (o, n) {
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
+ if (!m) return o;
+ var i = m.call(o), r, ar = [], e;
+ try {
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
+ }
+ catch (error) { e = { error: error }; }
+ finally {
+ try {
+ if (r && !r.done && (m = i["return"])) m.call(i);
+ }
+ finally { if (e) throw e.error; }
+ }
+ return ar;
+ };
+
+ /** @deprecated */
+ __spread = function () {
+ for (var ar = [], i = 0; i < arguments.length; i++)
+ ar = ar.concat(__read(arguments[i]));
+ return ar;
+ };
+
+ /** @deprecated */
+ __spreadArrays = function () {
+ for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
+ for (var r = Array(s), k = 0, i = 0; i < il; i++)
+ for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
+ r[k] = a[j];
+ return r;
+ };
+
+ __spreadArray = function (to, from, pack) {
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
+ if (ar || !(i in from)) {
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
+ ar[i] = from[i];
+ }
+ }
+ return to.concat(ar || Array.prototype.slice.call(from));
+ };
+
+ __await = function (v) {
+ return this instanceof __await ? (this.v = v, this) : new __await(v);
+ };
+
+ __asyncGenerator = function (thisArg, _arguments, generator) {
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
+ function fulfill(value) { resume("next", value); }
+ function reject(value) { resume("throw", value); }
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
+ };
+
+ __asyncDelegator = function (o) {
+ var i, p;
+ return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
+ function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
+ };
+
+ __asyncValues = function (o) {
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
+ var m = o[Symbol.asyncIterator], i;
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
+ };
+
+ __makeTemplateObject = function (cooked, raw) {
+ if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
+ return cooked;
+ };
+
+ var __setModuleDefault = Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+ }) : function(o, v) {
+ o["default"] = v;
+ };
+
+ var ownKeys = function(o) {
+ ownKeys = Object.getOwnPropertyNames || function (o) {
+ var ar = [];
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
+ return ar;
+ };
+ return ownKeys(o);
+ };
+
+ __importStar = function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
+ __setModuleDefault(result, mod);
+ return result;
+ };
+
+ __importDefault = function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+ };
+
+ __classPrivateFieldGet = function (receiver, state, kind, f) {
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
+ };
+
+ __classPrivateFieldSet = function (receiver, state, value, kind, f) {
+ if (kind === "m") throw new TypeError("Private method is not writable");
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
+ };
+
+ __classPrivateFieldIn = function (state, receiver) {
+ if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
+ return typeof state === "function" ? receiver === state : state.has(receiver);
+ };
+
+ __addDisposableResource = function (env, value, async) {
+ if (value !== null && value !== void 0) {
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
+ var dispose, inner;
+ if (async) {
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
+ dispose = value[Symbol.asyncDispose];
+ }
+ if (dispose === void 0) {
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
+ dispose = value[Symbol.dispose];
+ if (async) inner = dispose;
+ }
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
+ env.stack.push({ value: value, dispose: dispose, async: async });
+ }
+ else if (async) {
+ env.stack.push({ async: true });
+ }
+ return value;
+ };
+
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
+ var e = new Error(message);
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
+ };
+
+ __disposeResources = function (env) {
+ function fail(e) {
+ env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
+ env.hasError = true;
+ }
+ var r, s = 0;
+ function next() {
+ while (r = env.stack.pop()) {
+ try {
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
+ if (r.dispose) {
+ var result = r.dispose.call(r.value);
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
+ }
+ else s |= 1;
+ }
+ catch (e) {
+ fail(e);
+ }
+ }
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
+ if (env.hasError) throw env.error;
+ }
+ return next();
+ };
+
+ __rewriteRelativeImportExtension = function (path, preserveJsx) {
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
+ });
+ }
+ return path;
+ };
+
+ exporter("__extends", __extends);
+ exporter("__assign", __assign);
+ exporter("__rest", __rest);
+ exporter("__decorate", __decorate);
+ exporter("__param", __param);
+ exporter("__esDecorate", __esDecorate);
+ exporter("__runInitializers", __runInitializers);
+ exporter("__propKey", __propKey);
+ exporter("__setFunctionName", __setFunctionName);
+ exporter("__metadata", __metadata);
+ exporter("__awaiter", __awaiter);
+ exporter("__generator", __generator);
+ exporter("__exportStar", __exportStar);
+ exporter("__createBinding", __createBinding);
+ exporter("__values", __values);
+ exporter("__read", __read);
+ exporter("__spread", __spread);
+ exporter("__spreadArrays", __spreadArrays);
+ exporter("__spreadArray", __spreadArray);
+ exporter("__await", __await);
+ exporter("__asyncGenerator", __asyncGenerator);
+ exporter("__asyncDelegator", __asyncDelegator);
+ exporter("__asyncValues", __asyncValues);
+ exporter("__makeTemplateObject", __makeTemplateObject);
+ exporter("__importStar", __importStar);
+ exporter("__importDefault", __importDefault);
+ exporter("__classPrivateFieldGet", __classPrivateFieldGet);
+ exporter("__classPrivateFieldSet", __classPrivateFieldSet);
+ exporter("__classPrivateFieldIn", __classPrivateFieldIn);
+ exporter("__addDisposableResource", __addDisposableResource);
+ exporter("__disposeResources", __disposeResources);
+ exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension);
+});
+
+0 && (0);
/***/ }),
@@ -159699,1303 +159835,1303 @@ exports.parseURL = __nccwpck_require__(20905).parseURL;
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
"use strict";
-
-const punycode = __nccwpck_require__(24876);
-const tr46 = __nccwpck_require__(1552);
-
-const specialSchemes = {
- ftp: 21,
- file: null,
- gopher: 70,
- http: 80,
- https: 443,
- ws: 80,
- wss: 443
-};
-
-const failure = Symbol("failure");
-
-function countSymbols(str) {
- return punycode.ucs2.decode(str).length;
-}
-
-function at(input, idx) {
- const c = input[idx];
- return isNaN(c) ? undefined : String.fromCodePoint(c);
-}
-
-function isASCIIDigit(c) {
- return c >= 0x30 && c <= 0x39;
-}
-
-function isASCIIAlpha(c) {
- return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
-}
-
-function isASCIIAlphanumeric(c) {
- return isASCIIAlpha(c) || isASCIIDigit(c);
-}
-
-function isASCIIHex(c) {
- return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66);
-}
-
-function isSingleDot(buffer) {
- return buffer === "." || buffer.toLowerCase() === "%2e";
-}
-
-function isDoubleDot(buffer) {
- buffer = buffer.toLowerCase();
- return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e";
-}
-
-function isWindowsDriveLetterCodePoints(cp1, cp2) {
- return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124);
-}
-
-function isWindowsDriveLetterString(string) {
- return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|");
-}
-
-function isNormalizedWindowsDriveLetterString(string) {
- return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":";
-}
-
-function containsForbiddenHostCodePoint(string) {
- return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1;
-}
-
-function containsForbiddenHostCodePointExcludingPercent(string) {
- return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1;
-}
-
-function isSpecialScheme(scheme) {
- return specialSchemes[scheme] !== undefined;
-}
-
-function isSpecial(url) {
- return isSpecialScheme(url.scheme);
-}
-
-function defaultPort(scheme) {
- return specialSchemes[scheme];
-}
-
-function percentEncode(c) {
- let hex = c.toString(16).toUpperCase();
- if (hex.length === 1) {
- hex = "0" + hex;
- }
-
- return "%" + hex;
-}
-
-function utf8PercentEncode(c) {
- const buf = new Buffer(c);
-
- let str = "";
-
- for (let i = 0; i < buf.length; ++i) {
- str += percentEncode(buf[i]);
- }
-
- return str;
-}
-
-function utf8PercentDecode(str) {
- const input = new Buffer(str);
- const output = [];
- for (let i = 0; i < input.length; ++i) {
- if (input[i] !== 37) {
- output.push(input[i]);
- } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) {
- output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16));
- i += 2;
- } else {
- output.push(input[i]);
- }
- }
- return new Buffer(output).toString();
-}
-
-function isC0ControlPercentEncode(c) {
- return c <= 0x1F || c > 0x7E;
-}
-
-const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]);
-function isPathPercentEncode(c) {
- return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c);
-}
-
-const extraUserinfoPercentEncodeSet =
- new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]);
-function isUserinfoPercentEncode(c) {
- return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c);
-}
-
-function percentEncodeChar(c, encodeSetPredicate) {
- const cStr = String.fromCodePoint(c);
-
- if (encodeSetPredicate(c)) {
- return utf8PercentEncode(cStr);
- }
-
- return cStr;
-}
-
-function parseIPv4Number(input) {
- let R = 10;
-
- if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") {
- input = input.substring(2);
- R = 16;
- } else if (input.length >= 2 && input.charAt(0) === "0") {
- input = input.substring(1);
- R = 8;
- }
-
- if (input === "") {
- return 0;
- }
-
- const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/);
- if (regex.test(input)) {
- return failure;
- }
-
- return parseInt(input, R);
-}
-
-function parseIPv4(input) {
- const parts = input.split(".");
- if (parts[parts.length - 1] === "") {
- if (parts.length > 1) {
- parts.pop();
- }
- }
-
- if (parts.length > 4) {
- return input;
- }
-
- const numbers = [];
- for (const part of parts) {
- if (part === "") {
- return input;
- }
- const n = parseIPv4Number(part);
- if (n === failure) {
- return input;
- }
-
- numbers.push(n);
- }
-
- for (let i = 0; i < numbers.length - 1; ++i) {
- if (numbers[i] > 255) {
- return failure;
- }
- }
- if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) {
- return failure;
- }
-
- let ipv4 = numbers.pop();
- let counter = 0;
-
- for (const n of numbers) {
- ipv4 += n * Math.pow(256, 3 - counter);
- ++counter;
- }
-
- return ipv4;
-}
-
-function serializeIPv4(address) {
- let output = "";
- let n = address;
-
- for (let i = 1; i <= 4; ++i) {
- output = String(n % 256) + output;
- if (i !== 4) {
- output = "." + output;
- }
- n = Math.floor(n / 256);
- }
-
- return output;
-}
-
-function parseIPv6(input) {
- const address = [0, 0, 0, 0, 0, 0, 0, 0];
- let pieceIndex = 0;
- let compress = null;
- let pointer = 0;
-
- input = punycode.ucs2.decode(input);
-
- if (input[pointer] === 58) {
- if (input[pointer + 1] !== 58) {
- return failure;
- }
-
- pointer += 2;
- ++pieceIndex;
- compress = pieceIndex;
- }
-
- while (pointer < input.length) {
- if (pieceIndex === 8) {
- return failure;
- }
-
- if (input[pointer] === 58) {
- if (compress !== null) {
- return failure;
- }
- ++pointer;
- ++pieceIndex;
- compress = pieceIndex;
- continue;
- }
-
- let value = 0;
- let length = 0;
-
- while (length < 4 && isASCIIHex(input[pointer])) {
- value = value * 0x10 + parseInt(at(input, pointer), 16);
- ++pointer;
- ++length;
- }
-
- if (input[pointer] === 46) {
- if (length === 0) {
- return failure;
- }
-
- pointer -= length;
-
- if (pieceIndex > 6) {
- return failure;
- }
-
- let numbersSeen = 0;
-
- while (input[pointer] !== undefined) {
- let ipv4Piece = null;
-
- if (numbersSeen > 0) {
- if (input[pointer] === 46 && numbersSeen < 4) {
- ++pointer;
- } else {
- return failure;
- }
- }
-
- if (!isASCIIDigit(input[pointer])) {
- return failure;
- }
-
- while (isASCIIDigit(input[pointer])) {
- const number = parseInt(at(input, pointer));
- if (ipv4Piece === null) {
- ipv4Piece = number;
- } else if (ipv4Piece === 0) {
- return failure;
- } else {
- ipv4Piece = ipv4Piece * 10 + number;
- }
- if (ipv4Piece > 255) {
- return failure;
- }
- ++pointer;
- }
-
- address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece;
-
- ++numbersSeen;
-
- if (numbersSeen === 2 || numbersSeen === 4) {
- ++pieceIndex;
- }
- }
-
- if (numbersSeen !== 4) {
- return failure;
- }
-
- break;
- } else if (input[pointer] === 58) {
- ++pointer;
- if (input[pointer] === undefined) {
- return failure;
- }
- } else if (input[pointer] !== undefined) {
- return failure;
- }
-
- address[pieceIndex] = value;
- ++pieceIndex;
- }
-
- if (compress !== null) {
- let swaps = pieceIndex - compress;
- pieceIndex = 7;
- while (pieceIndex !== 0 && swaps > 0) {
- const temp = address[compress + swaps - 1];
- address[compress + swaps - 1] = address[pieceIndex];
- address[pieceIndex] = temp;
- --pieceIndex;
- --swaps;
- }
- } else if (compress === null && pieceIndex !== 8) {
- return failure;
- }
-
- return address;
-}
-
-function serializeIPv6(address) {
- let output = "";
- const seqResult = findLongestZeroSequence(address);
- const compress = seqResult.idx;
- let ignore0 = false;
-
- for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) {
- if (ignore0 && address[pieceIndex] === 0) {
- continue;
- } else if (ignore0) {
- ignore0 = false;
- }
-
- if (compress === pieceIndex) {
- const separator = pieceIndex === 0 ? "::" : ":";
- output += separator;
- ignore0 = true;
- continue;
- }
-
- output += address[pieceIndex].toString(16);
-
- if (pieceIndex !== 7) {
- output += ":";
- }
- }
-
- return output;
-}
-
-function parseHost(input, isSpecialArg) {
- if (input[0] === "[") {
- if (input[input.length - 1] !== "]") {
- return failure;
- }
-
- return parseIPv6(input.substring(1, input.length - 1));
- }
-
- if (!isSpecialArg) {
- return parseOpaqueHost(input);
- }
-
- const domain = utf8PercentDecode(input);
- const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false);
- if (asciiDomain === null) {
- return failure;
- }
-
- if (containsForbiddenHostCodePoint(asciiDomain)) {
- return failure;
- }
-
- const ipv4Host = parseIPv4(asciiDomain);
- if (typeof ipv4Host === "number" || ipv4Host === failure) {
- return ipv4Host;
- }
-
- return asciiDomain;
-}
-
-function parseOpaqueHost(input) {
- if (containsForbiddenHostCodePointExcludingPercent(input)) {
- return failure;
- }
-
- let output = "";
- const decoded = punycode.ucs2.decode(input);
- for (let i = 0; i < decoded.length; ++i) {
- output += percentEncodeChar(decoded[i], isC0ControlPercentEncode);
- }
- return output;
-}
-
-function findLongestZeroSequence(arr) {
- let maxIdx = null;
- let maxLen = 1; // only find elements > 1
- let currStart = null;
- let currLen = 0;
-
- for (let i = 0; i < arr.length; ++i) {
- if (arr[i] !== 0) {
- if (currLen > maxLen) {
- maxIdx = currStart;
- maxLen = currLen;
- }
-
- currStart = null;
- currLen = 0;
- } else {
- if (currStart === null) {
- currStart = i;
- }
- ++currLen;
- }
- }
-
- // if trailing zeros
- if (currLen > maxLen) {
- maxIdx = currStart;
- maxLen = currLen;
- }
-
- return {
- idx: maxIdx,
- len: maxLen
- };
-}
-
-function serializeHost(host) {
- if (typeof host === "number") {
- return serializeIPv4(host);
- }
-
- // IPv6 serializer
- if (host instanceof Array) {
- return "[" + serializeIPv6(host) + "]";
- }
-
- return host;
-}
-
-function trimControlChars(url) {
- return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, "");
-}
-
-function trimTabAndNewline(url) {
- return url.replace(/\u0009|\u000A|\u000D/g, "");
-}
-
-function shortenPath(url) {
- const path = url.path;
- if (path.length === 0) {
- return;
- }
- if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) {
- return;
- }
-
- path.pop();
-}
-
-function includesCredentials(url) {
- return url.username !== "" || url.password !== "";
-}
-
-function cannotHaveAUsernamePasswordPort(url) {
- return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file";
-}
-
-function isNormalizedWindowsDriveLetter(string) {
- return /^[A-Za-z]:$/.test(string);
-}
-
-function URLStateMachine(input, base, encodingOverride, url, stateOverride) {
- this.pointer = 0;
- this.input = input;
- this.base = base || null;
- this.encodingOverride = encodingOverride || "utf-8";
- this.stateOverride = stateOverride;
- this.url = url;
- this.failure = false;
- this.parseError = false;
-
- if (!this.url) {
- this.url = {
- scheme: "",
- username: "",
- password: "",
- host: null,
- port: null,
- path: [],
- query: null,
- fragment: null,
-
- cannotBeABaseURL: false
- };
-
- const res = trimControlChars(this.input);
- if (res !== this.input) {
- this.parseError = true;
- }
- this.input = res;
- }
-
- const res = trimTabAndNewline(this.input);
- if (res !== this.input) {
- this.parseError = true;
- }
- this.input = res;
-
- this.state = stateOverride || "scheme start";
-
- this.buffer = "";
- this.atFlag = false;
- this.arrFlag = false;
- this.passwordTokenSeenFlag = false;
-
- this.input = punycode.ucs2.decode(this.input);
-
- for (; this.pointer <= this.input.length; ++this.pointer) {
- const c = this.input[this.pointer];
- const cStr = isNaN(c) ? undefined : String.fromCodePoint(c);
-
- // exec state machine
- const ret = this["parse " + this.state](c, cStr);
- if (!ret) {
- break; // terminate algorithm
- } else if (ret === failure) {
- this.failure = true;
- break;
- }
- }
-}
-
-URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) {
- if (isASCIIAlpha(c)) {
- this.buffer += cStr.toLowerCase();
- this.state = "scheme";
- } else if (!this.stateOverride) {
- this.state = "no scheme";
- --this.pointer;
- } else {
- this.parseError = true;
- return failure;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) {
- if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) {
- this.buffer += cStr.toLowerCase();
- } else if (c === 58) {
- if (this.stateOverride) {
- if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) {
- return false;
- }
-
- if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) {
- return false;
- }
-
- if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") {
- return false;
- }
-
- if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) {
- return false;
- }
- }
- this.url.scheme = this.buffer;
- this.buffer = "";
- if (this.stateOverride) {
- return false;
- }
- if (this.url.scheme === "file") {
- if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) {
- this.parseError = true;
- }
- this.state = "file";
- } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) {
- this.state = "special relative or authority";
- } else if (isSpecial(this.url)) {
- this.state = "special authority slashes";
- } else if (this.input[this.pointer + 1] === 47) {
- this.state = "path or authority";
- ++this.pointer;
- } else {
- this.url.cannotBeABaseURL = true;
- this.url.path.push("");
- this.state = "cannot-be-a-base-URL path";
- }
- } else if (!this.stateOverride) {
- this.buffer = "";
- this.state = "no scheme";
- this.pointer = -1;
- } else {
- this.parseError = true;
- return failure;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) {
- if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) {
- return failure;
- } else if (this.base.cannotBeABaseURL && c === 35) {
- this.url.scheme = this.base.scheme;
- this.url.path = this.base.path.slice();
- this.url.query = this.base.query;
- this.url.fragment = "";
- this.url.cannotBeABaseURL = true;
- this.state = "fragment";
- } else if (this.base.scheme === "file") {
- this.state = "file";
- --this.pointer;
- } else {
- this.state = "relative";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) {
- if (c === 47 && this.input[this.pointer + 1] === 47) {
- this.state = "special authority ignore slashes";
- ++this.pointer;
- } else {
- this.parseError = true;
- this.state = "relative";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) {
- if (c === 47) {
- this.state = "authority";
- } else {
- this.state = "path";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse relative"] = function parseRelative(c) {
- this.url.scheme = this.base.scheme;
- if (isNaN(c)) {
- this.url.username = this.base.username;
- this.url.password = this.base.password;
- this.url.host = this.base.host;
- this.url.port = this.base.port;
- this.url.path = this.base.path.slice();
- this.url.query = this.base.query;
- } else if (c === 47) {
- this.state = "relative slash";
- } else if (c === 63) {
- this.url.username = this.base.username;
- this.url.password = this.base.password;
- this.url.host = this.base.host;
- this.url.port = this.base.port;
- this.url.path = this.base.path.slice();
- this.url.query = "";
- this.state = "query";
- } else if (c === 35) {
- this.url.username = this.base.username;
- this.url.password = this.base.password;
- this.url.host = this.base.host;
- this.url.port = this.base.port;
- this.url.path = this.base.path.slice();
- this.url.query = this.base.query;
- this.url.fragment = "";
- this.state = "fragment";
- } else if (isSpecial(this.url) && c === 92) {
- this.parseError = true;
- this.state = "relative slash";
- } else {
- this.url.username = this.base.username;
- this.url.password = this.base.password;
- this.url.host = this.base.host;
- this.url.port = this.base.port;
- this.url.path = this.base.path.slice(0, this.base.path.length - 1);
-
- this.state = "path";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) {
- if (isSpecial(this.url) && (c === 47 || c === 92)) {
- if (c === 92) {
- this.parseError = true;
- }
- this.state = "special authority ignore slashes";
- } else if (c === 47) {
- this.state = "authority";
- } else {
- this.url.username = this.base.username;
- this.url.password = this.base.password;
- this.url.host = this.base.host;
- this.url.port = this.base.port;
- this.state = "path";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) {
- if (c === 47 && this.input[this.pointer + 1] === 47) {
- this.state = "special authority ignore slashes";
- ++this.pointer;
- } else {
- this.parseError = true;
- this.state = "special authority ignore slashes";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) {
- if (c !== 47 && c !== 92) {
- this.state = "authority";
- --this.pointer;
- } else {
- this.parseError = true;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) {
- if (c === 64) {
- this.parseError = true;
- if (this.atFlag) {
- this.buffer = "%40" + this.buffer;
- }
- this.atFlag = true;
-
- // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars
- const len = countSymbols(this.buffer);
- for (let pointer = 0; pointer < len; ++pointer) {
- const codePoint = this.buffer.codePointAt(pointer);
-
- if (codePoint === 58 && !this.passwordTokenSeenFlag) {
- this.passwordTokenSeenFlag = true;
- continue;
- }
- const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode);
- if (this.passwordTokenSeenFlag) {
- this.url.password += encodedCodePoints;
- } else {
- this.url.username += encodedCodePoints;
- }
- }
- this.buffer = "";
- } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
- (isSpecial(this.url) && c === 92)) {
- if (this.atFlag && this.buffer === "") {
- this.parseError = true;
- return failure;
- }
- this.pointer -= countSymbols(this.buffer) + 1;
- this.buffer = "";
- this.state = "host";
- } else {
- this.buffer += cStr;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse hostname"] =
-URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) {
- if (this.stateOverride && this.url.scheme === "file") {
- --this.pointer;
- this.state = "file host";
- } else if (c === 58 && !this.arrFlag) {
- if (this.buffer === "") {
- this.parseError = true;
- return failure;
- }
-
- const host = parseHost(this.buffer, isSpecial(this.url));
- if (host === failure) {
- return failure;
- }
-
- this.url.host = host;
- this.buffer = "";
- this.state = "port";
- if (this.stateOverride === "hostname") {
- return false;
- }
- } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
- (isSpecial(this.url) && c === 92)) {
- --this.pointer;
- if (isSpecial(this.url) && this.buffer === "") {
- this.parseError = true;
- return failure;
- } else if (this.stateOverride && this.buffer === "" &&
- (includesCredentials(this.url) || this.url.port !== null)) {
- this.parseError = true;
- return false;
- }
-
- const host = parseHost(this.buffer, isSpecial(this.url));
- if (host === failure) {
- return failure;
- }
-
- this.url.host = host;
- this.buffer = "";
- this.state = "path start";
- if (this.stateOverride) {
- return false;
- }
- } else {
- if (c === 91) {
- this.arrFlag = true;
- } else if (c === 93) {
- this.arrFlag = false;
- }
- this.buffer += cStr;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) {
- if (isASCIIDigit(c)) {
- this.buffer += cStr;
- } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
- (isSpecial(this.url) && c === 92) ||
- this.stateOverride) {
- if (this.buffer !== "") {
- const port = parseInt(this.buffer);
- if (port > Math.pow(2, 16) - 1) {
- this.parseError = true;
- return failure;
- }
- this.url.port = port === defaultPort(this.url.scheme) ? null : port;
- this.buffer = "";
- }
- if (this.stateOverride) {
- return false;
- }
- this.state = "path start";
- --this.pointer;
- } else {
- this.parseError = true;
- return failure;
- }
-
- return true;
-};
-
-const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]);
-
-URLStateMachine.prototype["parse file"] = function parseFile(c) {
- this.url.scheme = "file";
-
- if (c === 47 || c === 92) {
- if (c === 92) {
- this.parseError = true;
- }
- this.state = "file slash";
- } else if (this.base !== null && this.base.scheme === "file") {
- if (isNaN(c)) {
- this.url.host = this.base.host;
- this.url.path = this.base.path.slice();
- this.url.query = this.base.query;
- } else if (c === 63) {
- this.url.host = this.base.host;
- this.url.path = this.base.path.slice();
- this.url.query = "";
- this.state = "query";
- } else if (c === 35) {
- this.url.host = this.base.host;
- this.url.path = this.base.path.slice();
- this.url.query = this.base.query;
- this.url.fragment = "";
- this.state = "fragment";
- } else {
- if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points
- !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) ||
- (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points
- !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) {
- this.url.host = this.base.host;
- this.url.path = this.base.path.slice();
- shortenPath(this.url);
- } else {
- this.parseError = true;
- }
-
- this.state = "path";
- --this.pointer;
- }
- } else {
- this.state = "path";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) {
- if (c === 47 || c === 92) {
- if (c === 92) {
- this.parseError = true;
- }
- this.state = "file host";
- } else {
- if (this.base !== null && this.base.scheme === "file") {
- if (isNormalizedWindowsDriveLetterString(this.base.path[0])) {
- this.url.path.push(this.base.path[0]);
- } else {
- this.url.host = this.base.host;
- }
- }
- this.state = "path";
- --this.pointer;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) {
- if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) {
- --this.pointer;
- if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) {
- this.parseError = true;
- this.state = "path";
- } else if (this.buffer === "") {
- this.url.host = "";
- if (this.stateOverride) {
- return false;
- }
- this.state = "path start";
- } else {
- let host = parseHost(this.buffer, isSpecial(this.url));
- if (host === failure) {
- return failure;
- }
- if (host === "localhost") {
- host = "";
- }
- this.url.host = host;
-
- if (this.stateOverride) {
- return false;
- }
-
- this.buffer = "";
- this.state = "path start";
- }
- } else {
- this.buffer += cStr;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse path start"] = function parsePathStart(c) {
- if (isSpecial(this.url)) {
- if (c === 92) {
- this.parseError = true;
- }
- this.state = "path";
-
- if (c !== 47 && c !== 92) {
- --this.pointer;
- }
- } else if (!this.stateOverride && c === 63) {
- this.url.query = "";
- this.state = "query";
- } else if (!this.stateOverride && c === 35) {
- this.url.fragment = "";
- this.state = "fragment";
- } else if (c !== undefined) {
- this.state = "path";
- if (c !== 47) {
- --this.pointer;
- }
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse path"] = function parsePath(c) {
- if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) ||
- (!this.stateOverride && (c === 63 || c === 35))) {
- if (isSpecial(this.url) && c === 92) {
- this.parseError = true;
- }
-
- if (isDoubleDot(this.buffer)) {
- shortenPath(this.url);
- if (c !== 47 && !(isSpecial(this.url) && c === 92)) {
- this.url.path.push("");
- }
- } else if (isSingleDot(this.buffer) && c !== 47 &&
- !(isSpecial(this.url) && c === 92)) {
- this.url.path.push("");
- } else if (!isSingleDot(this.buffer)) {
- if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) {
- if (this.url.host !== "" && this.url.host !== null) {
- this.parseError = true;
- this.url.host = "";
- }
- this.buffer = this.buffer[0] + ":";
- }
- this.url.path.push(this.buffer);
- }
- this.buffer = "";
- if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) {
- while (this.url.path.length > 1 && this.url.path[0] === "") {
- this.parseError = true;
- this.url.path.shift();
- }
- }
- if (c === 63) {
- this.url.query = "";
- this.state = "query";
- }
- if (c === 35) {
- this.url.fragment = "";
- this.state = "fragment";
- }
- } else {
- // TODO: If c is not a URL code point and not "%", parse error.
-
- if (c === 37 &&
- (!isASCIIHex(this.input[this.pointer + 1]) ||
- !isASCIIHex(this.input[this.pointer + 2]))) {
- this.parseError = true;
- }
-
- this.buffer += percentEncodeChar(c, isPathPercentEncode);
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) {
- if (c === 63) {
- this.url.query = "";
- this.state = "query";
- } else if (c === 35) {
- this.url.fragment = "";
- this.state = "fragment";
- } else {
- // TODO: Add: not a URL code point
- if (!isNaN(c) && c !== 37) {
- this.parseError = true;
- }
-
- if (c === 37 &&
- (!isASCIIHex(this.input[this.pointer + 1]) ||
- !isASCIIHex(this.input[this.pointer + 2]))) {
- this.parseError = true;
- }
-
- if (!isNaN(c)) {
- this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode);
- }
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) {
- if (isNaN(c) || (!this.stateOverride && c === 35)) {
- if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") {
- this.encodingOverride = "utf-8";
- }
-
- const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead
- for (let i = 0; i < buffer.length; ++i) {
- if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 ||
- buffer[i] === 0x3C || buffer[i] === 0x3E) {
- this.url.query += percentEncode(buffer[i]);
- } else {
- this.url.query += String.fromCodePoint(buffer[i]);
- }
- }
-
- this.buffer = "";
- if (c === 35) {
- this.url.fragment = "";
- this.state = "fragment";
- }
- } else {
- // TODO: If c is not a URL code point and not "%", parse error.
- if (c === 37 &&
- (!isASCIIHex(this.input[this.pointer + 1]) ||
- !isASCIIHex(this.input[this.pointer + 2]))) {
- this.parseError = true;
- }
-
- this.buffer += cStr;
- }
-
- return true;
-};
-
-URLStateMachine.prototype["parse fragment"] = function parseFragment(c) {
- if (isNaN(c)) { // do nothing
- } else if (c === 0x0) {
- this.parseError = true;
- } else {
- // TODO: If c is not a URL code point and not "%", parse error.
- if (c === 37 &&
- (!isASCIIHex(this.input[this.pointer + 1]) ||
- !isASCIIHex(this.input[this.pointer + 2]))) {
- this.parseError = true;
- }
-
- this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode);
- }
-
- return true;
-};
-
-function serializeURL(url, excludeFragment) {
- let output = url.scheme + ":";
- if (url.host !== null) {
- output += "//";
-
- if (url.username !== "" || url.password !== "") {
- output += url.username;
- if (url.password !== "") {
- output += ":" + url.password;
- }
- output += "@";
- }
-
- output += serializeHost(url.host);
-
- if (url.port !== null) {
- output += ":" + url.port;
- }
- } else if (url.host === null && url.scheme === "file") {
- output += "//";
- }
-
- if (url.cannotBeABaseURL) {
- output += url.path[0];
- } else {
- for (const string of url.path) {
- output += "/" + string;
- }
- }
-
- if (url.query !== null) {
- output += "?" + url.query;
- }
-
- if (!excludeFragment && url.fragment !== null) {
- output += "#" + url.fragment;
- }
-
- return output;
-}
-
-function serializeOrigin(tuple) {
- let result = tuple.scheme + "://";
- result += serializeHost(tuple.host);
-
- if (tuple.port !== null) {
- result += ":" + tuple.port;
- }
-
- return result;
-}
-
-module.exports.serializeURL = serializeURL;
-
-module.exports.serializeURLOrigin = function (url) {
- // https://url.spec.whatwg.org/#concept-url-origin
- switch (url.scheme) {
- case "blob":
- try {
- return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0]));
- } catch (e) {
- // serializing an opaque origin returns "null"
- return "null";
- }
- case "ftp":
- case "gopher":
- case "http":
- case "https":
- case "ws":
- case "wss":
- return serializeOrigin({
- scheme: url.scheme,
- host: url.host,
- port: url.port
- });
- case "file":
- // spec says "exercise to the reader", chrome says "file://"
- return "file://";
- default:
- // serializing an opaque origin returns "null"
- return "null";
- }
-};
-
-module.exports.basicURLParse = function (input, options) {
- if (options === undefined) {
- options = {};
- }
-
- const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride);
- if (usm.failure) {
- return "failure";
- }
-
- return usm.url;
-};
-
-module.exports.setTheUsername = function (url, username) {
- url.username = "";
- const decoded = punycode.ucs2.decode(username);
- for (let i = 0; i < decoded.length; ++i) {
- url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
- }
-};
-
-module.exports.setThePassword = function (url, password) {
- url.password = "";
- const decoded = punycode.ucs2.decode(password);
- for (let i = 0; i < decoded.length; ++i) {
- url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
- }
-};
-
-module.exports.serializeHost = serializeHost;
-
-module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort;
-
-module.exports.serializeInteger = function (integer) {
- return String(integer);
-};
-
-module.exports.parseURL = function (input, options) {
- if (options === undefined) {
- options = {};
- }
-
- // We don't handle blobs, so this just delegates:
- return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride });
-};
+
+const punycode = __nccwpck_require__(24876);
+const tr46 = __nccwpck_require__(1552);
+
+const specialSchemes = {
+ ftp: 21,
+ file: null,
+ gopher: 70,
+ http: 80,
+ https: 443,
+ ws: 80,
+ wss: 443
+};
+
+const failure = Symbol("failure");
+
+function countSymbols(str) {
+ return punycode.ucs2.decode(str).length;
+}
+
+function at(input, idx) {
+ const c = input[idx];
+ return isNaN(c) ? undefined : String.fromCodePoint(c);
+}
+
+function isASCIIDigit(c) {
+ return c >= 0x30 && c <= 0x39;
+}
+
+function isASCIIAlpha(c) {
+ return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
+}
+
+function isASCIIAlphanumeric(c) {
+ return isASCIIAlpha(c) || isASCIIDigit(c);
+}
+
+function isASCIIHex(c) {
+ return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66);
+}
+
+function isSingleDot(buffer) {
+ return buffer === "." || buffer.toLowerCase() === "%2e";
+}
+
+function isDoubleDot(buffer) {
+ buffer = buffer.toLowerCase();
+ return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e";
+}
+
+function isWindowsDriveLetterCodePoints(cp1, cp2) {
+ return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124);
+}
+
+function isWindowsDriveLetterString(string) {
+ return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|");
+}
+
+function isNormalizedWindowsDriveLetterString(string) {
+ return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":";
+}
+
+function containsForbiddenHostCodePoint(string) {
+ return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1;
+}
+
+function containsForbiddenHostCodePointExcludingPercent(string) {
+ return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1;
+}
+
+function isSpecialScheme(scheme) {
+ return specialSchemes[scheme] !== undefined;
+}
+
+function isSpecial(url) {
+ return isSpecialScheme(url.scheme);
+}
+
+function defaultPort(scheme) {
+ return specialSchemes[scheme];
+}
+
+function percentEncode(c) {
+ let hex = c.toString(16).toUpperCase();
+ if (hex.length === 1) {
+ hex = "0" + hex;
+ }
+
+ return "%" + hex;
+}
+
+function utf8PercentEncode(c) {
+ const buf = new Buffer(c);
+
+ let str = "";
+
+ for (let i = 0; i < buf.length; ++i) {
+ str += percentEncode(buf[i]);
+ }
+
+ return str;
+}
+
+function utf8PercentDecode(str) {
+ const input = new Buffer(str);
+ const output = [];
+ for (let i = 0; i < input.length; ++i) {
+ if (input[i] !== 37) {
+ output.push(input[i]);
+ } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) {
+ output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16));
+ i += 2;
+ } else {
+ output.push(input[i]);
+ }
+ }
+ return new Buffer(output).toString();
+}
+
+function isC0ControlPercentEncode(c) {
+ return c <= 0x1F || c > 0x7E;
+}
+
+const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]);
+function isPathPercentEncode(c) {
+ return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c);
+}
+
+const extraUserinfoPercentEncodeSet =
+ new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]);
+function isUserinfoPercentEncode(c) {
+ return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c);
+}
+
+function percentEncodeChar(c, encodeSetPredicate) {
+ const cStr = String.fromCodePoint(c);
+
+ if (encodeSetPredicate(c)) {
+ return utf8PercentEncode(cStr);
+ }
+
+ return cStr;
+}
+
+function parseIPv4Number(input) {
+ let R = 10;
+
+ if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") {
+ input = input.substring(2);
+ R = 16;
+ } else if (input.length >= 2 && input.charAt(0) === "0") {
+ input = input.substring(1);
+ R = 8;
+ }
+
+ if (input === "") {
+ return 0;
+ }
+
+ const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/);
+ if (regex.test(input)) {
+ return failure;
+ }
+
+ return parseInt(input, R);
+}
+
+function parseIPv4(input) {
+ const parts = input.split(".");
+ if (parts[parts.length - 1] === "") {
+ if (parts.length > 1) {
+ parts.pop();
+ }
+ }
+
+ if (parts.length > 4) {
+ return input;
+ }
+
+ const numbers = [];
+ for (const part of parts) {
+ if (part === "") {
+ return input;
+ }
+ const n = parseIPv4Number(part);
+ if (n === failure) {
+ return input;
+ }
+
+ numbers.push(n);
+ }
+
+ for (let i = 0; i < numbers.length - 1; ++i) {
+ if (numbers[i] > 255) {
+ return failure;
+ }
+ }
+ if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) {
+ return failure;
+ }
+
+ let ipv4 = numbers.pop();
+ let counter = 0;
+
+ for (const n of numbers) {
+ ipv4 += n * Math.pow(256, 3 - counter);
+ ++counter;
+ }
+
+ return ipv4;
+}
+
+function serializeIPv4(address) {
+ let output = "";
+ let n = address;
+
+ for (let i = 1; i <= 4; ++i) {
+ output = String(n % 256) + output;
+ if (i !== 4) {
+ output = "." + output;
+ }
+ n = Math.floor(n / 256);
+ }
+
+ return output;
+}
+
+function parseIPv6(input) {
+ const address = [0, 0, 0, 0, 0, 0, 0, 0];
+ let pieceIndex = 0;
+ let compress = null;
+ let pointer = 0;
+
+ input = punycode.ucs2.decode(input);
+
+ if (input[pointer] === 58) {
+ if (input[pointer + 1] !== 58) {
+ return failure;
+ }
+
+ pointer += 2;
+ ++pieceIndex;
+ compress = pieceIndex;
+ }
+
+ while (pointer < input.length) {
+ if (pieceIndex === 8) {
+ return failure;
+ }
+
+ if (input[pointer] === 58) {
+ if (compress !== null) {
+ return failure;
+ }
+ ++pointer;
+ ++pieceIndex;
+ compress = pieceIndex;
+ continue;
+ }
+
+ let value = 0;
+ let length = 0;
+
+ while (length < 4 && isASCIIHex(input[pointer])) {
+ value = value * 0x10 + parseInt(at(input, pointer), 16);
+ ++pointer;
+ ++length;
+ }
+
+ if (input[pointer] === 46) {
+ if (length === 0) {
+ return failure;
+ }
+
+ pointer -= length;
+
+ if (pieceIndex > 6) {
+ return failure;
+ }
+
+ let numbersSeen = 0;
+
+ while (input[pointer] !== undefined) {
+ let ipv4Piece = null;
+
+ if (numbersSeen > 0) {
+ if (input[pointer] === 46 && numbersSeen < 4) {
+ ++pointer;
+ } else {
+ return failure;
+ }
+ }
+
+ if (!isASCIIDigit(input[pointer])) {
+ return failure;
+ }
+
+ while (isASCIIDigit(input[pointer])) {
+ const number = parseInt(at(input, pointer));
+ if (ipv4Piece === null) {
+ ipv4Piece = number;
+ } else if (ipv4Piece === 0) {
+ return failure;
+ } else {
+ ipv4Piece = ipv4Piece * 10 + number;
+ }
+ if (ipv4Piece > 255) {
+ return failure;
+ }
+ ++pointer;
+ }
+
+ address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece;
+
+ ++numbersSeen;
+
+ if (numbersSeen === 2 || numbersSeen === 4) {
+ ++pieceIndex;
+ }
+ }
+
+ if (numbersSeen !== 4) {
+ return failure;
+ }
+
+ break;
+ } else if (input[pointer] === 58) {
+ ++pointer;
+ if (input[pointer] === undefined) {
+ return failure;
+ }
+ } else if (input[pointer] !== undefined) {
+ return failure;
+ }
+
+ address[pieceIndex] = value;
+ ++pieceIndex;
+ }
+
+ if (compress !== null) {
+ let swaps = pieceIndex - compress;
+ pieceIndex = 7;
+ while (pieceIndex !== 0 && swaps > 0) {
+ const temp = address[compress + swaps - 1];
+ address[compress + swaps - 1] = address[pieceIndex];
+ address[pieceIndex] = temp;
+ --pieceIndex;
+ --swaps;
+ }
+ } else if (compress === null && pieceIndex !== 8) {
+ return failure;
+ }
+
+ return address;
+}
+
+function serializeIPv6(address) {
+ let output = "";
+ const seqResult = findLongestZeroSequence(address);
+ const compress = seqResult.idx;
+ let ignore0 = false;
+
+ for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) {
+ if (ignore0 && address[pieceIndex] === 0) {
+ continue;
+ } else if (ignore0) {
+ ignore0 = false;
+ }
+
+ if (compress === pieceIndex) {
+ const separator = pieceIndex === 0 ? "::" : ":";
+ output += separator;
+ ignore0 = true;
+ continue;
+ }
+
+ output += address[pieceIndex].toString(16);
+
+ if (pieceIndex !== 7) {
+ output += ":";
+ }
+ }
+
+ return output;
+}
+
+function parseHost(input, isSpecialArg) {
+ if (input[0] === "[") {
+ if (input[input.length - 1] !== "]") {
+ return failure;
+ }
+
+ return parseIPv6(input.substring(1, input.length - 1));
+ }
+
+ if (!isSpecialArg) {
+ return parseOpaqueHost(input);
+ }
+
+ const domain = utf8PercentDecode(input);
+ const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false);
+ if (asciiDomain === null) {
+ return failure;
+ }
+
+ if (containsForbiddenHostCodePoint(asciiDomain)) {
+ return failure;
+ }
+
+ const ipv4Host = parseIPv4(asciiDomain);
+ if (typeof ipv4Host === "number" || ipv4Host === failure) {
+ return ipv4Host;
+ }
+
+ return asciiDomain;
+}
+
+function parseOpaqueHost(input) {
+ if (containsForbiddenHostCodePointExcludingPercent(input)) {
+ return failure;
+ }
+
+ let output = "";
+ const decoded = punycode.ucs2.decode(input);
+ for (let i = 0; i < decoded.length; ++i) {
+ output += percentEncodeChar(decoded[i], isC0ControlPercentEncode);
+ }
+ return output;
+}
+
+function findLongestZeroSequence(arr) {
+ let maxIdx = null;
+ let maxLen = 1; // only find elements > 1
+ let currStart = null;
+ let currLen = 0;
+
+ for (let i = 0; i < arr.length; ++i) {
+ if (arr[i] !== 0) {
+ if (currLen > maxLen) {
+ maxIdx = currStart;
+ maxLen = currLen;
+ }
+
+ currStart = null;
+ currLen = 0;
+ } else {
+ if (currStart === null) {
+ currStart = i;
+ }
+ ++currLen;
+ }
+ }
+
+ // if trailing zeros
+ if (currLen > maxLen) {
+ maxIdx = currStart;
+ maxLen = currLen;
+ }
+
+ return {
+ idx: maxIdx,
+ len: maxLen
+ };
+}
+
+function serializeHost(host) {
+ if (typeof host === "number") {
+ return serializeIPv4(host);
+ }
+
+ // IPv6 serializer
+ if (host instanceof Array) {
+ return "[" + serializeIPv6(host) + "]";
+ }
+
+ return host;
+}
+
+function trimControlChars(url) {
+ return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, "");
+}
+
+function trimTabAndNewline(url) {
+ return url.replace(/\u0009|\u000A|\u000D/g, "");
+}
+
+function shortenPath(url) {
+ const path = url.path;
+ if (path.length === 0) {
+ return;
+ }
+ if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) {
+ return;
+ }
+
+ path.pop();
+}
+
+function includesCredentials(url) {
+ return url.username !== "" || url.password !== "";
+}
+
+function cannotHaveAUsernamePasswordPort(url) {
+ return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file";
+}
+
+function isNormalizedWindowsDriveLetter(string) {
+ return /^[A-Za-z]:$/.test(string);
+}
+
+function URLStateMachine(input, base, encodingOverride, url, stateOverride) {
+ this.pointer = 0;
+ this.input = input;
+ this.base = base || null;
+ this.encodingOverride = encodingOverride || "utf-8";
+ this.stateOverride = stateOverride;
+ this.url = url;
+ this.failure = false;
+ this.parseError = false;
+
+ if (!this.url) {
+ this.url = {
+ scheme: "",
+ username: "",
+ password: "",
+ host: null,
+ port: null,
+ path: [],
+ query: null,
+ fragment: null,
+
+ cannotBeABaseURL: false
+ };
+
+ const res = trimControlChars(this.input);
+ if (res !== this.input) {
+ this.parseError = true;
+ }
+ this.input = res;
+ }
+
+ const res = trimTabAndNewline(this.input);
+ if (res !== this.input) {
+ this.parseError = true;
+ }
+ this.input = res;
+
+ this.state = stateOverride || "scheme start";
+
+ this.buffer = "";
+ this.atFlag = false;
+ this.arrFlag = false;
+ this.passwordTokenSeenFlag = false;
+
+ this.input = punycode.ucs2.decode(this.input);
+
+ for (; this.pointer <= this.input.length; ++this.pointer) {
+ const c = this.input[this.pointer];
+ const cStr = isNaN(c) ? undefined : String.fromCodePoint(c);
+
+ // exec state machine
+ const ret = this["parse " + this.state](c, cStr);
+ if (!ret) {
+ break; // terminate algorithm
+ } else if (ret === failure) {
+ this.failure = true;
+ break;
+ }
+ }
+}
+
+URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) {
+ if (isASCIIAlpha(c)) {
+ this.buffer += cStr.toLowerCase();
+ this.state = "scheme";
+ } else if (!this.stateOverride) {
+ this.state = "no scheme";
+ --this.pointer;
+ } else {
+ this.parseError = true;
+ return failure;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) {
+ if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) {
+ this.buffer += cStr.toLowerCase();
+ } else if (c === 58) {
+ if (this.stateOverride) {
+ if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) {
+ return false;
+ }
+
+ if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) {
+ return false;
+ }
+
+ if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") {
+ return false;
+ }
+
+ if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) {
+ return false;
+ }
+ }
+ this.url.scheme = this.buffer;
+ this.buffer = "";
+ if (this.stateOverride) {
+ return false;
+ }
+ if (this.url.scheme === "file") {
+ if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) {
+ this.parseError = true;
+ }
+ this.state = "file";
+ } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) {
+ this.state = "special relative or authority";
+ } else if (isSpecial(this.url)) {
+ this.state = "special authority slashes";
+ } else if (this.input[this.pointer + 1] === 47) {
+ this.state = "path or authority";
+ ++this.pointer;
+ } else {
+ this.url.cannotBeABaseURL = true;
+ this.url.path.push("");
+ this.state = "cannot-be-a-base-URL path";
+ }
+ } else if (!this.stateOverride) {
+ this.buffer = "";
+ this.state = "no scheme";
+ this.pointer = -1;
+ } else {
+ this.parseError = true;
+ return failure;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) {
+ if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) {
+ return failure;
+ } else if (this.base.cannotBeABaseURL && c === 35) {
+ this.url.scheme = this.base.scheme;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ this.url.fragment = "";
+ this.url.cannotBeABaseURL = true;
+ this.state = "fragment";
+ } else if (this.base.scheme === "file") {
+ this.state = "file";
+ --this.pointer;
+ } else {
+ this.state = "relative";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) {
+ if (c === 47 && this.input[this.pointer + 1] === 47) {
+ this.state = "special authority ignore slashes";
+ ++this.pointer;
+ } else {
+ this.parseError = true;
+ this.state = "relative";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) {
+ if (c === 47) {
+ this.state = "authority";
+ } else {
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse relative"] = function parseRelative(c) {
+ this.url.scheme = this.base.scheme;
+ if (isNaN(c)) {
+ this.url.username = this.base.username;
+ this.url.password = this.base.password;
+ this.url.host = this.base.host;
+ this.url.port = this.base.port;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ } else if (c === 47) {
+ this.state = "relative slash";
+ } else if (c === 63) {
+ this.url.username = this.base.username;
+ this.url.password = this.base.password;
+ this.url.host = this.base.host;
+ this.url.port = this.base.port;
+ this.url.path = this.base.path.slice();
+ this.url.query = "";
+ this.state = "query";
+ } else if (c === 35) {
+ this.url.username = this.base.username;
+ this.url.password = this.base.password;
+ this.url.host = this.base.host;
+ this.url.port = this.base.port;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else if (isSpecial(this.url) && c === 92) {
+ this.parseError = true;
+ this.state = "relative slash";
+ } else {
+ this.url.username = this.base.username;
+ this.url.password = this.base.password;
+ this.url.host = this.base.host;
+ this.url.port = this.base.port;
+ this.url.path = this.base.path.slice(0, this.base.path.length - 1);
+
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) {
+ if (isSpecial(this.url) && (c === 47 || c === 92)) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "special authority ignore slashes";
+ } else if (c === 47) {
+ this.state = "authority";
+ } else {
+ this.url.username = this.base.username;
+ this.url.password = this.base.password;
+ this.url.host = this.base.host;
+ this.url.port = this.base.port;
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) {
+ if (c === 47 && this.input[this.pointer + 1] === 47) {
+ this.state = "special authority ignore slashes";
+ ++this.pointer;
+ } else {
+ this.parseError = true;
+ this.state = "special authority ignore slashes";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) {
+ if (c !== 47 && c !== 92) {
+ this.state = "authority";
+ --this.pointer;
+ } else {
+ this.parseError = true;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) {
+ if (c === 64) {
+ this.parseError = true;
+ if (this.atFlag) {
+ this.buffer = "%40" + this.buffer;
+ }
+ this.atFlag = true;
+
+ // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars
+ const len = countSymbols(this.buffer);
+ for (let pointer = 0; pointer < len; ++pointer) {
+ const codePoint = this.buffer.codePointAt(pointer);
+
+ if (codePoint === 58 && !this.passwordTokenSeenFlag) {
+ this.passwordTokenSeenFlag = true;
+ continue;
+ }
+ const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode);
+ if (this.passwordTokenSeenFlag) {
+ this.url.password += encodedCodePoints;
+ } else {
+ this.url.username += encodedCodePoints;
+ }
+ }
+ this.buffer = "";
+ } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
+ (isSpecial(this.url) && c === 92)) {
+ if (this.atFlag && this.buffer === "") {
+ this.parseError = true;
+ return failure;
+ }
+ this.pointer -= countSymbols(this.buffer) + 1;
+ this.buffer = "";
+ this.state = "host";
+ } else {
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse hostname"] =
+URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) {
+ if (this.stateOverride && this.url.scheme === "file") {
+ --this.pointer;
+ this.state = "file host";
+ } else if (c === 58 && !this.arrFlag) {
+ if (this.buffer === "") {
+ this.parseError = true;
+ return failure;
+ }
+
+ const host = parseHost(this.buffer, isSpecial(this.url));
+ if (host === failure) {
+ return failure;
+ }
+
+ this.url.host = host;
+ this.buffer = "";
+ this.state = "port";
+ if (this.stateOverride === "hostname") {
+ return false;
+ }
+ } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
+ (isSpecial(this.url) && c === 92)) {
+ --this.pointer;
+ if (isSpecial(this.url) && this.buffer === "") {
+ this.parseError = true;
+ return failure;
+ } else if (this.stateOverride && this.buffer === "" &&
+ (includesCredentials(this.url) || this.url.port !== null)) {
+ this.parseError = true;
+ return false;
+ }
+
+ const host = parseHost(this.buffer, isSpecial(this.url));
+ if (host === failure) {
+ return failure;
+ }
+
+ this.url.host = host;
+ this.buffer = "";
+ this.state = "path start";
+ if (this.stateOverride) {
+ return false;
+ }
+ } else {
+ if (c === 91) {
+ this.arrFlag = true;
+ } else if (c === 93) {
+ this.arrFlag = false;
+ }
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) {
+ if (isASCIIDigit(c)) {
+ this.buffer += cStr;
+ } else if (isNaN(c) || c === 47 || c === 63 || c === 35 ||
+ (isSpecial(this.url) && c === 92) ||
+ this.stateOverride) {
+ if (this.buffer !== "") {
+ const port = parseInt(this.buffer);
+ if (port > Math.pow(2, 16) - 1) {
+ this.parseError = true;
+ return failure;
+ }
+ this.url.port = port === defaultPort(this.url.scheme) ? null : port;
+ this.buffer = "";
+ }
+ if (this.stateOverride) {
+ return false;
+ }
+ this.state = "path start";
+ --this.pointer;
+ } else {
+ this.parseError = true;
+ return failure;
+ }
+
+ return true;
+};
+
+const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]);
+
+URLStateMachine.prototype["parse file"] = function parseFile(c) {
+ this.url.scheme = "file";
+
+ if (c === 47 || c === 92) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "file slash";
+ } else if (this.base !== null && this.base.scheme === "file") {
+ if (isNaN(c)) {
+ this.url.host = this.base.host;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ } else if (c === 63) {
+ this.url.host = this.base.host;
+ this.url.path = this.base.path.slice();
+ this.url.query = "";
+ this.state = "query";
+ } else if (c === 35) {
+ this.url.host = this.base.host;
+ this.url.path = this.base.path.slice();
+ this.url.query = this.base.query;
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else {
+ if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points
+ !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) ||
+ (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points
+ !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) {
+ this.url.host = this.base.host;
+ this.url.path = this.base.path.slice();
+ shortenPath(this.url);
+ } else {
+ this.parseError = true;
+ }
+
+ this.state = "path";
+ --this.pointer;
+ }
+ } else {
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) {
+ if (c === 47 || c === 92) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "file host";
+ } else {
+ if (this.base !== null && this.base.scheme === "file") {
+ if (isNormalizedWindowsDriveLetterString(this.base.path[0])) {
+ this.url.path.push(this.base.path[0]);
+ } else {
+ this.url.host = this.base.host;
+ }
+ }
+ this.state = "path";
+ --this.pointer;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) {
+ if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) {
+ --this.pointer;
+ if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) {
+ this.parseError = true;
+ this.state = "path";
+ } else if (this.buffer === "") {
+ this.url.host = "";
+ if (this.stateOverride) {
+ return false;
+ }
+ this.state = "path start";
+ } else {
+ let host = parseHost(this.buffer, isSpecial(this.url));
+ if (host === failure) {
+ return failure;
+ }
+ if (host === "localhost") {
+ host = "";
+ }
+ this.url.host = host;
+
+ if (this.stateOverride) {
+ return false;
+ }
+
+ this.buffer = "";
+ this.state = "path start";
+ }
+ } else {
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse path start"] = function parsePathStart(c) {
+ if (isSpecial(this.url)) {
+ if (c === 92) {
+ this.parseError = true;
+ }
+ this.state = "path";
+
+ if (c !== 47 && c !== 92) {
+ --this.pointer;
+ }
+ } else if (!this.stateOverride && c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ } else if (!this.stateOverride && c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else if (c !== undefined) {
+ this.state = "path";
+ if (c !== 47) {
+ --this.pointer;
+ }
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse path"] = function parsePath(c) {
+ if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) ||
+ (!this.stateOverride && (c === 63 || c === 35))) {
+ if (isSpecial(this.url) && c === 92) {
+ this.parseError = true;
+ }
+
+ if (isDoubleDot(this.buffer)) {
+ shortenPath(this.url);
+ if (c !== 47 && !(isSpecial(this.url) && c === 92)) {
+ this.url.path.push("");
+ }
+ } else if (isSingleDot(this.buffer) && c !== 47 &&
+ !(isSpecial(this.url) && c === 92)) {
+ this.url.path.push("");
+ } else if (!isSingleDot(this.buffer)) {
+ if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) {
+ if (this.url.host !== "" && this.url.host !== null) {
+ this.parseError = true;
+ this.url.host = "";
+ }
+ this.buffer = this.buffer[0] + ":";
+ }
+ this.url.path.push(this.buffer);
+ }
+ this.buffer = "";
+ if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) {
+ while (this.url.path.length > 1 && this.url.path[0] === "") {
+ this.parseError = true;
+ this.url.path.shift();
+ }
+ }
+ if (c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ }
+ if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ }
+ } else {
+ // TODO: If c is not a URL code point and not "%", parse error.
+
+ if (c === 37 &&
+ (!isASCIIHex(this.input[this.pointer + 1]) ||
+ !isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ this.buffer += percentEncodeChar(c, isPathPercentEncode);
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) {
+ if (c === 63) {
+ this.url.query = "";
+ this.state = "query";
+ } else if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ } else {
+ // TODO: Add: not a URL code point
+ if (!isNaN(c) && c !== 37) {
+ this.parseError = true;
+ }
+
+ if (c === 37 &&
+ (!isASCIIHex(this.input[this.pointer + 1]) ||
+ !isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ if (!isNaN(c)) {
+ this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode);
+ }
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) {
+ if (isNaN(c) || (!this.stateOverride && c === 35)) {
+ if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") {
+ this.encodingOverride = "utf-8";
+ }
+
+ const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead
+ for (let i = 0; i < buffer.length; ++i) {
+ if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 ||
+ buffer[i] === 0x3C || buffer[i] === 0x3E) {
+ this.url.query += percentEncode(buffer[i]);
+ } else {
+ this.url.query += String.fromCodePoint(buffer[i]);
+ }
+ }
+
+ this.buffer = "";
+ if (c === 35) {
+ this.url.fragment = "";
+ this.state = "fragment";
+ }
+ } else {
+ // TODO: If c is not a URL code point and not "%", parse error.
+ if (c === 37 &&
+ (!isASCIIHex(this.input[this.pointer + 1]) ||
+ !isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ this.buffer += cStr;
+ }
+
+ return true;
+};
+
+URLStateMachine.prototype["parse fragment"] = function parseFragment(c) {
+ if (isNaN(c)) { // do nothing
+ } else if (c === 0x0) {
+ this.parseError = true;
+ } else {
+ // TODO: If c is not a URL code point and not "%", parse error.
+ if (c === 37 &&
+ (!isASCIIHex(this.input[this.pointer + 1]) ||
+ !isASCIIHex(this.input[this.pointer + 2]))) {
+ this.parseError = true;
+ }
+
+ this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode);
+ }
+
+ return true;
+};
+
+function serializeURL(url, excludeFragment) {
+ let output = url.scheme + ":";
+ if (url.host !== null) {
+ output += "//";
+
+ if (url.username !== "" || url.password !== "") {
+ output += url.username;
+ if (url.password !== "") {
+ output += ":" + url.password;
+ }
+ output += "@";
+ }
+
+ output += serializeHost(url.host);
+
+ if (url.port !== null) {
+ output += ":" + url.port;
+ }
+ } else if (url.host === null && url.scheme === "file") {
+ output += "//";
+ }
+
+ if (url.cannotBeABaseURL) {
+ output += url.path[0];
+ } else {
+ for (const string of url.path) {
+ output += "/" + string;
+ }
+ }
+
+ if (url.query !== null) {
+ output += "?" + url.query;
+ }
+
+ if (!excludeFragment && url.fragment !== null) {
+ output += "#" + url.fragment;
+ }
+
+ return output;
+}
+
+function serializeOrigin(tuple) {
+ let result = tuple.scheme + "://";
+ result += serializeHost(tuple.host);
+
+ if (tuple.port !== null) {
+ result += ":" + tuple.port;
+ }
+
+ return result;
+}
+
+module.exports.serializeURL = serializeURL;
+
+module.exports.serializeURLOrigin = function (url) {
+ // https://url.spec.whatwg.org/#concept-url-origin
+ switch (url.scheme) {
+ case "blob":
+ try {
+ return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0]));
+ } catch (e) {
+ // serializing an opaque origin returns "null"
+ return "null";
+ }
+ case "ftp":
+ case "gopher":
+ case "http":
+ case "https":
+ case "ws":
+ case "wss":
+ return serializeOrigin({
+ scheme: url.scheme,
+ host: url.host,
+ port: url.port
+ });
+ case "file":
+ // spec says "exercise to the reader", chrome says "file://"
+ return "file://";
+ default:
+ // serializing an opaque origin returns "null"
+ return "null";
+ }
+};
+
+module.exports.basicURLParse = function (input, options) {
+ if (options === undefined) {
+ options = {};
+ }
+
+ const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride);
+ if (usm.failure) {
+ return "failure";
+ }
+
+ return usm.url;
+};
+
+module.exports.setTheUsername = function (url, username) {
+ url.username = "";
+ const decoded = punycode.ucs2.decode(username);
+ for (let i = 0; i < decoded.length; ++i) {
+ url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
+ }
+};
+
+module.exports.setThePassword = function (url, password) {
+ url.password = "";
+ const decoded = punycode.ucs2.decode(password);
+ for (let i = 0; i < decoded.length; ++i) {
+ url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode);
+ }
+};
+
+module.exports.serializeHost = serializeHost;
+
+module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort;
+
+module.exports.serializeInteger = function (integer) {
+ return String(integer);
+};
+
+module.exports.parseURL = function (input, options) {
+ if (options === undefined) {
+ options = {};
+ }
+
+ // We don't handle blobs, so this just delegates:
+ return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride });
+};
/***/ }),
@@ -198393,6 +198529,378 @@ function cleanEscapedString(input) {
}
+/***/ }),
+
+/***/ 27633:
+/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
+
+"use strict";
+
+exports.parseISO = parseISO;
+var _index = __nccwpck_require__(46104);
+
+var _index2 = __nccwpck_require__(25848);
+var _index3 = __nccwpck_require__(44826);
+
+/**
+ * The {@link parseISO} function options.
+ */
+
+/**
+ * @name parseISO
+ * @category Common Helpers
+ * @summary Parse ISO string
+ *
+ * @description
+ * Parse the given string in ISO 8601 format and return an instance of Date.
+ *
+ * Function accepts complete ISO 8601 formats as well as partial implementations.
+ * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
+ *
+ * If the argument isn't a string, the function cannot parse the string or
+ * the values are invalid, it returns Invalid Date.
+ *
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
+ *
+ * @param argument - The value to convert
+ * @param options - An object with options
+ *
+ * @returns The parsed date in the local time zone
+ *
+ * @example
+ * // Convert string '2014-02-11T11:30:30' to date:
+ * const result = parseISO('2014-02-11T11:30:30')
+ * //=> Tue Feb 11 2014 11:30:30
+ *
+ * @example
+ * // Convert string '+02014101' to date,
+ * // if the additional number of digits in the extended year format is 1:
+ * const result = parseISO('+02014101', { additionalDigits: 1 })
+ * //=> Fri Apr 11 2014 00:00:00
+ */
+function parseISO(argument, options) {
+ const invalidDate = () => (0, _index2.constructFrom)(options?.in, NaN);
+
+ const additionalDigits = options?.additionalDigits ?? 2;
+ const dateStrings = splitDateString(argument);
+
+ let date;
+ if (dateStrings.date) {
+ const parseYearResult = parseYear(dateStrings.date, additionalDigits);
+ date = parseDate(parseYearResult.restDateString, parseYearResult.year);
+ }
+
+ if (!date || isNaN(+date)) return invalidDate();
+
+ const timestamp = +date;
+ let time = 0;
+ let offset;
+
+ if (dateStrings.time) {
+ time = parseTime(dateStrings.time);
+ if (isNaN(time)) return invalidDate();
+ }
+
+ if (dateStrings.timezone) {
+ offset = parseTimezone(dateStrings.timezone);
+ if (isNaN(offset)) return invalidDate();
+ } else {
+ const tmpDate = new Date(timestamp + time);
+ const result = (0, _index3.toDate)(0, options?.in);
+ result.setFullYear(
+ tmpDate.getUTCFullYear(),
+ tmpDate.getUTCMonth(),
+ tmpDate.getUTCDate(),
+ );
+ result.setHours(
+ tmpDate.getUTCHours(),
+ tmpDate.getUTCMinutes(),
+ tmpDate.getUTCSeconds(),
+ tmpDate.getUTCMilliseconds(),
+ );
+ return result;
+ }
+
+ return (0, _index3.toDate)(timestamp + time + offset, options?.in);
+}
+
+const patterns = {
+ dateTimeDelimiter: /[T ]/,
+ timeZoneDelimiter: /[Z ]/i,
+ timezone: /([Z+-].*)$/,
+};
+
+const dateRegex =
+ /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
+const timeRegex =
+ /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
+const timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
+
+function splitDateString(dateString) {
+ const dateStrings = {};
+ const array = dateString.split(patterns.dateTimeDelimiter);
+ let timeString;
+
+ // The regex match should only return at maximum two array elements.
+ // [date], [time], or [date, time].
+ if (array.length > 2) {
+ return dateStrings;
+ }
+
+ if (/:/.test(array[0])) {
+ timeString = array[0];
+ } else {
+ dateStrings.date = array[0];
+ timeString = array[1];
+ if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
+ dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
+ timeString = dateString.substr(
+ dateStrings.date.length,
+ dateString.length,
+ );
+ }
+ }
+
+ if (timeString) {
+ const token = patterns.timezone.exec(timeString);
+ if (token) {
+ dateStrings.time = timeString.replace(token[1], "");
+ dateStrings.timezone = token[1];
+ } else {
+ dateStrings.time = timeString;
+ }
+ }
+
+ return dateStrings;
+}
+
+function parseYear(dateString, additionalDigits) {
+ const regex = new RegExp(
+ "^(?:(\\d{4}|[+-]\\d{" +
+ (4 + additionalDigits) +
+ "})|(\\d{2}|[+-]\\d{" +
+ (2 + additionalDigits) +
+ "})$)",
+ );
+
+ const captures = dateString.match(regex);
+ // Invalid ISO-formatted year
+ if (!captures) return { year: NaN, restDateString: "" };
+
+ const year = captures[1] ? parseInt(captures[1]) : null;
+ const century = captures[2] ? parseInt(captures[2]) : null;
+
+ // either year or century is null, not both
+ return {
+ year: century === null ? year : century * 100,
+ restDateString: dateString.slice((captures[1] || captures[2]).length),
+ };
+}
+
+function parseDate(dateString, year) {
+ // Invalid ISO-formatted year
+ if (year === null) return new Date(NaN);
+
+ const captures = dateString.match(dateRegex);
+ // Invalid ISO-formatted string
+ if (!captures) return new Date(NaN);
+
+ const isWeekDate = !!captures[4];
+ const dayOfYear = parseDateUnit(captures[1]);
+ const month = parseDateUnit(captures[2]) - 1;
+ const day = parseDateUnit(captures[3]);
+ const week = parseDateUnit(captures[4]);
+ const dayOfWeek = parseDateUnit(captures[5]) - 1;
+
+ if (isWeekDate) {
+ if (!validateWeekDate(year, week, dayOfWeek)) {
+ return new Date(NaN);
+ }
+ return dayOfISOWeekYear(year, week, dayOfWeek);
+ } else {
+ const date = new Date(0);
+ if (
+ !validateDate(year, month, day) ||
+ !validateDayOfYearDate(year, dayOfYear)
+ ) {
+ return new Date(NaN);
+ }
+ date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
+ return date;
+ }
+}
+
+function parseDateUnit(value) {
+ return value ? parseInt(value) : 1;
+}
+
+function parseTime(timeString) {
+ const captures = timeString.match(timeRegex);
+ if (!captures) return NaN; // Invalid ISO-formatted time
+
+ const hours = parseTimeUnit(captures[1]);
+ const minutes = parseTimeUnit(captures[2]);
+ const seconds = parseTimeUnit(captures[3]);
+
+ if (!validateTime(hours, minutes, seconds)) {
+ return NaN;
+ }
+
+ return (
+ hours * _index.millisecondsInHour +
+ minutes * _index.millisecondsInMinute +
+ seconds * 1000
+ );
+}
+
+function parseTimeUnit(value) {
+ return (value && parseFloat(value.replace(",", "."))) || 0;
+}
+
+function parseTimezone(timezoneString) {
+ if (timezoneString === "Z") return 0;
+
+ const captures = timezoneString.match(timezoneRegex);
+ if (!captures) return 0;
+
+ const sign = captures[1] === "+" ? -1 : 1;
+ const hours = parseInt(captures[2]);
+ const minutes = (captures[3] && parseInt(captures[3])) || 0;
+
+ if (!validateTimezone(hours, minutes)) {
+ return NaN;
+ }
+
+ return (
+ sign *
+ (hours * _index.millisecondsInHour + minutes * _index.millisecondsInMinute)
+ );
+}
+
+function dayOfISOWeekYear(isoWeekYear, week, day) {
+ const date = new Date(0);
+ date.setUTCFullYear(isoWeekYear, 0, 4);
+ const fourthOfJanuaryDay = date.getUTCDay() || 7;
+ const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
+ date.setUTCDate(date.getUTCDate() + diff);
+ return date;
+}
+
+// Validation functions
+
+// February is null to handle the leap year (using ||)
+const daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+function isLeapYearIndex(year) {
+ return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);
+}
+
+function validateDate(year, month, date) {
+ return (
+ month >= 0 &&
+ month <= 11 &&
+ date >= 1 &&
+ date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28))
+ );
+}
+
+function validateDayOfYearDate(year, dayOfYear) {
+ return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
+}
+
+function validateWeekDate(_year, week, day) {
+ return week >= 1 && week <= 53 && day >= 0 && day <= 6;
+}
+
+function validateTime(hours, minutes, seconds) {
+ if (hours === 24) {
+ return minutes === 0 && seconds === 0;
+ }
+
+ return (
+ seconds >= 0 &&
+ seconds < 60 &&
+ minutes >= 0 &&
+ minutes < 60 &&
+ hours >= 0 &&
+ hours < 25
+ );
+}
+
+function validateTimezone(_hours, minutes) {
+ return minutes >= 0 && minutes <= 59;
+}
+
+
+/***/ }),
+
+/***/ 26380:
+/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
+
+"use strict";
+
+exports.parseJSON = parseJSON;
+var _index = __nccwpck_require__(44826);
+
+/**
+ * The {@link parseJSON} function options.
+ */
+
+/**
+ * Converts a complete ISO date string in UTC time, the typical format for transmitting
+ * a date in JSON, to a JavaScript `Date` instance.
+ *
+ * This is a minimal implementation for converting dates retrieved from a JSON API to
+ * a `Date` instance which can be used with other functions in the `date-fns` library.
+ * The following formats are supported:
+ *
+ * - `2000-03-15T05:20:10.123Z`: The output of `.toISOString()` and `JSON.stringify(new Date())`
+ * - `2000-03-15T05:20:10Z`: Without milliseconds
+ * - `2000-03-15T05:20:10+00:00`: With a zero offset, the default JSON encoded format in some other languages
+ * - `2000-03-15T05:20:10+05:45`: With a positive or negative offset, the default JSON encoded format in some other languages
+ * - `2000-03-15T05:20:10+0000`: With a zero offset without a colon
+ * - `2000-03-15T05:20:10`: Without a trailing 'Z' symbol
+ * - `2000-03-15T05:20:10.1234567`: Up to 7 digits in milliseconds field. Only first 3 are taken into account since JS does not allow fractional milliseconds
+ * - `2000-03-15 05:20:10`: With a space instead of a 'T' separator for APIs returning a SQL date without reformatting
+ *
+ * For convenience and ease of use these other input types are also supported
+ * via [toDate](https://date-fns.org/docs/toDate):
+ *
+ * - A `Date` instance will be cloned
+ * - A `number` will be treated as a timestamp
+ *
+ * Any other input type or invalid date strings will return an `Invalid Date`.
+ *
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
+ *
+ * @param dateStr - A fully formed ISO8601 date string to convert
+ * @param options - An object with options
+ *
+ * @returns The parsed date in the local time zone
+ */
+function parseJSON(dateStr, options) {
+ const parts = dateStr.match(
+ /(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})(?:\.(\d{0,7}))?(?:Z|(.)(\d{2}):?(\d{2})?)?/,
+ );
+
+ if (!parts) return (0, _index.toDate)(NaN, options?.in);
+
+ return (0, _index.toDate)(
+ Date.UTC(
+ +parts[1],
+ +parts[2] - 1,
+ +parts[3],
+ +parts[4] - (+parts[9] || 0) * (parts[8] == "-" ? -1 : 1),
+ +parts[5] - (+parts[10] || 0) * (parts[8] == "-" ? -1 : 1),
+ +parts[6],
+ +((parts[7] || "0") + "00").substring(0, 3),
+ ),
+ options?.in,
+ );
+}
+
+
/***/ }),
/***/ 29861:
@@ -200925,378 +201433,6 @@ function isLeapYearIndex(year) {
}
-/***/ }),
-
-/***/ 27633:
-/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
-
-"use strict";
-
-exports.parseISO = parseISO;
-var _index = __nccwpck_require__(46104);
-
-var _index2 = __nccwpck_require__(25848);
-var _index3 = __nccwpck_require__(44826);
-
-/**
- * The {@link parseISO} function options.
- */
-
-/**
- * @name parseISO
- * @category Common Helpers
- * @summary Parse ISO string
- *
- * @description
- * Parse the given string in ISO 8601 format and return an instance of Date.
- *
- * Function accepts complete ISO 8601 formats as well as partial implementations.
- * ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
- *
- * If the argument isn't a string, the function cannot parse the string or
- * the values are invalid, it returns Invalid Date.
- *
- * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
- * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
- *
- * @param argument - The value to convert
- * @param options - An object with options
- *
- * @returns The parsed date in the local time zone
- *
- * @example
- * // Convert string '2014-02-11T11:30:30' to date:
- * const result = parseISO('2014-02-11T11:30:30')
- * //=> Tue Feb 11 2014 11:30:30
- *
- * @example
- * // Convert string '+02014101' to date,
- * // if the additional number of digits in the extended year format is 1:
- * const result = parseISO('+02014101', { additionalDigits: 1 })
- * //=> Fri Apr 11 2014 00:00:00
- */
-function parseISO(argument, options) {
- const invalidDate = () => (0, _index2.constructFrom)(options?.in, NaN);
-
- const additionalDigits = options?.additionalDigits ?? 2;
- const dateStrings = splitDateString(argument);
-
- let date;
- if (dateStrings.date) {
- const parseYearResult = parseYear(dateStrings.date, additionalDigits);
- date = parseDate(parseYearResult.restDateString, parseYearResult.year);
- }
-
- if (!date || isNaN(+date)) return invalidDate();
-
- const timestamp = +date;
- let time = 0;
- let offset;
-
- if (dateStrings.time) {
- time = parseTime(dateStrings.time);
- if (isNaN(time)) return invalidDate();
- }
-
- if (dateStrings.timezone) {
- offset = parseTimezone(dateStrings.timezone);
- if (isNaN(offset)) return invalidDate();
- } else {
- const tmpDate = new Date(timestamp + time);
- const result = (0, _index3.toDate)(0, options?.in);
- result.setFullYear(
- tmpDate.getUTCFullYear(),
- tmpDate.getUTCMonth(),
- tmpDate.getUTCDate(),
- );
- result.setHours(
- tmpDate.getUTCHours(),
- tmpDate.getUTCMinutes(),
- tmpDate.getUTCSeconds(),
- tmpDate.getUTCMilliseconds(),
- );
- return result;
- }
-
- return (0, _index3.toDate)(timestamp + time + offset, options?.in);
-}
-
-const patterns = {
- dateTimeDelimiter: /[T ]/,
- timeZoneDelimiter: /[Z ]/i,
- timezone: /([Z+-].*)$/,
-};
-
-const dateRegex =
- /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
-const timeRegex =
- /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
-const timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
-
-function splitDateString(dateString) {
- const dateStrings = {};
- const array = dateString.split(patterns.dateTimeDelimiter);
- let timeString;
-
- // The regex match should only return at maximum two array elements.
- // [date], [time], or [date, time].
- if (array.length > 2) {
- return dateStrings;
- }
-
- if (/:/.test(array[0])) {
- timeString = array[0];
- } else {
- dateStrings.date = array[0];
- timeString = array[1];
- if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
- dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
- timeString = dateString.substr(
- dateStrings.date.length,
- dateString.length,
- );
- }
- }
-
- if (timeString) {
- const token = patterns.timezone.exec(timeString);
- if (token) {
- dateStrings.time = timeString.replace(token[1], "");
- dateStrings.timezone = token[1];
- } else {
- dateStrings.time = timeString;
- }
- }
-
- return dateStrings;
-}
-
-function parseYear(dateString, additionalDigits) {
- const regex = new RegExp(
- "^(?:(\\d{4}|[+-]\\d{" +
- (4 + additionalDigits) +
- "})|(\\d{2}|[+-]\\d{" +
- (2 + additionalDigits) +
- "})$)",
- );
-
- const captures = dateString.match(regex);
- // Invalid ISO-formatted year
- if (!captures) return { year: NaN, restDateString: "" };
-
- const year = captures[1] ? parseInt(captures[1]) : null;
- const century = captures[2] ? parseInt(captures[2]) : null;
-
- // either year or century is null, not both
- return {
- year: century === null ? year : century * 100,
- restDateString: dateString.slice((captures[1] || captures[2]).length),
- };
-}
-
-function parseDate(dateString, year) {
- // Invalid ISO-formatted year
- if (year === null) return new Date(NaN);
-
- const captures = dateString.match(dateRegex);
- // Invalid ISO-formatted string
- if (!captures) return new Date(NaN);
-
- const isWeekDate = !!captures[4];
- const dayOfYear = parseDateUnit(captures[1]);
- const month = parseDateUnit(captures[2]) - 1;
- const day = parseDateUnit(captures[3]);
- const week = parseDateUnit(captures[4]);
- const dayOfWeek = parseDateUnit(captures[5]) - 1;
-
- if (isWeekDate) {
- if (!validateWeekDate(year, week, dayOfWeek)) {
- return new Date(NaN);
- }
- return dayOfISOWeekYear(year, week, dayOfWeek);
- } else {
- const date = new Date(0);
- if (
- !validateDate(year, month, day) ||
- !validateDayOfYearDate(year, dayOfYear)
- ) {
- return new Date(NaN);
- }
- date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
- return date;
- }
-}
-
-function parseDateUnit(value) {
- return value ? parseInt(value) : 1;
-}
-
-function parseTime(timeString) {
- const captures = timeString.match(timeRegex);
- if (!captures) return NaN; // Invalid ISO-formatted time
-
- const hours = parseTimeUnit(captures[1]);
- const minutes = parseTimeUnit(captures[2]);
- const seconds = parseTimeUnit(captures[3]);
-
- if (!validateTime(hours, minutes, seconds)) {
- return NaN;
- }
-
- return (
- hours * _index.millisecondsInHour +
- minutes * _index.millisecondsInMinute +
- seconds * 1000
- );
-}
-
-function parseTimeUnit(value) {
- return (value && parseFloat(value.replace(",", "."))) || 0;
-}
-
-function parseTimezone(timezoneString) {
- if (timezoneString === "Z") return 0;
-
- const captures = timezoneString.match(timezoneRegex);
- if (!captures) return 0;
-
- const sign = captures[1] === "+" ? -1 : 1;
- const hours = parseInt(captures[2]);
- const minutes = (captures[3] && parseInt(captures[3])) || 0;
-
- if (!validateTimezone(hours, minutes)) {
- return NaN;
- }
-
- return (
- sign *
- (hours * _index.millisecondsInHour + minutes * _index.millisecondsInMinute)
- );
-}
-
-function dayOfISOWeekYear(isoWeekYear, week, day) {
- const date = new Date(0);
- date.setUTCFullYear(isoWeekYear, 0, 4);
- const fourthOfJanuaryDay = date.getUTCDay() || 7;
- const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
- date.setUTCDate(date.getUTCDate() + diff);
- return date;
-}
-
-// Validation functions
-
-// February is null to handle the leap year (using ||)
-const daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
-
-function isLeapYearIndex(year) {
- return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);
-}
-
-function validateDate(year, month, date) {
- return (
- month >= 0 &&
- month <= 11 &&
- date >= 1 &&
- date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28))
- );
-}
-
-function validateDayOfYearDate(year, dayOfYear) {
- return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
-}
-
-function validateWeekDate(_year, week, day) {
- return week >= 1 && week <= 53 && day >= 0 && day <= 6;
-}
-
-function validateTime(hours, minutes, seconds) {
- if (hours === 24) {
- return minutes === 0 && seconds === 0;
- }
-
- return (
- seconds >= 0 &&
- seconds < 60 &&
- minutes >= 0 &&
- minutes < 60 &&
- hours >= 0 &&
- hours < 25
- );
-}
-
-function validateTimezone(_hours, minutes) {
- return minutes >= 0 && minutes <= 59;
-}
-
-
-/***/ }),
-
-/***/ 26380:
-/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
-
-"use strict";
-
-exports.parseJSON = parseJSON;
-var _index = __nccwpck_require__(44826);
-
-/**
- * The {@link parseJSON} function options.
- */
-
-/**
- * Converts a complete ISO date string in UTC time, the typical format for transmitting
- * a date in JSON, to a JavaScript `Date` instance.
- *
- * This is a minimal implementation for converting dates retrieved from a JSON API to
- * a `Date` instance which can be used with other functions in the `date-fns` library.
- * The following formats are supported:
- *
- * - `2000-03-15T05:20:10.123Z`: The output of `.toISOString()` and `JSON.stringify(new Date())`
- * - `2000-03-15T05:20:10Z`: Without milliseconds
- * - `2000-03-15T05:20:10+00:00`: With a zero offset, the default JSON encoded format in some other languages
- * - `2000-03-15T05:20:10+05:45`: With a positive or negative offset, the default JSON encoded format in some other languages
- * - `2000-03-15T05:20:10+0000`: With a zero offset without a colon
- * - `2000-03-15T05:20:10`: Without a trailing 'Z' symbol
- * - `2000-03-15T05:20:10.1234567`: Up to 7 digits in milliseconds field. Only first 3 are taken into account since JS does not allow fractional milliseconds
- * - `2000-03-15 05:20:10`: With a space instead of a 'T' separator for APIs returning a SQL date without reformatting
- *
- * For convenience and ease of use these other input types are also supported
- * via [toDate](https://date-fns.org/docs/toDate):
- *
- * - A `Date` instance will be cloned
- * - A `number` will be treated as a timestamp
- *
- * Any other input type or invalid date strings will return an `Invalid Date`.
- *
- * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
- *
- * @param dateStr - A fully formed ISO8601 date string to convert
- * @param options - An object with options
- *
- * @returns The parsed date in the local time zone
- */
-function parseJSON(dateStr, options) {
- const parts = dateStr.match(
- /(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})(?:\.(\d{0,7}))?(?:Z|(.)(\d{2}):?(\d{2})?)?/,
- );
-
- if (!parts) return (0, _index.toDate)(NaN, options?.in);
-
- return (0, _index.toDate)(
- Date.UTC(
- +parts[1],
- +parts[2] - 1,
- +parts[3],
- +parts[4] - (+parts[9] || 0) * (parts[8] == "-" ? -1 : 1),
- +parts[5] - (+parts[10] || 0) * (parts[8] == "-" ? -1 : 1),
- +parts[6],
- +((parts[7] || "0") + "00").substring(0, 3),
- ),
- options?.in,
- );
-}
-
-
/***/ }),
/***/ 80144:
diff --git a/package.json b/package.json
index ef4a08e2..7e3f1986 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"lint": "eslint .",
"package": "npm run build && ncc build --license licenses.txt",
"test": "jest",
- "test:coverage": "jest --coverage --collectCoverageFrom='src/**'"
+ "test:coverage": "jest --coverage --collectCoverageFrom=\"src/**\""
},
"repository": {
"type": "git",
diff --git a/src/action/decorate/action.ts b/src/action/decorate/action.ts
index 8a09f8eb..5ed67460 100644
--- a/src/action/decorate/action.ts
+++ b/src/action/decorate/action.ts
@@ -22,6 +22,6 @@ export async function decorateAction(analysisResult: AnalysisResult | undefined,
}
if (analysisResult && actionConfig.postAnnotations) {
- postAnnotations(analysisResult.projectResults);
+ await postAnnotations(analysisResult.projectResults);
}
}
diff --git a/src/action/decorate/summary.ts b/src/action/decorate/summary.ts
index f1f44947..68e3124c 100644
--- a/src/action/decorate/summary.ts
+++ b/src/action/decorate/summary.ts
@@ -330,11 +330,24 @@ export function createUnpostableAnnotationsDetails(unpostableAnnotations: Extend
unpostableAnnotations.forEach(reviewComment => {
const path = reviewComment.path;
const displayCount = reviewComment.displayCount ?? '';
- const icon = reviewComment.blocking?.state === 'after' ? ':warning:' : ':x:';
- const blocking =
- reviewComment.blocking?.state === 'after' && reviewComment.blocking.after
- ? `Blocking after ${format(reviewComment.blocking.after, 'yyyy-MM-dd')}`
- : 'Blocking';
+
+ let icon = '';
+ let blocking = '';
+ switch (reviewComment.blocking?.state) {
+ case 'no':
+ icon = ':beetle:';
+ blocking = 'Non-Blocking';
+ break;
+ case 'after':
+ icon = ':warning:';
+ blocking = `Blocking after${reviewComment.blocking.after ? ` ${format(reviewComment.blocking.after, 'yyyy-MM-dd')}` : ''}`;
+ break;
+ case 'yes':
+ default:
+ icon = ':x:';
+ blocking = 'Blocking';
+ break;
+ }
if (previousPath === '') {
body += `| ${path} |
`;
diff --git a/src/configuration/action.ts b/src/configuration/action.ts
index d3df4466..e48f783d 100644
--- a/src/configuration/action.ts
+++ b/src/configuration/action.ts
@@ -3,6 +3,44 @@ import { getBooleanInput, getInput } from '@actions/core';
import { RetryConfig } from './interfaces';
import { logger } from '../helper/logger';
+import { ExtendedAnnotation } from '../viewer/interfaces';
+
+export class ShowAnnotationSeverity {
+ static readonly BLOCKING = new ShowAnnotationSeverity('blocking', ['blocking'], ['yes']);
+ static readonly AFTER = new ShowAnnotationSeverity('blocking-after', ['blocking', 'after'], ['yes', 'after']);
+ static readonly ISSUE = new ShowAnnotationSeverity('issue', ['blocking', 'after', 'issue'], ['yes', 'after', 'no']);
+
+ private constructor(
+ readonly param: string,
+ readonly severities: string[],
+ readonly blockingStates: string[]
+ ) {}
+
+ static parse(input: string): ShowAnnotationSeverity {
+ const severity = input.toLowerCase();
+ switch (severity) {
+ case this.BLOCKING.param:
+ return this.BLOCKING;
+ case this.AFTER.param:
+ return this.AFTER;
+ case this.ISSUE.param:
+ return this.ISSUE;
+ }
+ throw Error(`Parameter 'showAnnotationSeverity' should be one of 'blocking', 'blocking-after' or 'issue'. Input given is '${input}'`);
+ }
+
+ getAnnotationSeverityFilter(): string {
+ if (this.severities.length > 1) {
+ return `AnnotationSeverity(Set(${this.severities.join(',')}))`;
+ } else {
+ return `AnnotationSeverity(${this.severities[0]})`;
+ }
+ }
+
+ shouldPostAnnotation(annotation: ExtendedAnnotation): boolean {
+ return annotation.postable && (annotation.blocking?.state === undefined || this.blockingStates.includes(annotation.blocking.state));
+ }
+}
export class ActionConfiguration {
readonly excludeMovedFiles: boolean;
@@ -11,7 +49,7 @@ export class ActionConfiguration {
readonly pullRequestApproval: boolean;
readonly retryConfig: RetryConfig;
readonly secretsFilter: string[];
- readonly showBlockingAfter: boolean;
+ readonly showAnnotationSeverity: ShowAnnotationSeverity;
constructor() {
this.excludeMovedFiles = getBooleanInput('excludeMovedFiles');
@@ -20,7 +58,7 @@ export class ActionConfiguration {
this.pullRequestApproval = getBooleanInput('pullRequestApproval');
this.retryConfig = this.validateAndGetRetryConfig(getInput('retryCodes'));
this.secretsFilter = this.getSecretsFilter(getInput('secretsFilter'));
- this.showBlockingAfter = getBooleanInput('showBlockingAfter');
+ this.showAnnotationSeverity = this.getAnnotationSeverity(getInput('showAnnotationSeverity'), getBooleanInput('showBlockingAfter'));
}
/**
@@ -70,4 +108,17 @@ export class ActionConfiguration {
return combinedFilters;
}
+
+ private getAnnotationSeverity(input: string, blockingAfter: boolean): ShowAnnotationSeverity {
+ // `showAnnotationSeverity` takes precedent over `blockingAfter`, which is deprecated.
+ if (input !== '') {
+ return ShowAnnotationSeverity.parse(input);
+ } else {
+ // if `showAnnotationSeverity` is not set use the value of `blockingAfter` to set a level.
+ if (!blockingAfter) {
+ return ShowAnnotationSeverity.BLOCKING;
+ }
+ return ShowAnnotationSeverity.AFTER;
+ }
+ }
}
diff --git a/src/configuration/github.ts b/src/configuration/github.ts
index a0e733a5..2b2c0044 100644
--- a/src/configuration/github.ts
+++ b/src/configuration/github.ts
@@ -7,7 +7,10 @@ export class GithubConfig {
readonly apiUrl: string;
readonly owner: string;
readonly reponame: string;
- readonly commitSha: string;
+ // Sha of the (merge) commit
+ readonly sha: string;
+ // Sha of the (underlying) commit that triggered the flow
+ readonly headSha: string | undefined;
readonly event: GithubEvent;
readonly job: string;
readonly action: string;
@@ -24,8 +27,9 @@ export class GithubConfig {
this.apiUrl = context.apiUrl;
this.owner = context.repo.owner;
this.reponame = context.repo.repo;
- this.commitSha = context.sha;
+ this.sha = context.sha;
this.event = this.getGithubEvent();
+ this.headSha = this.getHeadSha();
this.job = context.job.replace(/[\s|_]+/g, '-');
this.action = context.action.replace('__tiobe_', '');
this.workflow = context.workflow.replace(/[\s|_]+/g, '-');
@@ -80,6 +84,17 @@ export class GithubConfig {
}
}
+ private getHeadSha(): string | undefined {
+ // Should run after getGithubEvent
+ if (this.event.isPullRequest) {
+ const pr = context.payload.pull_request as { head?: { sha?: string } } | undefined;
+ logger.debug(`Found pull_request.head.sha: ${pr?.head?.sha ?? 'undefined'}`);
+ return pr?.head?.sha;
+ } else {
+ return context.sha;
+ }
+ }
+
getCommentIdentifier(): string {
return [this.workflow, this.job, this.runNumber, this.runAttempt].join('_');
}
diff --git a/src/github/annotations.ts b/src/github/annotations.ts
index 66c54c0b..1c7a7f15 100644
--- a/src/github/annotations.ts
+++ b/src/github/annotations.ts
@@ -1,4 +1,4 @@
-import { ReviewComment } from './interfaces';
+import { AnnotationLevel, CreateCheckRunParams, GithubAnnotation, ReviewComment, UpdateCheckRunParams } from './interfaces';
import { logger } from '../helper/logger';
import { ProjectResult } from '../helper/interfaces';
import { handleOctokitError } from '../helper/response';
@@ -38,41 +38,104 @@ export async function getPostedReviewComments(): Promise {
* Deletes the review comments of previous runs.
* @param postedReviewComments Previously posted review comments.
*/
-export function postAnnotations(projectResults: ProjectResult[]): void {
+export async function postAnnotations(projectResults: ProjectResult[]): Promise {
logger.header('Posting annotations.');
+ if (!githubConfig.headSha) {
+ logger.warning('Commit of underlying commit not found, cannot post annotations');
+ return;
+ }
+
+ const batchSize = 50;
+ const annotations = projectResults
+ .flatMap(projectResult => projectResult.annotations)
+ .filter(annotation => actionConfig.showAnnotationSeverity.shouldPostAnnotation(annotation))
+ .map(createGithubAnnotation);
+
+ if (annotations.length === 0) {
+ logger.info('No annotations to post.');
+ return;
+ }
+
+ let checkRunId = 0;
+ for (let i = 0; i < annotations.length; i += batchSize) {
+ const params = {
+ owner: githubConfig.owner,
+ repo: githubConfig.reponame,
+ output: {
+ title: 'TICS annotations',
+ summary: '',
+ annotations: annotations.slice(i, i + batchSize)
+ }
+ };
- projectResults.forEach(projectResult => {
- projectResult.annotations.forEach(annotation => {
- if (annotation.postable) {
- const title = annotation.msg;
- const body = createReviewCommentBody(annotation);
-
- if (annotation.blocking?.state === undefined || annotation.blocking.state === 'yes') {
- logger.warning(body, {
- file: annotation.path,
- startLine: annotation.line,
- title: title
- });
- } else if (annotation.blocking.state === 'after' && actionConfig.showBlockingAfter) {
- logger.notice(body, {
- file: annotation.path,
- startLine: annotation.line,
- title: title
- });
+ try {
+ if (i === 0) {
+ const pars: CreateCheckRunParams = {
+ ...params,
+ head_sha: githubConfig.headSha,
+ name: 'TICS annotations',
+ conclusion: i + batchSize >= annotations.length ? 'success' : undefined,
+ status: i + batchSize >= annotations.length ? undefined : 'in_progress'
+ };
+ logger.debug('Creating check run with: ' + JSON.stringify(pars));
+ const response = await octokit.rest.checks.create(pars);
+ checkRunId = response.data.id;
+ } else {
+ const pars: UpdateCheckRunParams = { ...params, check_run_id: checkRunId };
+ if (i + batchSize >= annotations.length) {
+ pars.conclusion = 'success';
}
+ logger.debug('Updating check run with: ' + JSON.stringify(pars));
+ await octokit.rest.checks.update(pars);
}
- });
- });
+ } catch (error) {
+ const message = handleOctokitError(error);
+ logger.notice(`Could not post (some) annotations: ${message}`);
+ }
+ }
+
+ logger.info('Posted all postable annotations');
+}
+
+function createGithubAnnotation(annotation: ExtendedAnnotation): GithubAnnotation {
+ const title = annotation.msg;
+ const body = createReviewCommentBody(annotation);
+
+ let level: AnnotationLevel;
+ switch (annotation.blocking?.state) {
+ case 'no':
+ case 'after':
+ level = 'notice';
+ break;
+ case 'yes':
+ default:
+ level = 'warning';
+ break;
+ }
- logger.info('Posted all postable annotations (none if there are no violations).');
+ return {
+ title: title,
+ message: body,
+ annotation_level: level,
+ path: annotation.path,
+ start_line: annotation.line,
+ end_line: annotation.line
+ };
}
function createReviewCommentBody(annotation: ExtendedAnnotation): string {
- let body = '';
- if (annotation.blocking?.state === 'yes') {
- body += `Blocking`;
- } else if (annotation.blocking?.state === 'after' && annotation.blocking.after) {
- body += `Blocking after: ${format(annotation.blocking.after, 'yyyy-MM-dd')}`;
+ let body: string;
+ switch (annotation.blocking?.state) {
+ case 'no':
+ body = 'Non-Blocking';
+ break;
+ case 'after':
+ body = `Blocking after${annotation.blocking.after ? ` ${format(annotation.blocking.after, 'yyyy-MM-dd')}` : ''}`;
+ break;
+ case 'yes':
+ default:
+ body = 'Blocking';
+ break;
}
const secondLine: string[] = [];
diff --git a/src/github/commits.ts b/src/github/commits.ts
index 41deaefd..910dde14 100644
--- a/src/github/commits.ts
+++ b/src/github/commits.ts
@@ -15,7 +15,7 @@ export async function getChangedFilesOfCommit(): Promise {
const params = {
owner: githubConfig.owner,
repo: githubConfig.reponame,
- ref: githubConfig.commitSha
+ ref: githubConfig.sha
};
let response: ChangedFile[] = [];
try {
diff --git a/src/github/interfaces.d.ts b/src/github/interfaces.d.ts
index d11d15bf..a702f729 100644
--- a/src/github/interfaces.d.ts
+++ b/src/github/interfaces.d.ts
@@ -1,4 +1,6 @@
import { PullRequestChangedFile } from '@octokit/graphql-schema';
+import { Endpoints } from '@octokit/types';
+import { ExtendedAnnotation } from '../viewer/interfaces';
type Side = 'LEFT' | 'RIGHT';
type AuthorAssociation = 'COLLABORATOR' | 'CONTRIBUTOR' | 'FIRST_TIMER' | 'FIRST_TIME_CONTRIBUTOR' | 'MANNEQUIN' | 'MEMBER' | 'NONE' | 'OWNER';
@@ -168,3 +170,19 @@ export interface ActionOutput {
conditions: string[];
annotations: ExtendedAnnotation[];
}
+
+export type AnnotationLevel = 'notice' | 'warning' | 'failure';
+export interface GithubAnnotation {
+ path: string;
+ start_line: number;
+ end_line: number;
+ start_column?: number;
+ end_column?: number;
+ annotation_level: AnnotationLevel;
+ message: string;
+ title?: string;
+ raw_details?: string;
+}
+
+export type CreateCheckRunParams = Endpoints['POST /repos/{owner}/{repo}/check-runs']['parameters'];
+export type UpdateCheckRunParams = Endpoints['PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}']['parameters'];
diff --git a/src/tics/analyzer.ts b/src/tics/analyzer.ts
index 5cbdf9c3..5d5d5d9f 100644
--- a/src/tics/analyzer.ts
+++ b/src/tics/analyzer.ts
@@ -81,7 +81,7 @@ async function buildRunCommand(fileListPath: string): Promise {
installCommand += ' &&';
}
} else if (platform() === 'linux') {
- installCommand = `TICS='${ticsConfig.viewerUrl}';`;
+ installCommand = `TICS='${ticsConfig.viewerUrl}'`;
} else {
installCommand = `$env:TICS='${ticsConfig.viewerUrl}'`;
}
diff --git a/src/viewer/annotations.ts b/src/viewer/annotations.ts
index 5a23ff5d..12321fa3 100644
--- a/src/viewer/annotations.ts
+++ b/src/viewer/annotations.ts
@@ -1,4 +1,4 @@
-import { ticsConfig } from '../configuration/config';
+import { actionConfig, ticsConfig } from '../configuration/config';
import { ChangedFile } from '../github/interfaces';
import { logger } from '../helper/logger';
import { getRetryErrorMessage } from '../helper/response';
@@ -58,7 +58,7 @@ async function fetchAnnotationsWithApiLinks(apiLinks: AnnotationApiLink[]): Prom
async function fetchAnnotationsByRun(identifier: TicsRunIdentifier): Promise {
const annotationsUrl = new URL(`${ticsConfig.baseUrl}/api/public/v1/Annotations?metric=QualityGate()`);
- let filters = `Project(${identifier.project}),AnnotationSeverity(Set(blocking,after))`;
+ let filters = `Project(${identifier.project}),${actionConfig.showAnnotationSeverity.getAnnotationSeverityFilter()}`;
if (identifier.cdtoken) {
filters += `,ClientData(${identifier.cdtoken})`;
} else if (identifier.date) {
diff --git a/test/.setup/mock.ts b/test/.setup/mock.ts
index 4d8fedc6..b21a83c0 100644
--- a/test/.setup/mock.ts
+++ b/test/.setup/mock.ts
@@ -1,12 +1,14 @@
import { jest } from '@jest/globals';
import { summary } from './summary_mock';
import { GithubEvent } from '../../src/configuration/github-event';
+import { ShowAnnotationSeverity } from '../../src/configuration/action';
export const githubConfigMock: {
apiUrl: string;
owner: string;
reponame: string;
- commitSha: string;
+ sha: string;
+ headSha: string;
event: GithubEvent;
job: string;
action: string;
@@ -22,7 +24,8 @@ export const githubConfigMock: {
apiUrl: 'github.com/api/v1/',
owner: 'tester',
reponame: 'test',
- commitSha: 'sha-128',
+ sha: 'sha-128',
+ headSha: 'head-sha-256',
event: GithubEvent.PUSH,
job: 'TICS',
action: 'tics-github-action',
@@ -62,7 +65,7 @@ export const actionConfigMock = {
postAnnotations: false,
postToConversation: false,
pullRequestApproval: false,
- showBlockingAfter: false
+ showAnnotationSeverity: ShowAnnotationSeverity.AFTER
};
export const ticsCliMock = {
@@ -120,6 +123,10 @@ jest.mock('../../src/github/octokit', () => {
},
rateLimit: {
get: jest.fn()
+ },
+ checks: {
+ create: jest.fn(),
+ update: jest.fn()
}
},
graphql: {
diff --git a/test/integration/configuration.test.ts b/test/integration/configuration.test.ts
index ca3c3c82..38f29522 100644
--- a/test/integration/configuration.test.ts
+++ b/test/integration/configuration.test.ts
@@ -7,6 +7,7 @@ process.env.INPUT_VIEWERURL = 'http://localhost/tiobeweb/TICS/api/cfg?name=defau
process.env.INPUT_EXCLUDEMOVEDFILES = 'false';
process.env.INPUT_INSTALLTICS = 'false';
process.env.INPUT_POSTANNOTATIONS = 'false';
+process.env.INPUT_SHOWNONBLOCKING = 'false';
process.env.INPUT_POSTTOCONVERSATION = 'false';
process.env.INPUT_PULLREQUESTAPPROVAL = 'false';
process.env.INPUT_SHOWBLOCKINGAFTER = 'true';
diff --git a/test/integration/httpclient.test.ts b/test/integration/httpclient.test.ts
index 35fdb42a..05e2ce34 100644
--- a/test/integration/httpclient.test.ts
+++ b/test/integration/httpclient.test.ts
@@ -20,6 +20,7 @@ process.env.INPUT_VIEWERURL = 'http://localhost/tiobeweb/TICS/api/cfg?name=defau
process.env.INPUT_EXCLUDEMOVEDFILES = 'false';
process.env.INPUT_INSTALLTICS = 'false';
process.env.INPUT_POSTANNOTATIONS = 'false';
+process.env.INPUT_SHOWNONBLOCKING = 'false';
process.env.INPUT_POSTTOCONVERSATION = 'false';
process.env.INPUT_PULLREQUESTAPPROVAL = 'false';
process.env.INPUT_SHOWBLOCKINGAFTER = 'true';
diff --git a/test/integration/octokit.test.ts b/test/integration/octokit.test.ts
index 3ffe828f..1ec883b9 100644
--- a/test/integration/octokit.test.ts
+++ b/test/integration/octokit.test.ts
@@ -22,6 +22,7 @@ process.env.INPUT_VIEWERURL = 'http://localhost/tiobeweb/TICS/api/cfg?name=defau
process.env.INPUT_EXCLUDEMOVEDFILES = 'false';
process.env.INPUT_INSTALLTICS = 'false';
process.env.INPUT_POSTANNOTATIONS = 'false';
+process.env.INPUT_SHOWNONBLOCKING = 'false';
process.env.INPUT_POSTTOCONVERSATION = 'false';
process.env.INPUT_PULLREQUESTAPPROVAL = 'false';
process.env.INPUT_SHOWBLOCKINGAFTER = 'true';
diff --git a/test/unit/configuration/action.test.ts b/test/unit/configuration/action.test.ts
index 5a94e459..8ce5869e 100644
--- a/test/unit/configuration/action.test.ts
+++ b/test/unit/configuration/action.test.ts
@@ -1,6 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals';
import * as core from '@actions/core';
-import { ActionConfiguration } from '../../../src/configuration/action';
+import { ActionConfiguration, ShowAnnotationSeverity } from '../../../src/configuration/action';
describe('action Configuration', () => {
let values: Record;
@@ -12,7 +12,7 @@ describe('action Configuration', () => {
pullRequestApproval: false,
retryConfig: { delay: 5, maxRetries: 10, codes: [419, 500, 501, 502, 503, 504] },
secretsFilter: ['TICSAUTHTOKEN', 'GITHUB_TOKEN', 'Authentication token', 'Authorization'],
- showBlockingAfter: false
+ showAnnotationSeverity: ShowAnnotationSeverity.BLOCKING // because getBooleanInput returns false by default
};
beforeEach(() => {
@@ -69,7 +69,7 @@ describe('action Configuration', () => {
pullRequestApproval: true,
retryConfig: { delay: 5, maxRetries: 10, codes: [401] },
secretsFilter: ['TICSAUTHTOKEN', 'GITHUB_TOKEN', 'Authentication token', 'Authorization', 'additional', 'secrets'],
- showBlockingAfter: true
+ showAnnotationSeverity: ShowAnnotationSeverity.AFTER
});
});
@@ -161,4 +161,48 @@ describe('action Configuration', () => {
expect(error.message).toContain("'500;502'");
});
});
+
+ describe('showAnnotationSeverity', () => {
+ it('should prefer showAnnotationSeverity over showBlockingAfter', () => {
+ values = { showBlockingAfter: 'false', showAnnotationSeverity: 'issue' };
+ const config1 = new ActionConfiguration();
+ expect(config1).toMatchObject({ ...expectDefault, showAnnotationSeverity: ShowAnnotationSeverity.ISSUE });
+
+ values = { showBlockingAfter: 'false', showAnnotationSeverity: 'blocking-after' };
+ const config2 = new ActionConfiguration();
+ expect(config2).toMatchObject({ ...expectDefault, showAnnotationSeverity: ShowAnnotationSeverity.AFTER });
+
+ values = { showBlockingAfter: 'false', showAnnotationSeverity: 'blocking' };
+ const config3 = new ActionConfiguration();
+ expect(config3).toMatchObject({ ...expectDefault, showAnnotationSeverity: ShowAnnotationSeverity.BLOCKING });
+ });
+
+ it('should use showBlockingAfter if showAnnotationSeverity is not set', () => {
+ values = { showBlockingAfter: 'false' };
+ const config1 = new ActionConfiguration();
+ expect(config1).toMatchObject({ ...expectDefault });
+
+ values = { showBlockingAfter: 'true' };
+ const config2 = new ActionConfiguration();
+ expect(config2).toMatchObject({ ...expectDefault, showAnnotationSeverity: ShowAnnotationSeverity.AFTER });
+ });
+
+ it('should throw Error when showAnnotationSeverity is incorrect', () => {
+ values = {
+ showAnnotationSeverity: 'bladiebla'
+ };
+
+ let error: any;
+ try {
+ new ActionConfiguration();
+ } catch (err) {
+ error = err;
+ }
+
+ expect(error).toBeInstanceOf(Error);
+ expect(error.message).toEqual(
+ "Parameter 'showAnnotationSeverity' should be one of 'blocking', 'blocking-after' or 'issue'. Input given is 'bladiebla'"
+ );
+ });
+ });
});
diff --git a/test/unit/configuration/github.test.ts b/test/unit/configuration/github.test.ts
index 60744837..509e3510 100644
--- a/test/unit/configuration/github.test.ts
+++ b/test/unit/configuration/github.test.ts
@@ -41,7 +41,7 @@ describe('gitHub Configuration', () => {
apiUrl: 'api.github.com',
owner: 'tiobe',
reponame: 'tics-github-action',
- commitSha: 'sha-128',
+ sha: 'sha-128',
event: { name: 'pull_request', isPullRequest: true },
id: `123_1_TICS_tics-github-action`,
pullRequestNumber: 1
diff --git a/test/unit/github/annotations.test.ts b/test/unit/github/annotations.test.ts
index ba8c3102..141a2b68 100644
--- a/test/unit/github/annotations.test.ts
+++ b/test/unit/github/annotations.test.ts
@@ -1,9 +1,19 @@
import { describe, expect, it, jest } from '@jest/globals';
import { deletePreviousReviewComments, getPostedReviewComments, postAnnotations } from '../../../src/github/annotations';
-import { emptyComment, fourMixedAnalysisResults, twoMixedAnalysisResults, warningComment } from './objects/annotations';
+import {
+ emptyComment,
+ fiveMixedAnalysisResults,
+ fourMixedAnalysisResults,
+ twohundredAnnotations,
+ twoMixedAnalysisResults,
+ warningComment
+} from './objects/annotations';
import { logger } from '../../../src/helper/logger';
import { octokit } from '../../../src/github/octokit';
import { actionConfigMock, githubConfigMock } from '../../.setup/mock';
+import { EOL } from 'os';
+import { SpiedFunction } from 'jest-mock';
+import { ShowAnnotationSeverity } from '../../../src/configuration/action';
describe('getPostedReviewComments', () => {
it('should throw error when a pullRequestNumber is not present', async () => {
@@ -95,100 +105,245 @@ describe('deletePreviousReviewComments', () => {
});
describe('postAnnotations', () => {
- it('should post two annotations when showBlockingAfter is true', () => {
- const warningSpy = jest.spyOn(logger, 'warning');
- const noticeSpy = jest.spyOn(logger, 'notice');
+ let createCheckSpy: jest.SpiedFunction;
+ let updateCheckSpy: jest.SpiedFunction;
+ let warningSpy: jest.SpiedFunction;
+ let infoSpy: jest.SpiedFunction;
+
+ beforeEach(() => {
+ createCheckSpy = jest.spyOn(octokit.rest.checks, 'create');
+ updateCheckSpy = jest.spyOn(octokit.rest.checks, 'update');
+ warningSpy = jest.spyOn(logger, 'warning');
+ infoSpy = jest.spyOn(logger, 'info');
+ });
- actionConfigMock.showBlockingAfter = true;
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
- postAnnotations(twoMixedAnalysisResults.projectResults);
+ it('should return if no head_sha is present', async () => {
+ const headSha = githubConfigMock.headSha;
+ githubConfigMock.headSha = '';
- expect(warningSpy).toHaveBeenCalledTimes(1);
- expect(warningSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking'), {
- file: 'path0.js',
- title: 'message 0',
- startLine: 0
- });
+ await postAnnotations(twoMixedAnalysisResults.projectResults);
- expect(noticeSpy).toHaveBeenCalledTimes(1);
- expect(noticeSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking after'), {
- file: 'path1.js',
- title: 'message 1',
- startLine: 1
- });
+ expect(warningSpy).toHaveBeenCalledWith('Commit of underlying commit not found, cannot post annotations');
+ githubConfigMock.headSha = headSha;
});
- it('should post four annotations when showBlockingAfter is true', () => {
- const warningSpy = jest.spyOn(logger, 'warning');
- const noticeSpy = jest.spyOn(logger, 'notice');
-
- actionConfigMock.showBlockingAfter = true;
+ it('should return if no annotations are present', async () => {
+ const test = structuredClone(twoMixedAnalysisResults.projectResults);
+ test[0].annotations = [];
+ await postAnnotations(test);
- postAnnotations(fourMixedAnalysisResults.projectResults);
+ expect(infoSpy).toHaveBeenCalledWith('No annotations to post.');
+ });
- expect(warningSpy).toHaveBeenCalledTimes(2);
- expect(warningSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking'), {
- file: 'path0.js',
- title: 'message 0',
- startLine: 0
- });
- expect(warningSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking'), {
- file: 'path2.js',
- title: 'message 2',
- startLine: 2
+ it('should post two annotations when showAnnotationSeverity is AFTER', async () => {
+ actionConfigMock.showAnnotationSeverity = ShowAnnotationSeverity.AFTER;
+
+ await postAnnotations(twoMixedAnalysisResults.projectResults);
+
+ expect(createCheckSpy).toHaveBeenCalledTimes(1);
+ expect(createCheckSpy).toHaveBeenCalledWith({
+ conclusion: 'success',
+ head_sha: 'head-sha-256',
+ name: 'TICS annotations',
+ output: {
+ annotations: [
+ {
+ annotation_level: 'warning',
+ end_line: 0,
+ message: `Blocking${EOL}Line: 0`,
+ path: 'path0.js',
+ start_line: 0,
+ title: 'message 0'
+ },
+ {
+ annotation_level: 'notice',
+ end_line: 1,
+ message: `Blocking after 1970-01-21${EOL}Level: 2, Category: category 1${EOL}Line: 1, Rule: rule 1`,
+ path: 'path1.js',
+ start_line: 1,
+ title: 'message 1'
+ }
+ ],
+ summary: '',
+ title: 'TICS annotations'
+ },
+ owner: 'tester',
+ repo: 'test',
+ status: undefined
});
+ expect(updateCheckSpy).toHaveBeenCalledTimes(0);
+ });
- expect(noticeSpy).toHaveBeenCalledTimes(2);
- expect(noticeSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking after'), {
- file: 'path1.js',
- title: 'message 1',
- startLine: 1
- });
- expect(noticeSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking after'), {
- file: 'path3.js',
- title: 'message 3',
- startLine: 3
+ it('should post four annotations when showAnnotationSeverity is AFTER', async () => {
+ actionConfigMock.showAnnotationSeverity = ShowAnnotationSeverity.AFTER;
+
+ await postAnnotations(fourMixedAnalysisResults.projectResults);
+
+ expect(createCheckSpy).toHaveBeenCalledTimes(1);
+ expect(createCheckSpy).toHaveBeenCalledWith({
+ conclusion: 'success',
+ head_sha: 'head-sha-256',
+ name: 'TICS annotations',
+ output: {
+ annotations: [
+ {
+ annotation_level: 'warning',
+ end_line: 0,
+ message: `Blocking${EOL}Line: 0`,
+ path: 'path0.js',
+ start_line: 0,
+ title: 'message 0'
+ },
+ {
+ annotation_level: 'notice',
+ end_line: 1,
+ message: `Blocking after 1970-01-21${EOL}Level: 2, Category: category 1${EOL}Line: 1, Rule: rule 1`,
+ path: 'path1.js',
+ start_line: 1,
+ title: 'message 1'
+ },
+ {
+ annotation_level: 'warning',
+ end_line: 2,
+ message: `Blocking${EOL}Level: 2, Category: category 2${EOL}Line: 2, Rule: rule 2`,
+ path: 'path2.js',
+ start_line: 2,
+ title: 'message 2'
+ },
+ {
+ annotation_level: 'notice',
+ end_line: 3,
+ message: `Blocking after${EOL}Level: 2, Category: category 3${EOL}Line: 3, Rule: rule 3${EOL}synopsis 3${EOL}Rule-help: https://ruleset/rule+3`,
+ path: 'path3.js',
+ start_line: 3,
+ title: 'message 3'
+ }
+ ],
+ summary: '',
+ title: 'TICS annotations'
+ },
+ owner: 'tester',
+ repo: 'test',
+ status: undefined
});
+ expect(updateCheckSpy).toHaveBeenCalledTimes(0);
});
- it('should post only a blocking annotation when showBlockingAfter is false', () => {
- const warningSpy = jest.spyOn(logger, 'warning');
- const noticeSpy = jest.spyOn(logger, 'notice');
-
- actionConfigMock.showBlockingAfter = false;
-
- postAnnotations(twoMixedAnalysisResults.projectResults);
-
- expect(warningSpy).toHaveBeenCalledTimes(1);
- expect(warningSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking'), {
- file: 'path0.js',
- title: 'message 0',
- startLine: 0
+ it('should post only one blocking annotation when showAnnotationSeverity is BLOCKING', async () => {
+ actionConfigMock.showAnnotationSeverity = ShowAnnotationSeverity.BLOCKING;
+
+ await postAnnotations(twoMixedAnalysisResults.projectResults);
+
+ expect(createCheckSpy).toHaveBeenCalledTimes(1);
+ expect(createCheckSpy).toHaveBeenCalledWith({
+ conclusion: 'success',
+ head_sha: 'head-sha-256',
+ name: 'TICS annotations',
+ output: {
+ annotations: [
+ {
+ annotation_level: 'warning',
+ end_line: 0,
+ message: `Blocking${EOL}Line: 0`,
+ path: 'path0.js',
+ start_line: 0,
+ title: 'message 0'
+ }
+ ],
+ summary: '',
+ title: 'TICS annotations'
+ },
+ owner: 'tester',
+ repo: 'test',
+ status: undefined
});
- expect(noticeSpy).toHaveBeenCalledTimes(0);
+ expect(updateCheckSpy).toHaveBeenCalledTimes(0);
});
- it('should post only two blocking annotations when showBlockingAfter is false', () => {
- const warningSpy = jest.spyOn(logger, 'warning');
- const noticeSpy = jest.spyOn(logger, 'notice');
-
- actionConfigMock.showBlockingAfter = false;
-
- postAnnotations(fourMixedAnalysisResults.projectResults);
-
- expect(warningSpy).toHaveBeenCalledTimes(2);
- expect(warningSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking'), {
- file: 'path0.js',
- title: 'message 0',
- startLine: 0
- });
- expect(warningSpy).toHaveBeenCalledWith(expect.stringContaining('Blocking'), {
- file: 'path2.js',
- title: 'message 2',
- startLine: 2
+ it('should post five annotations when showAnnotationSeverity is ISSUE', async () => {
+ actionConfigMock.showAnnotationSeverity = ShowAnnotationSeverity.ISSUE;
+
+ await postAnnotations(fiveMixedAnalysisResults.projectResults);
+
+ expect(createCheckSpy).toHaveBeenCalledTimes(1);
+ expect(createCheckSpy).toHaveBeenCalledWith({
+ conclusion: 'success',
+ head_sha: 'head-sha-256',
+ name: 'TICS annotations',
+ output: {
+ annotations: [
+ {
+ annotation_level: 'warning',
+ end_line: 0,
+ message: `Blocking${EOL}Line: 0`,
+ path: 'path0.js',
+ start_line: 0,
+ title: 'message 0'
+ },
+ {
+ annotation_level: 'notice',
+ end_line: 1,
+ message: `Blocking after 1970-01-21${EOL}Level: 2, Category: category 1${EOL}Line: 1, Rule: rule 1`,
+ path: 'path1.js',
+ start_line: 1,
+ title: 'message 1'
+ },
+ {
+ annotation_level: 'warning',
+ end_line: 2,
+ message: `Blocking${EOL}Level: 2, Category: category 2${EOL}Line: 2, Rule: rule 2`,
+ path: 'path2.js',
+ start_line: 2,
+ title: 'message 2'
+ },
+ {
+ annotation_level: 'notice',
+ end_line: 3,
+ message: `Blocking after${EOL}Level: 2, Category: category 3${EOL}Line: 3, Rule: rule 3${EOL}synopsis 3${EOL}Rule-help: https://ruleset/rule+3`,
+ path: 'path3.js',
+ start_line: 3,
+ title: 'message 3'
+ },
+ {
+ annotation_level: 'notice',
+ end_line: 2,
+ message: `Non-Blocking${EOL}Level: 2, Category: category 2${EOL}Line: 2, Rule: rule 2`,
+ path: 'path2.js',
+ start_line: 2,
+ title: 'message 2'
+ }
+ ],
+ summary: '',
+ title: 'TICS annotations'
+ },
+ owner: 'tester',
+ repo: 'test',
+ status: undefined
});
- expect(noticeSpy).toHaveBeenCalledTimes(0);
+ expect(updateCheckSpy).toHaveBeenCalledTimes(0);
+ });
+
+ it('should post 200 annotations if all are postable', async () => {
+ (createCheckSpy as SpiedFunction).mockResolvedValue({ data: { id: 1234 } });
+
+ await postAnnotations(twohundredAnnotations());
+
+ expect(createCheckSpy).toHaveBeenCalledTimes(1);
+ expect(updateCheckSpy).toHaveBeenCalledTimes(3);
+ expect(updateCheckSpy).toHaveBeenLastCalledWith(
+ expect.objectContaining({
+ check_run_id: 1234,
+ conclusion: 'success',
+ output: expect.objectContaining({
+ annotations: expect.arrayContaining(new Array(50).fill(expect.any(Object)))
+ })
+ })
+ );
});
});
diff --git a/test/unit/github/objects/annotations.ts b/test/unit/github/objects/annotations.ts
index 7d8b4f80..0ad7ef5d 100644
--- a/test/unit/github/objects/annotations.ts
+++ b/test/unit/github/objects/annotations.ts
@@ -1,5 +1,6 @@
import { Links, ReviewComment, User } from '../../../../src/github/interfaces';
-import { AnalysisResult, ExtendedAnnotation, TicsReviewComment } from '../../../../src/helper/interfaces';
+import { AnalysisResult, ProjectResult } from '../../../../src/helper/interfaces';
+import { ExtendedAnnotation } from '../../../../src/viewer/interfaces';
export const user: User = {
login: '',
@@ -101,7 +102,8 @@ export const analysisResults: AnalysisResult = {
blocking: {
state: 'yes'
},
- instanceName: 'CS'
+ instanceName: 'CS',
+ postable: false
}
],
qualityGate: {
@@ -191,8 +193,7 @@ const fourAnnotations: ExtendedAnnotation[] = [
gateId: 1,
displayCount: '1x',
blocking: {
- state: 'after',
- after: 1757429236
+ state: 'after'
},
instanceName: 'CS',
postable: true,
@@ -224,9 +225,11 @@ export const twoMixedAnalysisResults: AnalysisResult = {
gateId: 1,
displayCount: '1x',
blocking: {
- state: 'yes'
+ state: 'no'
},
- instanceName: 'CS'
+ instanceName: 'CS',
+ postable: true,
+ path: ''
}
],
qualityGate: {
@@ -267,7 +270,8 @@ export const fourMixedAnalysisResults: AnalysisResult = {
state: 'yes'
},
instanceName: 'CS',
- postable: false
+ postable: false,
+ path: ''
}
],
qualityGate: {
@@ -281,3 +285,84 @@ export const fourMixedAnalysisResults: AnalysisResult = {
],
passedWithWarning: false
};
+
+export const fiveMixedAnalysisResults: AnalysisResult = {
+ passed: false,
+ message: 'failed',
+ projectResults: [
+ {
+ project: '',
+ explorerUrl: '',
+ analyzedFiles: [],
+ annotations: [
+ ...fourAnnotations,
+ {
+ fullPath: 'HIE://project/branch/path2.js',
+ line: 2,
+ level: 2,
+ category: 'category 2',
+ rule: 'rule 2',
+ msg: 'message 2',
+ supp: false,
+ type: 'type 2',
+ count: 1,
+ gateId: 1,
+ displayCount: '1x',
+ blocking: {
+ state: 'no'
+ },
+ instanceName: 'CS',
+ postable: true,
+ path: 'path2.js'
+ }
+ ],
+ qualityGate: {
+ passed: false,
+ message: '',
+ url: '',
+ gates: [],
+ annotationsApiV1Links: []
+ }
+ }
+ ],
+ passedWithWarning: false
+};
+
+export const twohundredAnnotations = () => {
+ const projectResults: ProjectResult[] = [
+ {
+ project: '',
+ explorerUrl: '',
+ qualityGate: {
+ passed: false,
+ message: '',
+ url: '',
+ gates: [],
+ annotationsApiV1Links: []
+ },
+ analyzedFiles: [],
+ annotations: []
+ }
+ ];
+
+ for (let i = 0; i < 200; i++) {
+ projectResults[0].annotations.push({
+ fullPath: `HIE://path${0}.js`,
+ path: `path${i}.js`,
+ line: i,
+ msg: `message ${i}`,
+ supp: false,
+ type: `type ${i}`,
+ count: 1,
+ gateId: 1,
+ displayCount: '1x',
+ blocking: {
+ state: 'yes'
+ },
+ ruleset: `Coding Standard ${i}`,
+ instanceName: 'CS',
+ postable: true
+ });
+ }
+ return projectResults;
+};
diff --git a/test/unit/tics/analyzer.test.ts b/test/unit/tics/analyzer.test.ts
index 41ea457b..d2fad398 100644
--- a/test/unit/tics/analyzer.test.ts
+++ b/test/unit/tics/analyzer.test.ts
@@ -42,7 +42,7 @@ describe('test multiple types of configuration', () => {
expect(response.statusCode).toBe(0);
expect(response.completed).toBe(true);
- expect(spy).toHaveBeenCalledWith(`/bin/bash -c "TICS='http://base.com/tiobeweb/TICS/api/cfg?name=default'; TICS -ide github -help"`, [], {
+ expect(spy).toHaveBeenCalledWith(`/bin/bash -c "TICS='http://base.com/tiobeweb/TICS/api/cfg?name=default' TICS -ide github -help"`, [], {
listeners: { errline: expect.any(Function), stdline: expect.any(Function) },
silent: true
});
@@ -60,7 +60,7 @@ describe('test multiple types of configuration', () => {
expect(response.statusCode).toBe(0);
expect(response.completed).toBe(true);
expect(spy).toHaveBeenCalledWith(
- `/bin/bash -c "TICS='http://base.com/tiobeweb/TICS/api/cfg?name=default'; TICS -ide github '@/path/to' -viewer -project 'project' -calc GATE"`,
+ `/bin/bash -c "TICS='http://base.com/tiobeweb/TICS/api/cfg?name=default' TICS -ide github '@/path/to' -viewer -project 'project' -calc GATE"`,
[],
{
listeners: { errline: expect.any(Function), stdline: expect.any(Function) },
@@ -103,7 +103,7 @@ describe('test multiple types of configuration', () => {
expect(response.statusCode).toBe(0);
expect(response.completed).toBe(true);
expect(spy).toHaveBeenCalledWith(
- "/bin/bash -c \"TICS='http://base.com/tiobeweb/TICS/api/cfg?name=default'; TICS -ide github '@/path/to' -viewer -project 'project' -cdtoken token -calc CS -tmpdir '/home/ubuntu/test/123_TICS_1_tics-github-action' -log 9\"",
+ "/bin/bash -c \"TICS='http://base.com/tiobeweb/TICS/api/cfg?name=default' TICS -ide github '@/path/to' -viewer -project 'project' -cdtoken token -calc CS -tmpdir '/home/ubuntu/test/123_TICS_1_tics-github-action' -log 9\"",
[],
{
listeners: { errline: expect.any(Function), stdline: expect.any(Function) },
@@ -371,8 +371,8 @@ describe('test callback functions', () => {
it('should return single error if already exists in errorlist', async () => {
await jest.isolateModulesAsync(async () => {
- const analyzer = require("../../../src/tics/analyzer");
- const exec = require("@actions/exec");
+ const analyzer = require('../../../src/tics/analyzer');
+ const exec = require('@actions/exec');
(exec.exec as any).mockResolvedValue(0);
ticsConfigMock.installTics = false;
@@ -387,8 +387,8 @@ describe('test callback functions', () => {
it('should return two errors in errorlist', async () => {
await jest.isolateModulesAsync(async () => {
- const analyzer = require("../../../src/tics/analyzer");
- const exec = require("@actions/exec");
+ const analyzer = require('../../../src/tics/analyzer');
+ const exec = require('@actions/exec');
(exec.exec as any).mockResolvedValue(0);
const response = await analyzer.runTicsAnalyzer('/path/to');
@@ -402,16 +402,16 @@ describe('test callback functions', () => {
it('should return warnings in warningList', async () => {
await jest.isolateModulesAsync(async () => {
- const analyzer = require("../../../src/tics/analyzer");
- const exec = require("@actions/exec");
+ const analyzer = require('../../../src/tics/analyzer');
+ const exec = require('@actions/exec');
(exec.exec as any).mockResolvedValue(0);
-
+
const response = await analyzer.runTicsAnalyzer('/path/to');
(exec.exec as any).mock.calls[0][2].listeners.stdline('[WARNING 5057] Warning');
(exec.exec as any).mock.calls[0][2].listeners.stdline(`No files to analyze with option '-changed': all checkable files seem to be unchanged.`);
(exec.exec as any).mock.calls[0][2].listeners.stdline('[WARNING 666] Warning');
(exec.exec as any).mock.calls[0][2].listeners.stdline('[WARNING 777] Warning');
-
+
expect(response.warningList).toHaveLength(4);
expect(response.warningList).toEqual([
'[WARNING 5057] Warning',
@@ -424,8 +424,8 @@ describe('test callback functions', () => {
it('should add ExplorerUrl in response', async () => {
await jest.isolateModulesAsync(async () => {
- const analyzer = require("../../../src/tics/analyzer");
- const exec = require("@actions/exec");
+ const analyzer = require('../../../src/tics/analyzer');
+ const exec = require('@actions/exec');
(exec.exec as any).mockResolvedValue(0);
ticsConfigMock.displayUrl = 'http://viewer.com';
@@ -439,22 +439,22 @@ describe('test callback functions', () => {
it('should add all ExplorerUrls in response', async () => {
await jest.isolateModulesAsync(async () => {
- const analyzer = require("../../../src/tics/analyzer");
- const exec = require("@actions/exec");
+ const analyzer = require('../../../src/tics/analyzer');
+ const exec = require('@actions/exec');
(exec.exec as any).mockResolvedValue(0);
ticsConfigMock.displayUrl = 'http://viewer.com';
-
+
await analyzer.runTicsAnalyzer('/another/path');
- (exec.exec as any).mock.calls[0][2].listeners.stdline("http://base.com/Explorer.html#axes=ClientData0");
- (exec.exec as any).mock.calls[0][2].listeners.stdline("http://base.com/Explorer.html#axes=ClientData1");
- (exec.exec as any).mock.calls[0][2].listeners.stdline("http://base.com/Explorer.html#axes=ClientData2");
-
+ (exec.exec as any).mock.calls[0][2].listeners.stdline('http://base.com/Explorer.html#axes=ClientData0');
+ (exec.exec as any).mock.calls[0][2].listeners.stdline('http://base.com/Explorer.html#axes=ClientData1');
+ (exec.exec as any).mock.calls[0][2].listeners.stdline('http://base.com/Explorer.html#axes=ClientData2');
+
const response = await analyzer.runTicsAnalyzer('/another/path');
expect(response.explorerUrls).toEqual([
- "http://viewer.com/Explorer.html#axes=ClientData0",
- "http://viewer.com/Explorer.html#axes=ClientData1",
- "http://viewer.com/Explorer.html#axes=ClientData2",
+ 'http://viewer.com/Explorer.html#axes=ClientData0',
+ 'http://viewer.com/Explorer.html#axes=ClientData1',
+ 'http://viewer.com/Explorer.html#axes=ClientData2'
]);
});
});
diff --git a/test/unit/viewer/annotations.test.ts b/test/unit/viewer/annotations.test.ts
index 44a23fc6..1a82b4f4 100644
--- a/test/unit/viewer/annotations.test.ts
+++ b/test/unit/viewer/annotations.test.ts
@@ -7,6 +7,7 @@ import { GithubEvent } from '../../../src/configuration/github-event';
import { fetchAllAnnotations, groupAndExtendAnnotations } from '../../../src/viewer/annotations';
import { TicsRunIdentifier } from '../../../src/viewer/interfaces';
import { ViewerFeature, viewerVersion } from '../../../src/viewer/version';
+import { ShowAnnotationSeverity } from '../../../src/configuration/action';
describe('fetchAllAnnotations', () => {
let httpClientSpy: jest.SpiedFunction;
@@ -153,10 +154,11 @@ describe('fetchAllAnnotations', () => {
});
identifier.cdtoken = 'test';
+ actionConfigMock.showAnnotationSeverity = ShowAnnotationSeverity.BLOCKING;
const response = await fetchAllAnnotations(qualityGate, identifier);
expect(httpClientSpy).toHaveBeenCalledWith(
- 'http://base.url/api/public/v1/Annotations?metric=QualityGate%28%29&filters=Project%28project%29%2CAnnotationSeverity%28Set%28blocking%2Cafter%29%29%2CClientData%28test%29%2CWindow%28-1%29&fields=default%2CruleHelp%2Csynopsis%2Cruleset%2Cblocking'
+ 'http://base.url/api/public/v1/Annotations?metric=QualityGate%28%29&filters=Project%28project%29%2CAnnotationSeverity%28blocking%29%2CClientData%28test%29%2CWindow%28-1%29&fields=default%2CruleHelp%2Csynopsis%2Cruleset%2Cblocking'
);
expect(response).toEqual([
{ type: 'CS', line: 1, count: 1, instanceName: 'Coding Standard Violations', fullPath: 'HIE://project/branch/file.js', path: 'file.js' },
@@ -177,7 +179,7 @@ describe('fetchAllAnnotations', () => {
});
identifier.date = 15984835158;
- actionConfigMock.showBlockingAfter = true;
+ actionConfigMock.showAnnotationSeverity = ShowAnnotationSeverity.AFTER;
const response = await fetchAllAnnotations(qualityGate, identifier);
expect(httpClientSpy).toHaveBeenCalledWith(