diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml
index f5aad64..b829e9f 100644
--- a/.github/workflows/test-action.yml
+++ b/.github/workflows/test-action.yml
@@ -24,8 +24,8 @@ jobs:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
ATLAN_INSTANCE_URL: ${{secrets.ATLAN_INSTANCE_URL}}
ATLAN_API_TOKEN: ${{secrets.ATLAN_API_TOKEN}}
- # DBT_ENVIRONMENT_BRANCH_MAP: |
- # main: DBT-DEMO-PROD
- # beta: Wide World Importers PE1
- # test-action: Wide World Importers PE1
+ DBT_ENVIRONMENT_BRANCH_MAP: |
+ main: DBT-DEMO-PROD
+ beta: Wide World Importers PE1
+ test-action: Wide World Importers PE1
IGNORE_MODEL_ALIAS_MATCHING: true
diff --git a/src/api/create-resource.js b/adapters/api/create-resource.js
similarity index 69%
rename from src/api/create-resource.js
rename to adapters/api/create-resource.js
index d3f51de..95947e9 100644
--- a/src/api/create-resource.js
+++ b/adapters/api/create-resource.js
@@ -1,12 +1,12 @@
import { v4 as uuidv4 } from "uuid";
import fetch from "node-fetch";
import stringify from "json-stringify-safe";
-import { getAPIToken, getInstanceUrl } from "../utils/index.js";
+import {
+ ATLAN_INSTANCE_URL,
+ ATLAN_API_TOKEN,
+} from "../utils/get-environment-variables.js";
-const ATLAN_INSTANCE_URL = getInstanceUrl();
-const ATLAN_API_TOKEN = getAPIToken();
-
-export default async function createResource( //Done
+export default async function createResource(
guid,
name,
link,
@@ -49,14 +49,15 @@ export default async function createResource( //Done
.then((e) => e.json())
.catch((err) => {
console.log(err);
- sendSegmentEventOfIntegration("dbt_ci_action_failure", {
- reason: "failed_to_create_resource",
- asset_name: name,
- msg: err,
+ sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_failure",
+ properties: {
+ reason: "failed_to_create_resource",
+ asset_name: name, // This should change
+ msg: err,
+ },
});
});
- console.log("Created Resource:", response);
-
return response;
}
diff --git a/src/api/get-asset.js b/adapters/api/get-asset.js
similarity index 62%
rename from src/api/get-asset.js
rename to adapters/api/get-asset.js
index 97b0030..488a94e 100644
--- a/src/api/get-asset.js
+++ b/adapters/api/get-asset.js
@@ -1,17 +1,15 @@
import fetch from "node-fetch";
-import core from "@actions/core";
-import dotenv from "dotenv";
import stringify from "json-stringify-safe";
-
-dotenv.config();
-
-const ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
+import {
+ getErrorModelNotFound,
+ getErrorDoesNotMaterialize,
+} from "../templates/atlan.js";
+import {
+ ATLAN_INSTANCE_URL,
+ ATLAN_API_TOKEN,
+} from "../utils/get-environment-variables.js";
export default async function getAsset({
- //Done
name,
sendSegmentEventOfIntegration,
environment,
@@ -21,7 +19,7 @@ export default async function getAsset({
Authorization: `Bearer ${ATLAN_API_TOKEN}`,
"Content-Type": "application/json",
};
- console.log("At line 24 inside getAsset function");
+
var raw = stringify({
dsl: {
from: 0,
@@ -88,8 +86,7 @@ export default async function getAsset({
headers: myHeaders,
body: raw,
};
- console.log("Before SendSegmentEventOfIntegration");
- console.log("At line 92 inside getAsset");
+
var response = await fetch(
`${ATLAN_INSTANCE_URL}/api/meta/search/indexsearch#findAssetByExactName`,
requestOptions
@@ -105,16 +102,47 @@ export default async function getAsset({
},
});
});
- console.log("<><><><><><><><><><><><><>");
- console.log(response);
- if (!response?.entities?.length)
+
+ if (!response?.entities?.length) {
return {
- error: `❌ Model with name **${name}** could not be found or is deleted
`,
+ error: getErrorModelNotFound(name),
};
+ }
+
+ if (Array.isArray(response.entities)) {
+ response.entities.sort((entityA, entityB) => {
+ const hasDbtModelSqlAssetsA =
+ entityA.attributes.dbtModelSqlAssets &&
+ entityA.attributes.dbtModelSqlAssets.length > 0;
+ const hasDbtModelSqlAssetsB =
+ entityB.attributes.dbtModelSqlAssets &&
+ entityB.attributes.dbtModelSqlAssets.length > 0;
+
+ if (hasDbtModelSqlAssetsA && !hasDbtModelSqlAssetsB) {
+ return -1; // entityA comes before entityB
+ } else if (!hasDbtModelSqlAssetsA && hasDbtModelSqlAssetsB) {
+ return 1; // entityB comes before entityA
+ }
+
+ // Primary sorting criterion: Latest createTime comes first
+ if (entityA.createTime > entityB.createTime) {
+ return -1;
+ } else if (entityA.createTime < entityB.createTime) {
+ return 1;
+ }
+
+ return 0; // No difference in sorting for these two entities
+ });
+ }
if (!response?.entities[0]?.attributes?.dbtModelSqlAssets?.length > 0)
return {
- error: `❌ Model with name [${name}](${ATLAN_INSTANCE_URL}/assets/${response.entities[0].guid}/overview?utm_source=dbt_${integration}_action) does not materialise any asset
`,
+ error: getErrorDoesNotMaterialize(
+ name,
+ ATLAN_INSTANCE_URL,
+ response,
+ integration
+ ),
};
return response.entities[0];
diff --git a/src/api/get-classifications.js b/adapters/api/get-classifications.js
similarity index 60%
rename from src/api/get-classifications.js
rename to adapters/api/get-classifications.js
index c912590..cc954f2 100644
--- a/src/api/get-classifications.js
+++ b/adapters/api/get-classifications.js
@@ -1,10 +1,8 @@
import fetch from "node-fetch";
-import { sendSegmentEvent } from "./index.js";
-import stringify from "json-stringify-safe";
-import { getAPIToken, getInstanceUrl } from "../utils/index.js";
-
-const ATLAN_INSTANCE_URL = getInstanceUrl();
-const ATLAN_API_TOKEN = getAPIToken();
+import {
+ ATLAN_INSTANCE_URL,
+ ATLAN_API_TOKEN,
+} from "../utils/get-environment-variables.js";
export default async function getClassifications({
sendSegmentEventOfIntegration,
@@ -26,9 +24,12 @@ export default async function getClassifications({
)
.then((e) => e.json())
.catch((err) => {
- sendSegmentEventOfIntegration("dbt_ci_action_failure", {
- reason: "failed_to_get_classifications",
- msg: err,
+ sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_failure",
+ properties: {
+ reason: "failed_to_get_classifications",
+ msg: err,
+ },
});
});
diff --git a/src/api/get-downstream-assets.js b/adapters/api/get-downstream-assets.js
similarity index 77%
rename from src/api/get-downstream-assets.js
rename to adapters/api/get-downstream-assets.js
index 910db08..8dec807 100644
--- a/src/api/get-downstream-assets.js
+++ b/adapters/api/get-downstream-assets.js
@@ -1,23 +1,18 @@
import fetch from "node-fetch";
-import core from "@actions/core";
-import dotenv from "dotenv";
import {
getConnectorImage,
getCertificationImage,
getImageURL,
} from "../utils/index.js";
import stringify from "json-stringify-safe";
-
-dotenv.config();
-
-const ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
+import {
+ ATLAN_INSTANCE_URL,
+ ATLAN_API_TOKEN,
+} from "../utils/get-environment-variables.js";
const ASSETS_LIMIT = 100;
-export default async function getDownstreamAssets( //Done
+export default async function getDownstreamAssets(
asset,
guid,
totalModifiedFiles,
@@ -28,7 +23,7 @@ export default async function getDownstreamAssets( //Done
authorization: `Bearer ${ATLAN_API_TOKEN}`,
"content-type": "application/json",
};
- console.log("At line 31 inside getDownstreamAssets function");
+
var raw = stringify({
guid: guid,
size: Math.max(Math.ceil(ASSETS_LIMIT / totalModifiedFiles), 1),
@@ -96,12 +91,15 @@ ${getImageURL(
asset.guid
}/lineage/overview?utm_source=dbt_${integration}_action)`;
- sendSegmentEventOfIntegration("dbt_ci_action_failure", {
- reason: "failed_to_fetch_lineage",
- asset_guid: asset.guid,
- asset_name: asset.name,
- asset_typeName: asset.typeName,
- msg: err,
+ sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_failure",
+ properties: {
+ reason: "failed_to_fetch_lineage",
+ asset_guid: asset.guid,
+ asset_name: asset.name,
+ asset_typeName: asset.typeName,
+ msg: err,
+ },
});
return comment;
@@ -123,7 +121,6 @@ ${getImageURL(
error: handleError(err),
};
});
- console.log("At line 126 inside getDownstreamAssets function", response);
if (response.error) return response;
return response;
diff --git a/src/api/index.js b/adapters/api/index.js
similarity index 100%
rename from src/api/index.js
rename to adapters/api/index.js
diff --git a/src/api/segment.js b/adapters/api/segment.js
similarity index 63%
rename from src/api/segment.js
rename to adapters/api/segment.js
index bd01636..0a0e6f2 100644
--- a/src/api/segment.js
+++ b/adapters/api/segment.js
@@ -1,21 +1,16 @@
import fetch from "node-fetch";
-import core from "@actions/core";
-import dotenv from "dotenv";
-
-dotenv.config();
-
-const { IS_DEV } = process.env;
-const ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
+import {
+ IS_DEV,
+ ATLAN_INSTANCE_URL,
+ ATLAN_API_TOKEN,
+} from "../utils/get-environment-variables.js";
export async function sendSegmentEvent(action, body) {
const myHeaders = {
authorization: `Bearer ${ATLAN_API_TOKEN}`,
"content-type": "application/json",
};
- console.log("At line 18 inide sendSegmentEvent");
+
const requestOptions = {
method: "POST",
headers: myHeaders,
@@ -37,6 +32,6 @@ export async function sendSegmentEvent(action, body) {
} else {
console.log("send segment event", action, body);
}
- console.log("At line 40 inside sendSegmentEvent");
+
return response;
}
diff --git a/src/assets/atlan-logo.png b/adapters/assets/atlan-logo.png
similarity index 100%
rename from src/assets/atlan-logo.png
rename to adapters/assets/atlan-logo.png
diff --git a/src/assets/certification_deprecated.png b/adapters/assets/certification_deprecated.png
similarity index 100%
rename from src/assets/certification_deprecated.png
rename to adapters/assets/certification_deprecated.png
diff --git a/src/assets/certification_drafted.png b/adapters/assets/certification_drafted.png
similarity index 100%
rename from src/assets/certification_drafted.png
rename to adapters/assets/certification_drafted.png
diff --git a/src/assets/certification_verified.png b/adapters/assets/certification_verified.png
similarity index 100%
rename from src/assets/certification_verified.png
rename to adapters/assets/certification_verified.png
diff --git a/src/assets/connector_airflow.png b/adapters/assets/connector_airflow.png
similarity index 100%
rename from src/assets/connector_airflow.png
rename to adapters/assets/connector_airflow.png
diff --git a/src/assets/connector_athena.png b/adapters/assets/connector_athena.png
similarity index 100%
rename from src/assets/connector_athena.png
rename to adapters/assets/connector_athena.png
diff --git a/src/assets/connector_aws-s3.png b/adapters/assets/connector_aws-s3.png
similarity index 100%
rename from src/assets/connector_aws-s3.png
rename to adapters/assets/connector_aws-s3.png
diff --git a/src/assets/connector_azure-datalake.png b/adapters/assets/connector_azure-datalake.png
similarity index 100%
rename from src/assets/connector_azure-datalake.png
rename to adapters/assets/connector_azure-datalake.png
diff --git a/src/assets/connector_bigquery.png b/adapters/assets/connector_bigquery.png
similarity index 100%
rename from src/assets/connector_bigquery.png
rename to adapters/assets/connector_bigquery.png
diff --git a/src/assets/connector_databricks.png b/adapters/assets/connector_databricks.png
similarity index 100%
rename from src/assets/connector_databricks.png
rename to adapters/assets/connector_databricks.png
diff --git a/src/assets/connector_dbt.png b/adapters/assets/connector_dbt.png
similarity index 100%
rename from src/assets/connector_dbt.png
rename to adapters/assets/connector_dbt.png
diff --git a/src/assets/connector_gcp.png b/adapters/assets/connector_gcp.png
similarity index 100%
rename from src/assets/connector_gcp.png
rename to adapters/assets/connector_gcp.png
diff --git a/src/assets/connector_glue.png b/adapters/assets/connector_glue.png
similarity index 100%
rename from src/assets/connector_glue.png
rename to adapters/assets/connector_glue.png
diff --git a/src/assets/connector_grafana.png b/adapters/assets/connector_grafana.png
similarity index 100%
rename from src/assets/connector_grafana.png
rename to adapters/assets/connector_grafana.png
diff --git a/src/assets/connector_looker.png b/adapters/assets/connector_looker.png
similarity index 100%
rename from src/assets/connector_looker.png
rename to adapters/assets/connector_looker.png
diff --git a/src/assets/connector_mocks.png b/adapters/assets/connector_mocks.png
similarity index 100%
rename from src/assets/connector_mocks.png
rename to adapters/assets/connector_mocks.png
diff --git a/src/assets/connector_mysql.png b/adapters/assets/connector_mysql.png
similarity index 100%
rename from src/assets/connector_mysql.png
rename to adapters/assets/connector_mysql.png
diff --git a/src/assets/connector_oracle.png b/adapters/assets/connector_oracle.png
similarity index 100%
rename from src/assets/connector_oracle.png
rename to adapters/assets/connector_oracle.png
diff --git a/src/assets/connector_postgres.png b/adapters/assets/connector_postgres.png
similarity index 100%
rename from src/assets/connector_postgres.png
rename to adapters/assets/connector_postgres.png
diff --git a/src/assets/connector_powerbi.png b/adapters/assets/connector_powerbi.png
similarity index 100%
rename from src/assets/connector_powerbi.png
rename to adapters/assets/connector_powerbi.png
diff --git a/src/assets/connector_presto.png b/adapters/assets/connector_presto.png
similarity index 100%
rename from src/assets/connector_presto.png
rename to adapters/assets/connector_presto.png
diff --git a/src/assets/connector_python.png b/adapters/assets/connector_python.png
similarity index 100%
rename from src/assets/connector_python.png
rename to adapters/assets/connector_python.png
diff --git a/src/assets/connector_r.png b/adapters/assets/connector_r.png
similarity index 100%
rename from src/assets/connector_r.png
rename to adapters/assets/connector_r.png
diff --git a/src/assets/connector_redash.png b/adapters/assets/connector_redash.png
similarity index 100%
rename from src/assets/connector_redash.png
rename to adapters/assets/connector_redash.png
diff --git a/src/assets/connector_redshift.png b/adapters/assets/connector_redshift.png
similarity index 100%
rename from src/assets/connector_redshift.png
rename to adapters/assets/connector_redshift.png
diff --git a/src/assets/connector_sisense.png b/adapters/assets/connector_sisense.png
similarity index 100%
rename from src/assets/connector_sisense.png
rename to adapters/assets/connector_sisense.png
diff --git a/src/assets/connector_snowflake.png b/adapters/assets/connector_snowflake.png
similarity index 100%
rename from src/assets/connector_snowflake.png
rename to adapters/assets/connector_snowflake.png
diff --git a/src/assets/connector_tableau.png b/adapters/assets/connector_tableau.png
similarity index 100%
rename from src/assets/connector_tableau.png
rename to adapters/assets/connector_tableau.png
diff --git a/adapters/gateway.js b/adapters/gateway.js
index df652c5..6b4402e 100644
--- a/adapters/gateway.js
+++ b/adapters/gateway.js
@@ -1,9 +1,10 @@
// Common Gateway for all integrations
+import logger from "./logger/logger.js";
export async function runAction(token, integrationModule) {
if (token === undefined) {
- console.log("Token not provided.");
+ logger.logInfo("Token not provided.", "runAction");
return;
}
const integration = new integrationModule(token);
- await integration.run(); // Add error part
+ await integration.run();
}
diff --git a/adapters/index.js b/adapters/index.js
index 8b34844..16d2e29 100644
--- a/adapters/index.js
+++ b/adapters/index.js
@@ -1,18 +1,14 @@
// main.js
-import dotenv from "dotenv";
import { runAction } from "./gateway.js";
import GitHubIntegration from "./integrations/github-integration.js";
import GitLabIntegration from "./integrations/gitlab-integration.js";
-import core from "@actions/core";
-
-dotenv.config();
-
-const GITHUB_TOKEN = core.getInput("GITHUB_TOKEN") || process.env.GITHUB_TOKEN;
-const GITLAB_TOKEN = process.env.GITLAB_TOKEN;
+import {
+ GITLAB_TOKEN,
+ GITHUB_TOKEN,
+} from "./utils/get-environment-variables.js";
async function run() {
//Add new integrations over here
- console.log("oii");
await runAction(GITHUB_TOKEN, GitHubIntegration);
await runAction(GITLAB_TOKEN, GitLabIntegration);
}
diff --git a/adapters/integrations/github-integration.js b/adapters/integrations/github-integration.js
index 0988609..ff51448 100644
--- a/adapters/integrations/github-integration.js
+++ b/adapters/integrations/github-integration.js
@@ -1,490 +1,847 @@
// githubIntegration.js
-import dotenv from "dotenv"; // Check do we actually need it or not
import IntegrationInterface from "./contract/contract.js";
import github from "@actions/github";
-import { isIgnoreModelAliasMatching } from "../../src/utils/get-environment-variables.js";
+import stringify from "json-stringify-safe";
import {
getCertificationImage,
getConnectorImage,
-} from "../../src/utils/get-image-url.js";
-import { getEnvironments } from "../../src/utils/get-environment-variables.js";
-import stringify from "json-stringify-safe";
+ getEnvironments,
+ auth,
+ truncate,
+} from "../utils/index.js";
import {
getAsset,
getDownstreamAssets,
sendSegmentEvent,
createResource,
getClassifications,
-} from "../../src/api/index.js";
-import { getImageURL, auth } from "../../src/utils/index.js";
-import { isDev } from "../../src/utils/get-environment-variables.js";
-import { truncate } from "../../src/utils/create-comment.js";
-import { getInstanceUrl } from "../../src/utils/get-environment-variables.js";
-
-const IS_DEV = isDev();
-const ATLAN_INSTANCE_URL = getInstanceUrl();
-
-dotenv.config();
-
+} from "../api/index.js";
+import {
+ getSetResourceOnAssetComment,
+ getErrorResponseStatus401,
+ getErrorResponseStatusUndefined,
+ getAssetInfo,
+ getDownstreamTable,
+ getViewAssetButton,
+ getMDCommentForModel,
+ getMDCommentForMaterialisedView,
+ getTableMD,
+} from "../templates/github-integration.js";
+import { getNewModelAddedComment, getBaseComment } from "../templates/atlan.js";
+import {
+ IS_DEV,
+ ATLAN_INSTANCE_URL,
+ IGNORE_MODEL_ALIAS_MATCHING,
+} from "../utils/get-environment-variables.js";
+import logger from "../logger/logger.js";
+var headSHA;
+const integrationName = "github";
export default class GitHubIntegration extends IntegrationInterface {
constructor(token) {
super(token);
}
async run() {
- //Done
- //Complete
- console.log("Run Github");
- console.log(IS_DEV);
- const timeStart = Date.now();
- const { context } = github;
- console.log("Context:", context);
- const octokit = github.getOctokit(this.token);
- const { pull_request } = context?.payload;
- console.log(pull_request, "hii");
-
- console.log("Interesting");
- const { state, merged } = pull_request;
- console.log("state", state);
- console.log("merged", merged);
- if (!(await this.authIntegration({ octokit, context }))) {
- //DONE
- //Complete
- throw { message: "Wrong API Token" };
- }
+ try {
+ const timeStart = Date.now();
+ const { context } = github;
+
+ const octokit = github.getOctokit(this.token);
+ const { pull_request } = context?.payload;
+ const { state, merged } = pull_request;
+ headSHA = pull_request?.head?.sha;
+
+ logger.withInfo(
+ "GitHub Integration is running...",
+ integrationName,
+ headSHA,
+ "run"
+ );
- let total_assets = 0;
- console.log("After auth Integration");
- if (state === "open") {
- total_assets = await this.printDownstreamAssets({ octokit, context });
- } else if (state === "closed" && merged) {
- console.log("Hmm");
- total_assets = await this.setResourceOnAsset({ octokit, context });
- }
+ if (!(await this.authIntegration({ octokit, context }))) {
+ logger.withError(
+ "Authentication failed. Wrong API Token.",
+ integrationName,
+ headSHA,
+ "run"
+ );
+ throw { message: "Wrong API Token" };
+ }
- if (total_assets !== 0) {
- this.sendSegmentEventOfIntegration("dbt_ci_action_run", {
- //Complete
- asset_count: total_assets,
- total_time: Date.now() - timeStart,
- });
+ let total_assets = 0;
+
+ if (state === "open") {
+ total_assets = await this.printDownstreamAssets({ octokit, context });
+ } else if (state === "closed" && merged) {
+ total_assets = await this.setResourceOnAsset({ octokit, context });
+ }
+
+ if (total_assets !== 0) {
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_run",
+ properties: {
+ asset_count: total_assets,
+ total_time: Date.now() - timeStart,
+ },
+ });
+ }
+
+ logger.withInfo(
+ "Successfully Completed DBT_CI_ACTION",
+ integrationName,
+ headSHA,
+ "run"
+ );
+ } catch (error) {
+ logger.withError(
+ `Error in run(): ${error.message}`,
+ integrationName,
+ headSHA,
+ "run"
+ );
+ throw error;
}
}
async printDownstreamAssets({ octokit, context }) {
- //Done
- console.log("Brother");
- // const changedFiles = await this.getChangedFiles({ octokit, context }); //Complete
- var changedFiles = [
- {
- fileName: "instacart_beverages_order_customer",
- filePath: "instacart_beverages_order_customer.sql",
- status: "modified",
- },
- ];
- let comments = ``;
- let totalChangedFiles = 0;
-
- for (const { fileName, filePath, status } of changedFiles) {
- const aliasName = await this.getAssetName({
- //Complete
- octokit,
- context,
- fileName,
- filePath,
- });
- const assetName = isIgnoreModelAliasMatching() ? fileName : aliasName; //Complete
- console.log("acha2");
- const environments = getEnvironments();
-
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === context.payload.pull_request.base.ref) {
- environment = environmentName;
- break;
+ logger.withInfo(
+ "Printing downstream assets...",
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+
+ try {
+ const changedFiles = await this.getChangedFiles({ octokit, context });
+ let comments = ``;
+ let totalChangedFiles = 0;
+
+ for (const { fileName, filePath, status } of changedFiles) {
+ logger.withInfo(
+ `Processing file: ${fileName}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ const aliasName = await this.getAssetName({
+ octokit,
+ context,
+ fileName,
+ filePath,
+ });
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
+
+ const environments = getEnvironments();
+ let environment = null;
+ for (const [baseBranchName, environmentName] of environments) {
+ if (baseBranchName === context.payload.pull_request.base.ref) {
+ environment = environmentName;
+ break;
+ }
}
- }
- console.log("Before getAsset");
- const asset = await getAsset({
- //Done
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "github",
- });
- console.log("After getAsset");
- if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
- console.log("Status: ", status);
- if (status === "added") {
- comments += `### ${getConnectorImage("dbt")} ${fileName} 🆕
-Its a new model and not present in Atlan yet, you'll see the downstream impact for it after its present in Atlan.`;
- totalChangedFiles++;
- continue;
- }
- console.log("Before filtering");
- console.log("Asset", asset);
- if (asset.error) {
- comments += asset.error;
- totalChangedFiles++;
- continue;
- }
- const materialisedAsset = asset.attributes.dbtModelSqlAssets[0];
- const timeStart = Date.now();
- const totalModifiedFiles = changedFiles.filter(
- (i) => i.status === "modified"
- ).length;
- console.log("Before getDownstreamAssets");
- const downstreamAssets = await getDownstreamAssets(
- //Complete
- asset,
- materialisedAsset.guid,
- totalModifiedFiles
- );
- console.log("After getDownstreamAssets");
- if (downstreamAssets.error) {
- comments += downstreamAssets.error;
- totalChangedFiles++;
- continue;
- }
- console.log("At line 139 after getDownstreamAssets in printDownstream");
- this.sendSegmentEventOfIntegration("dbt_ci_action_downstream_unfurl", {
- //Complete
- asset_guid: asset.guid,
- asset_type: asset.typeName,
- downstream_count: downstreamAssets.entities.length,
- total_fetch_time: Date.now() - timeStart,
- });
- console.log("At line 147 after getDownstreamAssets in printDownstream");
- const classifications = await getClassifications({
- //Complete
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- });
+ logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "github",
+ });
+
+ if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
+
+ if (status === "added") {
+ logger.withInfo(
+ `New model added: ${fileName}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ comments += getNewModelAddedComment(fileName);
+ totalChangedFiles++;
+ continue;
+ }
- const comment = await this.renderDownstreamAssetsComment({
- //Done
- //Complete
- octokit,
- context,
- asset,
- materialisedAsset,
- downstreamAssets,
- classifications,
- });
+ if (asset.error) {
+ logger.withError(
+ `Asset error for ${assetName}: ${asset.error}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ comments += asset.error;
+ totalChangedFiles++;
+ continue;
+ }
- comments += comment;
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
- totalChangedFiles++;
- }
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
- comments = `### ${getImageURL("atlan-logo", 15, 15)} Atlan impact analysis
-Here is your downstream impact analysis for **${totalChangedFiles} ${
- totalChangedFiles > 1 ? "models" : "model"
- }** you have edited.
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "github"
+ );
-${comments}`;
+ if (downstreamAssets.error) {
+ logger.withError(
+ `Downstream assets error for ${assetName}: ${downstreamAssets.error}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ comments += downstreamAssets.error;
+ totalChangedFiles++;
+ continue;
+ }
- const existingComment = await this.checkCommentExists({ octokit, context }); //Complete
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
+
+ const classifications = await getClassifications({
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ });
+
+ const comment = await this.renderDownstreamAssetsComment({
+ octokit,
+ context,
+ asset,
+ materialisedAsset,
+ downstreamAssets,
+ classifications,
+ });
- if (totalChangedFiles > 0)
- await this.createIssueComment({
- //Complete
- octokit,
- context,
- content: comments,
- comment_id: existingComment?.id,
- });
+ comments += comment;
- if (totalChangedFiles === 0 && existingComment)
- await this.deleteComment({
- //Complete
+ totalChangedFiles++;
+ }
+
+ comments = getBaseComment(totalChangedFiles, comments);
+
+ const existingComment = await this.checkCommentExists({
octokit,
context,
- comment_id: existingComment.id,
});
- return totalChangedFiles;
+ logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+
+ if (totalChangedFiles > 0)
+ await this.createIssueComment({
+ octokit,
+ context,
+ content: comments,
+ comment_id: existingComment?.id,
+ });
+
+ if (totalChangedFiles === 0 && existingComment)
+ await this.deleteComment({
+ octokit,
+ context,
+ comment_id: existingComment?.id,
+ });
+
+ logger.withInfo(
+ "Successfully printed Downstream Assets",
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+
+ return totalChangedFiles;
+ } catch (error) {
+ logger.withError(
+ `Error in printDownstreamAssets: ${error.message}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ throw error;
+ }
}
async setResourceOnAsset({ octokit, context }) {
- //Done
- //Complete
- const changedFiles = await this.getChangedFiles({ octokit, context }); //Complete
- const { pull_request } = context.payload;
- var totalChangedFiles = 0;
-
- if (changedFiles.length === 0) return;
+ logger.withInfo(
+ "Setting resources on assets...",
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
- for (const { fileName, filePath } of changedFiles) {
- const assetName = await this.getAssetName({
- //Complete
- octokit,
- context,
- fileName,
- filePath,
- });
+ try {
+ const changedFiles = await this.getChangedFiles({ octokit, context });
+ const { pull_request } = context.payload;
+ var totalChangedFiles = 0;
+ let tableMd = ``;
+ let setResourceFailed = false;
+
+ if (changedFiles.length === 0) {
+ logger.withInfo(
+ "No changed files found. Skipping resource setup.",
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ return totalChangedFiles;
+ }
- const environments = getEnvironments();
+ for (const { fileName, filePath } of changedFiles) {
+ logger.withInfo(
+ `Processing file: ${fileName}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ const aliasName = await this.getAssetName({
+ octokit,
+ context,
+ fileName,
+ filePath,
+ });
+
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
+
+ logger.withInfo(
+ `Resolved asset name: ${assetName}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === context.payload.pull_request.base.ref) {
- environment = environmentName;
- break;
+ const environments = getEnvironments();
+ let environment = null;
+ for (const [baseBranchName, environmentName] of environments) {
+ if (baseBranchName === context.payload.pull_request.base.ref) {
+ environment = environmentName;
+ break;
+ }
}
- }
- const asset = await getAsset({
- //Done
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "github",
- });
+ logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
- if (asset.error) continue;
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "github",
+ });
+
+ if (asset.error) {
+ logger.withError(
+ `Failed to retrieve asset: ${assetName}, Error: ${asset.error}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
- const { guid: modelGuid } = asset;
- const { guid: tableAssetGuid } =
- asset?.attributes?.dbtModelSqlAssets?.[0];
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
- if (modelGuid)
- await createResource(
- //Complete
- modelGuid,
- "Pull Request on GitHub",
- pull_request.html_url,
- this.sendSegmentEventOfIntegration
- );
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
- if (tableAssetGuid)
- await createResource(
- //Complete
- tableAssetGuid,
- "Pull Request on GitHub",
- pull_request.html_url,
- this.sendSegmentEventOfIntegration
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "github"
);
- totalChangedFiles++;
- }
-
- const comment = await this.createIssueComment({
- //Complete
- octokit,
- context,
- content: `🎊 Congrats on the merge!
+ if (downstreamAssets.error) {
+ logger.withError(
+ `Failed to retrieve downstream assets for: ${assetName}, Error: ${downstreamAssets.error}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
-This pull request has been added as a resource to all the assets modified. ✅
-`,
- comment_id: null,
- forceNewComment: true,
- });
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
+
+ const model = asset;
+ const materialisedView = asset?.attributes?.dbtModelSqlAssets?.[0];
+
+ let PR_TITLE = pull_request.title;
+
+ if (downstreamAssets.entityCount != 0) {
+ if (model) {
+ const { guid: modelGuid } = model;
+ const resp = await createResource(
+ modelGuid,
+ PR_TITLE,
+ pull_request.html_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = getMDCommentForModel(ATLAN_INSTANCE_URL, model);
+ tableMd += getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger.withError(
+ `Setting resource failed for model: ${modelGuid}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
- return totalChangedFiles;
- }
+ if (materialisedView) {
+ const { guid: tableAssetGuid } = materialisedView;
+ const resp = await createResource(
+ tableAssetGuid,
+ PR_TITLE,
+ pull_request.html_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = getMDCommentForMaterialisedView(
+ ATLAN_INSTANCE_URL,
+ materialisedView
+ );
+ tableMd += getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger.withError(
+ `Setting resource failed for materialized view: ${tableAssetGuid}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
+ }
+ totalChangedFiles++;
+ }
- async authIntegration({ octokit, context }) {
- //DONE
- //COMPLETE
- console.log("Here is Context:", context);
- const response = await auth();
- console.log("Inside authIntegration befor comment exists");
- const existingComment = await this.checkCommentExists({ octokit, context });
-
- console.log("Existing Comment", existingComment);
-
- if (response?.status === 401) {
- console.log("Inside authIntegration befor createIssueComment");
- await this.createIssueComment({
+ const comment = await this.createIssueComment({
octokit,
context,
- content: `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` as this repository's action secret.
+ content: getSetResourceOnAssetComment(tableMd, setResourceFailed),
+ comment_id: null,
+ forceNewComment: true,
+ });
-Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+ logger.withInfo(
+ "Successfully set the resource on the asset",
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
-Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`,
- comment_id: existingComment?.id,
- });
- return false;
+ return totalChangedFiles;
+ } catch (error) {
+ logger.withError(
+ `Error in setResourceOnAsset: ${error}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ throw error;
}
+ }
+
+ async authIntegration({ octokit, context }) {
+ logger.withInfo(
+ "Authenticating with Atlan",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
- if (response === undefined) {
- await this.createIssueComment({
+ try {
+ const response = await auth();
+
+ const existingComment = await this.checkCommentExists({
octokit,
context,
- content: `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` as this repository's action secret.
+ });
-Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+ logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
-Make sure your Atlan Instance URL is set in the following format.
-\`https://tenant.atlan.com\`
+ if (response?.status === 401) {
+ logger.withError(
+ "Authentication failed: Status 401",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ octokit,
+ context,
+ content: getErrorResponseStatus401(ATLAN_INSTANCE_URL, context),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
-Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`,
- comment_id: existingComment?.id,
- });
- return false;
+ if (response === undefined) {
+ logger.withError(
+ "Authentication failed: Undefined response",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ octokit,
+ context,
+ content: getErrorResponseStatusUndefined(ATLAN_INSTANCE_URL, context),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
+ logger.withInfo(
+ "Successfully Authenticated with Atlan",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ return true;
+ } catch (error) {
+ logger.withError(
+ `Error in authIntegration: ${error.message}`,
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ throw error;
}
-
- return true;
}
async sendSegmentEventOfIntegration({ action, properties }) {
- //Done
- //FullyComplete
- // IMPORT ATLAN_INSTANCE_URL.
- const domain = new URL(ATLAN_INSTANCE_URL).hostname;
-
- const raw = stringify({
- category: "integration",
- object: "github",
- action,
- userId: "atlan-annonymous-github",
- properties: {
- ...properties,
- //get context for this
- // github_action_id: `https://github.com/${context.payload.repository.full_name}/actions/runs/${context.runId}`,
- domain,
- },
- });
+ try {
+ const domain = new URL(ATLAN_INSTANCE_URL).hostname;
+ const { context } = github; //confirm this
+ logger.withInfo(
+ `Sending Segment event for action: ${action}`,
+ integrationName,
+ headSHA,
+ "sendSegmentEventOfIntegration"
+ );
- return sendSegmentEvent(action, raw);
+ const raw = stringify({
+ category: "integration",
+ object: "github",
+ action,
+ userId: "atlan-annonymous-github",
+ properties: {
+ ...properties,
+ github_action_id: `https://github.com/${context?.payload?.repository?.full_name}/actions/runs/${context?.runId}`,
+ domain,
+ },
+ });
+
+ return sendSegmentEvent(action, raw);
+ } catch (error) {
+ logger.withError(
+ `Error sending Segment event for action: ${action} - ${error.message}`,
+ integrationName,
+ headSHA,
+ "sendSegmentEventOfIntegration"
+ );
+ throw error;
+ }
}
async getChangedFiles({ octokit, context }) {
- //Done
- //FullyComplete
- const { repository, pull_request } = context.payload,
- owner = repository.owner.login,
- repo = repository.name,
- pull_number = pull_request.number;
-
- const res = await octokit.request(
- `GET /repos/${owner}/${repo}/pulls/${pull_number}/files`,
- {
- owner,
- repo,
- pull_number,
- }
- );
+ try {
+ logger.withInfo(
+ "Fetching changed files...",
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
- var changedFiles = res.data
- .map(({ filename, status }) => {
- try {
- const [modelName] = filename
- .match(/.*models\/(.*)\.sql/)[1]
- .split("/")
- .reverse()[0]
- .split(".");
-
- if (modelName) {
- return {
- fileName: modelName,
- filePath: filename,
- status,
- };
- }
- } catch (e) {}
- })
- .filter((i) => i !== undefined);
+ const { repository, pull_request } = context.payload,
+ owner = repository.owner.login,
+ repo = repository.name,
+ pull_number = pull_request.number;
- changedFiles = changedFiles.filter((item, index) => {
- return (
- changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
- index
+ const res = await octokit.request(
+ `GET /repos/${owner}/${repo}/pulls/${pull_number}/files`,
+ {
+ owner,
+ repo,
+ pull_number,
+ }
);
- });
- console.log("Changed Files: ", changedFiles);
+ var changedFiles = res.data
+ .map(({ filename, status }) => {
+ try {
+ const [modelName] = filename
+ .match(/.*models\/(.*)\.sql/)[1]
+ .split("/")
+ .reverse()[0]
+ .split(".");
+
+ if (modelName) {
+ return {
+ fileName: modelName,
+ filePath: filename,
+ status,
+ };
+ }
+ } catch (e) {
+ logger.withError(
+ `Error processing file: ${filename} - ${e.message}`,
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
+ }
+ })
+ .filter((i) => i !== undefined);
+
+ changedFiles = changedFiles.filter((item, index) => {
+ return (
+ changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
+ index
+ );
+ });
- return changedFiles;
+ logger.withInfo(
+ "Successfully fetched changed files",
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
+
+ return changedFiles;
+ } catch (error) {
+ logger.withError(
+ `Error fetching changed files - ${error.message}`,
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
+ throw error;
+ }
}
async getAssetName({ octokit, context, fileName, filePath }) {
- //Done
- // FullyComplete
- var regExp =
- /{{\s*config\s*\(\s*(?:[^,]*,)*\s*alias\s*=\s*['"]([^'"]+)['"](?:\s*,[^,]*)*\s*\)\s*}}/im;
- var fileContents = await this.getFileContents({
- octokit,
- context,
- filePath,
- });
+ try {
+ logger.withInfo(
+ "Getting asset name...",
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
- if (fileContents) {
- var matches = regExp.exec(fileContents);
+ var regExp =
+ /{{\s*config\s*\(\s*(?:[^,]*,)*\s*alias\s*=\s*['"]([^'"]+)['"](?:\s*,[^,]*)*\s*\)\s*}}/im;
+ var fileContents = await this.getFileContents({
+ octokit,
+ context,
+ filePath,
+ });
- if (matches) {
- return matches[1].trim();
+ if (fileContents) {
+ var matches = regExp.exec(fileContents);
+ if (matches) {
+ logger.withInfo(
+ `Found a match: ${matches[1].trim()}`,
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
+ return matches[1].trim();
+ }
}
+ logger.withInfo(
+ `Using filename as asset name: ${fileName}`,
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
+ return fileName;
+ } catch (error) {
+ logger.withError(
+ `Error getting asset name - ${error.message}`,
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
+ throw error;
}
-
- return fileName;
}
async getFileContents({ octokit, context, filePath }) {
- //Done
- // FullyComplete
- const { repository, pull_request } = context.payload,
- owner = repository.owner.login,
- repo = repository.name,
- head_sha = pull_request.head.sha;
-
- const res = await octokit
- .request(
- `GET /repos/${owner}/${repo}/contents/${filePath}?ref=${head_sha}`,
- {
- owner,
- repo,
- path: filePath,
- }
- )
- .catch((e) => {
- console.log("Error fetching file contents: ", e);
- return null;
- });
-
- if (!res) return null;
+ try {
+ logger.withInfo(
+ "Fetching file contents...",
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
- const buff = Buffer.from(res.data.content, "base64");
+ const { repository, pull_request } = context.payload,
+ owner = repository.owner.login,
+ repo = repository.name,
+ head_sha = pull_request.head.sha;
+
+ const res = await octokit
+ .request(
+ `GET /repos/${owner}/${repo}/contents/${filePath}?ref=${head_sha}`,
+ {
+ owner,
+ repo,
+ path: filePath,
+ }
+ )
+ .catch((e) => {
+ logger.withError(
+ `Error fetching file contents: ${e.message}`,
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
+ return null;
+ });
+
+ if (!res) return null;
+
+ const buff = Buffer.from(res.data.content, "base64");
+
+ logger.withInfo(
+ "Successfully fetched file contents",
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
- return buff.toString("utf8");
+ return buff.toString("utf8");
+ } catch (error) {
+ logger.withError(
+ `Error in getFileContents: ${error.message}`,
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
+ throw error;
+ }
}
async checkCommentExists({ octokit, context }) {
- //Done
- //FullyComplete
- if (IS_DEV) return null;
+ logger.withInfo(
+ "Checking for existing comments...",
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+
+ if (IS_DEV) {
+ logger.withInfo(
+ "Development mode enabled. Skipping comment check.",
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ return null;
+ }
const { pull_request } = context.payload;
- const comments = await octokit.rest.issues.listComments({
- ...context.repo,
- issue_number: pull_request.number,
- });
+ try {
+ const comments = await octokit.rest.issues.listComments({
+ ...context.repo,
+ issue_number: pull_request.number,
+ });
- return comments.data.find(
- (comment) =>
- comment.user.login === "github-actions[bot]" &&
- comment.body.includes(
- ""
- )
- );
+ const existingComment = comments.data.find(
+ (comment) =>
+ comment.user.login === "github-actions[bot]" &&
+ comment.body.includes(
+ ""
+ )
+ );
+ if (existingComment) {
+ logger.withInfo(
+ "Found existing comment: " + existingComment?.id,
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ } else {
+ logger.withInfo(
+ "No existing comment found",
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ }
+
+ return existingComment;
+ } catch (error) {
+ logger.withError(
+ "Error checking for existing comments: " + error.message,
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ throw error;
+ }
}
async createIssueComment({
- //Done
- // FullyComplete
octokit,
context,
content,
comment_id = null,
forceNewComment = false,
}) {
- console.log("Inside CreateIssue:", context);
- console.log("Inside CreateIssue Comment");
+ logger.withInfo(
+ "Creating an issue comment...",
+ integrationName,
+ headSHA,
+ "createIssueComment"
+ );
+
const { pull_request } = context?.payload || {};
- console.log("Inside CreateIssue Comment");
+
content = `
${content}`;
@@ -494,10 +851,15 @@ ${content}`;
body: content,
};
- console.log(content, content.length);
- console.log("Inside CreateIssue Comment Complete");
-
- if (IS_DEV) return content;
+ if (IS_DEV) {
+ logger.withInfo(
+ "Development mode enabled. Skipping comment creation.",
+ integrationName,
+ headSHA,
+ "createIssueComment"
+ );
+ return content;
+ }
if (comment_id && !forceNewComment)
return octokit.rest.issues.updateComment({ ...commentObj, comment_id });
@@ -505,8 +867,13 @@ ${content}`;
}
async deleteComment({ octokit, context, comment_id }) {
- //Done
- //FullyComplete
+ logger.withInfo(
+ `Deleted comment with ID ${comment_id}`,
+ integrationName,
+ headSHA,
+ "deleteComment"
+ );
+
const { pull_request } = context.payload;
return octokit.rest.issues.deleteComment({
@@ -517,8 +884,6 @@ ${content}`;
}
async renderDownstreamAssetsComment({
- //Done
- //FullyComplete
octokit,
context,
asset,
@@ -526,163 +891,148 @@ ${content}`;
downstreamAssets,
classifications,
}) {
- let impactedData = downstreamAssets.entities.map(
- ({
- displayText,
- guid,
- typeName,
- attributes,
- meanings,
- classificationNames,
- }) => {
- // Modifying the typeName and getting the readableTypeName
- let readableTypeName = typeName
- .toLowerCase()
- .replace(attributes.connectorName, "")
- .toUpperCase();
-
- // Filtering classifications based on classificationNames
- let classificationsObj = classifications.filter(({ name }) =>
- classificationNames.includes(name)
- );
+ logger.withInfo(
+ "Rendering Downstream Assets...",
+ integrationName,
+ headSHA,
+ "renderDownstreamAssetsComment"
+ );
+ try {
+ let impactedData = downstreamAssets.entities.map(
+ ({
+ displayText,
+ guid,
+ typeName,
+ attributes,
+ meanings,
+ classificationNames,
+ }) => {
+ // Modifying the typeName and getting the readableTypeName
+ let readableTypeName = typeName
+ .toLowerCase()
+ .replace(attributes.connectorName, "")
+ .toUpperCase();
+
+ // Filtering classifications based on classificationNames
+ let classificationsObj = classifications.filter(({ name }) =>
+ classificationNames.includes(name)
+ );
+
+ // Modifying the readableTypeName
+ readableTypeName =
+ readableTypeName.charAt(0).toUpperCase() +
+ readableTypeName.slice(1).toLowerCase();
+
+ return [
+ guid,
+ truncate(displayText),
+ truncate(attributes.connectorName),
+ truncate(readableTypeName),
+ truncate(
+ attributes?.userDescription || attributes?.description || ""
+ ),
+ attributes?.certificateStatus || "",
+ truncate(
+ [...attributes?.ownerUsers, ...attributes?.ownerGroups] || []
+ ),
+ truncate(
+ meanings.map(
+ ({ displayText, termGuid }) =>
+ `[${displayText}](${ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_github_action)`
+ )
+ ),
+ truncate(
+ classificationsObj?.map(
+ ({ name, displayName }) => `\`${displayName}\``
+ )
+ ),
+ attributes?.sourceURL || "",
+ ];
+ }
+ );
- // Modifying the readableTypeName
- readableTypeName =
- readableTypeName.charAt(0).toUpperCase() +
- readableTypeName.slice(1).toLowerCase();
+ // Sorting the impactedData first by typeName and then by connectorName
+ impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
+ impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
- return [
+ // Creating rows for the downstream table
+ let rows = impactedData.map(
+ ([
guid,
- truncate(displayText),
- truncate(attributes.connectorName),
- truncate(readableTypeName),
- truncate(
- attributes?.userDescription || attributes?.description || ""
- ),
- attributes?.certificateStatus || "",
- truncate(
- [...attributes?.ownerUsers, ...attributes?.ownerGroups] || []
- ),
- truncate(
- meanings.map(
- ({ displayText, termGuid }) =>
- `[${displayText}](${ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_github_action)`
- )
- ),
- truncate(
- classificationsObj?.map(
- ({ name, displayName }) => `\`${displayName}\``
- )
- ),
- attributes?.sourceURL || "",
- ];
- }
- );
-
- // Sorting the impactedData first by typeName and then by connectorName
- impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
- impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
-
- // Creating rows for the downstream table
- let rows = impactedData.map(
- ([
- guid,
- displayText,
- connectorName,
- typeName,
- description,
- certificateStatus,
- owners,
- meanings,
- classifications,
- sourceUrl,
- ]) => {
- // Getting connector and certification images
- const connectorImage = getConnectorImage(connectorName);
- const certificationImage = certificateStatus
- ? getCertificationImage(certificateStatus)
- : "";
-
- return [
- `${connectorImage} [${displayText}](${ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_github_action) ${certificationImage}`,
- `\`${typeName}\``,
+ displayText,
+ connectorName,
+ typeName,
description,
+ certificateStatus,
owners,
meanings,
classifications,
- sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
- ];
- }
- );
+ sourceUrl,
+ ]) => {
+ // Getting connector and certification images
+ const connectorImage = getConnectorImage(connectorName);
+ const certificationImage = certificateStatus
+ ? getCertificationImage(certificateStatus)
+ : "";
+
+ return [
+ `${connectorImage} [${displayText}](${ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_github_action) ${certificationImage}`,
+ `\`${typeName}\``,
+ description,
+ owners,
+ meanings,
+ classifications,
+ sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
+ ];
+ }
+ );
- const environmentName =
- materialisedAsset?.attributes?.assetDbtEnvironmentName;
- const projectName = materialisedAsset?.attributes?.assetDbtProjectName;
- // Generating asset information
- const assetInfo = `### ${getConnectorImage(
- asset.attributes.connectorName
- )} [${asset.displayText}](${ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }/overview?utm_source=dbt_github_action) ${
- asset.attributes?.certificateStatus
- ? getCertificationImage(asset.attributes.certificateStatus)
- : ""
- }
-Materialised asset: ${getConnectorImage(
- materialisedAsset.attributes.connectorName
- )} [${materialisedAsset.attributes.name}](${ATLAN_INSTANCE_URL}/assets/${
- materialisedAsset.guid
- }/overview?utm_source=dbt_github_action) ${
- materialisedAsset.attributes?.certificateStatus
- ? getCertificationImage(materialisedAsset.attributes.certificateStatus)
- : ""
- }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ""}${
- projectName ? ` | Project Name: \`${projectName}\`` : ""
- }`;
-
- // Generating the downstream table
- const downstreamTable = `${
- downstreamAssets.entityCount
- } downstream assets 👇
-
-Name | Type | Description | Owners | Terms | Classifications | Source URL
---- | --- | --- | --- | --- | --- | ---
-${rows
- .map((row) =>
- row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
- )
- .join("\n")}
-
-${
- downstreamAssets.hasMore
- ? `[See more downstream assets at Atlan](${ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_github_action)`
- : ""
-}
+ const environmentName =
+ materialisedAsset?.attributes?.assetDbtEnvironmentName;
+ const projectName = materialisedAsset?.attributes?.assetDbtProjectName;
+ // Generating asset information
- `;
+ const assetInfo = getAssetInfo(
+ ATLAN_INSTANCE_URL,
+ asset,
+ materialisedAsset,
+ environmentName,
+ projectName
+ );
+
+ // Generating the downstream table
+ const downstreamTable = getDownstreamTable(
+ ATLAN_INSTANCE_URL,
+ downstreamAssets,
+ rows,
+ materialisedAsset
+ );
- // Generating the "View asset in Atlan" button
- const viewAssetButton = `${getImageURL(
- "atlan-logo",
- 15,
- 15
- )} [View asset in Atlan](${ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }/overview?utm_source=dbt_github_action)`;
+ // Generating the "View asset in Atlan" button
+ const viewAssetButton = getViewAssetButton(ATLAN_INSTANCE_URL, asset);
- // Generating the final comment based on the presence of downstream assets
- if (downstreamAssets.entities.length > 0) {
- return `${assetInfo}
+ // Generating the final comment based on the presence of downstream assets
+ if (downstreamAssets.entities.length > 0) {
+ return `${assetInfo}
${downstreamTable}
${viewAssetButton}`;
- } else {
- return `${assetInfo}
+ } else {
+ return `${assetInfo}
No downstream assets found.
${viewAssetButton}`;
+ }
+ } catch (error) {
+ logger.withError(
+ `Error rendering Downstream Assets: ${error.message}`,
+ integrationName,
+ headSHA,
+ "renderDownstreamAssetsComment"
+ );
+ throw error;
}
}
}
diff --git a/adapters/integrations/gitlab-integration.js b/adapters/integrations/gitlab-integration.js
index 87506db..8110b19 100644
--- a/adapters/integrations/gitlab-integration.js
+++ b/adapters/integrations/gitlab-integration.js
@@ -1,6 +1,4 @@
// gitlabIntegration.js
-import dotenv from "dotenv";
-
import IntegrationInterface from "./contract/contract.js";
import { Gitlab } from "@gitbeaker/rest";
import {
@@ -8,16 +6,44 @@ import {
getAsset,
getDownstreamAssets,
sendSegmentEvent,
-} from "../../src/api/index.js";
-import { getImageURL, auth } from "../../src/utils/index.js";
-import { getGitLabEnvironments } from "../../src/utils/get-environment-variables.js";
-import { getConnectorImage } from "../../src/utils/index.js";
-import { getCertificationImage } from "../../src/utils/index.js";
+ getClassifications,
+} from "../api/index.js";
+import {
+ auth,
+ getConnectorImage,
+ getCertificationImage,
+ getGitLabEnvironments,
+ truncate,
+} from "../utils/index.js";
import stringify from "json-stringify-safe";
-
-dotenv.config();
-const ATLAN_INSTANCE_URL = process.env.ATLAN_INSTANCE_URL;
-const { IS_DEV } = process.env;
+import {
+ getSetResourceOnAssetComment,
+ getErrorResponseStatus401,
+ getErrorResponseStatusUndefined,
+ getAssetInfo,
+ getDownstreamTable,
+ getViewAssetButton,
+ getMDCommentForModel,
+ getMDCommentForMaterialisedView,
+ getTableMD,
+} from "../templates/gitlab-integration.js";
+import { getNewModelAddedComment, getBaseComment } from "../templates/atlan.js";
+import {
+ IS_DEV,
+ ATLAN_INSTANCE_URL,
+ CI_PROJECT_PATH,
+ CI_PROJECT_ID,
+ CI_JOB_URL,
+ IGNORE_MODEL_ALIAS_MATCHING,
+ CI_COMMIT_MESSAGE,
+ CI_PROJECT_NAME,
+ CI_COMMIT_SHA,
+ getCIMergeRequestIID,
+ CI_PROJECT_NAMESPACE,
+} from "../utils/get-environment-variables.js";
+import logger from "../logger/logger.js";
+const integrationName = "gitlab";
+var CI_MERGE_REQUEST_IID;
export default class GitLabIntegration extends IntegrationInterface {
constructor(token) {
@@ -25,290 +51,576 @@ export default class GitLabIntegration extends IntegrationInterface {
}
async run() {
- //Done
- console.log("Run Gitlab");
- const timeStart = Date.now();
+ try {
+ const timeStart = Date.now();
+ const gitlab = new Gitlab({
+ host: "https://gitlab.com",
+ token: this.token,
+ });
- const gitlab = new Gitlab({
- host: "https://gitlab.com",
- token: this.token,
- });
+ CI_MERGE_REQUEST_IID = await getCIMergeRequestIID(
+ gitlab,
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+ );
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ var mergeRequestCommit = await gitlab.Commits.allMergeRequests(
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+ );
- if (!(await this.authIntegration({ gitlab })))
- //Done
- throw { message: "Wrong API Token" };
+ logger.withInfo(
+ "GitLab Integration is running...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
- const { state, web_url, source_branch } = await gitlab.MergeRequests.show(
- CI_PROJECT_PATH,
- CI_MERGE_REQUEST_IID
- );
- console.log("At line 47", state, web_url, source_branch);
- let total_assets = 0;
+ if (!(await this.authIntegration({ gitlab }))) {
+ logger.withError(
+ "Authentication failed. Wrong API Token.",
+ integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
+ throw { message: "Wrong API Token" };
+ }
- if (state === "opened") {
- total_assets = await this.printDownstreamAssets({
- gitlab,
- source_branch,
- });
- } else if (state === "merged") {
- total_assets = await this.setResourceOnAsset({
- gitlab,
- web_url,
- source_branch,
- });
- }
+ let total_assets = 0;
+
+ if (
+ mergeRequestCommit.length &&
+ mergeRequestCommit[0]?.state == "merged"
+ ) {
+ const { web_url, target_branch, diff_refs } =
+ await gitlab.MergeRequests.show(
+ CI_PROJECT_PATH,
+ mergeRequestCommit[0]?.iid
+ );
+ total_assets = await this.setResourceOnAsset({
+ gitlab,
+ web_url,
+ target_branch,
+ diff_refs,
+ });
+ } else {
+ const { target_branch, diff_refs } = await gitlab.MergeRequests.show(
+ CI_PROJECT_PATH,
+ CI_MERGE_REQUEST_IID
+ );
+
+ total_assets = await this.printDownstreamAssets({
+ gitlab,
+ target_branch,
+ diff_refs,
+ });
+ }
- if (total_assets !== 0)
- this.sendSegmentEventOfIntegration("dbt_ci_action_run", {
- asset_count: total_assets,
- total_time: Date.now() - timeStart,
- });
+ if (total_assets !== 0)
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_run",
+ properties: {
+ asset_count: total_assets,
+ total_time: Date.now() - timeStart,
+ },
+ });
+
+ logger.withInfo(
+ "Successfully Completed DBT_CI_PIPELINE",
+ integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
+ } catch (error) {
+ logger.withError(
+ `Error in run(): ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
+ throw error;
+ }
}
- async printDownstreamAssets({ gitlab, source_branch }) {
- //Done
- // Implementation for printing impact on GitHub
- // Use this.token to access the token
- console.log("At line 74 inside printDownstreamAssets");
- const changedFiles = await this.getChangedFiles({ gitlab }); //Complete
- console.log("At line 75", changedFiles);
- let comments = ``;
- let totalChangedFiles = 0;
-
- for (const { fileName, filePath, headSHA } of changedFiles) {
- const assetName = await this.getAssetName({
- //Complete
- gitlab,
- fileName,
- filePath,
- headSHA,
- });
- console.log("At line 88");
- const environments = getGitLabEnvironments();
- console.log("At line 90", environments);
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === source_branch) {
- environment = environmentName;
- break;
+ async printDownstreamAssets({ gitlab, target_branch, diff_refs }) {
+ logger.withInfo(
+ "Printing downstream assets...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+
+ try {
+ const changedFiles = await this.getChangedFiles({ gitlab, diff_refs });
+
+ let comments = ``;
+ let totalChangedFiles = 0;
+
+ for (const { fileName, filePath, headSHA, status } of changedFiles) {
+ logger.withInfo(
+ `Processing file: ${fileName}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ const aliasName = await this.getAssetName({
+ gitlab,
+ fileName,
+ filePath,
+ headSHA,
+ });
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
+
+ const environments = getGitLabEnvironments();
+ let environment = null;
+ for (const baseBranchName of Object.keys(environments)) {
+ const environmentName = environments[baseBranchName];
+ if (baseBranchName === target_branch) {
+ environment = environmentName;
+ break;
+ }
}
- }
- console.log("At line 98", environment);
- const asset = await getAsset({
- //Complete
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "gitlab",
- });
- if (asset.error) {
- comments += asset.error;
- totalChangedFiles++;
- continue;
- }
- console.log("At line 112", asset);
- //Cross-check this part once with Jaagrav.
-
- const totalModifiedFiles = changedFiles.filter(
- (i) => i.status === "modified"
- ).length;
- console.log("At line 118", totalModifiedFiles);
- const { guid } = asset.attributes.sqlAsset;
- const timeStart = Date.now();
- const downstreamAssets = await getDownstreamAssets(
- //Done
- asset,
- guid,
- totalModifiedFiles,
- this.sendSegmentEventOfIntegration,
- "gitlab"
- );
- console.log("At line 129 Completed getDownstreamAssets");
- if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
+ logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "gitlab",
+ });
+
+ if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
+
+ if (status === "added") {
+ logger.withInfo(
+ `New model added: ${fileName}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ comments += getNewModelAddedComment(fileName);
+ totalChangedFiles++;
+ continue;
+ }
+
+ if (asset.error) {
+ logger.withError(
+ `Asset error for ${assetName}: ${asset.error}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ comments += asset.error;
+ totalChangedFiles++;
+ continue;
+ }
+
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
+
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
+
+ const { guid } = asset;
+
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "gitlab"
+ );
+
+ if (downstreamAssets.error) {
+ logger.withError(
+ `Downstream assets error for ${assetName}: ${downstreamAssets.error}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ comments += downstreamAssets.error;
+ totalChangedFiles++;
+ continue;
+ }
+
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
+
+ const classifications = await getClassifications({
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ });
+
+ const comment = await this.renderDownstreamAssetsComment({
+ asset,
+ downstreamAssets,
+ classifications,
+ materialisedAsset,
+ });
+
+ comments += comment;
- if (downstreamAssets.error) {
- comments += downstreamAssets.error;
totalChangedFiles++;
- continue;
}
- this.sendSegmentEventOfIntegration("dbt_ci_action_downstream_unfurl", {
- //Complete
- asset_guid: asset.guid,
- asset_type: asset.typeName,
- downstream_count: downstreamAssets.length,
- total_fetch_time: Date.now() - timeStart,
- });
+ comments = getBaseComment(totalChangedFiles, comments);
- const comment = await this.renderDownstreamAssetsComment({
- //Complete
- asset,
- downstreamAssets,
- });
+ const existingComment = await this.checkCommentExists({ gitlab });
- comments += comment;
+ logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+
+ if (totalChangedFiles > 0)
+ await this.createIssueComment({
+ gitlab,
+ content: comments,
+ comment_id: existingComment?.id,
+ });
+
+ if (totalChangedFiles === 0 && existingComment)
+ await this.deleteComment({ gitlab, comment_id: existingComment?.id });
+
+ logger.withInfo(
+ "Successfully printed Downstream Assets",
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
- totalChangedFiles++;
+ return totalChangedFiles;
+ } catch (error) {
+ logger.withError(
+ `Error in printDownstreamAssets: ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ throw error;
}
+ }
- comments = `### ${getImageURL("atlan-logo", 15, 15)} Atlan impact analysis
-Here is your downstream impact analysis for **${totalChangedFiles} ${
- totalChangedFiles > 1 ? "models" : "model"
- }** you have edited.
-
-${comments}`;
- console.log("At line 163 in printDownstreamAssets");
- const existingComment = await this.checkCommentExists({ gitlab }); //Complete
- console.log("At line 165 after checkCommentExists");
- if (totalChangedFiles > 0)
- await this.createIssueComment({
- //Complete
- gitlab,
- comments,
- comment_id: existingComment?.id,
- });
+ async setResourceOnAsset({ gitlab, web_url, target_branch, diff_refs }) {
+ logger.withInfo(
+ "Setting resources on assets...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
- if (totalChangedFiles === 0 && existingComment)
- await this.deleteComment({ gitlab, comment_id: existingComment.id }); //Complete
- console.log("Completed PrintDownstreamAssets");
- return totalChangedFiles;
- }
+ try {
+ const changedFiles = await this.getChangedFiles({ gitlab, diff_refs });
+
+ var totalChangedFiles = 0;
+ let tableMd = ``;
+ let setResourceFailed = false;
+ if (changedFiles.length === 0) {
+ logger.withInfo(
+ "No changed files found. Skipping resource setup.",
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ return totalChangedFiles;
+ }
- async setResourceOnAsset({ gitlab, web_url, source_branch }) {
- //Done
- // Implementation for setting resources on GitHub
- // Use this.token to access the token
- const changedFiles = await this.getChangedFiles({ gitlab }); //Done
- var totalChangedFiles = 0;
+ for (const { fileName, filePath, headSHA } of changedFiles) {
+ const aliasName = await this.getAssetName({
+ gitlab,
+ fileName,
+ filePath,
+ headSHA,
+ });
+
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
+
+ logger.withInfo(
+ `Resolved asset name: ${assetName}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+
+ const environments = getGitLabEnvironments();
+ let environment = null;
+ for (const baseBranchName of Object.keys(environments)) {
+ const environmentName = environments[baseBranchName];
+ if (baseBranchName === target_branch) {
+ environment = environmentName;
+ break;
+ }
+ }
- if (changedFiles.length === 0) return;
+ logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "gitlab",
+ });
+
+ if (asset.error) {
+ logger.withError(
+ `Failed to retrieve asset: ${assetName}, Error: ${asset.error}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
- for (const { fileName, filePath, headSHA } of changedFiles) {
- const assetName = await this.getAssetName({
- gitlab,
- fileName,
- filePath,
- headSHA,
- });
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
+
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
+
+ const { guid } = asset;
+
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "gitlab"
+ );
+
+ if (downstreamAssets.error) {
+ logger.withError(
+ `Failed to retrieve downstream assets for: ${assetName}, Error: ${downstreamAssets.error}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
- const environments = getGitLabEnvironments();
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
+
+ const model = asset;
+ const materialisedView = asset?.attributes?.dbtModelSqlAssets?.[0];
+
+ var lines = CI_COMMIT_MESSAGE.split("\n");
+ var CI_MERGE_REQUEST_TITLE = lines[2];
+
+ if (downstreamAssets.entityCount != 0) {
+ if (model) {
+ const { guid: modelGuid } = model;
+ const resp = await createResource(
+ modelGuid,
+ CI_MERGE_REQUEST_TITLE,
+ web_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = getMDCommentForModel(ATLAN_INSTANCE_URL, model);
+ tableMd += getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger.withError(
+ `Setting resource failed for model: ${modelGuid}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === source_branch) {
- environment = environmentName;
- break;
+ if (materialisedView) {
+ const { guid: tableAssetGuid } = materialisedView;
+ const resp = await createResource(
+ tableAssetGuid,
+ CI_MERGE_REQUEST_TITLE,
+ web_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = getMDCommentForMaterialisedView(
+ ATLAN_INSTANCE_URL,
+ materialisedView
+ );
+ tableMd += getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger.withError(
+ `Setting resource failed for materialized view: ${tableAssetGuid}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
}
+
+ totalChangedFiles++;
}
- const asset = await getAsset({
- //Done
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "gitlab",
+ const comment = await this.createIssueComment({
+ gitlab,
+ content: getSetResourceOnAssetComment(tableMd, setResourceFailed),
+ comment_id: null,
+ forceNewComment: true,
});
- if (!asset) continue;
-
- const { guid: modelGuid } = asset;
- const { guid: tableAssetGuid } = asset.attributes.sqlAsset;
-
- await createResource(
- //Done
- //Complete
- modelGuid,
- "Pull Request on GitLab",
- web_url,
- this.sendSegmentEventOfIntegration
- );
- await createResource(
- //Done
- tableAssetGuid,
- "Pull Request on GitLab",
- web_url,
- this.sendSegmentEventOfIntegration
+ logger.withInfo(
+ "Successfully set the resource on the asset",
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
);
- totalChangedFiles++;
+ return totalChangedFiles;
+ } catch (error) {
+ logger.withError(
+ `Error in setResourceOnAsset: ${error}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ throw error;
}
-
- const comment = await this.createIssueComment({
- //Done
- //Complete
- gitlab,
- content: `🎊 Congrats on the merge!
-
-This pull request has been added as a resource to all the assets modified. ✅
-`,
- comment_id: null,
- forceNewComment: true,
- });
-
- return totalChangedFiles;
}
async authIntegration({ gitlab }) {
- //Done
- const response = await auth();
+ logger.withInfo(
+ "Authenticating with Atlan",
+ integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
- if (response?.status === 401) {
- //Complete
- await this.createIssueComment(
- gitlab,
- `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` in your .gitlab-ci.yml file.
+ try {
+ const response = await auth();
-Atlan Instance URL: ${ATLAN_INSTANCE_URL}`
- );
- return false;
- }
+ const existingComment = await this.checkCommentExists({ gitlab });
- if (response === undefined) {
- await this.createIssueComment(
- gitlab,
- `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` in your .gitlab-ci.yml file.
-
-Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+ logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
-Make sure your Atlan Instance URL is set in the following format.
-\`https://tenant.atlan.com\`
+ if (response?.status === 401) {
+ logger.withError(
+ "Authentication failed: Status 401",
+ integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ gitlab,
+ content: getErrorResponseStatus401(
+ ATLAN_INSTANCE_URL,
+ CI_PROJECT_NAME,
+ CI_PROJECT_NAMESPACE
+ ),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
-`
+ if (response === undefined) {
+ logger.withError(
+ "Authentication failed: Undefined response",
+ integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ gitlab,
+ content: getErrorResponseStatusUndefined(
+ ATLAN_INSTANCE_URL,
+ CI_PROJECT_NAME,
+ CI_PROJECT_NAMESPACE
+ ),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
+ logger.withInfo(
+ "Successfully Authenticated with Atlan",
+ integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
+ return true;
+ } catch (error) {
+ logger.withError(
+ `Error in authIntegration: ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
);
- return false;
+ throw error;
}
-
- return true;
}
async createIssueComment({
- //Done
- //Complete
gitlab,
content,
comment_id = null,
forceNewComment = false,
}) {
- console.log("At line 295 inside createIssueComment");
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ logger.withInfo(
+ "Creating an issue comment...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "createIssueComment"
+ );
content = `
${content}`;
- console.log("At line 301 inside createIssueComment", content);
-
- if (IS_DEV) return content;
+ if (IS_DEV) {
+ logger.withInfo(
+ "Development mode enabled. Skipping comment creation.",
+ integrationName,
+ CI_COMMIT_SHA,
+ "createIssueComment"
+ );
+ return content;
+ }
- if (comment_id && !forceNewComment)
+ if (comment_id && !forceNewComment) {
return await gitlab.MergeRequestNotes.edit(
- CI_PROJECT_PATH,
+ CI_PROJECT_ID,
CI_MERGE_REQUEST_IID,
comment_id,
- content
+ {
+ body: content,
+ }
);
+ }
return await gitlab.MergeRequestNotes.create(
CI_PROJECT_PATH,
CI_MERGE_REQUEST_IID,
@@ -317,154 +629,277 @@ ${content}`;
}
async sendSegmentEventOfIntegration({ action, properties }) {
- //Done
- //Complete
- // Implement your sendSegmentEvent logic here
- // IMPORT ATLAN_INSTANCE_URL.
- console.log("At line 324 inside sendSegmentOfIntegration");
- const domain = new URL(ATLAN_INSTANCE_URL).hostname;
- const { CI_PROJECT_PATH, CI_JOB_URL } = process.env;
-
- const raw = stringify({
- category: "integration",
- object: "gitlab",
- action,
- userId: "atlan-annonymous-github",
- properties: {
- ...properties,
- gitlab_job_id: CI_JOB_URL,
- domain,
- },
- });
- // IMPORT SEGMENTEVENT
- return sendSegmentEvent(action, raw);
+ try {
+ const domain = new URL(ATLAN_INSTANCE_URL).hostname;
+ logger.withInfo(
+ `Sending Segment event for action: ${action}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "sendSegmentEventOfIntegration"
+ );
+
+ const raw = stringify({
+ category: "integration",
+ object: "gitlab",
+ action,
+ userId: "atlan-annonymous-github",
+ properties: {
+ ...properties,
+ gitlab_job_id: CI_JOB_URL,
+ domain,
+ },
+ });
+
+ return sendSegmentEvent(action, raw);
+ } catch (error) {
+ logger.withError(
+ `Error sending Segment event for action: ${action} - ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "sendSegmentEventOfIntegration"
+ );
+ throw error;
+ }
}
- async getChangedFiles({ gitlab }) {
- //Done
- //Complete
- console.log("At line 344 Inside getChangedFiles");
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ async getChangedFiles({ gitlab, diff_refs }) {
+ try {
+ logger.withInfo(
+ "Fetching changed files...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
+ );
- const { changes, diff_refs } = await gitlab.MergeRequests.changes(
- CI_PROJECT_PATH,
- CI_MERGE_REQUEST_IID
- );
- console.log("At line 351 Inside getChangedFiles");
- var changedFiles = changes
- .map(({ new_path, old_path }) => {
- try {
- const [modelName] = new_path
- .match(/.*models\/(.*)\.sql/)[1]
- .split("/")
- .reverse()[0]
- .split(".");
-
- //Cross-check this with Jaagrav. ###
- if (modelName) {
- if (old_path === null) {
- return {
- fileName: modelName,
- filePath: new_path,
- headSHA: diff_refs.head_sha,
- status: "added",
- };
- } else if (new_path !== old_path) {
- // File is renamed or moved
- return {
- fileName: modelName,
- filePath: new_path,
- headSHA: diff_refs.head_sha,
- status: "renamed_or_moved",
- };
- } else {
- // File is modified
- return {
- fileName: modelName,
- filePath: new_path,
- headSHA: diff_refs.head_sha,
- status: "modified",
- };
+ var changes = await gitlab.MergeRequests.allDiffs(
+ CI_PROJECT_PATH,
+ CI_MERGE_REQUEST_IID
+ );
+
+ var changedFiles = changes
+ .map(({ new_path, old_path, new_file }) => {
+ try {
+ const [modelName] = new_path
+ .match(/.*models\/(.*)\.sql/)[1]
+ .split("/")
+ .reverse()[0]
+ .split(".");
+
+ if (modelName) {
+ if (new_file) {
+ return {
+ fileName: modelName,
+ filePath: new_path,
+ headSHA: diff_refs.head_sha,
+ status: "added",
+ };
+ } else if (new_path !== old_path) {
+ // File is renamed or moved
+ return {
+ fileName: modelName,
+ filePath: new_path,
+ headSHA: diff_refs.head_sha,
+ status: "renamed_or_moved",
+ };
+ } else {
+ // File is modified
+ return {
+ fileName: modelName,
+ filePath: new_path,
+ headSHA: diff_refs.head_sha,
+ status: "modified",
+ };
+ }
}
+ } catch (e) {
+ logger.withError(
+ `Error processing file`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
+ );
}
- } catch (e) {}
- })
- .filter((i) => i !== undefined);
+ })
+ .filter((i) => i !== undefined);
+
+ changedFiles = changedFiles.filter((item, index) => {
+ return (
+ changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
+ index
+ );
+ });
- changedFiles = changedFiles.filter((item, index) => {
- return (
- changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
- index
+ logger.withInfo(
+ "Successfully fetched changed files",
+ integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
);
- });
-
- console.log("At line 399 Completed getChangedFiles ", changedFiles);
- return changedFiles;
+ return changedFiles;
+ } catch (error) {
+ logger.withError(
+ `Error fetching changed files - ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
+ );
+ throw error;
+ }
}
async getAssetName({ gitlab, fileName, filePath, headSHA }) {
- //Done
- //Complete
- console.log("At line 407 inside getAssetName");
- var regExp = /config\(.*alias=\'([^']+)\'.*\)/im;
- var fileContents = await this.getFileContents({
- gitlab,
- filePath,
- headSHA,
- });
- console.log("At line 414 inside getAssetName");
- var matches = regExp.exec(fileContents);
- console.log("At line 416");
- if (matches) {
- return matches[1];
+ try {
+ logger.withInfo(
+ "Getting asset name...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
+
+ var regExp =
+ /{{\s*config\s*\(\s*(?:[^,]*,)*\s*alias\s*=\s*['"]([^'"]+)['"](?:\s*,[^,]*)*\s*\)\s*}}/im;
+ var fileContents = await this.getFileContents({
+ gitlab,
+ filePath,
+ headSHA,
+ });
+
+ if (fileContents) {
+ var matches = regExp.exec(fileContents);
+ if (matches) {
+ logger.withInfo(
+ `Found a match: ${matches[1].trim()}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
+ return matches[1].trim();
+ }
+ }
+
+ logger.withInfo(
+ `Using filename as asset name: ${fileName}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
+
+ return fileName;
+ } catch (error) {
+ logger.withError(
+ `Error getting asset name - ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
+ throw error;
}
- console.log("At line 420 completed getAssetName");
- return fileName;
}
async getFileContents({ gitlab, filePath, headSHA }) {
- //Done
- //Complete
- console.log("At line 427 inside getFileContents");
- const { CI_PROJECT_PATH } = process.env;
- const { content } = await gitlab.RepositoryFiles.show(
- CI_PROJECT_PATH,
- filePath,
- headSHA
- );
- const buff = Buffer.from(content, "base64");
- console.log("At line 435 inside getFileContents");
- return buff.toString("utf8");
+ try {
+ logger.withInfo(
+ "Fetching file contents...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "getFileContents"
+ );
+
+ const { content } = await gitlab.RepositoryFiles.show(
+ CI_PROJECT_PATH,
+ filePath,
+ headSHA
+ );
+ const buff = Buffer.from(content, "base64");
+
+ logger.withInfo(
+ "Successfully fetched file contents",
+ integrationName,
+ CI_COMMIT_SHA,
+ "getFileContents"
+ );
+
+ return buff.toString("utf8");
+ } catch (error) {
+ logger.withError(
+ `Error in getFileContents: ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "getFileContents"
+ );
+ throw error;
+ }
}
async checkCommentExists({ gitlab }) {
- //Done
- //Complete
- console.log("At line 442 inside checkCommentExists");
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
- if (IS_DEV) return null;
-
- const comments = await gitlab.MergeRequestNotes.all(
- CI_PROJECT_PATH,
- CI_MERGE_REQUEST_IID
+ logger.withInfo(
+ "Checking for existing comments...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
);
- return comments.find(
- // Why here we have hardocded value? What should be over here inplace of this.
- (comment) =>
- comment.author.username === "Jaagrav" &&
- comment.body.includes(
- ""
- )
- );
+ if (IS_DEV) {
+ logger.withInfo(
+ "Development mode enabled. Skipping comment check.",
+ integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ return null;
+ }
+
+ try {
+ const comments = await gitlab.MergeRequestNotes.all(
+ CI_PROJECT_PATH,
+ CI_MERGE_REQUEST_IID
+ );
+
+ const identifier = `project_${CI_PROJECT_ID}_bot_`;
+
+ const existingComment = comments.find(
+ (comment) =>
+ comment.author.username.includes(identifier) &&
+ comment.body.includes(
+ ""
+ )
+ );
+ if (existingComment) {
+ logger.withInfo(
+ "Found existing comment: " + existingComment?.id,
+ integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ } else {
+ logger.withInfo(
+ "No existing comment found",
+ integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ }
+
+ return existingComment;
+ } catch (error) {
+ logger.withError(
+ "Error checking for existing comments: " + error.message,
+ integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ throw error;
+ }
}
async deleteComment({ gitlab, comment_id }) {
- //Done
- //Complete
- console.log("At line 464 inside deleteComment");
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ logger.withInfo(
+ `Deleted comment with ID ${comment_id}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "deleteComment"
+ );
return await gitlab.MergeRequestNotes.remove(
CI_PROJECT_PATH,
@@ -473,95 +908,154 @@ ${content}`;
);
}
- async renderDownstreamAssetsComment({ asset, downstreamAssets }) {
- //Done
- console.log("At line 474 inside renderDownstreamAssetsComment");
- let impactedData = downstreamAssets.map(
- ({ displayText, guid, typeName, attributes, meanings }) => {
- let readableTypeName = typeName
- .toLowerCase()
- .replace(attributes.connectorName, "")
- .toUpperCase();
- readableTypeName =
- readableTypeName.charAt(0).toUpperCase() +
- readableTypeName.slice(1).toLowerCase();
- return [
+ async renderDownstreamAssetsComment({
+ asset,
+ downstreamAssets,
+ classifications,
+ materialisedAsset,
+ }) {
+ logger.withInfo(
+ "Rendering Downstream Assets...",
+ integrationName,
+ CI_COMMIT_SHA,
+ "renderDownstreamAssetsComment"
+ );
+
+ try {
+ let impactedData = downstreamAssets.entities.map(
+ ({
+ displayText,
+ guid,
+ typeName,
+ attributes,
+ meanings,
+ classificationNames,
+ }) => {
+ // Modifying the typeName and getting the readableTypeName
+ let readableTypeName = typeName
+ .toLowerCase()
+ .replace(attributes.connectorName, "")
+ .toUpperCase();
+
+ // Filtering classifications based on classificationNames
+ let classificationsObj = classifications.filter(({ name }) =>
+ classificationNames.includes(name)
+ );
+
+ // Modifying the readableTypeName
+ readableTypeName =
+ readableTypeName.charAt(0).toUpperCase() +
+ readableTypeName.slice(1).toLowerCase();
+
+ return [
+ guid,
+ truncate(displayText),
+ truncate(attributes.connectorName),
+ truncate(readableTypeName),
+ truncate(
+ attributes?.userDescription || attributes?.description || ""
+ ),
+ attributes?.certificateStatus || "",
+ truncate(
+ [...attributes?.ownerUsers, ...attributes?.ownerGroups] || []
+ ),
+ truncate(
+ meanings.map(
+ ({ displayText, termGuid }) =>
+ `[${displayText}](${ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_gitlab_action)`
+ )
+ ),
+ truncate(
+ classificationsObj?.map(
+ ({ name, displayName }) => `\`${displayName}\``
+ )
+ ),
+ attributes?.sourceURL || "",
+ ];
+ }
+ );
+
+ // Sorting the impactedData first by typeName and then by connectorName
+ impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
+ impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
+
+ // Creating rows for the downstream table
+ let rows = impactedData.map(
+ ([
guid,
displayText,
- attributes.connectorName,
- readableTypeName,
- attributes?.userDescription || attributes?.description || "",
- attributes?.certificateStatus || "",
- [...attributes?.ownerUsers, ...attributes?.ownerGroups] || [],
- meanings
- .map(
- ({ displayText, termGuid }) =>
- `[${displayText}](${ATLAN_INSTANCE_URL}/assets/${termGuid}?utm_source=dbt_gitlab_action)`
- )
- ?.join(", ") || " ",
- attributes?.sourceURL || "",
- ];
- }
- );
- console.log("At line 502 in renderDownstreamAsset");
- impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3])); // Sort by typeName
- impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2])); // Sort by connectorName
-
- let rows = impactedData.map(
- ([
- guid,
- displayText,
- connectorName,
- typeName,
- description,
- certificateStatus,
- owners,
- meanings,
- sourceUrl,
- ]) => {
- const connectorImage = getConnectorImage(connectorName),
- certificationImage = certificateStatus
+ connectorName,
+ typeName,
+ description,
+ certificateStatus,
+ owners,
+ meanings,
+ classifications,
+ sourceUrl,
+ ]) => {
+ // Getting connector and certification images
+ const connectorImage = getConnectorImage(connectorName);
+ const certificationImage = certificateStatus
? getCertificationImage(certificateStatus)
: "";
- return [
- `${connectorImage} [${displayText}](${ATLAN_INSTANCE_URL}/assets/${guid}?utm_source=dbt_gitlab_action) ${certificationImage}`,
- `\`${typeName}\``,
- description,
- owners.join(", ") || " ",
- meanings,
- sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
- ];
- }
- );
+ return [
+ `${connectorImage} [${displayText}](${ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_gitlab_action) ${certificationImage}`,
+ `\`${typeName}\``,
+ description,
+ owners,
+ meanings,
+ classifications,
+ sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
+ ];
+ }
+ );
- const comment = `### ${getConnectorImage(
- asset.attributes.connectorName
- )} [${asset.displayText}](${ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }?utm_source=dbt_gitlab_action) ${
- asset.attributes?.certificateStatus
- ? getCertificationImage(asset.attributes.certificateStatus)
- : ""
- }
+ const environmentName =
+ materialisedAsset?.attributes?.assetDbtEnvironmentName;
+ const projectName = materialisedAsset?.attributes?.assetDbtProjectName;
+ // Generating asset information
+ const assetInfo = getAssetInfo(
+ ATLAN_INSTANCE_URL,
+ asset,
+ materialisedAsset,
+ environmentName,
+ projectName
+ );
- **${downstreamAssets.length} downstream assets** 👇
- Name | Type | Description | Owners | Terms | Source URL
- --- | --- | --- | --- | --- | ---
- ${rows
- .map((row) =>
- row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
- )
- .join("\n")}
-
- ${getImageURL(
- "atlan-logo",
- 15,
- 15
- )} [View asset in Atlan](${ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }?utm_source=dbt_gitlab_action)`;
- console.log("At line 560 Completed renderDownstream");
- return comment;
+ // Generating the downstream table
+ const downstreamTable = getDownstreamTable(
+ ATLAN_INSTANCE_URL,
+ downstreamAssets,
+ rows,
+ materialisedAsset
+ );
+
+ // Generating the "View asset in Atlan" button
+ const viewAssetButton = getViewAssetButton(ATLAN_INSTANCE_URL, asset);
+
+ // Generating the final comment based on the presence of downstream assets
+ if (downstreamAssets.entities.length > 0) {
+ return `${assetInfo}
+
+${downstreamTable}
+
+${viewAssetButton}`;
+ } else {
+ return `${assetInfo}
+
+No downstream assets found.
+
+${viewAssetButton}`;
+ }
+ } catch (error) {
+ logger.withError(
+ `Error rendering Downstream Assets: ${error.message}`,
+ integrationName,
+ CI_COMMIT_SHA,
+ "renderDownstreamAssetsComment"
+ );
+ throw error;
+ }
}
}
diff --git a/adapters/logger/logger.js b/adapters/logger/logger.js
new file mode 100644
index 0000000..ef36876
--- /dev/null
+++ b/adapters/logger/logger.js
@@ -0,0 +1,65 @@
+// logger.js
+
+function getCurrentTimestamp() {
+ const now = new Date();
+ return now.toISOString();
+}
+
+function logInfo(message, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "ERROR",
+ timestamp,
+ method,
+ message,
+ };
+ console.error(logEntry);
+}
+
+function withInfo(message, vcs, sha, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "INFO",
+ timestamp,
+ vcs,
+ sha,
+ method,
+ message,
+ };
+ console.log(logEntry);
+}
+
+function withError(message, vcs, sha, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "ERROR",
+ timestamp,
+ vcs,
+ sha,
+ method,
+ message,
+ };
+ console.error(logEntry);
+}
+
+function debug(message, vcs, sha, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "DEBUG",
+ timestamp,
+ vcs,
+ sha,
+ method,
+ message,
+ };
+ console.debug(logEntry);
+}
+
+const logger = {
+ withInfo,
+ withError,
+ debug,
+ logInfo,
+};
+
+export default logger;
diff --git a/adapters/templates/atlan.js b/adapters/templates/atlan.js
new file mode 100644
index 0000000..d84e475
--- /dev/null
+++ b/adapters/templates/atlan.js
@@ -0,0 +1,32 @@
+import {getConnectorImage, getImageURL} from "../utils/index.js"
+
+export function getErrorModelNotFound(name) {
+ return `
+
❌ Model with name **${name}** could not be found or is deleted
+ `;
+}
+
+export function getErrorDoesNotMaterialize(
+ name,
+ ATLAN_INSTANCE_URL,
+ response,
+ integration
+) {
+
+ return `
+
❌ Model with name [${name}](${ATLAN_INSTANCE_URL}/assets/${response.entities[0].guid}/overview?utm_source=dbt_${integration}_action) does not materialise any asset
`;
+}
+
+export function getNewModelAddedComment(fileName) {
+ return `### ${getConnectorImage("dbt")} ${fileName} 🆕
+ Its a new model and not present in Atlan yet, you'll see the downstream impact for it after its present in Atlan.`
+}
+
+export function getBaseComment(totalChangedFiles, comments) {
+ return `### ${getImageURL("atlan-logo", 15, 15)} Atlan impact analysis
+ Here is your downstream impact analysis for **${totalChangedFiles} ${
+ totalChangedFiles > 1 ? "models" : "model"
+ }** you have edited.
+
+ ${comments}`
+}
\ No newline at end of file
diff --git a/adapters/templates/github-integration.js b/adapters/templates/github-integration.js
new file mode 100644
index 0000000..8e0cb8e
--- /dev/null
+++ b/adapters/templates/github-integration.js
@@ -0,0 +1,102 @@
+import { getImageURL, getConnectorImage, getCertificationImage } from "../utils/index.js";
+
+export function getErrorResponseStatus401 (ATLAN_INSTANCE_URL, context) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` as this repository's action secret.
+
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+export function getErrorResponseStatusUndefined(ATLAN_INSTANCE_URL, context) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` as this repository's action secret.
+
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Make sure your Atlan Instance URL is set in the following format.
+\`https://tenant.atlan.com\`
+
+Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+export function getSetResourceOnAssetComment(tableMd, setResourceFailed) {
+ return `## 🎊 Congrats on the merge!
+
+This pull request has been added as a resource to the following assets:
+Name | Resource set successfully
+--- | ---
+${tableMd}
+${setResourceFailed ? '> Seems like we were unable to set the resources for some of the assets due to insufficient permissions. To ensure that the pull request is linked as a resource, you will need to assign the right persona with requisite permissions to the API token.' : ''}
+`
+}
+
+export function getAssetInfo(ATLAN_INSTANCE_URL, asset, materialisedAsset, environmentName, projectName) {
+ return `### ${getConnectorImage(
+ asset.attributes.connectorName
+ )} [${asset.displayText}](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_github_action) ${
+ asset.attributes?.certificateStatus
+ ? getCertificationImage(asset.attributes.certificateStatus)
+ : ""
+ }
+ Materialised asset: ${getConnectorImage(
+ materialisedAsset.attributes.connectorName
+ )} [${materialisedAsset.attributes.name}](${ATLAN_INSTANCE_URL}/assets/${
+ materialisedAsset.guid
+ }/overview?utm_source=dbt_github_action) ${
+ materialisedAsset.attributes?.certificateStatus
+ ? getCertificationImage(materialisedAsset.attributes.certificateStatus)
+ : ""
+ }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ""}${
+ projectName ? ` | Project Name: \`${projectName}\`` : ""
+ }`
+}
+
+export function getDownstreamTable(ATLAN_INSTANCE_URL, downstreamAssets, rows, materialisedAsset) {
+ return `${
+ downstreamAssets.entityCount
+ } downstream assets 👇
+
+ Name | Type | Description | Owners | Terms | Classifications | Source URL
+ --- | --- | --- | --- | --- | --- | ---
+ ${rows
+ .map((row) =>
+ row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
+ )
+ .join("\n")}
+
+ ${
+ downstreamAssets.hasMore
+ ? `[See more downstream assets at Atlan](${ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_github_action)`
+ : ""
+ }
+
+ `
+}
+
+export function getViewAssetButton(ATLAN_INSTANCE_URL, asset) {
+ return `${getImageURL(
+ "atlan-logo",
+ 15,
+ 15
+ )} [View asset in Atlan](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_github_action)`
+}
+
+export function getMDCommentForModel(ATLAN_INSTANCE_URL, model) {
+ return `${getConnectorImage(model?.attributes?.connectorName)} [${
+ model?.displayText
+ }](${ATLAN_INSTANCE_URL}/assets/${model?.guid}/overview?utm_source=dbt_github_action)`
+}
+
+export function getMDCommentForMaterialisedView(ATLAN_INSTANCE_URL, materialisedView) {
+ return `${getConnectorImage(materialisedView?.attributes?.connectorName)} [${
+ materialisedView?.attributes?.name
+ }](${ATLAN_INSTANCE_URL}/assets/${materialisedView?.guid}/overview?utm_source=dbt_github_action)`
+}
+
+export function getTableMD(md, resp) {
+ return `${md} | ${resp ? '✅' : '❌'} \n`
+}
\ No newline at end of file
diff --git a/adapters/templates/gitlab-integration.js b/adapters/templates/gitlab-integration.js
new file mode 100644
index 0000000..e5f547d
--- /dev/null
+++ b/adapters/templates/gitlab-integration.js
@@ -0,0 +1,102 @@
+import { getImageURL, getConnectorImage, getCertificationImage } from "../utils/index.js";
+
+export function getErrorResponseStatus401 (ATLAN_INSTANCE_URL, CI_PROJECT_NAME, CI_PROJECT_NAMESPACE) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` as this repository's CI/CD variable.
+
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Set your CI/CD variables [here](https://gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/-/settings/ci_cd). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+export function getErrorResponseStatusUndefined(ATLAN_INSTANCE_URL, CI_PROJECT_NAME, CI_PROJECT_NAMESPACE) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` as this repository's CI/CD variable.
+
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Make sure your Atlan Instance URL is set in the following format.
+\`https://tenant.atlan.com\`
+
+Set your CI/CD variables [here](https://gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/-/settings/ci_cd). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+export function getSetResourceOnAssetComment(tableMd, setResourceFailed) {
+ return `## 🎊 Congrats on the merge!
+
+ This pull request has been added as a resource to the following assets:
+ Name | Resource set successfully
+ --- | ---
+ ${tableMd}
+ ${setResourceFailed ? '> Seems like we were unable to set the resources for some of the assets due to insufficient permissions. To ensure that the pull request is linked as a resource, you will need to assign the right persona with requisite permissions to the API token.' : ''}
+ `
+}
+
+export function getAssetInfo(ATLAN_INSTANCE_URL, asset, materialisedAsset, environmentName, projectName) {
+ return `### ${getConnectorImage(
+ asset.attributes.connectorName
+ )} [${asset.displayText}](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_gitlab_action) ${
+ asset.attributes?.certificateStatus
+ ? getCertificationImage(asset.attributes.certificateStatus)
+ : ""
+ }
+Materialised asset: ${getConnectorImage(
+ materialisedAsset.attributes.connectorName
+ )} [${materialisedAsset.attributes.name}](${ATLAN_INSTANCE_URL}/assets/${
+ materialisedAsset.guid
+ }/overview?utm_source=dbt_gitlab_action) ${
+ materialisedAsset.attributes?.certificateStatus
+ ? getCertificationImage(materialisedAsset.attributes.certificateStatus)
+ : ""
+ }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ""}${
+ projectName ? ` | Project Name: \`${projectName}\`` : ""
+ }`
+}
+
+export function getDownstreamTable(ATLAN_INSTANCE_URL, downstreamAssets, rows, materialisedAsset) {
+ return `${
+ downstreamAssets.entityCount
+ } downstream assets 👇
+
+Name | Type | Description | Owners | Terms | Classifications | Source URL
+--- | --- | --- | --- | --- | --- | ---
+${rows
+ .map((row) =>
+ row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
+ )
+ .join("\n")}
+
+${
+ downstreamAssets.hasMore
+ ? `[See more downstream assets at Atlan](${ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_gitlab_action)`
+ : ""
+}
+
+ `
+}
+
+export function getViewAssetButton(ATLAN_INSTANCE_URL, asset) {
+ return `${getImageURL(
+ "atlan-logo",
+ 15,
+ 15
+ )} [View asset in Atlan](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_gitlab_action)`
+}
+
+export function getMDCommentForModel(ATLAN_INSTANCE_URL, model) {
+ return `${getConnectorImage(model?.attributes?.connectorName)} [${
+ model?.displayText
+ }](${ATLAN_INSTANCE_URL}/assets/${model?.guid}/overview?utm_source=dbt_gitlab_action)`
+}
+
+export function getMDCommentForMaterialisedView(ATLAN_INSTANCE_URL, materialisedView) {
+ return `${getConnectorImage(materialisedView?.attributes?.connectorName)} [${
+ materialisedView?.attributes?.name
+ }](${ATLAN_INSTANCE_URL}/assets/${materialisedView?.guid}/overview?utm_source=dbt_gitlab_action)`
+}
+
+export function getTableMD(md, resp) {
+ return `${md} | ${resp ? '✅' : '❌'} \n`
+}
\ No newline at end of file
diff --git a/src/utils/auth.js b/adapters/utils/auth.js
similarity index 51%
rename from src/utils/auth.js
rename to adapters/utils/auth.js
index 029a168..ba09b6e 100644
--- a/src/utils/auth.js
+++ b/adapters/utils/auth.js
@@ -1,17 +1,10 @@
import fetch from "node-fetch";
-import dotenv from "dotenv";
-import core from "@actions/core";
-
-dotenv.config();
-
-const ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
+import {
+ ATLAN_INSTANCE_URL,
+ ATLAN_API_TOKEN,
+} from "./get-environment-variables.js";
export async function auth() {
- //Done
- console.log("Inside auth in utils.js");
var myHeaders = {
authorization: `Bearer ${ATLAN_API_TOKEN}`,
"content-type": "application/json",
@@ -26,6 +19,6 @@ export async function auth() {
`${ATLAN_INSTANCE_URL}/api/meta`,
requestOptions
).catch((err) => {});
- console.log("Completed auth in utils.js");
+
return response;
}
diff --git a/adapters/utils/create-comment.js b/adapters/utils/create-comment.js
new file mode 100644
index 0000000..e07e89a
--- /dev/null
+++ b/adapters/utils/create-comment.js
@@ -0,0 +1,9 @@
+export function truncate(value) {
+ if (typeof value === "string")
+ return value.length > 100 ? value.substring(0, 100) + "..." : value;
+ if (Array.isArray(value))
+ return value.length > 10
+ ? value.slice(0, 10).join(", ") + "..."
+ : value.join(", ");
+ return "";
+}
diff --git a/adapters/utils/get-environment-variables.js b/adapters/utils/get-environment-variables.js
new file mode 100644
index 0000000..30416a3
--- /dev/null
+++ b/adapters/utils/get-environment-variables.js
@@ -0,0 +1,84 @@
+import dotenv from "dotenv";
+import core from "@actions/core";
+dotenv.config();
+
+//Common env variables
+export const ATLAN_INSTANCE_URL = new URL(
+ process.env.ATLAN_INSTANCE_URL || core.getInput("ATLAN_INSTANCE_URL")
+).origin;
+
+export const ATLAN_API_TOKEN =
+ process.env.ATLAN_API_TOKEN || core.getInput("ATLAN_API_TOKEN");
+
+export const IS_DEV = process.env.IS_DEV;
+
+export const IGNORE_MODEL_ALIAS_MATCHING =
+ (process.env.IGNORE_MODEL_ALIAS_MATCHING ||
+ core.getInput("IGNORE_MODEL_ALIAS_MATCHING")) == "true";
+
+//GITLAB SPECIFIC ENV VARIABLES
+export async function getCIMergeRequestIID(
+ gitlab,
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+) {
+ if (!process.env.CI_MERGE_REQUEST_IID) {
+ const mergeRequestCommit = await gitlab.Commits.allMergeRequests(
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+ );
+
+ const firstMergeRequest = mergeRequestCommit[0];
+ if (firstMergeRequest) {
+ return firstMergeRequest.iid;
+ }
+ }
+
+ return process.env.CI_MERGE_REQUEST_IID;
+}
+
+export const {
+ CI_PROJECT_PATH,
+ CI_PROJECT_ID,
+ CI_JOB_URL,
+ GITLAB_TOKEN,
+ CI_COMMIT_MESSAGE,
+ GITLAB_USER_LOGIN,
+ CI_PROJECT_NAME,
+ CI_COMMIT_SHA,
+ CI_PROJECT_NAMESPACE,
+} = process.env;
+
+export function getGitLabEnvironments() {
+ const { DBT_ENVIRONMENT_BRANCH_MAP } = process.env;
+
+ if (DBT_ENVIRONMENT_BRANCH_MAP) {
+ const environmentLines = DBT_ENVIRONMENT_BRANCH_MAP.split("\n");
+ const environmentMap = {};
+
+ environmentLines.forEach((line) => {
+ const [environment, branch] = line.split(":").map((item) => item.trim());
+ if (environment && branch) {
+ environmentMap[environment] = branch;
+ }
+ });
+
+ return environmentMap;
+ } else {
+ return {};
+ }
+}
+
+//GITHUB SPECIFIC ENV VARIABLES
+export const GITHUB_TOKEN =
+ core.getInput("GITHUB_TOKEN") || process.env.GITHUB_TOKEN;
+
+export const getEnvironments = () => {
+ return (
+ core
+ .getInput("DBT_ENVIRONMENT_BRANCH_MAP")
+ ?.trim()
+ ?.split("\n")
+ ?.map((i) => i.split(":").map((i) => i.trim())) ?? []
+ );
+};
diff --git a/src/utils/get-image-url.js b/adapters/utils/get-image-url.js
similarity index 100%
rename from src/utils/get-image-url.js
rename to adapters/utils/get-image-url.js
diff --git a/src/utils/hosted-images.js b/adapters/utils/hosted-images.js
similarity index 100%
rename from src/utils/hosted-images.js
rename to adapters/utils/hosted-images.js
diff --git a/adapters/utils/index.js b/adapters/utils/index.js
new file mode 100644
index 0000000..68c4e24
--- /dev/null
+++ b/adapters/utils/index.js
@@ -0,0 +1,12 @@
+export {
+ getImageURL,
+ getConnectorImage,
+ getCertificationImage,
+} from "./get-image-url.js";
+export { default as hostedImages } from "./hosted-images.js";
+export { truncate } from "./create-comment.js";
+export { auth } from "./auth.js";
+export {
+ getGitLabEnvironments,
+ getEnvironments,
+} from "./get-environment-variables.js";
diff --git a/dist/index.js b/dist/index.js
index 387470f..40a1a98 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -6760,6 +6760,176 @@ exports.Response = Response;
exports.FetchError = FetchError;
+/***/ }),
+
+/***/ 1884:
+/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
+
+
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+exports.RateLimit = exports.Sema = void 0;
+const events_1 = __importDefault(__nccwpck_require__(2361));
+function arrayMove(src, srcIndex, dst, dstIndex, len) {
+ for (let j = 0; j < len; ++j) {
+ dst[j + dstIndex] = src[j + srcIndex];
+ src[j + srcIndex] = void 0;
+ }
+}
+function pow2AtLeast(n) {
+ n = n >>> 0;
+ n = n - 1;
+ n = n | (n >> 1);
+ n = n | (n >> 2);
+ n = n | (n >> 4);
+ n = n | (n >> 8);
+ n = n | (n >> 16);
+ return n + 1;
+}
+function getCapacity(capacity) {
+ return pow2AtLeast(Math.min(Math.max(16, capacity), 1073741824));
+}
+// Deque is based on https://github.com/petkaantonov/deque/blob/master/js/deque.js
+// Released under the MIT License: https://github.com/petkaantonov/deque/blob/6ef4b6400ad3ba82853fdcc6531a38eb4f78c18c/LICENSE
+class Deque {
+ constructor(capacity) {
+ this._capacity = getCapacity(capacity);
+ this._length = 0;
+ this._front = 0;
+ this.arr = [];
+ }
+ push(item) {
+ const length = this._length;
+ this.checkCapacity(length + 1);
+ const i = (this._front + length) & (this._capacity - 1);
+ this.arr[i] = item;
+ this._length = length + 1;
+ return length + 1;
+ }
+ pop() {
+ const length = this._length;
+ if (length === 0) {
+ return void 0;
+ }
+ const i = (this._front + length - 1) & (this._capacity - 1);
+ const ret = this.arr[i];
+ this.arr[i] = void 0;
+ this._length = length - 1;
+ return ret;
+ }
+ shift() {
+ const length = this._length;
+ if (length === 0) {
+ return void 0;
+ }
+ const front = this._front;
+ const ret = this.arr[front];
+ this.arr[front] = void 0;
+ this._front = (front + 1) & (this._capacity - 1);
+ this._length = length - 1;
+ return ret;
+ }
+ get length() {
+ return this._length;
+ }
+ checkCapacity(size) {
+ if (this._capacity < size) {
+ this.resizeTo(getCapacity(this._capacity * 1.5 + 16));
+ }
+ }
+ resizeTo(capacity) {
+ const oldCapacity = this._capacity;
+ this._capacity = capacity;
+ const front = this._front;
+ const length = this._length;
+ if (front + length > oldCapacity) {
+ const moveItemsCount = (front + length) & (oldCapacity - 1);
+ arrayMove(this.arr, 0, this.arr, oldCapacity, moveItemsCount);
+ }
+ }
+}
+class ReleaseEmitter extends events_1.default {
+}
+function isFn(x) {
+ return typeof x === 'function';
+}
+function defaultInit() {
+ return '1';
+}
+class Sema {
+ constructor(nr, { initFn = defaultInit, pauseFn, resumeFn, capacity = 10, } = {}) {
+ if (isFn(pauseFn) !== isFn(resumeFn)) {
+ throw new Error('pauseFn and resumeFn must be both set for pausing');
+ }
+ this.nrTokens = nr;
+ this.free = new Deque(nr);
+ this.waiting = new Deque(capacity);
+ this.releaseEmitter = new ReleaseEmitter();
+ this.noTokens = initFn === defaultInit;
+ this.pauseFn = pauseFn;
+ this.resumeFn = resumeFn;
+ this.paused = false;
+ this.releaseEmitter.on('release', (token) => {
+ const p = this.waiting.shift();
+ if (p) {
+ p.resolve(token);
+ }
+ else {
+ if (this.resumeFn && this.paused) {
+ this.paused = false;
+ this.resumeFn();
+ }
+ this.free.push(token);
+ }
+ });
+ for (let i = 0; i < nr; i++) {
+ this.free.push(initFn());
+ }
+ }
+ tryAcquire() {
+ return this.free.pop();
+ }
+ async acquire() {
+ let token = this.tryAcquire();
+ if (token !== void 0) {
+ return token;
+ }
+ return new Promise((resolve, reject) => {
+ if (this.pauseFn && !this.paused) {
+ this.paused = true;
+ this.pauseFn();
+ }
+ this.waiting.push({ resolve, reject });
+ });
+ }
+ release(token) {
+ this.releaseEmitter.emit('release', this.noTokens ? '1' : token);
+ }
+ drain() {
+ const a = new Array(this.nrTokens);
+ for (let i = 0; i < this.nrTokens; i++) {
+ a[i] = this.acquire();
+ }
+ return Promise.all(a);
+ }
+ nrWaiting() {
+ return this.waiting.length;
+ }
+}
+exports.Sema = Sema;
+function RateLimit(rps, { timeUnit = 1000, uniformDistribution = false, } = {}) {
+ const sema = new Sema(uniformDistribution ? 1 : rps);
+ const delay = uniformDistribution ? timeUnit / rps : timeUnit;
+ return async function rl() {
+ await sema.acquire();
+ setTimeout(() => sema.release(), delay);
+ };
+}
+exports.RateLimit = RateLimit;
+
+
/***/ }),
/***/ 3682:
@@ -6943,1434 +7113,5227 @@ function removeHook(state, name, method) {
/***/ }),
-/***/ 8803:
+/***/ 610:
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
-var GetIntrinsic = __nccwpck_require__(4538);
+const stringify = __nccwpck_require__(8750);
+const compile = __nccwpck_require__(9434);
+const expand = __nccwpck_require__(5873);
+const parse = __nccwpck_require__(6477);
-var callBind = __nccwpck_require__(2977);
+/**
+ * Expand the given pattern or create a regex-compatible string.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)']
+ * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c']
+ * ```
+ * @param {String} `str`
+ * @param {Object} `options`
+ * @return {String}
+ * @api public
+ */
-var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));
+const braces = (input, options = {}) => {
+ let output = [];
-module.exports = function callBoundIntrinsic(name, allowMissing) {
- var intrinsic = GetIntrinsic(name, !!allowMissing);
- if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
- return callBind(intrinsic);
- }
- return intrinsic;
+ if (Array.isArray(input)) {
+ for (let pattern of input) {
+ let result = braces.create(pattern, options);
+ if (Array.isArray(result)) {
+ output.push(...result);
+ } else {
+ output.push(result);
+ }
+ }
+ } else {
+ output = [].concat(braces.create(input, options));
+ }
+
+ if (options && options.expand === true && options.nodupes === true) {
+ output = [...new Set(output)];
+ }
+ return output;
};
+/**
+ * Parse the given `str` with the given `options`.
+ *
+ * ```js
+ * // braces.parse(pattern, [, options]);
+ * const ast = braces.parse('a/{b,c}/d');
+ * console.log(ast);
+ * ```
+ * @param {String} pattern Brace pattern to parse
+ * @param {Object} options
+ * @return {Object} Returns an AST
+ * @api public
+ */
-/***/ }),
+braces.parse = (input, options = {}) => parse(input, options);
-/***/ 2977:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+/**
+ * Creates a braces string from an AST, or an AST node.
+ *
+ * ```js
+ * const braces = require('braces');
+ * let ast = braces.parse('foo/{a,b}/bar');
+ * console.log(stringify(ast.nodes[2])); //=> '{a,b}'
+ * ```
+ * @param {String} `input` Brace pattern or AST.
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
+
+braces.stringify = (input, options = {}) => {
+ if (typeof input === 'string') {
+ return stringify(braces.parse(input, options), options);
+ }
+ return stringify(input, options);
+};
+/**
+ * Compiles a brace pattern into a regex-compatible, optimized string.
+ * This method is called by the main [braces](#braces) function by default.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces.compile('a/{b,c}/d'));
+ * //=> ['a/(b|c)/d']
+ * ```
+ * @param {String} `input` Brace pattern or AST.
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
+braces.compile = (input, options = {}) => {
+ if (typeof input === 'string') {
+ input = braces.parse(input, options);
+ }
+ return compile(input, options);
+};
-var bind = __nccwpck_require__(8334);
-var GetIntrinsic = __nccwpck_require__(4538);
+/**
+ * Expands a brace pattern into an array. This method is called by the
+ * main [braces](#braces) function when `options.expand` is true. Before
+ * using this method it's recommended that you read the [performance notes](#performance))
+ * and advantages of using [.compile](#compile) instead.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces.expand('a/{b,c}/d'));
+ * //=> ['a/b/d', 'a/c/d'];
+ * ```
+ * @param {String} `pattern` Brace pattern
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
-var $apply = GetIntrinsic('%Function.prototype.apply%');
-var $call = GetIntrinsic('%Function.prototype.call%');
-var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);
+braces.expand = (input, options = {}) => {
+ if (typeof input === 'string') {
+ input = braces.parse(input, options);
+ }
-var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);
-var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
-var $max = GetIntrinsic('%Math.max%');
+ let result = expand(input, options);
-if ($defineProperty) {
- try {
- $defineProperty({}, 'a', { value: 1 });
- } catch (e) {
- // IE 8 has a broken defineProperty
- $defineProperty = null;
- }
-}
+ // filter out empty strings if specified
+ if (options.noempty === true) {
+ result = result.filter(Boolean);
+ }
-module.exports = function callBind(originalFunction) {
- var func = $reflectApply(bind, $call, arguments);
- if ($gOPD && $defineProperty) {
- var desc = $gOPD(func, 'length');
- if (desc.configurable) {
- // original length, plus the receiver, minus any additional arguments (after the receiver)
- $defineProperty(
- func,
- 'length',
- { value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }
- );
- }
- }
- return func;
+ // filter out duplicates if specified
+ if (options.nodupes === true) {
+ result = [...new Set(result)];
+ }
+
+ return result;
};
-var applyBind = function applyBind() {
- return $reflectApply(bind, $apply, arguments);
+/**
+ * Processes a brace pattern and returns either an expanded array
+ * (if `options.expand` is true), a highly optimized regex-compatible string.
+ * This method is called by the main [braces](#braces) function.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}'))
+ * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)'
+ * ```
+ * @param {String} `pattern` Brace pattern
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
+
+braces.create = (input, options = {}) => {
+ if (input === '' || input.length < 3) {
+ return [input];
+ }
+
+ return options.expand !== true
+ ? braces.compile(input, options)
+ : braces.expand(input, options);
};
-if ($defineProperty) {
- $defineProperty(module.exports, 'apply', { value: applyBind });
-} else {
- module.exports.apply = applyBind;
-}
+/**
+ * Expose "braces"
+ */
+
+module.exports = braces;
/***/ }),
-/***/ 8932:
-/***/ ((__unused_webpack_module, exports) => {
+/***/ 9434:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
-Object.defineProperty(exports, "__esModule", ({ value: true }));
+const fill = __nccwpck_require__(6330);
+const utils = __nccwpck_require__(5207);
-class Deprecation extends Error {
- constructor(message) {
- super(message); // Maintains proper stack trace (only available on V8)
+const compile = (ast, options = {}) => {
+ let walk = (node, parent = {}) => {
+ let invalidBlock = utils.isInvalidBrace(parent);
+ let invalidNode = node.invalid === true && options.escapeInvalid === true;
+ let invalid = invalidBlock === true || invalidNode === true;
+ let prefix = options.escapeInvalid === true ? '\\' : '';
+ let output = '';
- /* istanbul ignore next */
+ if (node.isOpen === true) {
+ return prefix + node.value;
+ }
+ if (node.isClose === true) {
+ return prefix + node.value;
+ }
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, this.constructor);
+ if (node.type === 'open') {
+ return invalid ? (prefix + node.value) : '(';
}
- this.name = 'Deprecation';
- }
+ if (node.type === 'close') {
+ return invalid ? (prefix + node.value) : ')';
+ }
-}
+ if (node.type === 'comma') {
+ return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|');
+ }
-exports.Deprecation = Deprecation;
+ if (node.value) {
+ return node.value;
+ }
+
+ if (node.nodes && node.ranges > 0) {
+ let args = utils.reduce(node.nodes);
+ let range = fill(...args, { ...options, wrap: false, toRegex: true });
+
+ if (range.length !== 0) {
+ return args.length > 1 && range.length > 1 ? `(${range})` : range;
+ }
+ }
+
+ if (node.nodes) {
+ for (let child of node.nodes) {
+ output += walk(child, node);
+ }
+ }
+ return output;
+ };
+
+ return walk(ast);
+};
+
+module.exports = compile;
/***/ }),
-/***/ 2437:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+/***/ 8774:
+/***/ ((module) => {
-const fs = __nccwpck_require__(7147)
-const path = __nccwpck_require__(1017)
-const os = __nccwpck_require__(2037)
-const packageJson = __nccwpck_require__(9968)
-const version = packageJson.version
-const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
+module.exports = {
+ MAX_LENGTH: 1024 * 64,
+
+ // Digits
+ CHAR_0: '0', /* 0 */
+ CHAR_9: '9', /* 9 */
+
+ // Alphabet chars.
+ CHAR_UPPERCASE_A: 'A', /* A */
+ CHAR_LOWERCASE_A: 'a', /* a */
+ CHAR_UPPERCASE_Z: 'Z', /* Z */
+ CHAR_LOWERCASE_Z: 'z', /* z */
+
+ CHAR_LEFT_PARENTHESES: '(', /* ( */
+ CHAR_RIGHT_PARENTHESES: ')', /* ) */
+
+ CHAR_ASTERISK: '*', /* * */
+
+ // Non-alphabetic chars.
+ CHAR_AMPERSAND: '&', /* & */
+ CHAR_AT: '@', /* @ */
+ CHAR_BACKSLASH: '\\', /* \ */
+ CHAR_BACKTICK: '`', /* ` */
+ CHAR_CARRIAGE_RETURN: '\r', /* \r */
+ CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */
+ CHAR_COLON: ':', /* : */
+ CHAR_COMMA: ',', /* , */
+ CHAR_DOLLAR: '$', /* . */
+ CHAR_DOT: '.', /* . */
+ CHAR_DOUBLE_QUOTE: '"', /* " */
+ CHAR_EQUAL: '=', /* = */
+ CHAR_EXCLAMATION_MARK: '!', /* ! */
+ CHAR_FORM_FEED: '\f', /* \f */
+ CHAR_FORWARD_SLASH: '/', /* / */
+ CHAR_HASH: '#', /* # */
+ CHAR_HYPHEN_MINUS: '-', /* - */
+ CHAR_LEFT_ANGLE_BRACKET: '<', /* < */
+ CHAR_LEFT_CURLY_BRACE: '{', /* { */
+ CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */
+ CHAR_LINE_FEED: '\n', /* \n */
+ CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */
+ CHAR_PERCENT: '%', /* % */
+ CHAR_PLUS: '+', /* + */
+ CHAR_QUESTION_MARK: '?', /* ? */
+ CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */
+ CHAR_RIGHT_CURLY_BRACE: '}', /* } */
+ CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */
+ CHAR_SEMICOLON: ';', /* ; */
+ CHAR_SINGLE_QUOTE: '\'', /* ' */
+ CHAR_SPACE: ' ', /* */
+ CHAR_TAB: '\t', /* \t */
+ CHAR_UNDERSCORE: '_', /* _ */
+ CHAR_VERTICAL_LINE: '|', /* | */
+ CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */
+};
-// Parser src into an Object
-function parse (src) {
- const obj = {}
- // Convert buffer to string
- let lines = src.toString()
+/***/ }),
- // Convert line breaks to same format
- lines = lines.replace(/\r\n?/mg, '\n')
+/***/ 5873:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
- let match
- while ((match = LINE.exec(lines)) != null) {
- const key = match[1]
- // Default undefined or null to empty string
- let value = (match[2] || '')
- // Remove whitespace
- value = value.trim()
+const fill = __nccwpck_require__(6330);
+const stringify = __nccwpck_require__(8750);
+const utils = __nccwpck_require__(5207);
- // Check if double quoted
- const maybeQuote = value[0]
+const append = (queue = '', stash = '', enclose = false) => {
+ let result = [];
- // Remove surrounding quotes
- value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
+ queue = [].concat(queue);
+ stash = [].concat(stash);
- // Expand newlines if double quoted
- if (maybeQuote === '"') {
- value = value.replace(/\\n/g, '\n')
- value = value.replace(/\\r/g, '\r')
- }
+ if (!stash.length) return queue;
+ if (!queue.length) {
+ return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash;
+ }
- // Add to object
- obj[key] = value
+ for (let item of queue) {
+ if (Array.isArray(item)) {
+ for (let value of item) {
+ result.push(append(value, stash, enclose));
+ }
+ } else {
+ for (let ele of stash) {
+ if (enclose === true && typeof ele === 'string') ele = `{${ele}}`;
+ result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele));
+ }
+ }
}
+ return utils.flatten(result);
+};
- return obj
-}
+const expand = (ast, options = {}) => {
+ let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit;
-function _log (message) {
- console.log(`[dotenv@${version}][DEBUG] ${message}`)
-}
+ let walk = (node, parent = {}) => {
+ node.queue = [];
-function _resolveHome (envPath) {
- return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
-}
+ let p = parent;
+ let q = parent.queue;
-// Populates process.env from .env file
-function config (options) {
- let dotenvPath = path.resolve(process.cwd(), '.env')
- let encoding = 'utf8'
- const debug = Boolean(options && options.debug)
- const override = Boolean(options && options.override)
+ while (p.type !== 'brace' && p.type !== 'root' && p.parent) {
+ p = p.parent;
+ q = p.queue;
+ }
- if (options) {
- if (options.path != null) {
- dotenvPath = _resolveHome(options.path)
+ if (node.invalid || node.dollar) {
+ q.push(append(q.pop(), stringify(node, options)));
+ return;
}
- if (options.encoding != null) {
- encoding = options.encoding
+
+ if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) {
+ q.push(append(q.pop(), ['{}']));
+ return;
}
- }
- try {
- // Specifying an encoding returns a string instead of a buffer
- const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }))
+ if (node.nodes && node.ranges > 0) {
+ let args = utils.reduce(node.nodes);
- Object.keys(parsed).forEach(function (key) {
- if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
- process.env[key] = parsed[key]
- } else {
- if (override === true) {
- process.env[key] = parsed[key]
- }
+ if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
+ throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
+ }
- if (debug) {
- if (override === true) {
- _log(`"${key}" is already defined in \`process.env\` and WAS overwritten`)
- } else {
- _log(`"${key}" is already defined in \`process.env\` and was NOT overwritten`)
- }
- }
+ let range = fill(...args, options);
+ if (range.length === 0) {
+ range = stringify(node, options);
}
- })
- return { parsed }
- } catch (e) {
- if (debug) {
- _log(`Failed to load ${dotenvPath} ${e.message}`)
+ q.push(append(q.pop(), range));
+ node.nodes = [];
+ return;
}
- return { error: e }
- }
-}
+ let enclose = utils.encloseBrace(node);
+ let queue = node.queue;
+ let block = node;
-const DotenvModule = {
- config,
- parse
-}
+ while (block.type !== 'brace' && block.type !== 'root' && block.parent) {
+ block = block.parent;
+ queue = block.queue;
+ }
-module.exports.config = DotenvModule.config
-module.exports.parse = DotenvModule.parse
-module.exports = DotenvModule
+ for (let i = 0; i < node.nodes.length; i++) {
+ let child = node.nodes[i];
+
+ if (child.type === 'comma' && node.type === 'brace') {
+ if (i === 1) queue.push('');
+ queue.push('');
+ continue;
+ }
+
+ if (child.type === 'close') {
+ q.push(append(q.pop(), queue, enclose));
+ continue;
+ }
+
+ if (child.value && child.type !== 'open') {
+ queue.push(append(queue.pop(), child.value));
+ continue;
+ }
+
+ if (child.nodes) {
+ walk(child, node);
+ }
+ }
+
+ return queue;
+ };
+
+ return utils.flatten(walk(ast));
+};
+
+module.exports = expand;
/***/ }),
-/***/ 9320:
-/***/ ((module) => {
+/***/ 6477:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
-/* eslint no-invalid-this: 1 */
+const stringify = __nccwpck_require__(8750);
-var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
-var slice = Array.prototype.slice;
-var toStr = Object.prototype.toString;
-var funcType = '[object Function]';
+/**
+ * Constants
+ */
-module.exports = function bind(that) {
- var target = this;
- if (typeof target !== 'function' || toStr.call(target) !== funcType) {
- throw new TypeError(ERROR_MESSAGE + target);
+const {
+ MAX_LENGTH,
+ CHAR_BACKSLASH, /* \ */
+ CHAR_BACKTICK, /* ` */
+ CHAR_COMMA, /* , */
+ CHAR_DOT, /* . */
+ CHAR_LEFT_PARENTHESES, /* ( */
+ CHAR_RIGHT_PARENTHESES, /* ) */
+ CHAR_LEFT_CURLY_BRACE, /* { */
+ CHAR_RIGHT_CURLY_BRACE, /* } */
+ CHAR_LEFT_SQUARE_BRACKET, /* [ */
+ CHAR_RIGHT_SQUARE_BRACKET, /* ] */
+ CHAR_DOUBLE_QUOTE, /* " */
+ CHAR_SINGLE_QUOTE, /* ' */
+ CHAR_NO_BREAK_SPACE,
+ CHAR_ZERO_WIDTH_NOBREAK_SPACE
+} = __nccwpck_require__(8774);
+
+/**
+ * parse
+ */
+
+const parse = (input, options = {}) => {
+ if (typeof input !== 'string') {
+ throw new TypeError('Expected a string');
+ }
+
+ let opts = options || {};
+ let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
+ if (input.length > max) {
+ throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`);
+ }
+
+ let ast = { type: 'root', input, nodes: [] };
+ let stack = [ast];
+ let block = ast;
+ let prev = ast;
+ let brackets = 0;
+ let length = input.length;
+ let index = 0;
+ let depth = 0;
+ let value;
+ let memo = {};
+
+ /**
+ * Helpers
+ */
+
+ const advance = () => input[index++];
+ const push = node => {
+ if (node.type === 'text' && prev.type === 'dot') {
+ prev.type = 'text';
}
- var args = slice.call(arguments, 1);
- var bound;
- var binder = function () {
- if (this instanceof bound) {
- var result = target.apply(
- this,
- args.concat(slice.call(arguments))
- );
- if (Object(result) === result) {
- return result;
- }
- return this;
- } else {
- return target.apply(
- that,
- args.concat(slice.call(arguments))
- );
+ if (prev && prev.type === 'text' && node.type === 'text') {
+ prev.value += node.value;
+ return;
+ }
+
+ block.nodes.push(node);
+ node.parent = block;
+ node.prev = prev;
+ prev = node;
+ return node;
+ };
+
+ push({ type: 'bos' });
+
+ while (index < length) {
+ block = stack[stack.length - 1];
+ value = advance();
+
+ /**
+ * Invalid chars
+ */
+
+ if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) {
+ continue;
+ }
+
+ /**
+ * Escaped chars
+ */
+
+ if (value === CHAR_BACKSLASH) {
+ push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() });
+ continue;
+ }
+
+ /**
+ * Right square bracket (literal): ']'
+ */
+
+ if (value === CHAR_RIGHT_SQUARE_BRACKET) {
+ push({ type: 'text', value: '\\' + value });
+ continue;
+ }
+
+ /**
+ * Left square bracket: '['
+ */
+
+ if (value === CHAR_LEFT_SQUARE_BRACKET) {
+ brackets++;
+
+ let closed = true;
+ let next;
+
+ while (index < length && (next = advance())) {
+ value += next;
+
+ if (next === CHAR_LEFT_SQUARE_BRACKET) {
+ brackets++;
+ continue;
}
- };
- var boundLength = Math.max(0, target.length - args.length);
- var boundArgs = [];
- for (var i = 0; i < boundLength; i++) {
- boundArgs.push('$' + i);
+ if (next === CHAR_BACKSLASH) {
+ value += advance();
+ continue;
+ }
+
+ if (next === CHAR_RIGHT_SQUARE_BRACKET) {
+ brackets--;
+
+ if (brackets === 0) {
+ break;
+ }
+ }
+ }
+
+ push({ type: 'text', value });
+ continue;
}
- bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
+ /**
+ * Parentheses
+ */
- if (target.prototype) {
- var Empty = function Empty() {};
- Empty.prototype = target.prototype;
- bound.prototype = new Empty();
- Empty.prototype = null;
+ if (value === CHAR_LEFT_PARENTHESES) {
+ block = push({ type: 'paren', nodes: [] });
+ stack.push(block);
+ push({ type: 'text', value });
+ continue;
}
- return bound;
-};
+ if (value === CHAR_RIGHT_PARENTHESES) {
+ if (block.type !== 'paren') {
+ push({ type: 'text', value });
+ continue;
+ }
+ block = stack.pop();
+ push({ type: 'text', value });
+ block = stack[stack.length - 1];
+ continue;
+ }
+ /**
+ * Quotes: '|"|`
+ */
-/***/ }),
+ if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) {
+ let open = value;
+ let next;
-/***/ 8334:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+ if (options.keepQuotes !== true) {
+ value = '';
+ }
+ while (index < length && (next = advance())) {
+ if (next === CHAR_BACKSLASH) {
+ value += next + advance();
+ continue;
+ }
+ if (next === open) {
+ if (options.keepQuotes === true) value += next;
+ break;
+ }
-var implementation = __nccwpck_require__(9320);
+ value += next;
+ }
-module.exports = Function.prototype.bind || implementation;
+ push({ type: 'text', value });
+ continue;
+ }
+
+ /**
+ * Left curly brace: '{'
+ */
+
+ if (value === CHAR_LEFT_CURLY_BRACE) {
+ depth++;
+
+ let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true;
+ let brace = {
+ type: 'brace',
+ open: true,
+ close: false,
+ dollar,
+ depth,
+ commas: 0,
+ ranges: 0,
+ nodes: []
+ };
+
+ block = push(brace);
+ stack.push(block);
+ push({ type: 'open', value });
+ continue;
+ }
+
+ /**
+ * Right curly brace: '}'
+ */
+
+ if (value === CHAR_RIGHT_CURLY_BRACE) {
+ if (block.type !== 'brace') {
+ push({ type: 'text', value });
+ continue;
+ }
+
+ let type = 'close';
+ block = stack.pop();
+ block.close = true;
+
+ push({ type, value });
+ depth--;
+
+ block = stack[stack.length - 1];
+ continue;
+ }
+
+ /**
+ * Comma: ','
+ */
+
+ if (value === CHAR_COMMA && depth > 0) {
+ if (block.ranges > 0) {
+ block.ranges = 0;
+ let open = block.nodes.shift();
+ block.nodes = [open, { type: 'text', value: stringify(block) }];
+ }
+
+ push({ type: 'comma', value });
+ block.commas++;
+ continue;
+ }
+
+ /**
+ * Dot: '.'
+ */
+
+ if (value === CHAR_DOT && depth > 0 && block.commas === 0) {
+ let siblings = block.nodes;
+
+ if (depth === 0 || siblings.length === 0) {
+ push({ type: 'text', value });
+ continue;
+ }
+
+ if (prev.type === 'dot') {
+ block.range = [];
+ prev.value += value;
+ prev.type = 'range';
+
+ if (block.nodes.length !== 3 && block.nodes.length !== 5) {
+ block.invalid = true;
+ block.ranges = 0;
+ prev.type = 'text';
+ continue;
+ }
+
+ block.ranges++;
+ block.args = [];
+ continue;
+ }
+
+ if (prev.type === 'range') {
+ siblings.pop();
+
+ let before = siblings[siblings.length - 1];
+ before.value += prev.value + value;
+ prev = before;
+ block.ranges--;
+ continue;
+ }
+
+ push({ type: 'dot', value });
+ continue;
+ }
+
+ /**
+ * Text
+ */
+
+ push({ type: 'text', value });
+ }
+
+ // Mark imbalanced braces and brackets as invalid
+ do {
+ block = stack.pop();
+
+ if (block.type !== 'root') {
+ block.nodes.forEach(node => {
+ if (!node.nodes) {
+ if (node.type === 'open') node.isOpen = true;
+ if (node.type === 'close') node.isClose = true;
+ if (!node.nodes) node.type = 'text';
+ node.invalid = true;
+ }
+ });
+
+ // get the location of the block on parent.nodes (block's siblings)
+ let parent = stack[stack.length - 1];
+ let index = parent.nodes.indexOf(block);
+ // replace the (invalid) block with it's nodes
+ parent.nodes.splice(index, 1, ...block.nodes);
+ }
+ } while (stack.length > 0);
+
+ push({ type: 'eos' });
+ return ast;
+};
+
+module.exports = parse;
/***/ }),
-/***/ 4538:
+/***/ 8750:
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
-var undefined;
+const utils = __nccwpck_require__(5207);
-var $SyntaxError = SyntaxError;
-var $Function = Function;
-var $TypeError = TypeError;
+module.exports = (ast, options = {}) => {
+ let stringify = (node, parent = {}) => {
+ let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent);
+ let invalidNode = node.invalid === true && options.escapeInvalid === true;
+ let output = '';
-// eslint-disable-next-line consistent-return
-var getEvalledConstructor = function (expressionSyntax) {
- try {
- return $Function('"use strict"; return (' + expressionSyntax + ').constructor;')();
- } catch (e) {}
+ if (node.value) {
+ if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) {
+ return '\\' + node.value;
+ }
+ return node.value;
+ }
+
+ if (node.value) {
+ return node.value;
+ }
+
+ if (node.nodes) {
+ for (let child of node.nodes) {
+ output += stringify(child);
+ }
+ }
+ return output;
+ };
+
+ return stringify(ast);
};
-var $gOPD = Object.getOwnPropertyDescriptor;
-if ($gOPD) {
- try {
- $gOPD({}, '');
- } catch (e) {
- $gOPD = null; // this is IE 8, which has a broken gOPD
- }
-}
-var throwTypeError = function () {
- throw new $TypeError();
+
+/***/ }),
+
+/***/ 5207:
+/***/ ((__unused_webpack_module, exports) => {
+
+
+
+exports.isInteger = num => {
+ if (typeof num === 'number') {
+ return Number.isInteger(num);
+ }
+ if (typeof num === 'string' && num.trim() !== '') {
+ return Number.isInteger(Number(num));
+ }
+ return false;
};
-var ThrowTypeError = $gOPD
- ? (function () {
- try {
- // eslint-disable-next-line no-unused-expressions, no-caller, no-restricted-properties
- arguments.callee; // IE 8 does not throw here
- return throwTypeError;
- } catch (calleeThrows) {
- try {
- // IE 8 throws on Object.getOwnPropertyDescriptor(arguments, '')
- return $gOPD(arguments, 'callee').get;
- } catch (gOPDthrows) {
- return throwTypeError;
- }
- }
- }())
- : throwTypeError;
-var hasSymbols = __nccwpck_require__(587)();
-var hasProto = __nccwpck_require__(5894)();
+/**
+ * Find a node of the given type
+ */
-var getProto = Object.getPrototypeOf || (
- hasProto
- ? function (x) { return x.__proto__; } // eslint-disable-line no-proto
- : null
-);
+exports.find = (node, type) => node.nodes.find(node => node.type === type);
-var needsEval = {};
+/**
+ * Find a node of the given type
+ */
-var TypedArray = typeof Uint8Array === 'undefined' || !getProto ? undefined : getProto(Uint8Array);
+exports.exceedsLimit = (min, max, step = 1, limit) => {
+ if (limit === false) return false;
+ if (!exports.isInteger(min) || !exports.isInteger(max)) return false;
+ return ((Number(max) - Number(min)) / Number(step)) >= limit;
+};
-var INTRINSICS = {
- '%AggregateError%': typeof AggregateError === 'undefined' ? undefined : AggregateError,
- '%Array%': Array,
- '%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer,
- '%ArrayIteratorPrototype%': hasSymbols && getProto ? getProto([][Symbol.iterator]()) : undefined,
- '%AsyncFromSyncIteratorPrototype%': undefined,
- '%AsyncFunction%': needsEval,
- '%AsyncGenerator%': needsEval,
- '%AsyncGeneratorFunction%': needsEval,
- '%AsyncIteratorPrototype%': needsEval,
- '%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics,
- '%BigInt%': typeof BigInt === 'undefined' ? undefined : BigInt,
- '%BigInt64Array%': typeof BigInt64Array === 'undefined' ? undefined : BigInt64Array,
- '%BigUint64Array%': typeof BigUint64Array === 'undefined' ? undefined : BigUint64Array,
- '%Boolean%': Boolean,
- '%DataView%': typeof DataView === 'undefined' ? undefined : DataView,
- '%Date%': Date,
- '%decodeURI%': decodeURI,
- '%decodeURIComponent%': decodeURIComponent,
- '%encodeURI%': encodeURI,
- '%encodeURIComponent%': encodeURIComponent,
- '%Error%': Error,
- '%eval%': eval, // eslint-disable-line no-eval
- '%EvalError%': EvalError,
- '%Float32Array%': typeof Float32Array === 'undefined' ? undefined : Float32Array,
- '%Float64Array%': typeof Float64Array === 'undefined' ? undefined : Float64Array,
- '%FinalizationRegistry%': typeof FinalizationRegistry === 'undefined' ? undefined : FinalizationRegistry,
- '%Function%': $Function,
- '%GeneratorFunction%': needsEval,
- '%Int8Array%': typeof Int8Array === 'undefined' ? undefined : Int8Array,
- '%Int16Array%': typeof Int16Array === 'undefined' ? undefined : Int16Array,
- '%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array,
- '%isFinite%': isFinite,
- '%isNaN%': isNaN,
- '%IteratorPrototype%': hasSymbols && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined,
- '%JSON%': typeof JSON === 'object' ? JSON : undefined,
- '%Map%': typeof Map === 'undefined' ? undefined : Map,
- '%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Map()[Symbol.iterator]()),
- '%Math%': Math,
- '%Number%': Number,
- '%Object%': Object,
- '%parseFloat%': parseFloat,
- '%parseInt%': parseInt,
- '%Promise%': typeof Promise === 'undefined' ? undefined : Promise,
- '%Proxy%': typeof Proxy === 'undefined' ? undefined : Proxy,
- '%RangeError%': RangeError,
- '%ReferenceError%': ReferenceError,
- '%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect,
- '%RegExp%': RegExp,
- '%Set%': typeof Set === 'undefined' ? undefined : Set,
- '%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Set()[Symbol.iterator]()),
- '%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer,
- '%String%': String,
- '%StringIteratorPrototype%': hasSymbols && getProto ? getProto(''[Symbol.iterator]()) : undefined,
- '%Symbol%': hasSymbols ? Symbol : undefined,
- '%SyntaxError%': $SyntaxError,
- '%ThrowTypeError%': ThrowTypeError,
- '%TypedArray%': TypedArray,
- '%TypeError%': $TypeError,
- '%Uint8Array%': typeof Uint8Array === 'undefined' ? undefined : Uint8Array,
- '%Uint8ClampedArray%': typeof Uint8ClampedArray === 'undefined' ? undefined : Uint8ClampedArray,
- '%Uint16Array%': typeof Uint16Array === 'undefined' ? undefined : Uint16Array,
- '%Uint32Array%': typeof Uint32Array === 'undefined' ? undefined : Uint32Array,
- '%URIError%': URIError,
- '%WeakMap%': typeof WeakMap === 'undefined' ? undefined : WeakMap,
- '%WeakRef%': typeof WeakRef === 'undefined' ? undefined : WeakRef,
- '%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet
+/**
+ * Escape the given node with '\\' before node.value
+ */
+
+exports.escapeNode = (block, n = 0, type) => {
+ let node = block.nodes[n];
+ if (!node) return;
+
+ if ((type && node.type === type) || node.type === 'open' || node.type === 'close') {
+ if (node.escaped !== true) {
+ node.value = '\\' + node.value;
+ node.escaped = true;
+ }
+ }
};
-if (getProto) {
+/**
+ * Returns true if the given brace node should be enclosed in literal braces
+ */
+
+exports.encloseBrace = node => {
+ if (node.type !== 'brace') return false;
+ if ((node.commas >> 0 + node.ranges >> 0) === 0) {
+ node.invalid = true;
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Returns true if a brace node is invalid.
+ */
+
+exports.isInvalidBrace = block => {
+ if (block.type !== 'brace') return false;
+ if (block.invalid === true || block.dollar) return true;
+ if ((block.commas >> 0 + block.ranges >> 0) === 0) {
+ block.invalid = true;
+ return true;
+ }
+ if (block.open !== true || block.close !== true) {
+ block.invalid = true;
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Returns true if a node is an open or close node
+ */
+
+exports.isOpenOrClose = node => {
+ if (node.type === 'open' || node.type === 'close') {
+ return true;
+ }
+ return node.open === true || node.close === true;
+};
+
+/**
+ * Reduce an array of text nodes.
+ */
+
+exports.reduce = nodes => nodes.reduce((acc, node) => {
+ if (node.type === 'text') acc.push(node.value);
+ if (node.type === 'range') node.type = 'text';
+ return acc;
+}, []);
+
+/**
+ * Flatten an array
+ */
+
+exports.flatten = (...args) => {
+ const result = [];
+ const flat = arr => {
+ for (let i = 0; i < arr.length; i++) {
+ let ele = arr[i];
+ Array.isArray(ele) ? flat(ele, result) : ele !== void 0 && result.push(ele);
+ }
+ return result;
+ };
+ flat(args);
+ return result;
+};
+
+
+/***/ }),
+
+/***/ 8803:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+var GetIntrinsic = __nccwpck_require__(4538);
+
+var callBind = __nccwpck_require__(2977);
+
+var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));
+
+module.exports = function callBoundIntrinsic(name, allowMissing) {
+ var intrinsic = GetIntrinsic(name, !!allowMissing);
+ if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
+ return callBind(intrinsic);
+ }
+ return intrinsic;
+};
+
+
+/***/ }),
+
+/***/ 2977:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+var bind = __nccwpck_require__(8334);
+var GetIntrinsic = __nccwpck_require__(4538);
+
+var $apply = GetIntrinsic('%Function.prototype.apply%');
+var $call = GetIntrinsic('%Function.prototype.call%');
+var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);
+
+var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);
+var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
+var $max = GetIntrinsic('%Math.max%');
+
+if ($defineProperty) {
try {
- null.error; // eslint-disable-line no-unused-expressions
+ $defineProperty({}, 'a', { value: 1 });
} catch (e) {
- // https://github.com/tc39/proposal-shadowrealm/pull/384#issuecomment-1364264229
- var errorProto = getProto(getProto(e));
- INTRINSICS['%Error.prototype%'] = errorProto;
+ // IE 8 has a broken defineProperty
+ $defineProperty = null;
}
}
-var doEval = function doEval(name) {
- var value;
- if (name === '%AsyncFunction%') {
- value = getEvalledConstructor('async function () {}');
- } else if (name === '%GeneratorFunction%') {
- value = getEvalledConstructor('function* () {}');
- } else if (name === '%AsyncGeneratorFunction%') {
- value = getEvalledConstructor('async function* () {}');
- } else if (name === '%AsyncGenerator%') {
- var fn = doEval('%AsyncGeneratorFunction%');
- if (fn) {
- value = fn.prototype;
- }
- } else if (name === '%AsyncIteratorPrototype%') {
- var gen = doEval('%AsyncGenerator%');
- if (gen && getProto) {
- value = getProto(gen.prototype);
+module.exports = function callBind(originalFunction) {
+ var func = $reflectApply(bind, $call, arguments);
+ if ($gOPD && $defineProperty) {
+ var desc = $gOPD(func, 'length');
+ if (desc.configurable) {
+ // original length, plus the receiver, minus any additional arguments (after the receiver)
+ $defineProperty(
+ func,
+ 'length',
+ { value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }
+ );
}
}
+ return func;
+};
- INTRINSICS[name] = value;
+var applyBind = function applyBind() {
+ return $reflectApply(bind, $apply, arguments);
+};
+
+if ($defineProperty) {
+ $defineProperty(module.exports, 'apply', { value: applyBind });
+} else {
+ module.exports.apply = applyBind;
+}
+
+
+/***/ }),
+
+/***/ 8932:
+/***/ ((__unused_webpack_module, exports) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+
+class Deprecation extends Error {
+ constructor(message) {
+ super(message); // Maintains proper stack trace (only available on V8)
+
+ /* istanbul ignore next */
+
+ if (Error.captureStackTrace) {
+ Error.captureStackTrace(this, this.constructor);
+ }
+
+ this.name = 'Deprecation';
+ }
+
+}
+
+exports.Deprecation = Deprecation;
+
+
+/***/ }),
+
+/***/ 2437:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+const fs = __nccwpck_require__(7147)
+const path = __nccwpck_require__(1017)
+const os = __nccwpck_require__(2037)
+const packageJson = __nccwpck_require__(9968)
+
+const version = packageJson.version
+
+const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
+
+// Parser src into an Object
+function parse (src) {
+ const obj = {}
+
+ // Convert buffer to string
+ let lines = src.toString()
+
+ // Convert line breaks to same format
+ lines = lines.replace(/\r\n?/mg, '\n')
+
+ let match
+ while ((match = LINE.exec(lines)) != null) {
+ const key = match[1]
+
+ // Default undefined or null to empty string
+ let value = (match[2] || '')
+
+ // Remove whitespace
+ value = value.trim()
+
+ // Check if double quoted
+ const maybeQuote = value[0]
+
+ // Remove surrounding quotes
+ value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
+
+ // Expand newlines if double quoted
+ if (maybeQuote === '"') {
+ value = value.replace(/\\n/g, '\n')
+ value = value.replace(/\\r/g, '\r')
+ }
+
+ // Add to object
+ obj[key] = value
+ }
+
+ return obj
+}
+
+function _log (message) {
+ console.log(`[dotenv@${version}][DEBUG] ${message}`)
+}
+
+function _resolveHome (envPath) {
+ return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
+}
+
+// Populates process.env from .env file
+function config (options) {
+ let dotenvPath = path.resolve(process.cwd(), '.env')
+ let encoding = 'utf8'
+ const debug = Boolean(options && options.debug)
+ const override = Boolean(options && options.override)
+
+ if (options) {
+ if (options.path != null) {
+ dotenvPath = _resolveHome(options.path)
+ }
+ if (options.encoding != null) {
+ encoding = options.encoding
+ }
+ }
+
+ try {
+ // Specifying an encoding returns a string instead of a buffer
+ const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }))
+
+ Object.keys(parsed).forEach(function (key) {
+ if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
+ process.env[key] = parsed[key]
+ } else {
+ if (override === true) {
+ process.env[key] = parsed[key]
+ }
+
+ if (debug) {
+ if (override === true) {
+ _log(`"${key}" is already defined in \`process.env\` and WAS overwritten`)
+ } else {
+ _log(`"${key}" is already defined in \`process.env\` and was NOT overwritten`)
+ }
+ }
+ }
+ })
+
+ return { parsed }
+ } catch (e) {
+ if (debug) {
+ _log(`Failed to load ${dotenvPath} ${e.message}`)
+ }
+
+ return { error: e }
+ }
+}
+
+const DotenvModule = {
+ config,
+ parse
+}
+
+module.exports.config = DotenvModule.config
+module.exports.parse = DotenvModule.parse
+module.exports = DotenvModule
+
+
+/***/ }),
+
+/***/ 6330:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+/*!
+ * fill-range
+ *
+ * Copyright (c) 2014-present, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+
+
+const util = __nccwpck_require__(3837);
+const toRegexRange = __nccwpck_require__(1861);
+
+const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
+
+const transform = toNumber => {
+ return value => toNumber === true ? Number(value) : String(value);
+};
+
+const isValidValue = value => {
+ return typeof value === 'number' || (typeof value === 'string' && value !== '');
+};
+
+const isNumber = num => Number.isInteger(+num);
+
+const zeros = input => {
+ let value = `${input}`;
+ let index = -1;
+ if (value[0] === '-') value = value.slice(1);
+ if (value === '0') return false;
+ while (value[++index] === '0');
+ return index > 0;
+};
+
+const stringify = (start, end, options) => {
+ if (typeof start === 'string' || typeof end === 'string') {
+ return true;
+ }
+ return options.stringify === true;
+};
+
+const pad = (input, maxLength, toNumber) => {
+ if (maxLength > 0) {
+ let dash = input[0] === '-' ? '-' : '';
+ if (dash) input = input.slice(1);
+ input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0'));
+ }
+ if (toNumber === false) {
+ return String(input);
+ }
+ return input;
+};
+
+const toMaxLen = (input, maxLength) => {
+ let negative = input[0] === '-' ? '-' : '';
+ if (negative) {
+ input = input.slice(1);
+ maxLength--;
+ }
+ while (input.length < maxLength) input = '0' + input;
+ return negative ? ('-' + input) : input;
+};
+
+const toSequence = (parts, options) => {
+ parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
+ parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
+
+ let prefix = options.capture ? '' : '?:';
+ let positives = '';
+ let negatives = '';
+ let result;
+
+ if (parts.positives.length) {
+ positives = parts.positives.join('|');
+ }
+
+ if (parts.negatives.length) {
+ negatives = `-(${prefix}${parts.negatives.join('|')})`;
+ }
+
+ if (positives && negatives) {
+ result = `${positives}|${negatives}`;
+ } else {
+ result = positives || negatives;
+ }
+
+ if (options.wrap) {
+ return `(${prefix}${result})`;
+ }
+
+ return result;
+};
+
+const toRange = (a, b, isNumbers, options) => {
+ if (isNumbers) {
+ return toRegexRange(a, b, { wrap: false, ...options });
+ }
+
+ let start = String.fromCharCode(a);
+ if (a === b) return start;
+
+ let stop = String.fromCharCode(b);
+ return `[${start}-${stop}]`;
+};
+
+const toRegex = (start, end, options) => {
+ if (Array.isArray(start)) {
+ let wrap = options.wrap === true;
+ let prefix = options.capture ? '' : '?:';
+ return wrap ? `(${prefix}${start.join('|')})` : start.join('|');
+ }
+ return toRegexRange(start, end, options);
+};
+
+const rangeError = (...args) => {
+ return new RangeError('Invalid range arguments: ' + util.inspect(...args));
+};
+
+const invalidRange = (start, end, options) => {
+ if (options.strictRanges === true) throw rangeError([start, end]);
+ return [];
+};
+
+const invalidStep = (step, options) => {
+ if (options.strictRanges === true) {
+ throw new TypeError(`Expected step "${step}" to be a number`);
+ }
+ return [];
+};
+
+const fillNumbers = (start, end, step = 1, options = {}) => {
+ let a = Number(start);
+ let b = Number(end);
+
+ if (!Number.isInteger(a) || !Number.isInteger(b)) {
+ if (options.strictRanges === true) throw rangeError([start, end]);
+ return [];
+ }
+
+ // fix negative zero
+ if (a === 0) a = 0;
+ if (b === 0) b = 0;
+
+ let descending = a > b;
+ let startString = String(start);
+ let endString = String(end);
+ let stepString = String(step);
+ step = Math.max(Math.abs(step), 1);
+
+ let padded = zeros(startString) || zeros(endString) || zeros(stepString);
+ let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0;
+ let toNumber = padded === false && stringify(start, end, options) === false;
+ let format = options.transform || transform(toNumber);
+
+ if (options.toRegex && step === 1) {
+ return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options);
+ }
+
+ let parts = { negatives: [], positives: [] };
+ let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num));
+ let range = [];
+ let index = 0;
+
+ while (descending ? a >= b : a <= b) {
+ if (options.toRegex === true && step > 1) {
+ push(a);
+ } else {
+ range.push(pad(format(a, index), maxLen, toNumber));
+ }
+ a = descending ? a - step : a + step;
+ index++;
+ }
+
+ if (options.toRegex === true) {
+ return step > 1
+ ? toSequence(parts, options)
+ : toRegex(range, null, { wrap: false, ...options });
+ }
+
+ return range;
+};
+
+const fillLetters = (start, end, step = 1, options = {}) => {
+ if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) {
+ return invalidRange(start, end, options);
+ }
+
+
+ let format = options.transform || (val => String.fromCharCode(val));
+ let a = `${start}`.charCodeAt(0);
+ let b = `${end}`.charCodeAt(0);
+
+ let descending = a > b;
+ let min = Math.min(a, b);
+ let max = Math.max(a, b);
+
+ if (options.toRegex && step === 1) {
+ return toRange(min, max, false, options);
+ }
+
+ let range = [];
+ let index = 0;
+
+ while (descending ? a >= b : a <= b) {
+ range.push(format(a, index));
+ a = descending ? a - step : a + step;
+ index++;
+ }
+
+ if (options.toRegex === true) {
+ return toRegex(range, null, { wrap: false, options });
+ }
+
+ return range;
+};
+
+const fill = (start, end, step, options = {}) => {
+ if (end == null && isValidValue(start)) {
+ return [start];
+ }
+
+ if (!isValidValue(start) || !isValidValue(end)) {
+ return invalidRange(start, end, options);
+ }
+
+ if (typeof step === 'function') {
+ return fill(start, end, 1, { transform: step });
+ }
+
+ if (isObject(step)) {
+ return fill(start, end, 0, step);
+ }
+
+ let opts = { ...options };
+ if (opts.capture === true) opts.wrap = true;
+ step = step || opts.step || 1;
+
+ if (!isNumber(step)) {
+ if (step != null && !isObject(step)) return invalidStep(step, opts);
+ return fill(start, end, 1, step);
+ }
+
+ if (isNumber(start) && isNumber(end)) {
+ return fillNumbers(start, end, step, opts);
+ }
+
+ return fillLetters(start, end, Math.max(Math.abs(step), 1), opts);
+};
+
+module.exports = fill;
+
+
+/***/ }),
+
+/***/ 9320:
+/***/ ((module) => {
+
+
+
+/* eslint no-invalid-this: 1 */
+
+var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
+var slice = Array.prototype.slice;
+var toStr = Object.prototype.toString;
+var funcType = '[object Function]';
+
+module.exports = function bind(that) {
+ var target = this;
+ if (typeof target !== 'function' || toStr.call(target) !== funcType) {
+ throw new TypeError(ERROR_MESSAGE + target);
+ }
+ var args = slice.call(arguments, 1);
+
+ var bound;
+ var binder = function () {
+ if (this instanceof bound) {
+ var result = target.apply(
+ this,
+ args.concat(slice.call(arguments))
+ );
+ if (Object(result) === result) {
+ return result;
+ }
+ return this;
+ } else {
+ return target.apply(
+ that,
+ args.concat(slice.call(arguments))
+ );
+ }
+ };
+
+ var boundLength = Math.max(0, target.length - args.length);
+ var boundArgs = [];
+ for (var i = 0; i < boundLength; i++) {
+ boundArgs.push('$' + i);
+ }
+
+ bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
+
+ if (target.prototype) {
+ var Empty = function Empty() {};
+ Empty.prototype = target.prototype;
+ bound.prototype = new Empty();
+ Empty.prototype = null;
+ }
+
+ return bound;
+};
+
+
+/***/ }),
+
+/***/ 8334:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+var implementation = __nccwpck_require__(9320);
+
+module.exports = Function.prototype.bind || implementation;
+
+
+/***/ }),
+
+/***/ 4538:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+var undefined;
+
+var $SyntaxError = SyntaxError;
+var $Function = Function;
+var $TypeError = TypeError;
+
+// eslint-disable-next-line consistent-return
+var getEvalledConstructor = function (expressionSyntax) {
+ try {
+ return $Function('"use strict"; return (' + expressionSyntax + ').constructor;')();
+ } catch (e) {}
+};
+
+var $gOPD = Object.getOwnPropertyDescriptor;
+if ($gOPD) {
+ try {
+ $gOPD({}, '');
+ } catch (e) {
+ $gOPD = null; // this is IE 8, which has a broken gOPD
+ }
+}
+
+var throwTypeError = function () {
+ throw new $TypeError();
+};
+var ThrowTypeError = $gOPD
+ ? (function () {
+ try {
+ // eslint-disable-next-line no-unused-expressions, no-caller, no-restricted-properties
+ arguments.callee; // IE 8 does not throw here
+ return throwTypeError;
+ } catch (calleeThrows) {
+ try {
+ // IE 8 throws on Object.getOwnPropertyDescriptor(arguments, '')
+ return $gOPD(arguments, 'callee').get;
+ } catch (gOPDthrows) {
+ return throwTypeError;
+ }
+ }
+ }())
+ : throwTypeError;
+
+var hasSymbols = __nccwpck_require__(587)();
+var hasProto = __nccwpck_require__(5894)();
+
+var getProto = Object.getPrototypeOf || (
+ hasProto
+ ? function (x) { return x.__proto__; } // eslint-disable-line no-proto
+ : null
+);
+
+var needsEval = {};
+
+var TypedArray = typeof Uint8Array === 'undefined' || !getProto ? undefined : getProto(Uint8Array);
+
+var INTRINSICS = {
+ '%AggregateError%': typeof AggregateError === 'undefined' ? undefined : AggregateError,
+ '%Array%': Array,
+ '%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer,
+ '%ArrayIteratorPrototype%': hasSymbols && getProto ? getProto([][Symbol.iterator]()) : undefined,
+ '%AsyncFromSyncIteratorPrototype%': undefined,
+ '%AsyncFunction%': needsEval,
+ '%AsyncGenerator%': needsEval,
+ '%AsyncGeneratorFunction%': needsEval,
+ '%AsyncIteratorPrototype%': needsEval,
+ '%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics,
+ '%BigInt%': typeof BigInt === 'undefined' ? undefined : BigInt,
+ '%BigInt64Array%': typeof BigInt64Array === 'undefined' ? undefined : BigInt64Array,
+ '%BigUint64Array%': typeof BigUint64Array === 'undefined' ? undefined : BigUint64Array,
+ '%Boolean%': Boolean,
+ '%DataView%': typeof DataView === 'undefined' ? undefined : DataView,
+ '%Date%': Date,
+ '%decodeURI%': decodeURI,
+ '%decodeURIComponent%': decodeURIComponent,
+ '%encodeURI%': encodeURI,
+ '%encodeURIComponent%': encodeURIComponent,
+ '%Error%': Error,
+ '%eval%': eval, // eslint-disable-line no-eval
+ '%EvalError%': EvalError,
+ '%Float32Array%': typeof Float32Array === 'undefined' ? undefined : Float32Array,
+ '%Float64Array%': typeof Float64Array === 'undefined' ? undefined : Float64Array,
+ '%FinalizationRegistry%': typeof FinalizationRegistry === 'undefined' ? undefined : FinalizationRegistry,
+ '%Function%': $Function,
+ '%GeneratorFunction%': needsEval,
+ '%Int8Array%': typeof Int8Array === 'undefined' ? undefined : Int8Array,
+ '%Int16Array%': typeof Int16Array === 'undefined' ? undefined : Int16Array,
+ '%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array,
+ '%isFinite%': isFinite,
+ '%isNaN%': isNaN,
+ '%IteratorPrototype%': hasSymbols && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined,
+ '%JSON%': typeof JSON === 'object' ? JSON : undefined,
+ '%Map%': typeof Map === 'undefined' ? undefined : Map,
+ '%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Map()[Symbol.iterator]()),
+ '%Math%': Math,
+ '%Number%': Number,
+ '%Object%': Object,
+ '%parseFloat%': parseFloat,
+ '%parseInt%': parseInt,
+ '%Promise%': typeof Promise === 'undefined' ? undefined : Promise,
+ '%Proxy%': typeof Proxy === 'undefined' ? undefined : Proxy,
+ '%RangeError%': RangeError,
+ '%ReferenceError%': ReferenceError,
+ '%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect,
+ '%RegExp%': RegExp,
+ '%Set%': typeof Set === 'undefined' ? undefined : Set,
+ '%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Set()[Symbol.iterator]()),
+ '%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer,
+ '%String%': String,
+ '%StringIteratorPrototype%': hasSymbols && getProto ? getProto(''[Symbol.iterator]()) : undefined,
+ '%Symbol%': hasSymbols ? Symbol : undefined,
+ '%SyntaxError%': $SyntaxError,
+ '%ThrowTypeError%': ThrowTypeError,
+ '%TypedArray%': TypedArray,
+ '%TypeError%': $TypeError,
+ '%Uint8Array%': typeof Uint8Array === 'undefined' ? undefined : Uint8Array,
+ '%Uint8ClampedArray%': typeof Uint8ClampedArray === 'undefined' ? undefined : Uint8ClampedArray,
+ '%Uint16Array%': typeof Uint16Array === 'undefined' ? undefined : Uint16Array,
+ '%Uint32Array%': typeof Uint32Array === 'undefined' ? undefined : Uint32Array,
+ '%URIError%': URIError,
+ '%WeakMap%': typeof WeakMap === 'undefined' ? undefined : WeakMap,
+ '%WeakRef%': typeof WeakRef === 'undefined' ? undefined : WeakRef,
+ '%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet
+};
+
+if (getProto) {
+ try {
+ null.error; // eslint-disable-line no-unused-expressions
+ } catch (e) {
+ // https://github.com/tc39/proposal-shadowrealm/pull/384#issuecomment-1364264229
+ var errorProto = getProto(getProto(e));
+ INTRINSICS['%Error.prototype%'] = errorProto;
+ }
+}
+
+var doEval = function doEval(name) {
+ var value;
+ if (name === '%AsyncFunction%') {
+ value = getEvalledConstructor('async function () {}');
+ } else if (name === '%GeneratorFunction%') {
+ value = getEvalledConstructor('function* () {}');
+ } else if (name === '%AsyncGeneratorFunction%') {
+ value = getEvalledConstructor('async function* () {}');
+ } else if (name === '%AsyncGenerator%') {
+ var fn = doEval('%AsyncGeneratorFunction%');
+ if (fn) {
+ value = fn.prototype;
+ }
+ } else if (name === '%AsyncIteratorPrototype%') {
+ var gen = doEval('%AsyncGenerator%');
+ if (gen && getProto) {
+ value = getProto(gen.prototype);
+ }
+ }
+
+ INTRINSICS[name] = value;
+
+ return value;
+};
+
+var LEGACY_ALIASES = {
+ '%ArrayBufferPrototype%': ['ArrayBuffer', 'prototype'],
+ '%ArrayPrototype%': ['Array', 'prototype'],
+ '%ArrayProto_entries%': ['Array', 'prototype', 'entries'],
+ '%ArrayProto_forEach%': ['Array', 'prototype', 'forEach'],
+ '%ArrayProto_keys%': ['Array', 'prototype', 'keys'],
+ '%ArrayProto_values%': ['Array', 'prototype', 'values'],
+ '%AsyncFunctionPrototype%': ['AsyncFunction', 'prototype'],
+ '%AsyncGenerator%': ['AsyncGeneratorFunction', 'prototype'],
+ '%AsyncGeneratorPrototype%': ['AsyncGeneratorFunction', 'prototype', 'prototype'],
+ '%BooleanPrototype%': ['Boolean', 'prototype'],
+ '%DataViewPrototype%': ['DataView', 'prototype'],
+ '%DatePrototype%': ['Date', 'prototype'],
+ '%ErrorPrototype%': ['Error', 'prototype'],
+ '%EvalErrorPrototype%': ['EvalError', 'prototype'],
+ '%Float32ArrayPrototype%': ['Float32Array', 'prototype'],
+ '%Float64ArrayPrototype%': ['Float64Array', 'prototype'],
+ '%FunctionPrototype%': ['Function', 'prototype'],
+ '%Generator%': ['GeneratorFunction', 'prototype'],
+ '%GeneratorPrototype%': ['GeneratorFunction', 'prototype', 'prototype'],
+ '%Int8ArrayPrototype%': ['Int8Array', 'prototype'],
+ '%Int16ArrayPrototype%': ['Int16Array', 'prototype'],
+ '%Int32ArrayPrototype%': ['Int32Array', 'prototype'],
+ '%JSONParse%': ['JSON', 'parse'],
+ '%JSONStringify%': ['JSON', 'stringify'],
+ '%MapPrototype%': ['Map', 'prototype'],
+ '%NumberPrototype%': ['Number', 'prototype'],
+ '%ObjectPrototype%': ['Object', 'prototype'],
+ '%ObjProto_toString%': ['Object', 'prototype', 'toString'],
+ '%ObjProto_valueOf%': ['Object', 'prototype', 'valueOf'],
+ '%PromisePrototype%': ['Promise', 'prototype'],
+ '%PromiseProto_then%': ['Promise', 'prototype', 'then'],
+ '%Promise_all%': ['Promise', 'all'],
+ '%Promise_reject%': ['Promise', 'reject'],
+ '%Promise_resolve%': ['Promise', 'resolve'],
+ '%RangeErrorPrototype%': ['RangeError', 'prototype'],
+ '%ReferenceErrorPrototype%': ['ReferenceError', 'prototype'],
+ '%RegExpPrototype%': ['RegExp', 'prototype'],
+ '%SetPrototype%': ['Set', 'prototype'],
+ '%SharedArrayBufferPrototype%': ['SharedArrayBuffer', 'prototype'],
+ '%StringPrototype%': ['String', 'prototype'],
+ '%SymbolPrototype%': ['Symbol', 'prototype'],
+ '%SyntaxErrorPrototype%': ['SyntaxError', 'prototype'],
+ '%TypedArrayPrototype%': ['TypedArray', 'prototype'],
+ '%TypeErrorPrototype%': ['TypeError', 'prototype'],
+ '%Uint8ArrayPrototype%': ['Uint8Array', 'prototype'],
+ '%Uint8ClampedArrayPrototype%': ['Uint8ClampedArray', 'prototype'],
+ '%Uint16ArrayPrototype%': ['Uint16Array', 'prototype'],
+ '%Uint32ArrayPrototype%': ['Uint32Array', 'prototype'],
+ '%URIErrorPrototype%': ['URIError', 'prototype'],
+ '%WeakMapPrototype%': ['WeakMap', 'prototype'],
+ '%WeakSetPrototype%': ['WeakSet', 'prototype']
+};
+
+var bind = __nccwpck_require__(8334);
+var hasOwn = __nccwpck_require__(6339);
+var $concat = bind.call(Function.call, Array.prototype.concat);
+var $spliceApply = bind.call(Function.apply, Array.prototype.splice);
+var $replace = bind.call(Function.call, String.prototype.replace);
+var $strSlice = bind.call(Function.call, String.prototype.slice);
+var $exec = bind.call(Function.call, RegExp.prototype.exec);
+
+/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */
+var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;
+var reEscapeChar = /\\(\\)?/g; /** Used to match backslashes in property paths. */
+var stringToPath = function stringToPath(string) {
+ var first = $strSlice(string, 0, 1);
+ var last = $strSlice(string, -1);
+ if (first === '%' && last !== '%') {
+ throw new $SyntaxError('invalid intrinsic syntax, expected closing `%`');
+ } else if (last === '%' && first !== '%') {
+ throw new $SyntaxError('invalid intrinsic syntax, expected opening `%`');
+ }
+ var result = [];
+ $replace(string, rePropName, function (match, number, quote, subString) {
+ result[result.length] = quote ? $replace(subString, reEscapeChar, '$1') : number || match;
+ });
+ return result;
+};
+/* end adaptation */
+
+var getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) {
+ var intrinsicName = name;
+ var alias;
+ if (hasOwn(LEGACY_ALIASES, intrinsicName)) {
+ alias = LEGACY_ALIASES[intrinsicName];
+ intrinsicName = '%' + alias[0] + '%';
+ }
+
+ if (hasOwn(INTRINSICS, intrinsicName)) {
+ var value = INTRINSICS[intrinsicName];
+ if (value === needsEval) {
+ value = doEval(intrinsicName);
+ }
+ if (typeof value === 'undefined' && !allowMissing) {
+ throw new $TypeError('intrinsic ' + name + ' exists, but is not available. Please file an issue!');
+ }
+
+ return {
+ alias: alias,
+ name: intrinsicName,
+ value: value
+ };
+ }
+
+ throw new $SyntaxError('intrinsic ' + name + ' does not exist!');
+};
+
+module.exports = function GetIntrinsic(name, allowMissing) {
+ if (typeof name !== 'string' || name.length === 0) {
+ throw new $TypeError('intrinsic name must be a non-empty string');
+ }
+ if (arguments.length > 1 && typeof allowMissing !== 'boolean') {
+ throw new $TypeError('"allowMissing" argument must be a boolean');
+ }
+
+ if ($exec(/^%?[^%]*%?$/, name) === null) {
+ throw new $SyntaxError('`%` may not be present anywhere but at the beginning and end of the intrinsic name');
+ }
+ var parts = stringToPath(name);
+ var intrinsicBaseName = parts.length > 0 ? parts[0] : '';
+
+ var intrinsic = getBaseIntrinsic('%' + intrinsicBaseName + '%', allowMissing);
+ var intrinsicRealName = intrinsic.name;
+ var value = intrinsic.value;
+ var skipFurtherCaching = false;
+
+ var alias = intrinsic.alias;
+ if (alias) {
+ intrinsicBaseName = alias[0];
+ $spliceApply(parts, $concat([0, 1], alias));
+ }
+
+ for (var i = 1, isOwn = true; i < parts.length; i += 1) {
+ var part = parts[i];
+ var first = $strSlice(part, 0, 1);
+ var last = $strSlice(part, -1);
+ if (
+ (
+ (first === '"' || first === "'" || first === '`')
+ || (last === '"' || last === "'" || last === '`')
+ )
+ && first !== last
+ ) {
+ throw new $SyntaxError('property names with quotes must have matching quotes');
+ }
+ if (part === 'constructor' || !isOwn) {
+ skipFurtherCaching = true;
+ }
+
+ intrinsicBaseName += '.' + part;
+ intrinsicRealName = '%' + intrinsicBaseName + '%';
+
+ if (hasOwn(INTRINSICS, intrinsicRealName)) {
+ value = INTRINSICS[intrinsicRealName];
+ } else if (value != null) {
+ if (!(part in value)) {
+ if (!allowMissing) {
+ throw new $TypeError('base intrinsic for ' + name + ' exists, but the property is not available.');
+ }
+ return void undefined;
+ }
+ if ($gOPD && (i + 1) >= parts.length) {
+ var desc = $gOPD(value, part);
+ isOwn = !!desc;
+
+ // By convention, when a data property is converted to an accessor
+ // property to emulate a data property that does not suffer from
+ // the override mistake, that accessor's getter is marked with
+ // an `originalValue` property. Here, when we detect this, we
+ // uphold the illusion by pretending to see that original data
+ // property, i.e., returning the value rather than the getter
+ // itself.
+ if (isOwn && 'get' in desc && !('originalValue' in desc.get)) {
+ value = desc.get;
+ } else {
+ value = value[part];
+ }
+ } else {
+ isOwn = hasOwn(value, part);
+ value = value[part];
+ }
+
+ if (isOwn && !skipFurtherCaching) {
+ INTRINSICS[intrinsicRealName] = value;
+ }
+ }
+ }
+ return value;
+};
+
+
+/***/ }),
+
+/***/ 5894:
+/***/ ((module) => {
+
+
+
+var test = {
+ foo: {}
+};
+
+var $Object = Object;
+
+module.exports = function hasProto() {
+ return { __proto__: test }.foo === test.foo && !({ __proto__: null } instanceof $Object);
+};
+
+
+/***/ }),
+
+/***/ 587:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+var origSymbol = typeof Symbol !== 'undefined' && Symbol;
+var hasSymbolSham = __nccwpck_require__(7747);
+
+module.exports = function hasNativeSymbols() {
+ if (typeof origSymbol !== 'function') { return false; }
+ if (typeof Symbol !== 'function') { return false; }
+ if (typeof origSymbol('foo') !== 'symbol') { return false; }
+ if (typeof Symbol('bar') !== 'symbol') { return false; }
+
+ return hasSymbolSham();
+};
+
+
+/***/ }),
+
+/***/ 7747:
+/***/ ((module) => {
+
+
+
+/* eslint complexity: [2, 18], max-statements: [2, 33] */
+module.exports = function hasSymbols() {
+ if (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; }
+ if (typeof Symbol.iterator === 'symbol') { return true; }
+
+ var obj = {};
+ var sym = Symbol('test');
+ var symObj = Object(sym);
+ if (typeof sym === 'string') { return false; }
+
+ if (Object.prototype.toString.call(sym) !== '[object Symbol]') { return false; }
+ if (Object.prototype.toString.call(symObj) !== '[object Symbol]') { return false; }
+
+ // temp disabled per https://github.com/ljharb/object.assign/issues/17
+ // if (sym instanceof Symbol) { return false; }
+ // temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4
+ // if (!(symObj instanceof Symbol)) { return false; }
+
+ // if (typeof Symbol.prototype.toString !== 'function') { return false; }
+ // if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; }
+
+ var symVal = 42;
+ obj[sym] = symVal;
+ for (sym in obj) { return false; } // eslint-disable-line no-restricted-syntax, no-unreachable-loop
+ if (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; }
+
+ if (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; }
+
+ var syms = Object.getOwnPropertySymbols(obj);
+ if (syms.length !== 1 || syms[0] !== sym) { return false; }
+
+ if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; }
+
+ if (typeof Object.getOwnPropertyDescriptor === 'function') {
+ var descriptor = Object.getOwnPropertyDescriptor(obj, sym);
+ if (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; }
+ }
+
+ return true;
+};
+
+
+/***/ }),
+
+/***/ 6339:
+/***/ ((module) => {
+
+
+
+var hasOwnProperty = {}.hasOwnProperty;
+var call = Function.prototype.call;
+
+module.exports = call.bind ? call.bind(hasOwnProperty) : function (O, P) {
+ return call.call(hasOwnProperty, O, P);
+};
+
+
+/***/ }),
+
+/***/ 5680:
+/***/ ((module) => {
+
+/*!
+ * is-number
+ *
+ * Copyright (c) 2014-present, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+
+
+module.exports = function(num) {
+ if (typeof num === 'number') {
+ return num - num === 0;
+ }
+ if (typeof num === 'string' && num.trim() !== '') {
+ return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
+ }
+ return false;
+};
+
+
+/***/ }),
+
+/***/ 3287:
+/***/ ((__unused_webpack_module, exports) => {
+
+
+
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+
+/*!
+ * is-plain-object
+ *
+ * Copyright (c) 2014-2017, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+function isObject(o) {
+ return Object.prototype.toString.call(o) === '[object Object]';
+}
+
+function isPlainObject(o) {
+ var ctor,prot;
+
+ if (isObject(o) === false) return false;
+
+ // If has modified constructor
+ ctor = o.constructor;
+ if (ctor === undefined) return true;
+
+ // If has modified prototype
+ prot = ctor.prototype;
+ if (isObject(prot) === false) return false;
+
+ // If constructor does not have an Object-specific method
+ if (prot.hasOwnProperty('isPrototypeOf') === false) {
+ return false;
+ }
+
+ // Most likely a plain Object
+ return true;
+}
+
+exports.isPlainObject = isPlainObject;
+
+
+/***/ }),
+
+/***/ 7073:
+/***/ ((module, exports) => {
+
+exports = module.exports = stringify
+exports.getSerialize = serializer
+
+function stringify(obj, replacer, spaces, cycleReplacer) {
+ return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
+}
+
+function serializer(replacer, cycleReplacer) {
+ var stack = [], keys = []
+
+ if (cycleReplacer == null) cycleReplacer = function(key, value) {
+ if (stack[0] === value) return "[Circular ~]"
+ return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"
+ }
+
+ return function(key, value) {
+ if (stack.length > 0) {
+ var thisPos = stack.indexOf(this)
+ ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
+ ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
+ if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
+ }
+ else stack.push(value)
+
+ return replacer == null ? value : replacer.call(this, key, value)
+ }
+}
+
+
+/***/ }),
+
+/***/ 6228:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+const util = __nccwpck_require__(3837);
+const braces = __nccwpck_require__(610);
+const picomatch = __nccwpck_require__(8569);
+const utils = __nccwpck_require__(479);
+const isEmptyString = val => val === '' || val === './';
+
+/**
+ * Returns an array of strings that match one or more glob patterns.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm(list, patterns[, options]);
+ *
+ * console.log(mm(['a.js', 'a.txt'], ['*.js']));
+ * //=> [ 'a.js' ]
+ * ```
+ * @param {String|Array} `list` List of strings to match.
+ * @param {String|Array} `patterns` One or more glob patterns to use for matching.
+ * @param {Object} `options` See available [options](#options)
+ * @return {Array} Returns an array of matches
+ * @summary false
+ * @api public
+ */
+
+const micromatch = (list, patterns, options) => {
+ patterns = [].concat(patterns);
+ list = [].concat(list);
+
+ let omit = new Set();
+ let keep = new Set();
+ let items = new Set();
+ let negatives = 0;
+
+ let onResult = state => {
+ items.add(state.output);
+ if (options && options.onResult) {
+ options.onResult(state);
+ }
+ };
+
+ for (let i = 0; i < patterns.length; i++) {
+ let isMatch = picomatch(String(patterns[i]), { ...options, onResult }, true);
+ let negated = isMatch.state.negated || isMatch.state.negatedExtglob;
+ if (negated) negatives++;
+
+ for (let item of list) {
+ let matched = isMatch(item, true);
+
+ let match = negated ? !matched.isMatch : matched.isMatch;
+ if (!match) continue;
+
+ if (negated) {
+ omit.add(matched.output);
+ } else {
+ omit.delete(matched.output);
+ keep.add(matched.output);
+ }
+ }
+ }
+
+ let result = negatives === patterns.length ? [...items] : [...keep];
+ let matches = result.filter(item => !omit.has(item));
+
+ if (options && matches.length === 0) {
+ if (options.failglob === true) {
+ throw new Error(`No matches found for "${patterns.join(', ')}"`);
+ }
+
+ if (options.nonull === true || options.nullglob === true) {
+ return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns;
+ }
+ }
+
+ return matches;
+};
+
+/**
+ * Backwards compatibility
+ */
+
+micromatch.match = micromatch;
+
+/**
+ * Returns a matcher function from the given glob `pattern` and `options`.
+ * The returned function takes a string to match as its only argument and returns
+ * true if the string is a match.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.matcher(pattern[, options]);
+ *
+ * const isMatch = mm.matcher('*.!(*a)');
+ * console.log(isMatch('a.a')); //=> false
+ * console.log(isMatch('a.b')); //=> true
+ * ```
+ * @param {String} `pattern` Glob pattern
+ * @param {Object} `options`
+ * @return {Function} Returns a matcher function.
+ * @api public
+ */
+
+micromatch.matcher = (pattern, options) => picomatch(pattern, options);
+
+/**
+ * Returns true if **any** of the given glob `patterns` match the specified `string`.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.isMatch(string, patterns[, options]);
+ *
+ * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true
+ * console.log(mm.isMatch('a.a', 'b.*')); //=> false
+ * ```
+ * @param {String} `str` The string to test.
+ * @param {String|Array} `patterns` One or more glob patterns to use for matching.
+ * @param {Object} `[options]` See available [options](#options).
+ * @return {Boolean} Returns true if any patterns match `str`
+ * @api public
+ */
+
+micromatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
+
+/**
+ * Backwards compatibility
+ */
+
+micromatch.any = micromatch.isMatch;
+
+/**
+ * Returns a list of strings that _**do not match any**_ of the given `patterns`.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.not(list, patterns[, options]);
+ *
+ * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a'));
+ * //=> ['b.b', 'c.c']
+ * ```
+ * @param {Array} `list` Array of strings to match.
+ * @param {String|Array} `patterns` One or more glob pattern to use for matching.
+ * @param {Object} `options` See available [options](#options) for changing how matches are performed
+ * @return {Array} Returns an array of strings that **do not match** the given patterns.
+ * @api public
+ */
+
+micromatch.not = (list, patterns, options = {}) => {
+ patterns = [].concat(patterns).map(String);
+ let result = new Set();
+ let items = [];
+
+ let onResult = state => {
+ if (options.onResult) options.onResult(state);
+ items.push(state.output);
+ };
+
+ let matches = new Set(micromatch(list, patterns, { ...options, onResult }));
+
+ for (let item of items) {
+ if (!matches.has(item)) {
+ result.add(item);
+ }
+ }
+ return [...result];
+};
+
+/**
+ * Returns true if the given `string` contains the given pattern. Similar
+ * to [.isMatch](#isMatch) but the pattern can match any part of the string.
+ *
+ * ```js
+ * var mm = require('micromatch');
+ * // mm.contains(string, pattern[, options]);
+ *
+ * console.log(mm.contains('aa/bb/cc', '*b'));
+ * //=> true
+ * console.log(mm.contains('aa/bb/cc', '*d'));
+ * //=> false
+ * ```
+ * @param {String} `str` The string to match.
+ * @param {String|Array} `patterns` Glob pattern to use for matching.
+ * @param {Object} `options` See available [options](#options) for changing how matches are performed
+ * @return {Boolean} Returns true if any of the patterns matches any part of `str`.
+ * @api public
+ */
+
+micromatch.contains = (str, pattern, options) => {
+ if (typeof str !== 'string') {
+ throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
+ }
+
+ if (Array.isArray(pattern)) {
+ return pattern.some(p => micromatch.contains(str, p, options));
+ }
+
+ if (typeof pattern === 'string') {
+ if (isEmptyString(str) || isEmptyString(pattern)) {
+ return false;
+ }
+
+ if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) {
+ return true;
+ }
+ }
+
+ return micromatch.isMatch(str, pattern, { ...options, contains: true });
+};
+
+/**
+ * Filter the keys of the given object with the given `glob` pattern
+ * and `options`. Does not attempt to match nested keys. If you need this feature,
+ * use [glob-object][] instead.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.matchKeys(object, patterns[, options]);
+ *
+ * const obj = { aa: 'a', ab: 'b', ac: 'c' };
+ * console.log(mm.matchKeys(obj, '*b'));
+ * //=> { ab: 'b' }
+ * ```
+ * @param {Object} `object` The object with keys to filter.
+ * @param {String|Array} `patterns` One or more glob patterns to use for matching.
+ * @param {Object} `options` See available [options](#options) for changing how matches are performed
+ * @return {Object} Returns an object with only keys that match the given patterns.
+ * @api public
+ */
+
+micromatch.matchKeys = (obj, patterns, options) => {
+ if (!utils.isObject(obj)) {
+ throw new TypeError('Expected the first argument to be an object');
+ }
+ let keys = micromatch(Object.keys(obj), patterns, options);
+ let res = {};
+ for (let key of keys) res[key] = obj[key];
+ return res;
+};
+
+/**
+ * Returns true if some of the strings in the given `list` match any of the given glob `patterns`.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.some(list, patterns[, options]);
+ *
+ * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
+ * // true
+ * console.log(mm.some(['foo.js'], ['*.js', '!foo.js']));
+ * // false
+ * ```
+ * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found.
+ * @param {String|Array} `patterns` One or more glob patterns to use for matching.
+ * @param {Object} `options` See available [options](#options) for changing how matches are performed
+ * @return {Boolean} Returns true if any `patterns` matches any of the strings in `list`
+ * @api public
+ */
+
+micromatch.some = (list, patterns, options) => {
+ let items = [].concat(list);
+
+ for (let pattern of [].concat(patterns)) {
+ let isMatch = picomatch(String(pattern), options);
+ if (items.some(item => isMatch(item))) {
+ return true;
+ }
+ }
+ return false;
+};
+
+/**
+ * Returns true if every string in the given `list` matches
+ * any of the given glob `patterns`.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.every(list, patterns[, options]);
+ *
+ * console.log(mm.every('foo.js', ['foo.js']));
+ * // true
+ * console.log(mm.every(['foo.js', 'bar.js'], ['*.js']));
+ * // true
+ * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
+ * // false
+ * console.log(mm.every(['foo.js'], ['*.js', '!foo.js']));
+ * // false
+ * ```
+ * @param {String|Array} `list` The string or array of strings to test.
+ * @param {String|Array} `patterns` One or more glob patterns to use for matching.
+ * @param {Object} `options` See available [options](#options) for changing how matches are performed
+ * @return {Boolean} Returns true if all `patterns` matches all of the strings in `list`
+ * @api public
+ */
+
+micromatch.every = (list, patterns, options) => {
+ let items = [].concat(list);
+
+ for (let pattern of [].concat(patterns)) {
+ let isMatch = picomatch(String(pattern), options);
+ if (!items.every(item => isMatch(item))) {
+ return false;
+ }
+ }
+ return true;
+};
+
+/**
+ * Returns true if **all** of the given `patterns` match
+ * the specified string.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.all(string, patterns[, options]);
+ *
+ * console.log(mm.all('foo.js', ['foo.js']));
+ * // true
+ *
+ * console.log(mm.all('foo.js', ['*.js', '!foo.js']));
+ * // false
+ *
+ * console.log(mm.all('foo.js', ['*.js', 'foo.js']));
+ * // true
+ *
+ * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js']));
+ * // true
+ * ```
+ * @param {String|Array} `str` The string to test.
+ * @param {String|Array} `patterns` One or more glob patterns to use for matching.
+ * @param {Object} `options` See available [options](#options) for changing how matches are performed
+ * @return {Boolean} Returns true if any patterns match `str`
+ * @api public
+ */
+
+micromatch.all = (str, patterns, options) => {
+ if (typeof str !== 'string') {
+ throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
+ }
+
+ return [].concat(patterns).every(p => picomatch(p, options)(str));
+};
+
+/**
+ * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.capture(pattern, string[, options]);
+ *
+ * console.log(mm.capture('test/*.js', 'test/foo.js'));
+ * //=> ['foo']
+ * console.log(mm.capture('test/*.js', 'foo/bar.css'));
+ * //=> null
+ * ```
+ * @param {String} `glob` Glob pattern to use for matching.
+ * @param {String} `input` String to match
+ * @param {Object} `options` See available [options](#options) for changing how matches are performed
+ * @return {Array|null} Returns an array of captures if the input matches the glob pattern, otherwise `null`.
+ * @api public
+ */
+
+micromatch.capture = (glob, input, options) => {
+ let posix = utils.isWindows(options);
+ let regex = picomatch.makeRe(String(glob), { ...options, capture: true });
+ let match = regex.exec(posix ? utils.toPosixSlashes(input) : input);
+
+ if (match) {
+ return match.slice(1).map(v => v === void 0 ? '' : v);
+ }
+};
+
+/**
+ * Create a regular expression from the given glob `pattern`.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * // mm.makeRe(pattern[, options]);
+ *
+ * console.log(mm.makeRe('*.js'));
+ * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/
+ * ```
+ * @param {String} `pattern` A glob pattern to convert to regex.
+ * @param {Object} `options`
+ * @return {RegExp} Returns a regex created from the given pattern.
+ * @api public
+ */
+
+micromatch.makeRe = (...args) => picomatch.makeRe(...args);
+
+/**
+ * Scan a glob pattern to separate the pattern into segments. Used
+ * by the [split](#split) method.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * const state = mm.scan(pattern[, options]);
+ * ```
+ * @param {String} `pattern`
+ * @param {Object} `options`
+ * @return {Object} Returns an object with
+ * @api public
+ */
+
+micromatch.scan = (...args) => picomatch.scan(...args);
+
+/**
+ * Parse a glob pattern to create the source string for a regular
+ * expression.
+ *
+ * ```js
+ * const mm = require('micromatch');
+ * const state = mm.parse(pattern[, options]);
+ * ```
+ * @param {String} `glob`
+ * @param {Object} `options`
+ * @return {Object} Returns an object with useful properties and output to be used as regex source string.
+ * @api public
+ */
+
+micromatch.parse = (patterns, options) => {
+ let res = [];
+ for (let pattern of [].concat(patterns || [])) {
+ for (let str of braces(String(pattern), options)) {
+ res.push(picomatch.parse(str, options));
+ }
+ }
+ return res;
+};
+
+/**
+ * Process the given brace `pattern`.
+ *
+ * ```js
+ * const { braces } = require('micromatch');
+ * console.log(braces('foo/{a,b,c}/bar'));
+ * //=> [ 'foo/(a|b|c)/bar' ]
+ *
+ * console.log(braces('foo/{a,b,c}/bar', { expand: true }));
+ * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ]
+ * ```
+ * @param {String} `pattern` String with brace pattern to process.
+ * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options.
+ * @return {Array}
+ * @api public
+ */
+
+micromatch.braces = (pattern, options) => {
+ if (typeof pattern !== 'string') throw new TypeError('Expected a string');
+ if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) {
+ return [pattern];
+ }
+ return braces(pattern, options);
+};
+
+/**
+ * Expand braces
+ */
+
+micromatch.braceExpand = (pattern, options) => {
+ if (typeof pattern !== 'string') throw new TypeError('Expected a string');
+ return micromatch.braces(pattern, { ...options, expand: true });
+};
+
+/**
+ * Expose micromatch
+ */
+
+module.exports = micromatch;
+
+
+/***/ }),
+
+/***/ 7760:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+/*! node-domexception. MIT License. Jimmy Wärting */
+
+if (!globalThis.DOMException) {
+ try {
+ const { MessageChannel } = __nccwpck_require__(1267),
+ port = new MessageChannel().port1,
+ ab = new ArrayBuffer()
+ port.postMessage(ab, [ab, ab])
+ } catch (err) {
+ err.constructor.name === 'DOMException' && (
+ globalThis.DOMException = err.constructor
+ )
+ }
+}
+
+module.exports = globalThis.DOMException
+
+
+/***/ }),
+
+/***/ 504:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+var hasMap = typeof Map === 'function' && Map.prototype;
+var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null;
+var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null;
+var mapForEach = hasMap && Map.prototype.forEach;
+var hasSet = typeof Set === 'function' && Set.prototype;
+var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null;
+var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'function' ? setSizeDescriptor.get : null;
+var setForEach = hasSet && Set.prototype.forEach;
+var hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype;
+var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null;
+var hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype;
+var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null;
+var hasWeakRef = typeof WeakRef === 'function' && WeakRef.prototype;
+var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null;
+var booleanValueOf = Boolean.prototype.valueOf;
+var objectToString = Object.prototype.toString;
+var functionToString = Function.prototype.toString;
+var $match = String.prototype.match;
+var $slice = String.prototype.slice;
+var $replace = String.prototype.replace;
+var $toUpperCase = String.prototype.toUpperCase;
+var $toLowerCase = String.prototype.toLowerCase;
+var $test = RegExp.prototype.test;
+var $concat = Array.prototype.concat;
+var $join = Array.prototype.join;
+var $arrSlice = Array.prototype.slice;
+var $floor = Math.floor;
+var bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null;
+var gOPS = Object.getOwnPropertySymbols;
+var symToString = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? Symbol.prototype.toString : null;
+var hasShammedSymbols = typeof Symbol === 'function' && typeof Symbol.iterator === 'object';
+// ie, `has-tostringtag/shams
+var toStringTag = typeof Symbol === 'function' && Symbol.toStringTag && (typeof Symbol.toStringTag === hasShammedSymbols ? 'object' : 'symbol')
+ ? Symbol.toStringTag
+ : null;
+var isEnumerable = Object.prototype.propertyIsEnumerable;
+
+var gPO = (typeof Reflect === 'function' ? Reflect.getPrototypeOf : Object.getPrototypeOf) || (
+ [].__proto__ === Array.prototype // eslint-disable-line no-proto
+ ? function (O) {
+ return O.__proto__; // eslint-disable-line no-proto
+ }
+ : null
+);
+
+function addNumericSeparator(num, str) {
+ if (
+ num === Infinity
+ || num === -Infinity
+ || num !== num
+ || (num && num > -1000 && num < 1000)
+ || $test.call(/e/, str)
+ ) {
+ return str;
+ }
+ var sepRegex = /[0-9](?=(?:[0-9]{3})+(?![0-9]))/g;
+ if (typeof num === 'number') {
+ var int = num < 0 ? -$floor(-num) : $floor(num); // trunc(num)
+ if (int !== num) {
+ var intStr = String(int);
+ var dec = $slice.call(str, intStr.length + 1);
+ return $replace.call(intStr, sepRegex, '$&_') + '.' + $replace.call($replace.call(dec, /([0-9]{3})/g, '$&_'), /_$/, '');
+ }
+ }
+ return $replace.call(str, sepRegex, '$&_');
+}
+
+var utilInspect = __nccwpck_require__(7265);
+var inspectCustom = utilInspect.custom;
+var inspectSymbol = isSymbol(inspectCustom) ? inspectCustom : null;
+
+module.exports = function inspect_(obj, options, depth, seen) {
+ var opts = options || {};
+
+ if (has(opts, 'quoteStyle') && (opts.quoteStyle !== 'single' && opts.quoteStyle !== 'double')) {
+ throw new TypeError('option "quoteStyle" must be "single" or "double"');
+ }
+ if (
+ has(opts, 'maxStringLength') && (typeof opts.maxStringLength === 'number'
+ ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity
+ : opts.maxStringLength !== null
+ )
+ ) {
+ throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');
+ }
+ var customInspect = has(opts, 'customInspect') ? opts.customInspect : true;
+ if (typeof customInspect !== 'boolean' && customInspect !== 'symbol') {
+ throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`');
+ }
+
+ if (
+ has(opts, 'indent')
+ && opts.indent !== null
+ && opts.indent !== '\t'
+ && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0)
+ ) {
+ throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`');
+ }
+ if (has(opts, 'numericSeparator') && typeof opts.numericSeparator !== 'boolean') {
+ throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');
+ }
+ var numericSeparator = opts.numericSeparator;
+
+ if (typeof obj === 'undefined') {
+ return 'undefined';
+ }
+ if (obj === null) {
+ return 'null';
+ }
+ if (typeof obj === 'boolean') {
+ return obj ? 'true' : 'false';
+ }
+
+ if (typeof obj === 'string') {
+ return inspectString(obj, opts);
+ }
+ if (typeof obj === 'number') {
+ if (obj === 0) {
+ return Infinity / obj > 0 ? '0' : '-0';
+ }
+ var str = String(obj);
+ return numericSeparator ? addNumericSeparator(obj, str) : str;
+ }
+ if (typeof obj === 'bigint') {
+ var bigIntStr = String(obj) + 'n';
+ return numericSeparator ? addNumericSeparator(obj, bigIntStr) : bigIntStr;
+ }
+
+ var maxDepth = typeof opts.depth === 'undefined' ? 5 : opts.depth;
+ if (typeof depth === 'undefined') { depth = 0; }
+ if (depth >= maxDepth && maxDepth > 0 && typeof obj === 'object') {
+ return isArray(obj) ? '[Array]' : '[Object]';
+ }
+
+ var indent = getIndent(opts, depth);
+
+ if (typeof seen === 'undefined') {
+ seen = [];
+ } else if (indexOf(seen, obj) >= 0) {
+ return '[Circular]';
+ }
+
+ function inspect(value, from, noIndent) {
+ if (from) {
+ seen = $arrSlice.call(seen);
+ seen.push(from);
+ }
+ if (noIndent) {
+ var newOpts = {
+ depth: opts.depth
+ };
+ if (has(opts, 'quoteStyle')) {
+ newOpts.quoteStyle = opts.quoteStyle;
+ }
+ return inspect_(value, newOpts, depth + 1, seen);
+ }
+ return inspect_(value, opts, depth + 1, seen);
+ }
+
+ if (typeof obj === 'function' && !isRegExp(obj)) { // in older engines, regexes are callable
+ var name = nameOf(obj);
+ var keys = arrObjKeys(obj, inspect);
+ return '[Function' + (name ? ': ' + name : ' (anonymous)') + ']' + (keys.length > 0 ? ' { ' + $join.call(keys, ', ') + ' }' : '');
+ }
+ if (isSymbol(obj)) {
+ var symString = hasShammedSymbols ? $replace.call(String(obj), /^(Symbol\(.*\))_[^)]*$/, '$1') : symToString.call(obj);
+ return typeof obj === 'object' && !hasShammedSymbols ? markBoxed(symString) : symString;
+ }
+ if (isElement(obj)) {
+ var s = '<' + $toLowerCase.call(String(obj.nodeName));
+ var attrs = obj.attributes || [];
+ for (var i = 0; i < attrs.length; i++) {
+ s += ' ' + attrs[i].name + '=' + wrapQuotes(quote(attrs[i].value), 'double', opts);
+ }
+ s += '>';
+ if (obj.childNodes && obj.childNodes.length) { s += '...'; }
+ s += '' + $toLowerCase.call(String(obj.nodeName)) + '>';
+ return s;
+ }
+ if (isArray(obj)) {
+ if (obj.length === 0) { return '[]'; }
+ var xs = arrObjKeys(obj, inspect);
+ if (indent && !singleLineValues(xs)) {
+ return '[' + indentedJoin(xs, indent) + ']';
+ }
+ return '[ ' + $join.call(xs, ', ') + ' ]';
+ }
+ if (isError(obj)) {
+ var parts = arrObjKeys(obj, inspect);
+ if (!('cause' in Error.prototype) && 'cause' in obj && !isEnumerable.call(obj, 'cause')) {
+ return '{ [' + String(obj) + '] ' + $join.call($concat.call('[cause]: ' + inspect(obj.cause), parts), ', ') + ' }';
+ }
+ if (parts.length === 0) { return '[' + String(obj) + ']'; }
+ return '{ [' + String(obj) + '] ' + $join.call(parts, ', ') + ' }';
+ }
+ if (typeof obj === 'object' && customInspect) {
+ if (inspectSymbol && typeof obj[inspectSymbol] === 'function' && utilInspect) {
+ return utilInspect(obj, { depth: maxDepth - depth });
+ } else if (customInspect !== 'symbol' && typeof obj.inspect === 'function') {
+ return obj.inspect();
+ }
+ }
+ if (isMap(obj)) {
+ var mapParts = [];
+ if (mapForEach) {
+ mapForEach.call(obj, function (value, key) {
+ mapParts.push(inspect(key, obj, true) + ' => ' + inspect(value, obj));
+ });
+ }
+ return collectionOf('Map', mapSize.call(obj), mapParts, indent);
+ }
+ if (isSet(obj)) {
+ var setParts = [];
+ if (setForEach) {
+ setForEach.call(obj, function (value) {
+ setParts.push(inspect(value, obj));
+ });
+ }
+ return collectionOf('Set', setSize.call(obj), setParts, indent);
+ }
+ if (isWeakMap(obj)) {
+ return weakCollectionOf('WeakMap');
+ }
+ if (isWeakSet(obj)) {
+ return weakCollectionOf('WeakSet');
+ }
+ if (isWeakRef(obj)) {
+ return weakCollectionOf('WeakRef');
+ }
+ if (isNumber(obj)) {
+ return markBoxed(inspect(Number(obj)));
+ }
+ if (isBigInt(obj)) {
+ return markBoxed(inspect(bigIntValueOf.call(obj)));
+ }
+ if (isBoolean(obj)) {
+ return markBoxed(booleanValueOf.call(obj));
+ }
+ if (isString(obj)) {
+ return markBoxed(inspect(String(obj)));
+ }
+ if (!isDate(obj) && !isRegExp(obj)) {
+ var ys = arrObjKeys(obj, inspect);
+ var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
+ var protoTag = obj instanceof Object ? '' : 'null prototype';
+ var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? 'Object' : '';
+ var constructorTag = isPlainObject || typeof obj.constructor !== 'function' ? '' : obj.constructor.name ? obj.constructor.name + ' ' : '';
+ var tag = constructorTag + (stringTag || protoTag ? '[' + $join.call($concat.call([], stringTag || [], protoTag || []), ': ') + '] ' : '');
+ if (ys.length === 0) { return tag + '{}'; }
+ if (indent) {
+ return tag + '{' + indentedJoin(ys, indent) + '}';
+ }
+ return tag + '{ ' + $join.call(ys, ', ') + ' }';
+ }
+ return String(obj);
+};
+
+function wrapQuotes(s, defaultStyle, opts) {
+ var quoteChar = (opts.quoteStyle || defaultStyle) === 'double' ? '"' : "'";
+ return quoteChar + s + quoteChar;
+}
+
+function quote(s) {
+ return $replace.call(String(s), /"/g, '"');
+}
+
+function isArray(obj) { return toStr(obj) === '[object Array]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+function isDate(obj) { return toStr(obj) === '[object Date]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+function isRegExp(obj) { return toStr(obj) === '[object RegExp]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+function isError(obj) { return toStr(obj) === '[object Error]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+function isString(obj) { return toStr(obj) === '[object String]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+function isNumber(obj) { return toStr(obj) === '[object Number]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+function isBoolean(obj) { return toStr(obj) === '[object Boolean]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+
+// Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives
+function isSymbol(obj) {
+ if (hasShammedSymbols) {
+ return obj && typeof obj === 'object' && obj instanceof Symbol;
+ }
+ if (typeof obj === 'symbol') {
+ return true;
+ }
+ if (!obj || typeof obj !== 'object' || !symToString) {
+ return false;
+ }
+ try {
+ symToString.call(obj);
+ return true;
+ } catch (e) {}
+ return false;
+}
+
+function isBigInt(obj) {
+ if (!obj || typeof obj !== 'object' || !bigIntValueOf) {
+ return false;
+ }
+ try {
+ bigIntValueOf.call(obj);
+ return true;
+ } catch (e) {}
+ return false;
+}
+
+var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; };
+function has(obj, key) {
+ return hasOwn.call(obj, key);
+}
+
+function toStr(obj) {
+ return objectToString.call(obj);
+}
+
+function nameOf(f) {
+ if (f.name) { return f.name; }
+ var m = $match.call(functionToString.call(f), /^function\s*([\w$]+)/);
+ if (m) { return m[1]; }
+ return null;
+}
+
+function indexOf(xs, x) {
+ if (xs.indexOf) { return xs.indexOf(x); }
+ for (var i = 0, l = xs.length; i < l; i++) {
+ if (xs[i] === x) { return i; }
+ }
+ return -1;
+}
+
+function isMap(x) {
+ if (!mapSize || !x || typeof x !== 'object') {
+ return false;
+ }
+ try {
+ mapSize.call(x);
+ try {
+ setSize.call(x);
+ } catch (s) {
+ return true;
+ }
+ return x instanceof Map; // core-js workaround, pre-v2.5.0
+ } catch (e) {}
+ return false;
+}
+
+function isWeakMap(x) {
+ if (!weakMapHas || !x || typeof x !== 'object') {
+ return false;
+ }
+ try {
+ weakMapHas.call(x, weakMapHas);
+ try {
+ weakSetHas.call(x, weakSetHas);
+ } catch (s) {
+ return true;
+ }
+ return x instanceof WeakMap; // core-js workaround, pre-v2.5.0
+ } catch (e) {}
+ return false;
+}
+
+function isWeakRef(x) {
+ if (!weakRefDeref || !x || typeof x !== 'object') {
+ return false;
+ }
+ try {
+ weakRefDeref.call(x);
+ return true;
+ } catch (e) {}
+ return false;
+}
+
+function isSet(x) {
+ if (!setSize || !x || typeof x !== 'object') {
+ return false;
+ }
+ try {
+ setSize.call(x);
+ try {
+ mapSize.call(x);
+ } catch (m) {
+ return true;
+ }
+ return x instanceof Set; // core-js workaround, pre-v2.5.0
+ } catch (e) {}
+ return false;
+}
+
+function isWeakSet(x) {
+ if (!weakSetHas || !x || typeof x !== 'object') {
+ return false;
+ }
+ try {
+ weakSetHas.call(x, weakSetHas);
+ try {
+ weakMapHas.call(x, weakMapHas);
+ } catch (s) {
+ return true;
+ }
+ return x instanceof WeakSet; // core-js workaround, pre-v2.5.0
+ } catch (e) {}
+ return false;
+}
+
+function isElement(x) {
+ if (!x || typeof x !== 'object') { return false; }
+ if (typeof HTMLElement !== 'undefined' && x instanceof HTMLElement) {
+ return true;
+ }
+ return typeof x.nodeName === 'string' && typeof x.getAttribute === 'function';
+}
+
+function inspectString(str, opts) {
+ if (str.length > opts.maxStringLength) {
+ var remaining = str.length - opts.maxStringLength;
+ var trailer = '... ' + remaining + ' more character' + (remaining > 1 ? 's' : '');
+ return inspectString($slice.call(str, 0, opts.maxStringLength), opts) + trailer;
+ }
+ // eslint-disable-next-line no-control-regex
+ var s = $replace.call($replace.call(str, /(['\\])/g, '\\$1'), /[\x00-\x1f]/g, lowbyte);
+ return wrapQuotes(s, 'single', opts);
+}
+
+function lowbyte(c) {
+ var n = c.charCodeAt(0);
+ var x = {
+ 8: 'b',
+ 9: 't',
+ 10: 'n',
+ 12: 'f',
+ 13: 'r'
+ }[n];
+ if (x) { return '\\' + x; }
+ return '\\x' + (n < 0x10 ? '0' : '') + $toUpperCase.call(n.toString(16));
+}
+
+function markBoxed(str) {
+ return 'Object(' + str + ')';
+}
+
+function weakCollectionOf(type) {
+ return type + ' { ? }';
+}
+
+function collectionOf(type, size, entries, indent) {
+ var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ', ');
+ return type + ' (' + size + ') {' + joinedEntries + '}';
+}
+
+function singleLineValues(xs) {
+ for (var i = 0; i < xs.length; i++) {
+ if (indexOf(xs[i], '\n') >= 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function getIndent(opts, depth) {
+ var baseIndent;
+ if (opts.indent === '\t') {
+ baseIndent = '\t';
+ } else if (typeof opts.indent === 'number' && opts.indent > 0) {
+ baseIndent = $join.call(Array(opts.indent + 1), ' ');
+ } else {
+ return null;
+ }
+ return {
+ base: baseIndent,
+ prev: $join.call(Array(depth + 1), baseIndent)
+ };
+}
+
+function indentedJoin(xs, indent) {
+ if (xs.length === 0) { return ''; }
+ var lineJoiner = '\n' + indent.prev + indent.base;
+ return lineJoiner + $join.call(xs, ',' + lineJoiner) + '\n' + indent.prev;
+}
+
+function arrObjKeys(obj, inspect) {
+ var isArr = isArray(obj);
+ var xs = [];
+ if (isArr) {
+ xs.length = obj.length;
+ for (var i = 0; i < obj.length; i++) {
+ xs[i] = has(obj, i) ? inspect(obj[i], obj) : '';
+ }
+ }
+ var syms = typeof gOPS === 'function' ? gOPS(obj) : [];
+ var symMap;
+ if (hasShammedSymbols) {
+ symMap = {};
+ for (var k = 0; k < syms.length; k++) {
+ symMap['$' + syms[k]] = syms[k];
+ }
+ }
+
+ for (var key in obj) { // eslint-disable-line no-restricted-syntax
+ if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
+ if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
+ if (hasShammedSymbols && symMap['$' + key] instanceof Symbol) {
+ // this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section
+ continue; // eslint-disable-line no-restricted-syntax, no-continue
+ } else if ($test.call(/[^\w$]/, key)) {
+ xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj));
+ } else {
+ xs.push(key + ': ' + inspect(obj[key], obj));
+ }
+ }
+ if (typeof gOPS === 'function') {
+ for (var j = 0; j < syms.length; j++) {
+ if (isEnumerable.call(obj, syms[j])) {
+ xs.push('[' + inspect(syms[j]) + ']: ' + inspect(obj[syms[j]], obj));
+ }
+ }
+ }
+ return xs;
+}
+
+
+/***/ }),
+
+/***/ 7265:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+module.exports = __nccwpck_require__(3837).inspect;
+
+
+/***/ }),
+
+/***/ 1223:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+var wrappy = __nccwpck_require__(2940)
+module.exports = wrappy(once)
+module.exports.strict = wrappy(onceStrict)
+
+once.proto = once(function () {
+ Object.defineProperty(Function.prototype, 'once', {
+ value: function () {
+ return once(this)
+ },
+ configurable: true
+ })
+
+ Object.defineProperty(Function.prototype, 'onceStrict', {
+ value: function () {
+ return onceStrict(this)
+ },
+ configurable: true
+ })
+})
+
+function once (fn) {
+ var f = function () {
+ if (f.called) return f.value
+ f.called = true
+ return f.value = fn.apply(this, arguments)
+ }
+ f.called = false
+ return f
+}
+
+function onceStrict (fn) {
+ var f = function () {
+ if (f.called)
+ throw new Error(f.onceError)
+ f.called = true
+ return f.value = fn.apply(this, arguments)
+ }
+ var name = fn.name || 'Function wrapped with `once`'
+ f.onceError = name + " shouldn't be called more than once"
+ f.called = false
+ return f
+}
+
+
+/***/ }),
+
+/***/ 8569:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+module.exports = __nccwpck_require__(3322);
+
+
+/***/ }),
+
+/***/ 6099:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+const path = __nccwpck_require__(1017);
+const WIN_SLASH = '\\\\/';
+const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
+
+/**
+ * Posix glob regex
+ */
+
+const DOT_LITERAL = '\\.';
+const PLUS_LITERAL = '\\+';
+const QMARK_LITERAL = '\\?';
+const SLASH_LITERAL = '\\/';
+const ONE_CHAR = '(?=.)';
+const QMARK = '[^/]';
+const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`;
+const START_ANCHOR = `(?:^|${SLASH_LITERAL})`;
+const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`;
+const NO_DOT = `(?!${DOT_LITERAL})`;
+const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`;
+const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`;
+const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`;
+const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`;
+const STAR = `${QMARK}*?`;
+
+const POSIX_CHARS = {
+ DOT_LITERAL,
+ PLUS_LITERAL,
+ QMARK_LITERAL,
+ SLASH_LITERAL,
+ ONE_CHAR,
+ QMARK,
+ END_ANCHOR,
+ DOTS_SLASH,
+ NO_DOT,
+ NO_DOTS,
+ NO_DOT_SLASH,
+ NO_DOTS_SLASH,
+ QMARK_NO_DOT,
+ STAR,
+ START_ANCHOR
+};
+
+/**
+ * Windows glob regex
+ */
+
+const WINDOWS_CHARS = {
+ ...POSIX_CHARS,
+
+ SLASH_LITERAL: `[${WIN_SLASH}]`,
+ QMARK: WIN_NO_SLASH,
+ STAR: `${WIN_NO_SLASH}*?`,
+ DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`,
+ NO_DOT: `(?!${DOT_LITERAL})`,
+ NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
+ NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`,
+ NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
+ QMARK_NO_DOT: `[^.${WIN_SLASH}]`,
+ START_ANCHOR: `(?:^|[${WIN_SLASH}])`,
+ END_ANCHOR: `(?:[${WIN_SLASH}]|$)`
+};
+
+/**
+ * POSIX Bracket Regex
+ */
+
+const POSIX_REGEX_SOURCE = {
+ alnum: 'a-zA-Z0-9',
+ alpha: 'a-zA-Z',
+ ascii: '\\x00-\\x7F',
+ blank: ' \\t',
+ cntrl: '\\x00-\\x1F\\x7F',
+ digit: '0-9',
+ graph: '\\x21-\\x7E',
+ lower: 'a-z',
+ print: '\\x20-\\x7E ',
+ punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~',
+ space: ' \\t\\r\\n\\v\\f',
+ upper: 'A-Z',
+ word: 'A-Za-z0-9_',
+ xdigit: 'A-Fa-f0-9'
+};
+
+module.exports = {
+ MAX_LENGTH: 1024 * 64,
+ POSIX_REGEX_SOURCE,
+
+ // regular expressions
+ REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g,
+ REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/,
+ REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/,
+ REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g,
+ REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g,
+ REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g,
+
+ // Replace globs with equivalent patterns to reduce parsing time.
+ REPLACEMENTS: {
+ '***': '*',
+ '**/**': '**',
+ '**/**/**': '**'
+ },
+
+ // Digits
+ CHAR_0: 48, /* 0 */
+ CHAR_9: 57, /* 9 */
+
+ // Alphabet chars.
+ CHAR_UPPERCASE_A: 65, /* A */
+ CHAR_LOWERCASE_A: 97, /* a */
+ CHAR_UPPERCASE_Z: 90, /* Z */
+ CHAR_LOWERCASE_Z: 122, /* z */
+
+ CHAR_LEFT_PARENTHESES: 40, /* ( */
+ CHAR_RIGHT_PARENTHESES: 41, /* ) */
+
+ CHAR_ASTERISK: 42, /* * */
+
+ // Non-alphabetic chars.
+ CHAR_AMPERSAND: 38, /* & */
+ CHAR_AT: 64, /* @ */
+ CHAR_BACKWARD_SLASH: 92, /* \ */
+ CHAR_CARRIAGE_RETURN: 13, /* \r */
+ CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */
+ CHAR_COLON: 58, /* : */
+ CHAR_COMMA: 44, /* , */
+ CHAR_DOT: 46, /* . */
+ CHAR_DOUBLE_QUOTE: 34, /* " */
+ CHAR_EQUAL: 61, /* = */
+ CHAR_EXCLAMATION_MARK: 33, /* ! */
+ CHAR_FORM_FEED: 12, /* \f */
+ CHAR_FORWARD_SLASH: 47, /* / */
+ CHAR_GRAVE_ACCENT: 96, /* ` */
+ CHAR_HASH: 35, /* # */
+ CHAR_HYPHEN_MINUS: 45, /* - */
+ CHAR_LEFT_ANGLE_BRACKET: 60, /* < */
+ CHAR_LEFT_CURLY_BRACE: 123, /* { */
+ CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */
+ CHAR_LINE_FEED: 10, /* \n */
+ CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */
+ CHAR_PERCENT: 37, /* % */
+ CHAR_PLUS: 43, /* + */
+ CHAR_QUESTION_MARK: 63, /* ? */
+ CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */
+ CHAR_RIGHT_CURLY_BRACE: 125, /* } */
+ CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */
+ CHAR_SEMICOLON: 59, /* ; */
+ CHAR_SINGLE_QUOTE: 39, /* ' */
+ CHAR_SPACE: 32, /* */
+ CHAR_TAB: 9, /* \t */
+ CHAR_UNDERSCORE: 95, /* _ */
+ CHAR_VERTICAL_LINE: 124, /* | */
+ CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */
+
+ SEP: path.sep,
+
+ /**
+ * Create EXTGLOB_CHARS
+ */
+
+ extglobChars(chars) {
+ return {
+ '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` },
+ '?': { type: 'qmark', open: '(?:', close: ')?' },
+ '+': { type: 'plus', open: '(?:', close: ')+' },
+ '*': { type: 'star', open: '(?:', close: ')*' },
+ '@': { type: 'at', open: '(?:', close: ')' }
+ };
+ },
+
+ /**
+ * Create GLOB_CHARS
+ */
+
+ globChars(win32) {
+ return win32 === true ? WINDOWS_CHARS : POSIX_CHARS;
+ }
+};
+
+
+/***/ }),
+
+/***/ 2139:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+
+
+const constants = __nccwpck_require__(6099);
+const utils = __nccwpck_require__(479);
+
+/**
+ * Constants
+ */
+
+const {
+ MAX_LENGTH,
+ POSIX_REGEX_SOURCE,
+ REGEX_NON_SPECIAL_CHARS,
+ REGEX_SPECIAL_CHARS_BACKREF,
+ REPLACEMENTS
+} = constants;
+
+/**
+ * Helpers
+ */
+
+const expandRange = (args, options) => {
+ if (typeof options.expandRange === 'function') {
+ return options.expandRange(...args, options);
+ }
+
+ args.sort();
+ const value = `[${args.join('-')}]`;
+
+ try {
+ /* eslint-disable-next-line no-new */
+ new RegExp(value);
+ } catch (ex) {
+ return args.map(v => utils.escapeRegex(v)).join('..');
+ }
+
+ return value;
+};
+
+/**
+ * Create the message for a syntax error
+ */
+
+const syntaxError = (type, char) => {
+ return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
+};
+
+/**
+ * Parse the given input string.
+ * @param {String} input
+ * @param {Object} options
+ * @return {Object}
+ */
+
+const parse = (input, options) => {
+ if (typeof input !== 'string') {
+ throw new TypeError('Expected a string');
+ }
+
+ input = REPLACEMENTS[input] || input;
+
+ const opts = { ...options };
+ const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
+
+ let len = input.length;
+ if (len > max) {
+ throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
+ }
+
+ const bos = { type: 'bos', value: '', output: opts.prepend || '' };
+ const tokens = [bos];
+
+ const capture = opts.capture ? '' : '?:';
+ const win32 = utils.isWindows(options);
+
+ // create constants based on platform, for windows or posix
+ const PLATFORM_CHARS = constants.globChars(win32);
+ const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS);
+
+ const {
+ DOT_LITERAL,
+ PLUS_LITERAL,
+ SLASH_LITERAL,
+ ONE_CHAR,
+ DOTS_SLASH,
+ NO_DOT,
+ NO_DOT_SLASH,
+ NO_DOTS_SLASH,
+ QMARK,
+ QMARK_NO_DOT,
+ STAR,
+ START_ANCHOR
+ } = PLATFORM_CHARS;
+
+ const globstar = opts => {
+ return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
+ };
+
+ const nodot = opts.dot ? '' : NO_DOT;
+ const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT;
+ let star = opts.bash === true ? globstar(opts) : STAR;
+
+ if (opts.capture) {
+ star = `(${star})`;
+ }
+
+ // minimatch options support
+ if (typeof opts.noext === 'boolean') {
+ opts.noextglob = opts.noext;
+ }
+
+ const state = {
+ input,
+ index: -1,
+ start: 0,
+ dot: opts.dot === true,
+ consumed: '',
+ output: '',
+ prefix: '',
+ backtrack: false,
+ negated: false,
+ brackets: 0,
+ braces: 0,
+ parens: 0,
+ quotes: 0,
+ globstar: false,
+ tokens
+ };
+
+ input = utils.removePrefix(input, state);
+ len = input.length;
+
+ const extglobs = [];
+ const braces = [];
+ const stack = [];
+ let prev = bos;
+ let value;
+
+ /**
+ * Tokenizing helpers
+ */
+
+ const eos = () => state.index === len - 1;
+ const peek = state.peek = (n = 1) => input[state.index + n];
+ const advance = state.advance = () => input[++state.index] || '';
+ const remaining = () => input.slice(state.index + 1);
+ const consume = (value = '', num = 0) => {
+ state.consumed += value;
+ state.index += num;
+ };
+
+ const append = token => {
+ state.output += token.output != null ? token.output : token.value;
+ consume(token.value);
+ };
+
+ const negate = () => {
+ let count = 1;
+
+ while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) {
+ advance();
+ state.start++;
+ count++;
+ }
+
+ if (count % 2 === 0) {
+ return false;
+ }
+
+ state.negated = true;
+ state.start++;
+ return true;
+ };
+
+ const increment = type => {
+ state[type]++;
+ stack.push(type);
+ };
+
+ const decrement = type => {
+ state[type]--;
+ stack.pop();
+ };
+
+ /**
+ * Push tokens onto the tokens array. This helper speeds up
+ * tokenizing by 1) helping us avoid backtracking as much as possible,
+ * and 2) helping us avoid creating extra tokens when consecutive
+ * characters are plain text. This improves performance and simplifies
+ * lookbehinds.
+ */
+
+ const push = tok => {
+ if (prev.type === 'globstar') {
+ const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace');
+ const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren'));
+
+ if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) {
+ state.output = state.output.slice(0, -prev.output.length);
+ prev.type = 'star';
+ prev.value = '*';
+ prev.output = star;
+ state.output += prev.output;
+ }
+ }
+
+ if (extglobs.length && tok.type !== 'paren') {
+ extglobs[extglobs.length - 1].inner += tok.value;
+ }
+
+ if (tok.value || tok.output) append(tok);
+ if (prev && prev.type === 'text' && tok.type === 'text') {
+ prev.value += tok.value;
+ prev.output = (prev.output || '') + tok.value;
+ return;
+ }
+
+ tok.prev = prev;
+ tokens.push(tok);
+ prev = tok;
+ };
+
+ const extglobOpen = (type, value) => {
+ const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' };
+
+ token.prev = prev;
+ token.parens = state.parens;
+ token.output = state.output;
+ const output = (opts.capture ? '(' : '') + token.open;
+
+ increment('parens');
+ push({ type, value, output: state.output ? '' : ONE_CHAR });
+ push({ type: 'paren', extglob: true, value: advance(), output });
+ extglobs.push(token);
+ };
+
+ const extglobClose = token => {
+ let output = token.close + (opts.capture ? ')' : '');
+ let rest;
+
+ if (token.type === 'negate') {
+ let extglobStar = star;
+
+ if (token.inner && token.inner.length > 1 && token.inner.includes('/')) {
+ extglobStar = globstar(opts);
+ }
+
+ if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) {
+ output = token.close = `)$))${extglobStar}`;
+ }
+
+ if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
+ // Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis.
+ // In this case, we need to parse the string and use it in the output of the original pattern.
+ // Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`.
+ //
+ // Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`.
+ const expression = parse(rest, { ...options, fastpaths: false }).output;
+
+ output = token.close = `)${expression})${extglobStar})`;
+ }
+
+ if (token.prev.type === 'bos') {
+ state.negatedExtglob = true;
+ }
+ }
+
+ push({ type: 'paren', extglob: true, value, output });
+ decrement('parens');
+ };
+
+ /**
+ * Fast paths
+ */
+
+ if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) {
+ let backslashes = false;
+
+ let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
+ if (first === '\\') {
+ backslashes = true;
+ return m;
+ }
+
+ if (first === '?') {
+ if (esc) {
+ return esc + first + (rest ? QMARK.repeat(rest.length) : '');
+ }
+ if (index === 0) {
+ return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : '');
+ }
+ return QMARK.repeat(chars.length);
+ }
+
+ if (first === '.') {
+ return DOT_LITERAL.repeat(chars.length);
+ }
+
+ if (first === '*') {
+ if (esc) {
+ return esc + first + (rest ? star : '');
+ }
+ return star;
+ }
+ return esc ? m : `\\${m}`;
+ });
+
+ if (backslashes === true) {
+ if (opts.unescape === true) {
+ output = output.replace(/\\/g, '');
+ } else {
+ output = output.replace(/\\+/g, m => {
+ return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : '');
+ });
+ }
+ }
+
+ if (output === input && opts.contains === true) {
+ state.output = input;
+ return state;
+ }
+
+ state.output = utils.wrapOutput(output, state, options);
+ return state;
+ }
+
+ /**
+ * Tokenize input until we reach end-of-string
+ */
+
+ while (!eos()) {
+ value = advance();
+
+ if (value === '\u0000') {
+ continue;
+ }
+
+ /**
+ * Escaped characters
+ */
+
+ if (value === '\\') {
+ const next = peek();
+
+ if (next === '/' && opts.bash !== true) {
+ continue;
+ }
+
+ if (next === '.' || next === ';') {
+ continue;
+ }
+
+ if (!next) {
+ value += '\\';
+ push({ type: 'text', value });
+ continue;
+ }
+
+ // collapse slashes to reduce potential for exploits
+ const match = /^\\+/.exec(remaining());
+ let slashes = 0;
+
+ if (match && match[0].length > 2) {
+ slashes = match[0].length;
+ state.index += slashes;
+ if (slashes % 2 !== 0) {
+ value += '\\';
+ }
+ }
+
+ if (opts.unescape === true) {
+ value = advance();
+ } else {
+ value += advance();
+ }
+
+ if (state.brackets === 0) {
+ push({ type: 'text', value });
+ continue;
+ }
+ }
+
+ /**
+ * If we're inside a regex character class, continue
+ * until we reach the closing bracket.
+ */
+
+ if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) {
+ if (opts.posix !== false && value === ':') {
+ const inner = prev.value.slice(1);
+ if (inner.includes('[')) {
+ prev.posix = true;
+
+ if (inner.includes(':')) {
+ const idx = prev.value.lastIndexOf('[');
+ const pre = prev.value.slice(0, idx);
+ const rest = prev.value.slice(idx + 2);
+ const posix = POSIX_REGEX_SOURCE[rest];
+ if (posix) {
+ prev.value = pre + posix;
+ state.backtrack = true;
+ advance();
+
+ if (!bos.output && tokens.indexOf(prev) === 1) {
+ bos.output = ONE_CHAR;
+ }
+ continue;
+ }
+ }
+ }
+ }
+
+ if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) {
+ value = `\\${value}`;
+ }
+
+ if (value === ']' && (prev.value === '[' || prev.value === '[^')) {
+ value = `\\${value}`;
+ }
+
+ if (opts.posix === true && value === '!' && prev.value === '[') {
+ value = '^';
+ }
+
+ prev.value += value;
+ append({ value });
+ continue;
+ }
+
+ /**
+ * If we're inside a quoted string, continue
+ * until we reach the closing double quote.
+ */
+
+ if (state.quotes === 1 && value !== '"') {
+ value = utils.escapeRegex(value);
+ prev.value += value;
+ append({ value });
+ continue;
+ }
+
+ /**
+ * Double quotes
+ */
+
+ if (value === '"') {
+ state.quotes = state.quotes === 1 ? 0 : 1;
+ if (opts.keepQuotes === true) {
+ push({ type: 'text', value });
+ }
+ continue;
+ }
+
+ /**
+ * Parentheses
+ */
+
+ if (value === '(') {
+ increment('parens');
+ push({ type: 'paren', value });
+ continue;
+ }
+
+ if (value === ')') {
+ if (state.parens === 0 && opts.strictBrackets === true) {
+ throw new SyntaxError(syntaxError('opening', '('));
+ }
+
+ const extglob = extglobs[extglobs.length - 1];
+ if (extglob && state.parens === extglob.parens + 1) {
+ extglobClose(extglobs.pop());
+ continue;
+ }
+
+ push({ type: 'paren', value, output: state.parens ? ')' : '\\)' });
+ decrement('parens');
+ continue;
+ }
+
+ /**
+ * Square brackets
+ */
+
+ if (value === '[') {
+ if (opts.nobracket === true || !remaining().includes(']')) {
+ if (opts.nobracket !== true && opts.strictBrackets === true) {
+ throw new SyntaxError(syntaxError('closing', ']'));
+ }
+
+ value = `\\${value}`;
+ } else {
+ increment('brackets');
+ }
+
+ push({ type: 'bracket', value });
+ continue;
+ }
+
+ if (value === ']') {
+ if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) {
+ push({ type: 'text', value, output: `\\${value}` });
+ continue;
+ }
+
+ if (state.brackets === 0) {
+ if (opts.strictBrackets === true) {
+ throw new SyntaxError(syntaxError('opening', '['));
+ }
+
+ push({ type: 'text', value, output: `\\${value}` });
+ continue;
+ }
+
+ decrement('brackets');
+
+ const prevValue = prev.value.slice(1);
+ if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) {
+ value = `/${value}`;
+ }
+
+ prev.value += value;
+ append({ value });
+
+ // when literal brackets are explicitly disabled
+ // assume we should match with a regex character class
+ if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) {
+ continue;
+ }
+
+ const escaped = utils.escapeRegex(prev.value);
+ state.output = state.output.slice(0, -prev.value.length);
+
+ // when literal brackets are explicitly enabled
+ // assume we should escape the brackets to match literal characters
+ if (opts.literalBrackets === true) {
+ state.output += escaped;
+ prev.value = escaped;
+ continue;
+ }
+
+ // when the user specifies nothing, try to match both
+ prev.value = `(${capture}${escaped}|${prev.value})`;
+ state.output += prev.value;
+ continue;
+ }
+
+ /**
+ * Braces
+ */
+
+ if (value === '{' && opts.nobrace !== true) {
+ increment('braces');
+
+ const open = {
+ type: 'brace',
+ value,
+ output: '(',
+ outputIndex: state.output.length,
+ tokensIndex: state.tokens.length
+ };
+
+ braces.push(open);
+ push(open);
+ continue;
+ }
+
+ if (value === '}') {
+ const brace = braces[braces.length - 1];
+
+ if (opts.nobrace === true || !brace) {
+ push({ type: 'text', value, output: value });
+ continue;
+ }
+
+ let output = ')';
+
+ if (brace.dots === true) {
+ const arr = tokens.slice();
+ const range = [];
+
+ for (let i = arr.length - 1; i >= 0; i--) {
+ tokens.pop();
+ if (arr[i].type === 'brace') {
+ break;
+ }
+ if (arr[i].type !== 'dots') {
+ range.unshift(arr[i].value);
+ }
+ }
+
+ output = expandRange(range, opts);
+ state.backtrack = true;
+ }
+
+ if (brace.comma !== true && brace.dots !== true) {
+ const out = state.output.slice(0, brace.outputIndex);
+ const toks = state.tokens.slice(brace.tokensIndex);
+ brace.value = brace.output = '\\{';
+ value = output = '\\}';
+ state.output = out;
+ for (const t of toks) {
+ state.output += (t.output || t.value);
+ }
+ }
+
+ push({ type: 'brace', value, output });
+ decrement('braces');
+ braces.pop();
+ continue;
+ }
+
+ /**
+ * Pipes
+ */
+
+ if (value === '|') {
+ if (extglobs.length > 0) {
+ extglobs[extglobs.length - 1].conditions++;
+ }
+ push({ type: 'text', value });
+ continue;
+ }
+
+ /**
+ * Commas
+ */
+
+ if (value === ',') {
+ let output = value;
+
+ const brace = braces[braces.length - 1];
+ if (brace && stack[stack.length - 1] === 'braces') {
+ brace.comma = true;
+ output = '|';
+ }
+
+ push({ type: 'comma', value, output });
+ continue;
+ }
+
+ /**
+ * Slashes
+ */
+
+ if (value === '/') {
+ // if the beginning of the glob is "./", advance the start
+ // to the current index, and don't add the "./" characters
+ // to the state. This greatly simplifies lookbehinds when
+ // checking for BOS characters like "!" and "." (not "./")
+ if (prev.type === 'dot' && state.index === state.start + 1) {
+ state.start = state.index + 1;
+ state.consumed = '';
+ state.output = '';
+ tokens.pop();
+ prev = bos; // reset "prev" to the first token
+ continue;
+ }
+
+ push({ type: 'slash', value, output: SLASH_LITERAL });
+ continue;
+ }
+
+ /**
+ * Dots
+ */
+
+ if (value === '.') {
+ if (state.braces > 0 && prev.type === 'dot') {
+ if (prev.value === '.') prev.output = DOT_LITERAL;
+ const brace = braces[braces.length - 1];
+ prev.type = 'dots';
+ prev.output += value;
+ prev.value += value;
+ brace.dots = true;
+ continue;
+ }
+
+ if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') {
+ push({ type: 'text', value, output: DOT_LITERAL });
+ continue;
+ }
+
+ push({ type: 'dot', value, output: DOT_LITERAL });
+ continue;
+ }
+
+ /**
+ * Question marks
+ */
+
+ if (value === '?') {
+ const isGroup = prev && prev.value === '(';
+ if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
+ extglobOpen('qmark', value);
+ continue;
+ }
+
+ if (prev && prev.type === 'paren') {
+ const next = peek();
+ let output = value;
+
+ if (next === '<' && !utils.supportsLookbehinds()) {
+ throw new Error('Node.js v10 or higher is required for regex lookbehinds');
+ }
+
+ if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) {
+ output = `\\${value}`;
+ }
+
+ push({ type: 'text', value, output });
+ continue;
+ }
+
+ if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) {
+ push({ type: 'qmark', value, output: QMARK_NO_DOT });
+ continue;
+ }
+
+ push({ type: 'qmark', value, output: QMARK });
+ continue;
+ }
+
+ /**
+ * Exclamation
+ */
+
+ if (value === '!') {
+ if (opts.noextglob !== true && peek() === '(') {
+ if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) {
+ extglobOpen('negate', value);
+ continue;
+ }
+ }
+
+ if (opts.nonegate !== true && state.index === 0) {
+ negate();
+ continue;
+ }
+ }
+
+ /**
+ * Plus
+ */
+
+ if (value === '+') {
+ if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
+ extglobOpen('plus', value);
+ continue;
+ }
+
+ if ((prev && prev.value === '(') || opts.regex === false) {
+ push({ type: 'plus', value, output: PLUS_LITERAL });
+ continue;
+ }
+
+ if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) {
+ push({ type: 'plus', value });
+ continue;
+ }
+
+ push({ type: 'plus', value: PLUS_LITERAL });
+ continue;
+ }
+
+ /**
+ * Plain text
+ */
+
+ if (value === '@') {
+ if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
+ push({ type: 'at', extglob: true, value, output: '' });
+ continue;
+ }
+
+ push({ type: 'text', value });
+ continue;
+ }
+
+ /**
+ * Plain text
+ */
+
+ if (value !== '*') {
+ if (value === '$' || value === '^') {
+ value = `\\${value}`;
+ }
+
+ const match = REGEX_NON_SPECIAL_CHARS.exec(remaining());
+ if (match) {
+ value += match[0];
+ state.index += match[0].length;
+ }
+
+ push({ type: 'text', value });
+ continue;
+ }
+
+ /**
+ * Stars
+ */
+
+ if (prev && (prev.type === 'globstar' || prev.star === true)) {
+ prev.type = 'star';
+ prev.star = true;
+ prev.value += value;
+ prev.output = star;
+ state.backtrack = true;
+ state.globstar = true;
+ consume(value);
+ continue;
+ }
+
+ let rest = remaining();
+ if (opts.noextglob !== true && /^\([^?]/.test(rest)) {
+ extglobOpen('star', value);
+ continue;
+ }
+
+ if (prev.type === 'star') {
+ if (opts.noglobstar === true) {
+ consume(value);
+ continue;
+ }
- return value;
-};
+ const prior = prev.prev;
+ const before = prior.prev;
+ const isStart = prior.type === 'slash' || prior.type === 'bos';
+ const afterStar = before && (before.type === 'star' || before.type === 'globstar');
-var LEGACY_ALIASES = {
- '%ArrayBufferPrototype%': ['ArrayBuffer', 'prototype'],
- '%ArrayPrototype%': ['Array', 'prototype'],
- '%ArrayProto_entries%': ['Array', 'prototype', 'entries'],
- '%ArrayProto_forEach%': ['Array', 'prototype', 'forEach'],
- '%ArrayProto_keys%': ['Array', 'prototype', 'keys'],
- '%ArrayProto_values%': ['Array', 'prototype', 'values'],
- '%AsyncFunctionPrototype%': ['AsyncFunction', 'prototype'],
- '%AsyncGenerator%': ['AsyncGeneratorFunction', 'prototype'],
- '%AsyncGeneratorPrototype%': ['AsyncGeneratorFunction', 'prototype', 'prototype'],
- '%BooleanPrototype%': ['Boolean', 'prototype'],
- '%DataViewPrototype%': ['DataView', 'prototype'],
- '%DatePrototype%': ['Date', 'prototype'],
- '%ErrorPrototype%': ['Error', 'prototype'],
- '%EvalErrorPrototype%': ['EvalError', 'prototype'],
- '%Float32ArrayPrototype%': ['Float32Array', 'prototype'],
- '%Float64ArrayPrototype%': ['Float64Array', 'prototype'],
- '%FunctionPrototype%': ['Function', 'prototype'],
- '%Generator%': ['GeneratorFunction', 'prototype'],
- '%GeneratorPrototype%': ['GeneratorFunction', 'prototype', 'prototype'],
- '%Int8ArrayPrototype%': ['Int8Array', 'prototype'],
- '%Int16ArrayPrototype%': ['Int16Array', 'prototype'],
- '%Int32ArrayPrototype%': ['Int32Array', 'prototype'],
- '%JSONParse%': ['JSON', 'parse'],
- '%JSONStringify%': ['JSON', 'stringify'],
- '%MapPrototype%': ['Map', 'prototype'],
- '%NumberPrototype%': ['Number', 'prototype'],
- '%ObjectPrototype%': ['Object', 'prototype'],
- '%ObjProto_toString%': ['Object', 'prototype', 'toString'],
- '%ObjProto_valueOf%': ['Object', 'prototype', 'valueOf'],
- '%PromisePrototype%': ['Promise', 'prototype'],
- '%PromiseProto_then%': ['Promise', 'prototype', 'then'],
- '%Promise_all%': ['Promise', 'all'],
- '%Promise_reject%': ['Promise', 'reject'],
- '%Promise_resolve%': ['Promise', 'resolve'],
- '%RangeErrorPrototype%': ['RangeError', 'prototype'],
- '%ReferenceErrorPrototype%': ['ReferenceError', 'prototype'],
- '%RegExpPrototype%': ['RegExp', 'prototype'],
- '%SetPrototype%': ['Set', 'prototype'],
- '%SharedArrayBufferPrototype%': ['SharedArrayBuffer', 'prototype'],
- '%StringPrototype%': ['String', 'prototype'],
- '%SymbolPrototype%': ['Symbol', 'prototype'],
- '%SyntaxErrorPrototype%': ['SyntaxError', 'prototype'],
- '%TypedArrayPrototype%': ['TypedArray', 'prototype'],
- '%TypeErrorPrototype%': ['TypeError', 'prototype'],
- '%Uint8ArrayPrototype%': ['Uint8Array', 'prototype'],
- '%Uint8ClampedArrayPrototype%': ['Uint8ClampedArray', 'prototype'],
- '%Uint16ArrayPrototype%': ['Uint16Array', 'prototype'],
- '%Uint32ArrayPrototype%': ['Uint32Array', 'prototype'],
- '%URIErrorPrototype%': ['URIError', 'prototype'],
- '%WeakMapPrototype%': ['WeakMap', 'prototype'],
- '%WeakSetPrototype%': ['WeakSet', 'prototype']
-};
+ if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) {
+ push({ type: 'star', value, output: '' });
+ continue;
+ }
-var bind = __nccwpck_require__(8334);
-var hasOwn = __nccwpck_require__(6339);
-var $concat = bind.call(Function.call, Array.prototype.concat);
-var $spliceApply = bind.call(Function.apply, Array.prototype.splice);
-var $replace = bind.call(Function.call, String.prototype.replace);
-var $strSlice = bind.call(Function.call, String.prototype.slice);
-var $exec = bind.call(Function.call, RegExp.prototype.exec);
+ const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace');
+ const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren');
+ if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) {
+ push({ type: 'star', value, output: '' });
+ continue;
+ }
-/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */
-var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;
-var reEscapeChar = /\\(\\)?/g; /** Used to match backslashes in property paths. */
-var stringToPath = function stringToPath(string) {
- var first = $strSlice(string, 0, 1);
- var last = $strSlice(string, -1);
- if (first === '%' && last !== '%') {
- throw new $SyntaxError('invalid intrinsic syntax, expected closing `%`');
- } else if (last === '%' && first !== '%') {
- throw new $SyntaxError('invalid intrinsic syntax, expected opening `%`');
- }
- var result = [];
- $replace(string, rePropName, function (match, number, quote, subString) {
- result[result.length] = quote ? $replace(subString, reEscapeChar, '$1') : number || match;
- });
- return result;
-};
-/* end adaptation */
+ // strip consecutive `/**/`
+ while (rest.slice(0, 3) === '/**') {
+ const after = input[state.index + 4];
+ if (after && after !== '/') {
+ break;
+ }
+ rest = rest.slice(3);
+ consume('/**', 3);
+ }
-var getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) {
- var intrinsicName = name;
- var alias;
- if (hasOwn(LEGACY_ALIASES, intrinsicName)) {
- alias = LEGACY_ALIASES[intrinsicName];
- intrinsicName = '%' + alias[0] + '%';
- }
+ if (prior.type === 'bos' && eos()) {
+ prev.type = 'globstar';
+ prev.value += value;
+ prev.output = globstar(opts);
+ state.output = prev.output;
+ state.globstar = true;
+ consume(value);
+ continue;
+ }
- if (hasOwn(INTRINSICS, intrinsicName)) {
- var value = INTRINSICS[intrinsicName];
- if (value === needsEval) {
- value = doEval(intrinsicName);
- }
- if (typeof value === 'undefined' && !allowMissing) {
- throw new $TypeError('intrinsic ' + name + ' exists, but is not available. Please file an issue!');
- }
+ if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) {
+ state.output = state.output.slice(0, -(prior.output + prev.output).length);
+ prior.output = `(?:${prior.output}`;
- return {
- alias: alias,
- name: intrinsicName,
- value: value
- };
- }
+ prev.type = 'globstar';
+ prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)');
+ prev.value += value;
+ state.globstar = true;
+ state.output += prior.output + prev.output;
+ consume(value);
+ continue;
+ }
- throw new $SyntaxError('intrinsic ' + name + ' does not exist!');
-};
+ if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') {
+ const end = rest[1] !== void 0 ? '|$' : '';
-module.exports = function GetIntrinsic(name, allowMissing) {
- if (typeof name !== 'string' || name.length === 0) {
- throw new $TypeError('intrinsic name must be a non-empty string');
- }
- if (arguments.length > 1 && typeof allowMissing !== 'boolean') {
- throw new $TypeError('"allowMissing" argument must be a boolean');
- }
+ state.output = state.output.slice(0, -(prior.output + prev.output).length);
+ prior.output = `(?:${prior.output}`;
- if ($exec(/^%?[^%]*%?$/, name) === null) {
- throw new $SyntaxError('`%` may not be present anywhere but at the beginning and end of the intrinsic name');
- }
- var parts = stringToPath(name);
- var intrinsicBaseName = parts.length > 0 ? parts[0] : '';
+ prev.type = 'globstar';
+ prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`;
+ prev.value += value;
- var intrinsic = getBaseIntrinsic('%' + intrinsicBaseName + '%', allowMissing);
- var intrinsicRealName = intrinsic.name;
- var value = intrinsic.value;
- var skipFurtherCaching = false;
+ state.output += prior.output + prev.output;
+ state.globstar = true;
- var alias = intrinsic.alias;
- if (alias) {
- intrinsicBaseName = alias[0];
- $spliceApply(parts, $concat([0, 1], alias));
- }
+ consume(value + advance());
- for (var i = 1, isOwn = true; i < parts.length; i += 1) {
- var part = parts[i];
- var first = $strSlice(part, 0, 1);
- var last = $strSlice(part, -1);
- if (
- (
- (first === '"' || first === "'" || first === '`')
- || (last === '"' || last === "'" || last === '`')
- )
- && first !== last
- ) {
- throw new $SyntaxError('property names with quotes must have matching quotes');
- }
- if (part === 'constructor' || !isOwn) {
- skipFurtherCaching = true;
- }
+ push({ type: 'slash', value: '/', output: '' });
+ continue;
+ }
- intrinsicBaseName += '.' + part;
- intrinsicRealName = '%' + intrinsicBaseName + '%';
+ if (prior.type === 'bos' && rest[0] === '/') {
+ prev.type = 'globstar';
+ prev.value += value;
+ prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`;
+ state.output = prev.output;
+ state.globstar = true;
+ consume(value + advance());
+ push({ type: 'slash', value: '/', output: '' });
+ continue;
+ }
- if (hasOwn(INTRINSICS, intrinsicRealName)) {
- value = INTRINSICS[intrinsicRealName];
- } else if (value != null) {
- if (!(part in value)) {
- if (!allowMissing) {
- throw new $TypeError('base intrinsic for ' + name + ' exists, but the property is not available.');
- }
- return void undefined;
- }
- if ($gOPD && (i + 1) >= parts.length) {
- var desc = $gOPD(value, part);
- isOwn = !!desc;
+ // remove single star from output
+ state.output = state.output.slice(0, -prev.output.length);
- // By convention, when a data property is converted to an accessor
- // property to emulate a data property that does not suffer from
- // the override mistake, that accessor's getter is marked with
- // an `originalValue` property. Here, when we detect this, we
- // uphold the illusion by pretending to see that original data
- // property, i.e., returning the value rather than the getter
- // itself.
- if (isOwn && 'get' in desc && !('originalValue' in desc.get)) {
- value = desc.get;
- } else {
- value = value[part];
- }
- } else {
- isOwn = hasOwn(value, part);
- value = value[part];
- }
+ // reset previous token to globstar
+ prev.type = 'globstar';
+ prev.output = globstar(opts);
+ prev.value += value;
- if (isOwn && !skipFurtherCaching) {
- INTRINSICS[intrinsicRealName] = value;
- }
- }
- }
- return value;
-};
+ // reset output with globstar
+ state.output += prev.output;
+ state.globstar = true;
+ consume(value);
+ continue;
+ }
+ const token = { type: 'star', value, output: star };
-/***/ }),
+ if (opts.bash === true) {
+ token.output = '.*?';
+ if (prev.type === 'bos' || prev.type === 'slash') {
+ token.output = nodot + token.output;
+ }
+ push(token);
+ continue;
+ }
-/***/ 5894:
-/***/ ((module) => {
+ if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) {
+ token.output = value;
+ push(token);
+ continue;
+ }
+ if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') {
+ if (prev.type === 'dot') {
+ state.output += NO_DOT_SLASH;
+ prev.output += NO_DOT_SLASH;
+ } else if (opts.dot === true) {
+ state.output += NO_DOTS_SLASH;
+ prev.output += NO_DOTS_SLASH;
-var test = {
- foo: {}
-};
+ } else {
+ state.output += nodot;
+ prev.output += nodot;
+ }
-var $Object = Object;
+ if (peek() !== '*') {
+ state.output += ONE_CHAR;
+ prev.output += ONE_CHAR;
+ }
+ }
-module.exports = function hasProto() {
- return { __proto__: test }.foo === test.foo && !({ __proto__: null } instanceof $Object);
-};
+ push(token);
+ }
+ while (state.brackets > 0) {
+ if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']'));
+ state.output = utils.escapeLast(state.output, '[');
+ decrement('brackets');
+ }
-/***/ }),
+ while (state.parens > 0) {
+ if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')'));
+ state.output = utils.escapeLast(state.output, '(');
+ decrement('parens');
+ }
-/***/ 587:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+ while (state.braces > 0) {
+ if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}'));
+ state.output = utils.escapeLast(state.output, '{');
+ decrement('braces');
+ }
+ if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) {
+ push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` });
+ }
+ // rebuild the output if we had to backtrack at any point
+ if (state.backtrack === true) {
+ state.output = '';
-var origSymbol = typeof Symbol !== 'undefined' && Symbol;
-var hasSymbolSham = __nccwpck_require__(7747);
+ for (const token of state.tokens) {
+ state.output += token.output != null ? token.output : token.value;
-module.exports = function hasNativeSymbols() {
- if (typeof origSymbol !== 'function') { return false; }
- if (typeof Symbol !== 'function') { return false; }
- if (typeof origSymbol('foo') !== 'symbol') { return false; }
- if (typeof Symbol('bar') !== 'symbol') { return false; }
+ if (token.suffix) {
+ state.output += token.suffix;
+ }
+ }
+ }
- return hasSymbolSham();
+ return state;
};
+/**
+ * Fast paths for creating regular expressions for common glob patterns.
+ * This can significantly speed up processing and has very little downside
+ * impact when none of the fast paths match.
+ */
-/***/ }),
-
-/***/ 7747:
-/***/ ((module) => {
+parse.fastpaths = (input, options) => {
+ const opts = { ...options };
+ const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
+ const len = input.length;
+ if (len > max) {
+ throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
+ }
+
+ input = REPLACEMENTS[input] || input;
+ const win32 = utils.isWindows(options);
+
+ // create constants based on platform, for windows or posix
+ const {
+ DOT_LITERAL,
+ SLASH_LITERAL,
+ ONE_CHAR,
+ DOTS_SLASH,
+ NO_DOT,
+ NO_DOTS,
+ NO_DOTS_SLASH,
+ STAR,
+ START_ANCHOR
+ } = constants.globChars(win32);
+
+ const nodot = opts.dot ? NO_DOTS : NO_DOT;
+ const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
+ const capture = opts.capture ? '' : '?:';
+ const state = { negated: false, prefix: '' };
+ let star = opts.bash === true ? '.*?' : STAR;
+
+ if (opts.capture) {
+ star = `(${star})`;
+ }
+
+ const globstar = opts => {
+ if (opts.noglobstar === true) return star;
+ return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
+ };
+ const create = str => {
+ switch (str) {
+ case '*':
+ return `${nodot}${ONE_CHAR}${star}`;
+ case '.*':
+ return `${DOT_LITERAL}${ONE_CHAR}${star}`;
-/* eslint complexity: [2, 18], max-statements: [2, 33] */
-module.exports = function hasSymbols() {
- if (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; }
- if (typeof Symbol.iterator === 'symbol') { return true; }
+ case '*.*':
+ return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
- var obj = {};
- var sym = Symbol('test');
- var symObj = Object(sym);
- if (typeof sym === 'string') { return false; }
+ case '*/*':
+ return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`;
- if (Object.prototype.toString.call(sym) !== '[object Symbol]') { return false; }
- if (Object.prototype.toString.call(symObj) !== '[object Symbol]') { return false; }
+ case '**':
+ return nodot + globstar(opts);
- // temp disabled per https://github.com/ljharb/object.assign/issues/17
- // if (sym instanceof Symbol) { return false; }
- // temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4
- // if (!(symObj instanceof Symbol)) { return false; }
+ case '**/*':
+ return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`;
- // if (typeof Symbol.prototype.toString !== 'function') { return false; }
- // if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; }
+ case '**/*.*':
+ return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
- var symVal = 42;
- obj[sym] = symVal;
- for (sym in obj) { return false; } // eslint-disable-line no-restricted-syntax, no-unreachable-loop
- if (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; }
+ case '**/.*':
+ return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`;
- if (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; }
+ default: {
+ const match = /^(.*?)\.(\w+)$/.exec(str);
+ if (!match) return;
- var syms = Object.getOwnPropertySymbols(obj);
- if (syms.length !== 1 || syms[0] !== sym) { return false; }
+ const source = create(match[1]);
+ if (!source) return;
- if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; }
+ return source + DOT_LITERAL + match[2];
+ }
+ }
+ };
- if (typeof Object.getOwnPropertyDescriptor === 'function') {
- var descriptor = Object.getOwnPropertyDescriptor(obj, sym);
- if (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; }
- }
+ const output = utils.removePrefix(input, state);
+ let source = create(output);
- return true;
+ if (source && opts.strictSlashes !== true) {
+ source += `${SLASH_LITERAL}?`;
+ }
+
+ return source;
};
+module.exports = parse;
+
/***/ }),
-/***/ 6339:
+/***/ 3322:
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
-var bind = __nccwpck_require__(8334);
+const path = __nccwpck_require__(1017);
+const scan = __nccwpck_require__(2429);
+const parse = __nccwpck_require__(2139);
+const utils = __nccwpck_require__(479);
+const constants = __nccwpck_require__(6099);
+const isObject = val => val && typeof val === 'object' && !Array.isArray(val);
-module.exports = bind.call(Function.call, Object.prototype.hasOwnProperty);
+/**
+ * Creates a matcher function from one or more glob patterns. The
+ * returned function takes a string to match as its first argument,
+ * and returns true if the string is a match. The returned matcher
+ * function also takes a boolean as the second argument that, when true,
+ * returns an object with additional information.
+ *
+ * ```js
+ * const picomatch = require('picomatch');
+ * // picomatch(glob[, options]);
+ *
+ * const isMatch = picomatch('*.!(*a)');
+ * console.log(isMatch('a.a')); //=> false
+ * console.log(isMatch('a.b')); //=> true
+ * ```
+ * @name picomatch
+ * @param {String|Array} `globs` One or more glob patterns.
+ * @param {Object=} `options`
+ * @return {Function=} Returns a matcher function.
+ * @api public
+ */
+const picomatch = (glob, options, returnState = false) => {
+ if (Array.isArray(glob)) {
+ const fns = glob.map(input => picomatch(input, options, returnState));
+ const arrayMatcher = str => {
+ for (const isMatch of fns) {
+ const state = isMatch(str);
+ if (state) return state;
+ }
+ return false;
+ };
+ return arrayMatcher;
+ }
-/***/ }),
+ const isState = isObject(glob) && glob.tokens && glob.input;
-/***/ 3287:
-/***/ ((__unused_webpack_module, exports) => {
+ if (glob === '' || (typeof glob !== 'string' && !isState)) {
+ throw new TypeError('Expected pattern to be a non-empty string');
+ }
+ const opts = options || {};
+ const posix = utils.isWindows(options);
+ const regex = isState
+ ? picomatch.compileRe(glob, options)
+ : picomatch.makeRe(glob, options, false, true);
+ const state = regex.state;
+ delete regex.state;
-Object.defineProperty(exports, "__esModule", ({ value: true }));
+ let isIgnored = () => false;
+ if (opts.ignore) {
+ const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null };
+ isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
+ }
-/*!
- * is-plain-object
+ const matcher = (input, returnObject = false) => {
+ const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix });
+ const result = { glob, state, regex, posix, input, output, match, isMatch };
+
+ if (typeof opts.onResult === 'function') {
+ opts.onResult(result);
+ }
+
+ if (isMatch === false) {
+ result.isMatch = false;
+ return returnObject ? result : false;
+ }
+
+ if (isIgnored(input)) {
+ if (typeof opts.onIgnore === 'function') {
+ opts.onIgnore(result);
+ }
+ result.isMatch = false;
+ return returnObject ? result : false;
+ }
+
+ if (typeof opts.onMatch === 'function') {
+ opts.onMatch(result);
+ }
+ return returnObject ? result : true;
+ };
+
+ if (returnState) {
+ matcher.state = state;
+ }
+
+ return matcher;
+};
+
+/**
+ * Test `input` with the given `regex`. This is used by the main
+ * `picomatch()` function to test the input string.
*
- * Copyright (c) 2014-2017, Jon Schlinkert.
- * Released under the MIT License.
+ * ```js
+ * const picomatch = require('picomatch');
+ * // picomatch.test(input, regex[, options]);
+ *
+ * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/));
+ * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' }
+ * ```
+ * @param {String} `input` String to test.
+ * @param {RegExp} `regex`
+ * @return {Object} Returns an object with matching info.
+ * @api public
*/
-function isObject(o) {
- return Object.prototype.toString.call(o) === '[object Object]';
-}
-
-function isPlainObject(o) {
- var ctor,prot;
+picomatch.test = (input, regex, options, { glob, posix } = {}) => {
+ if (typeof input !== 'string') {
+ throw new TypeError('Expected input to be a string');
+ }
- if (isObject(o) === false) return false;
+ if (input === '') {
+ return { isMatch: false, output: '' };
+ }
- // If has modified constructor
- ctor = o.constructor;
- if (ctor === undefined) return true;
+ const opts = options || {};
+ const format = opts.format || (posix ? utils.toPosixSlashes : null);
+ let match = input === glob;
+ let output = (match && format) ? format(input) : input;
- // If has modified prototype
- prot = ctor.prototype;
- if (isObject(prot) === false) return false;
+ if (match === false) {
+ output = format ? format(input) : input;
+ match = output === glob;
+ }
- // If constructor does not have an Object-specific method
- if (prot.hasOwnProperty('isPrototypeOf') === false) {
- return false;
+ if (match === false || opts.capture === true) {
+ if (opts.matchBase === true || opts.basename === true) {
+ match = picomatch.matchBase(input, regex, options, posix);
+ } else {
+ match = regex.exec(output);
+ }
}
- // Most likely a plain Object
- return true;
-}
+ return { isMatch: Boolean(match), match, output };
+};
-exports.isPlainObject = isPlainObject;
+/**
+ * Match the basename of a filepath.
+ *
+ * ```js
+ * const picomatch = require('picomatch');
+ * // picomatch.matchBase(input, glob[, options]);
+ * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true
+ * ```
+ * @param {String} `input` String to test.
+ * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe).
+ * @return {Boolean}
+ * @api public
+ */
+picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => {
+ const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
+ return regex.test(path.basename(input));
+};
-/***/ }),
+/**
+ * Returns true if **any** of the given glob `patterns` match the specified `string`.
+ *
+ * ```js
+ * const picomatch = require('picomatch');
+ * // picomatch.isMatch(string, patterns[, options]);
+ *
+ * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true
+ * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false
+ * ```
+ * @param {String|Array} str The string to test.
+ * @param {String|Array} patterns One or more glob patterns to use for matching.
+ * @param {Object} [options] See available [options](#options).
+ * @return {Boolean} Returns true if any patterns match `str`
+ * @api public
+ */
-/***/ 7073:
-/***/ ((module, exports) => {
+picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
-exports = module.exports = stringify
-exports.getSerialize = serializer
+/**
+ * Parse a glob pattern to create the source string for a regular
+ * expression.
+ *
+ * ```js
+ * const picomatch = require('picomatch');
+ * const result = picomatch.parse(pattern[, options]);
+ * ```
+ * @param {String} `pattern`
+ * @param {Object} `options`
+ * @return {Object} Returns an object with useful properties and output to be used as a regex source string.
+ * @api public
+ */
-function stringify(obj, replacer, spaces, cycleReplacer) {
- return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
-}
+picomatch.parse = (pattern, options) => {
+ if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options));
+ return parse(pattern, { ...options, fastpaths: false });
+};
-function serializer(replacer, cycleReplacer) {
- var stack = [], keys = []
+/**
+ * Scan a glob pattern to separate the pattern into segments.
+ *
+ * ```js
+ * const picomatch = require('picomatch');
+ * // picomatch.scan(input[, options]);
+ *
+ * const result = picomatch.scan('!./foo/*.js');
+ * console.log(result);
+ * { prefix: '!./',
+ * input: '!./foo/*.js',
+ * start: 3,
+ * base: 'foo',
+ * glob: '*.js',
+ * isBrace: false,
+ * isBracket: false,
+ * isGlob: true,
+ * isExtglob: false,
+ * isGlobstar: false,
+ * negated: true }
+ * ```
+ * @param {String} `input` Glob pattern to scan.
+ * @param {Object} `options`
+ * @return {Object} Returns an object with
+ * @api public
+ */
- if (cycleReplacer == null) cycleReplacer = function(key, value) {
- if (stack[0] === value) return "[Circular ~]"
- return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"
+picomatch.scan = (input, options) => scan(input, options);
+
+/**
+ * Compile a regular expression from the `state` object returned by the
+ * [parse()](#parse) method.
+ *
+ * @param {Object} `state`
+ * @param {Object} `options`
+ * @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser.
+ * @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging.
+ * @return {RegExp}
+ * @api public
+ */
+
+picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => {
+ if (returnOutput === true) {
+ return state.output;
}
- return function(key, value) {
- if (stack.length > 0) {
- var thisPos = stack.indexOf(this)
- ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
- ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
- if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
- }
- else stack.push(value)
+ const opts = options || {};
+ const prepend = opts.contains ? '' : '^';
+ const append = opts.contains ? '' : '$';
- return replacer == null ? value : replacer.call(this, key, value)
+ let source = `${prepend}(?:${state.output})${append}`;
+ if (state && state.negated === true) {
+ source = `^(?!${source}).*$`;
}
-}
+ const regex = picomatch.toRegex(source, options);
+ if (returnState === true) {
+ regex.state = state;
+ }
-/***/ }),
+ return regex;
+};
-/***/ 7760:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+/**
+ * Create a regular expression from a parsed glob pattern.
+ *
+ * ```js
+ * const picomatch = require('picomatch');
+ * const state = picomatch.parse('*.js');
+ * // picomatch.compileRe(state[, options]);
+ *
+ * console.log(picomatch.compileRe(state));
+ * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
+ * ```
+ * @param {String} `state` The object returned from the `.parse` method.
+ * @param {Object} `options`
+ * @param {Boolean} `returnOutput` Implementors may use this argument to return the compiled output, instead of a regular expression. This is not exposed on the options to prevent end-users from mutating the result.
+ * @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression.
+ * @return {RegExp} Returns a regex created from the given pattern.
+ * @api public
+ */
-/*! node-domexception. MIT License. Jimmy Wärting */
+picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => {
+ if (!input || typeof input !== 'string') {
+ throw new TypeError('Expected a non-empty string');
+ }
-if (!globalThis.DOMException) {
- try {
- const { MessageChannel } = __nccwpck_require__(1267),
- port = new MessageChannel().port1,
- ab = new ArrayBuffer()
- port.postMessage(ab, [ab, ab])
- } catch (err) {
- err.constructor.name === 'DOMException' && (
- globalThis.DOMException = err.constructor
- )
+ let parsed = { negated: false, fastpaths: true };
+
+ if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) {
+ parsed.output = parse.fastpaths(input, options);
}
-}
-module.exports = globalThis.DOMException
+ if (!parsed.output) {
+ parsed = parse(input, options);
+ }
+ return picomatch.compileRe(parsed, options, returnOutput, returnState);
+};
-/***/ }),
+/**
+ * Create a regular expression from the given regex source string.
+ *
+ * ```js
+ * const picomatch = require('picomatch');
+ * // picomatch.toRegex(source[, options]);
+ *
+ * const { output } = picomatch.parse('*.js');
+ * console.log(picomatch.toRegex(output));
+ * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
+ * ```
+ * @param {String} `source` Regular expression source string.
+ * @param {Object} `options`
+ * @return {RegExp}
+ * @api public
+ */
-/***/ 504:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+picomatch.toRegex = (source, options) => {
+ try {
+ const opts = options || {};
+ return new RegExp(source, opts.flags || (opts.nocase ? 'i' : ''));
+ } catch (err) {
+ if (options && options.debug === true) throw err;
+ return /$^/;
+ }
+};
-var hasMap = typeof Map === 'function' && Map.prototype;
-var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null;
-var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null;
-var mapForEach = hasMap && Map.prototype.forEach;
-var hasSet = typeof Set === 'function' && Set.prototype;
-var setSizeDescriptor = Object.getOwnPropertyDescriptor && hasSet ? Object.getOwnPropertyDescriptor(Set.prototype, 'size') : null;
-var setSize = hasSet && setSizeDescriptor && typeof setSizeDescriptor.get === 'function' ? setSizeDescriptor.get : null;
-var setForEach = hasSet && Set.prototype.forEach;
-var hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype;
-var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null;
-var hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype;
-var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null;
-var hasWeakRef = typeof WeakRef === 'function' && WeakRef.prototype;
-var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null;
-var booleanValueOf = Boolean.prototype.valueOf;
-var objectToString = Object.prototype.toString;
-var functionToString = Function.prototype.toString;
-var $match = String.prototype.match;
-var $slice = String.prototype.slice;
-var $replace = String.prototype.replace;
-var $toUpperCase = String.prototype.toUpperCase;
-var $toLowerCase = String.prototype.toLowerCase;
-var $test = RegExp.prototype.test;
-var $concat = Array.prototype.concat;
-var $join = Array.prototype.join;
-var $arrSlice = Array.prototype.slice;
-var $floor = Math.floor;
-var bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null;
-var gOPS = Object.getOwnPropertySymbols;
-var symToString = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? Symbol.prototype.toString : null;
-var hasShammedSymbols = typeof Symbol === 'function' && typeof Symbol.iterator === 'object';
-// ie, `has-tostringtag/shams
-var toStringTag = typeof Symbol === 'function' && Symbol.toStringTag && (typeof Symbol.toStringTag === hasShammedSymbols ? 'object' : 'symbol')
- ? Symbol.toStringTag
- : null;
-var isEnumerable = Object.prototype.propertyIsEnumerable;
+/**
+ * Picomatch constants.
+ * @return {Object}
+ */
-var gPO = (typeof Reflect === 'function' ? Reflect.getPrototypeOf : Object.getPrototypeOf) || (
- [].__proto__ === Array.prototype // eslint-disable-line no-proto
- ? function (O) {
- return O.__proto__; // eslint-disable-line no-proto
- }
- : null
-);
+picomatch.constants = constants;
-function addNumericSeparator(num, str) {
- if (
- num === Infinity
- || num === -Infinity
- || num !== num
- || (num && num > -1000 && num < 1000)
- || $test.call(/e/, str)
- ) {
- return str;
- }
- var sepRegex = /[0-9](?=(?:[0-9]{3})+(?![0-9]))/g;
- if (typeof num === 'number') {
- var int = num < 0 ? -$floor(-num) : $floor(num); // trunc(num)
- if (int !== num) {
- var intStr = String(int);
- var dec = $slice.call(str, intStr.length + 1);
- return $replace.call(intStr, sepRegex, '$&_') + '.' + $replace.call($replace.call(dec, /([0-9]{3})/g, '$&_'), /_$/, '');
- }
- }
- return $replace.call(str, sepRegex, '$&_');
-}
+/**
+ * Expose "picomatch"
+ */
-var utilInspect = __nccwpck_require__(7265);
-var inspectCustom = utilInspect.custom;
-var inspectSymbol = isSymbol(inspectCustom) ? inspectCustom : null;
+module.exports = picomatch;
-module.exports = function inspect_(obj, options, depth, seen) {
- var opts = options || {};
- if (has(opts, 'quoteStyle') && (opts.quoteStyle !== 'single' && opts.quoteStyle !== 'double')) {
- throw new TypeError('option "quoteStyle" must be "single" or "double"');
- }
- if (
- has(opts, 'maxStringLength') && (typeof opts.maxStringLength === 'number'
- ? opts.maxStringLength < 0 && opts.maxStringLength !== Infinity
- : opts.maxStringLength !== null
- )
- ) {
- throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');
- }
- var customInspect = has(opts, 'customInspect') ? opts.customInspect : true;
- if (typeof customInspect !== 'boolean' && customInspect !== 'symbol') {
- throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`');
- }
+/***/ }),
- if (
- has(opts, 'indent')
- && opts.indent !== null
- && opts.indent !== '\t'
- && !(parseInt(opts.indent, 10) === opts.indent && opts.indent > 0)
- ) {
- throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`');
- }
- if (has(opts, 'numericSeparator') && typeof opts.numericSeparator !== 'boolean') {
- throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');
- }
- var numericSeparator = opts.numericSeparator;
+/***/ 2429:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
- if (typeof obj === 'undefined') {
- return 'undefined';
- }
- if (obj === null) {
- return 'null';
- }
- if (typeof obj === 'boolean') {
- return obj ? 'true' : 'false';
- }
- if (typeof obj === 'string') {
- return inspectString(obj, opts);
- }
- if (typeof obj === 'number') {
- if (obj === 0) {
- return Infinity / obj > 0 ? '0' : '-0';
- }
- var str = String(obj);
- return numericSeparator ? addNumericSeparator(obj, str) : str;
- }
- if (typeof obj === 'bigint') {
- var bigIntStr = String(obj) + 'n';
- return numericSeparator ? addNumericSeparator(obj, bigIntStr) : bigIntStr;
- }
- var maxDepth = typeof opts.depth === 'undefined' ? 5 : opts.depth;
- if (typeof depth === 'undefined') { depth = 0; }
- if (depth >= maxDepth && maxDepth > 0 && typeof obj === 'object') {
- return isArray(obj) ? '[Array]' : '[Object]';
- }
+const utils = __nccwpck_require__(479);
+const {
+ CHAR_ASTERISK, /* * */
+ CHAR_AT, /* @ */
+ CHAR_BACKWARD_SLASH, /* \ */
+ CHAR_COMMA, /* , */
+ CHAR_DOT, /* . */
+ CHAR_EXCLAMATION_MARK, /* ! */
+ CHAR_FORWARD_SLASH, /* / */
+ CHAR_LEFT_CURLY_BRACE, /* { */
+ CHAR_LEFT_PARENTHESES, /* ( */
+ CHAR_LEFT_SQUARE_BRACKET, /* [ */
+ CHAR_PLUS, /* + */
+ CHAR_QUESTION_MARK, /* ? */
+ CHAR_RIGHT_CURLY_BRACE, /* } */
+ CHAR_RIGHT_PARENTHESES, /* ) */
+ CHAR_RIGHT_SQUARE_BRACKET /* ] */
+} = __nccwpck_require__(6099);
- var indent = getIndent(opts, depth);
+const isPathSeparator = code => {
+ return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
+};
- if (typeof seen === 'undefined') {
- seen = [];
- } else if (indexOf(seen, obj) >= 0) {
- return '[Circular]';
- }
+const depth = token => {
+ if (token.isPrefix !== true) {
+ token.depth = token.isGlobstar ? Infinity : 1;
+ }
+};
- function inspect(value, from, noIndent) {
- if (from) {
- seen = $arrSlice.call(seen);
- seen.push(from);
- }
- if (noIndent) {
- var newOpts = {
- depth: opts.depth
- };
- if (has(opts, 'quoteStyle')) {
- newOpts.quoteStyle = opts.quoteStyle;
- }
- return inspect_(value, newOpts, depth + 1, seen);
- }
- return inspect_(value, opts, depth + 1, seen);
- }
+/**
+ * Quickly scans a glob pattern and returns an object with a handful of
+ * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists),
+ * `glob` (the actual pattern), `negated` (true if the path starts with `!` but not
+ * with `!(`) and `negatedExtglob` (true if the path starts with `!(`).
+ *
+ * ```js
+ * const pm = require('picomatch');
+ * console.log(pm.scan('foo/bar/*.js'));
+ * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' }
+ * ```
+ * @param {String} `str`
+ * @param {Object} `options`
+ * @return {Object} Returns an object with tokens and regex source string.
+ * @api public
+ */
- if (typeof obj === 'function' && !isRegExp(obj)) { // in older engines, regexes are callable
- var name = nameOf(obj);
- var keys = arrObjKeys(obj, inspect);
- return '[Function' + (name ? ': ' + name : ' (anonymous)') + ']' + (keys.length > 0 ? ' { ' + $join.call(keys, ', ') + ' }' : '');
- }
- if (isSymbol(obj)) {
- var symString = hasShammedSymbols ? $replace.call(String(obj), /^(Symbol\(.*\))_[^)]*$/, '$1') : symToString.call(obj);
- return typeof obj === 'object' && !hasShammedSymbols ? markBoxed(symString) : symString;
- }
- if (isElement(obj)) {
- var s = '<' + $toLowerCase.call(String(obj.nodeName));
- var attrs = obj.attributes || [];
- for (var i = 0; i < attrs.length; i++) {
- s += ' ' + attrs[i].name + '=' + wrapQuotes(quote(attrs[i].value), 'double', opts);
- }
- s += '>';
- if (obj.childNodes && obj.childNodes.length) { s += '...'; }
- s += '' + $toLowerCase.call(String(obj.nodeName)) + '>';
- return s;
- }
- if (isArray(obj)) {
- if (obj.length === 0) { return '[]'; }
- var xs = arrObjKeys(obj, inspect);
- if (indent && !singleLineValues(xs)) {
- return '[' + indentedJoin(xs, indent) + ']';
- }
- return '[ ' + $join.call(xs, ', ') + ' ]';
- }
- if (isError(obj)) {
- var parts = arrObjKeys(obj, inspect);
- if (!('cause' in Error.prototype) && 'cause' in obj && !isEnumerable.call(obj, 'cause')) {
- return '{ [' + String(obj) + '] ' + $join.call($concat.call('[cause]: ' + inspect(obj.cause), parts), ', ') + ' }';
- }
- if (parts.length === 0) { return '[' + String(obj) + ']'; }
- return '{ [' + String(obj) + '] ' + $join.call(parts, ', ') + ' }';
- }
- if (typeof obj === 'object' && customInspect) {
- if (inspectSymbol && typeof obj[inspectSymbol] === 'function' && utilInspect) {
- return utilInspect(obj, { depth: maxDepth - depth });
- } else if (customInspect !== 'symbol' && typeof obj.inspect === 'function') {
- return obj.inspect();
- }
- }
- if (isMap(obj)) {
- var mapParts = [];
- if (mapForEach) {
- mapForEach.call(obj, function (value, key) {
- mapParts.push(inspect(key, obj, true) + ' => ' + inspect(value, obj));
- });
- }
- return collectionOf('Map', mapSize.call(obj), mapParts, indent);
+const scan = (input, options) => {
+ const opts = options || {};
+
+ const length = input.length - 1;
+ const scanToEnd = opts.parts === true || opts.scanToEnd === true;
+ const slashes = [];
+ const tokens = [];
+ const parts = [];
+
+ let str = input;
+ let index = -1;
+ let start = 0;
+ let lastIndex = 0;
+ let isBrace = false;
+ let isBracket = false;
+ let isGlob = false;
+ let isExtglob = false;
+ let isGlobstar = false;
+ let braceEscaped = false;
+ let backslashes = false;
+ let negated = false;
+ let negatedExtglob = false;
+ let finished = false;
+ let braces = 0;
+ let prev;
+ let code;
+ let token = { value: '', depth: 0, isGlob: false };
+
+ const eos = () => index >= length;
+ const peek = () => str.charCodeAt(index + 1);
+ const advance = () => {
+ prev = code;
+ return str.charCodeAt(++index);
+ };
+
+ while (index < length) {
+ code = advance();
+ let next;
+
+ if (code === CHAR_BACKWARD_SLASH) {
+ backslashes = token.backslashes = true;
+ code = advance();
+
+ if (code === CHAR_LEFT_CURLY_BRACE) {
+ braceEscaped = true;
+ }
+ continue;
}
- if (isSet(obj)) {
- var setParts = [];
- if (setForEach) {
- setForEach.call(obj, function (value) {
- setParts.push(inspect(value, obj));
- });
+
+ if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) {
+ braces++;
+
+ while (eos() !== true && (code = advance())) {
+ if (code === CHAR_BACKWARD_SLASH) {
+ backslashes = token.backslashes = true;
+ advance();
+ continue;
}
- return collectionOf('Set', setSize.call(obj), setParts, indent);
- }
- if (isWeakMap(obj)) {
- return weakCollectionOf('WeakMap');
- }
- if (isWeakSet(obj)) {
- return weakCollectionOf('WeakSet');
- }
- if (isWeakRef(obj)) {
- return weakCollectionOf('WeakRef');
- }
- if (isNumber(obj)) {
- return markBoxed(inspect(Number(obj)));
- }
- if (isBigInt(obj)) {
- return markBoxed(inspect(bigIntValueOf.call(obj)));
- }
- if (isBoolean(obj)) {
- return markBoxed(booleanValueOf.call(obj));
- }
- if (isString(obj)) {
- return markBoxed(inspect(String(obj)));
- }
- if (!isDate(obj) && !isRegExp(obj)) {
- var ys = arrObjKeys(obj, inspect);
- var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
- var protoTag = obj instanceof Object ? '' : 'null prototype';
- var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? 'Object' : '';
- var constructorTag = isPlainObject || typeof obj.constructor !== 'function' ? '' : obj.constructor.name ? obj.constructor.name + ' ' : '';
- var tag = constructorTag + (stringTag || protoTag ? '[' + $join.call($concat.call([], stringTag || [], protoTag || []), ': ') + '] ' : '');
- if (ys.length === 0) { return tag + '{}'; }
- if (indent) {
- return tag + '{' + indentedJoin(ys, indent) + '}';
+
+ if (code === CHAR_LEFT_CURLY_BRACE) {
+ braces++;
+ continue;
}
- return tag + '{ ' + $join.call(ys, ', ') + ' }';
- }
- return String(obj);
-};
-function wrapQuotes(s, defaultStyle, opts) {
- var quoteChar = (opts.quoteStyle || defaultStyle) === 'double' ? '"' : "'";
- return quoteChar + s + quoteChar;
-}
+ if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) {
+ isBrace = token.isBrace = true;
+ isGlob = token.isGlob = true;
+ finished = true;
-function quote(s) {
- return $replace.call(String(s), /"/g, '"');
-}
+ if (scanToEnd === true) {
+ continue;
+ }
-function isArray(obj) { return toStr(obj) === '[object Array]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
-function isDate(obj) { return toStr(obj) === '[object Date]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
-function isRegExp(obj) { return toStr(obj) === '[object RegExp]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
-function isError(obj) { return toStr(obj) === '[object Error]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
-function isString(obj) { return toStr(obj) === '[object String]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
-function isNumber(obj) { return toStr(obj) === '[object Number]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
-function isBoolean(obj) { return toStr(obj) === '[object Boolean]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
+ break;
+ }
-// Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives
-function isSymbol(obj) {
- if (hasShammedSymbols) {
- return obj && typeof obj === 'object' && obj instanceof Symbol;
- }
- if (typeof obj === 'symbol') {
- return true;
- }
- if (!obj || typeof obj !== 'object' || !symToString) {
- return false;
- }
- try {
- symToString.call(obj);
- return true;
- } catch (e) {}
- return false;
-}
+ if (braceEscaped !== true && code === CHAR_COMMA) {
+ isBrace = token.isBrace = true;
+ isGlob = token.isGlob = true;
+ finished = true;
-function isBigInt(obj) {
- if (!obj || typeof obj !== 'object' || !bigIntValueOf) {
- return false;
- }
- try {
- bigIntValueOf.call(obj);
- return true;
- } catch (e) {}
- return false;
-}
+ if (scanToEnd === true) {
+ continue;
+ }
-var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; };
-function has(obj, key) {
- return hasOwn.call(obj, key);
-}
+ break;
+ }
-function toStr(obj) {
- return objectToString.call(obj);
-}
+ if (code === CHAR_RIGHT_CURLY_BRACE) {
+ braces--;
-function nameOf(f) {
- if (f.name) { return f.name; }
- var m = $match.call(functionToString.call(f), /^function\s*([\w$]+)/);
- if (m) { return m[1]; }
- return null;
-}
+ if (braces === 0) {
+ braceEscaped = false;
+ isBrace = token.isBrace = true;
+ finished = true;
+ break;
+ }
+ }
+ }
-function indexOf(xs, x) {
- if (xs.indexOf) { return xs.indexOf(x); }
- for (var i = 0, l = xs.length; i < l; i++) {
- if (xs[i] === x) { return i; }
+ if (scanToEnd === true) {
+ continue;
+ }
+
+ break;
}
- return -1;
-}
-function isMap(x) {
- if (!mapSize || !x || typeof x !== 'object') {
- return false;
+ if (code === CHAR_FORWARD_SLASH) {
+ slashes.push(index);
+ tokens.push(token);
+ token = { value: '', depth: 0, isGlob: false };
+
+ if (finished === true) continue;
+ if (prev === CHAR_DOT && index === (start + 1)) {
+ start += 2;
+ continue;
+ }
+
+ lastIndex = index + 1;
+ continue;
}
- try {
- mapSize.call(x);
- try {
- setSize.call(x);
- } catch (s) {
- return true;
+
+ if (opts.noext !== true) {
+ const isExtglobChar = code === CHAR_PLUS
+ || code === CHAR_AT
+ || code === CHAR_ASTERISK
+ || code === CHAR_QUESTION_MARK
+ || code === CHAR_EXCLAMATION_MARK;
+
+ if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) {
+ isGlob = token.isGlob = true;
+ isExtglob = token.isExtglob = true;
+ finished = true;
+ if (code === CHAR_EXCLAMATION_MARK && index === start) {
+ negatedExtglob = true;
}
- return x instanceof Map; // core-js workaround, pre-v2.5.0
- } catch (e) {}
- return false;
-}
-function isWeakMap(x) {
- if (!weakMapHas || !x || typeof x !== 'object') {
- return false;
- }
- try {
- weakMapHas.call(x, weakMapHas);
- try {
- weakSetHas.call(x, weakSetHas);
- } catch (s) {
- return true;
+ if (scanToEnd === true) {
+ while (eos() !== true && (code = advance())) {
+ if (code === CHAR_BACKWARD_SLASH) {
+ backslashes = token.backslashes = true;
+ code = advance();
+ continue;
+ }
+
+ if (code === CHAR_RIGHT_PARENTHESES) {
+ isGlob = token.isGlob = true;
+ finished = true;
+ break;
+ }
+ }
+ continue;
}
- return x instanceof WeakMap; // core-js workaround, pre-v2.5.0
- } catch (e) {}
- return false;
-}
+ break;
+ }
+ }
-function isWeakRef(x) {
- if (!weakRefDeref || !x || typeof x !== 'object') {
- return false;
+ if (code === CHAR_ASTERISK) {
+ if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true;
+ isGlob = token.isGlob = true;
+ finished = true;
+
+ if (scanToEnd === true) {
+ continue;
+ }
+ break;
}
- try {
- weakRefDeref.call(x);
- return true;
- } catch (e) {}
- return false;
-}
-function isSet(x) {
- if (!setSize || !x || typeof x !== 'object') {
- return false;
+ if (code === CHAR_QUESTION_MARK) {
+ isGlob = token.isGlob = true;
+ finished = true;
+
+ if (scanToEnd === true) {
+ continue;
+ }
+ break;
}
- try {
- setSize.call(x);
- try {
- mapSize.call(x);
- } catch (m) {
- return true;
+
+ if (code === CHAR_LEFT_SQUARE_BRACKET) {
+ while (eos() !== true && (next = advance())) {
+ if (next === CHAR_BACKWARD_SLASH) {
+ backslashes = token.backslashes = true;
+ advance();
+ continue;
}
- return x instanceof Set; // core-js workaround, pre-v2.5.0
- } catch (e) {}
- return false;
-}
-function isWeakSet(x) {
- if (!weakSetHas || !x || typeof x !== 'object') {
- return false;
- }
- try {
- weakSetHas.call(x, weakSetHas);
- try {
- weakMapHas.call(x, weakMapHas);
- } catch (s) {
- return true;
+ if (next === CHAR_RIGHT_SQUARE_BRACKET) {
+ isBracket = token.isBracket = true;
+ isGlob = token.isGlob = true;
+ finished = true;
+ break;
}
- return x instanceof WeakSet; // core-js workaround, pre-v2.5.0
- } catch (e) {}
- return false;
-}
+ }
-function isElement(x) {
- if (!x || typeof x !== 'object') { return false; }
- if (typeof HTMLElement !== 'undefined' && x instanceof HTMLElement) {
- return true;
+ if (scanToEnd === true) {
+ continue;
+ }
+
+ break;
}
- return typeof x.nodeName === 'string' && typeof x.getAttribute === 'function';
-}
-function inspectString(str, opts) {
- if (str.length > opts.maxStringLength) {
- var remaining = str.length - opts.maxStringLength;
- var trailer = '... ' + remaining + ' more character' + (remaining > 1 ? 's' : '');
- return inspectString($slice.call(str, 0, opts.maxStringLength), opts) + trailer;
+ if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) {
+ negated = token.negated = true;
+ start++;
+ continue;
}
- // eslint-disable-next-line no-control-regex
- var s = $replace.call($replace.call(str, /(['\\])/g, '\\$1'), /[\x00-\x1f]/g, lowbyte);
- return wrapQuotes(s, 'single', opts);
-}
-function lowbyte(c) {
- var n = c.charCodeAt(0);
- var x = {
- 8: 'b',
- 9: 't',
- 10: 'n',
- 12: 'f',
- 13: 'r'
- }[n];
- if (x) { return '\\' + x; }
- return '\\x' + (n < 0x10 ? '0' : '') + $toUpperCase.call(n.toString(16));
-}
+ if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) {
+ isGlob = token.isGlob = true;
-function markBoxed(str) {
- return 'Object(' + str + ')';
-}
+ if (scanToEnd === true) {
+ while (eos() !== true && (code = advance())) {
+ if (code === CHAR_LEFT_PARENTHESES) {
+ backslashes = token.backslashes = true;
+ code = advance();
+ continue;
+ }
-function weakCollectionOf(type) {
- return type + ' { ? }';
-}
+ if (code === CHAR_RIGHT_PARENTHESES) {
+ finished = true;
+ break;
+ }
+ }
+ continue;
+ }
+ break;
+ }
-function collectionOf(type, size, entries, indent) {
- var joinedEntries = indent ? indentedJoin(entries, indent) : $join.call(entries, ', ');
- return type + ' (' + size + ') {' + joinedEntries + '}';
-}
+ if (isGlob === true) {
+ finished = true;
-function singleLineValues(xs) {
- for (var i = 0; i < xs.length; i++) {
- if (indexOf(xs[i], '\n') >= 0) {
- return false;
- }
+ if (scanToEnd === true) {
+ continue;
+ }
+
+ break;
}
- return true;
-}
+ }
-function getIndent(opts, depth) {
- var baseIndent;
- if (opts.indent === '\t') {
- baseIndent = '\t';
- } else if (typeof opts.indent === 'number' && opts.indent > 0) {
- baseIndent = $join.call(Array(opts.indent + 1), ' ');
- } else {
- return null;
+ if (opts.noext === true) {
+ isExtglob = false;
+ isGlob = false;
+ }
+
+ let base = str;
+ let prefix = '';
+ let glob = '';
+
+ if (start > 0) {
+ prefix = str.slice(0, start);
+ str = str.slice(start);
+ lastIndex -= start;
+ }
+
+ if (base && isGlob === true && lastIndex > 0) {
+ base = str.slice(0, lastIndex);
+ glob = str.slice(lastIndex);
+ } else if (isGlob === true) {
+ base = '';
+ glob = str;
+ } else {
+ base = str;
+ }
+
+ if (base && base !== '' && base !== '/' && base !== str) {
+ if (isPathSeparator(base.charCodeAt(base.length - 1))) {
+ base = base.slice(0, -1);
}
- return {
- base: baseIndent,
- prev: $join.call(Array(depth + 1), baseIndent)
- };
-}
+ }
-function indentedJoin(xs, indent) {
- if (xs.length === 0) { return ''; }
- var lineJoiner = '\n' + indent.prev + indent.base;
- return lineJoiner + $join.call(xs, ',' + lineJoiner) + '\n' + indent.prev;
-}
+ if (opts.unescape === true) {
+ if (glob) glob = utils.removeBackslashes(glob);
-function arrObjKeys(obj, inspect) {
- var isArr = isArray(obj);
- var xs = [];
- if (isArr) {
- xs.length = obj.length;
- for (var i = 0; i < obj.length; i++) {
- xs[i] = has(obj, i) ? inspect(obj[i], obj) : '';
- }
+ if (base && backslashes === true) {
+ base = utils.removeBackslashes(base);
}
- var syms = typeof gOPS === 'function' ? gOPS(obj) : [];
- var symMap;
- if (hasShammedSymbols) {
- symMap = {};
- for (var k = 0; k < syms.length; k++) {
- symMap['$' + syms[k]] = syms[k];
- }
+ }
+
+ const state = {
+ prefix,
+ input,
+ start,
+ base,
+ glob,
+ isBrace,
+ isBracket,
+ isGlob,
+ isExtglob,
+ isGlobstar,
+ negated,
+ negatedExtglob
+ };
+
+ if (opts.tokens === true) {
+ state.maxDepth = 0;
+ if (!isPathSeparator(code)) {
+ tokens.push(token);
}
+ state.tokens = tokens;
+ }
- for (var key in obj) { // eslint-disable-line no-restricted-syntax
- if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
- if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
- if (hasShammedSymbols && symMap['$' + key] instanceof Symbol) {
- // this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section
- continue; // eslint-disable-line no-restricted-syntax, no-continue
- } else if ($test.call(/[^\w$]/, key)) {
- xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj));
+ if (opts.parts === true || opts.tokens === true) {
+ let prevIndex;
+
+ for (let idx = 0; idx < slashes.length; idx++) {
+ const n = prevIndex ? prevIndex + 1 : start;
+ const i = slashes[idx];
+ const value = input.slice(n, i);
+ if (opts.tokens) {
+ if (idx === 0 && start !== 0) {
+ tokens[idx].isPrefix = true;
+ tokens[idx].value = prefix;
} else {
- xs.push(key + ': ' + inspect(obj[key], obj));
- }
- }
- if (typeof gOPS === 'function') {
- for (var j = 0; j < syms.length; j++) {
- if (isEnumerable.call(obj, syms[j])) {
- xs.push('[' + inspect(syms[j]) + ']: ' + inspect(obj[syms[j]], obj));
- }
+ tokens[idx].value = value;
}
+ depth(tokens[idx]);
+ state.maxDepth += tokens[idx].depth;
+ }
+ if (idx !== 0 || value !== '') {
+ parts.push(value);
+ }
+ prevIndex = i;
}
- return xs;
-}
+ if (prevIndex && prevIndex + 1 < input.length) {
+ const value = input.slice(prevIndex + 1);
+ parts.push(value);
-/***/ }),
+ if (opts.tokens) {
+ tokens[tokens.length - 1].value = value;
+ depth(tokens[tokens.length - 1]);
+ state.maxDepth += tokens[tokens.length - 1].depth;
+ }
+ }
-/***/ 7265:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+ state.slashes = slashes;
+ state.parts = parts;
+ }
-module.exports = __nccwpck_require__(3837).inspect;
+ return state;
+};
+
+module.exports = scan;
/***/ }),
-/***/ 1223:
-/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+/***/ 479:
+/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
-var wrappy = __nccwpck_require__(2940)
-module.exports = wrappy(once)
-module.exports.strict = wrappy(onceStrict)
-once.proto = once(function () {
- Object.defineProperty(Function.prototype, 'once', {
- value: function () {
- return once(this)
- },
- configurable: true
- })
- Object.defineProperty(Function.prototype, 'onceStrict', {
- value: function () {
- return onceStrict(this)
- },
- configurable: true
- })
-})
+const path = __nccwpck_require__(1017);
+const win32 = process.platform === 'win32';
+const {
+ REGEX_BACKSLASH,
+ REGEX_REMOVE_BACKSLASH,
+ REGEX_SPECIAL_CHARS,
+ REGEX_SPECIAL_CHARS_GLOBAL
+} = __nccwpck_require__(6099);
+
+exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
+exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str);
+exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str);
+exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1');
+exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/');
+
+exports.removeBackslashes = str => {
+ return str.replace(REGEX_REMOVE_BACKSLASH, match => {
+ return match === '\\' ? '' : match;
+ });
+};
-function once (fn) {
- var f = function () {
- if (f.called) return f.value
- f.called = true
- return f.value = fn.apply(this, arguments)
+exports.supportsLookbehinds = () => {
+ const segs = process.version.slice(1).split('.').map(Number);
+ if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) {
+ return true;
+ }
+ return false;
+};
+
+exports.isWindows = options => {
+ if (options && typeof options.windows === 'boolean') {
+ return options.windows;
+ }
+ return win32 === true || path.sep === '\\';
+};
+
+exports.escapeLast = (input, char, lastIdx) => {
+ const idx = input.lastIndexOf(char, lastIdx);
+ if (idx === -1) return input;
+ if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1);
+ return `${input.slice(0, idx)}\\${input.slice(idx)}`;
+};
+
+exports.removePrefix = (input, state = {}) => {
+ let output = input;
+ if (output.startsWith('./')) {
+ output = output.slice(2);
+ state.prefix = './';
}
- f.called = false
- return f
-}
+ return output;
+};
-function onceStrict (fn) {
- var f = function () {
- if (f.called)
- throw new Error(f.onceError)
- f.called = true
- return f.value = fn.apply(this, arguments)
+exports.wrapOutput = (input, state = {}, options = {}) => {
+ const prepend = options.contains ? '' : '^';
+ const append = options.contains ? '' : '$';
+
+ let output = `${prepend}(?:${input})${append}`;
+ if (state.negated === true) {
+ output = `(?:^(?!${output}).*$)`;
}
- var name = fn.name || 'Function wrapped with `once`'
- f.onceError = name + " shouldn't be called more than once"
- f.called = false
- return f
-}
+ return output;
+};
/***/ }),
@@ -9409,6 +13372,301 @@ module.exports = function getSideChannel() {
};
+/***/ }),
+
+/***/ 1861:
+/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
+
+/*!
+ * to-regex-range
+ *
+ * Copyright (c) 2015-present, Jon Schlinkert.
+ * Released under the MIT License.
+ */
+
+
+
+const isNumber = __nccwpck_require__(5680);
+
+const toRegexRange = (min, max, options) => {
+ if (isNumber(min) === false) {
+ throw new TypeError('toRegexRange: expected the first argument to be a number');
+ }
+
+ if (max === void 0 || min === max) {
+ return String(min);
+ }
+
+ if (isNumber(max) === false) {
+ throw new TypeError('toRegexRange: expected the second argument to be a number.');
+ }
+
+ let opts = { relaxZeros: true, ...options };
+ if (typeof opts.strictZeros === 'boolean') {
+ opts.relaxZeros = opts.strictZeros === false;
+ }
+
+ let relax = String(opts.relaxZeros);
+ let shorthand = String(opts.shorthand);
+ let capture = String(opts.capture);
+ let wrap = String(opts.wrap);
+ let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap;
+
+ if (toRegexRange.cache.hasOwnProperty(cacheKey)) {
+ return toRegexRange.cache[cacheKey].result;
+ }
+
+ let a = Math.min(min, max);
+ let b = Math.max(min, max);
+
+ if (Math.abs(a - b) === 1) {
+ let result = min + '|' + max;
+ if (opts.capture) {
+ return `(${result})`;
+ }
+ if (opts.wrap === false) {
+ return result;
+ }
+ return `(?:${result})`;
+ }
+
+ let isPadded = hasPadding(min) || hasPadding(max);
+ let state = { min, max, a, b };
+ let positives = [];
+ let negatives = [];
+
+ if (isPadded) {
+ state.isPadded = isPadded;
+ state.maxLen = String(state.max).length;
+ }
+
+ if (a < 0) {
+ let newMin = b < 0 ? Math.abs(b) : 1;
+ negatives = splitToPatterns(newMin, Math.abs(a), state, opts);
+ a = state.a = 0;
+ }
+
+ if (b >= 0) {
+ positives = splitToPatterns(a, b, state, opts);
+ }
+
+ state.negatives = negatives;
+ state.positives = positives;
+ state.result = collatePatterns(negatives, positives, opts);
+
+ if (opts.capture === true) {
+ state.result = `(${state.result})`;
+ } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) {
+ state.result = `(?:${state.result})`;
+ }
+
+ toRegexRange.cache[cacheKey] = state;
+ return state.result;
+};
+
+function collatePatterns(neg, pos, options) {
+ let onlyNegative = filterPatterns(neg, pos, '-', false, options) || [];
+ let onlyPositive = filterPatterns(pos, neg, '', false, options) || [];
+ let intersected = filterPatterns(neg, pos, '-?', true, options) || [];
+ let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive);
+ return subpatterns.join('|');
+}
+
+function splitToRanges(min, max) {
+ let nines = 1;
+ let zeros = 1;
+
+ let stop = countNines(min, nines);
+ let stops = new Set([max]);
+
+ while (min <= stop && stop <= max) {
+ stops.add(stop);
+ nines += 1;
+ stop = countNines(min, nines);
+ }
+
+ stop = countZeros(max + 1, zeros) - 1;
+
+ while (min < stop && stop <= max) {
+ stops.add(stop);
+ zeros += 1;
+ stop = countZeros(max + 1, zeros) - 1;
+ }
+
+ stops = [...stops];
+ stops.sort(compare);
+ return stops;
+}
+
+/**
+ * Convert a range to a regex pattern
+ * @param {Number} `start`
+ * @param {Number} `stop`
+ * @return {String}
+ */
+
+function rangeToPattern(start, stop, options) {
+ if (start === stop) {
+ return { pattern: start, count: [], digits: 0 };
+ }
+
+ let zipped = zip(start, stop);
+ let digits = zipped.length;
+ let pattern = '';
+ let count = 0;
+
+ for (let i = 0; i < digits; i++) {
+ let [startDigit, stopDigit] = zipped[i];
+
+ if (startDigit === stopDigit) {
+ pattern += startDigit;
+
+ } else if (startDigit !== '0' || stopDigit !== '9') {
+ pattern += toCharacterClass(startDigit, stopDigit, options);
+
+ } else {
+ count++;
+ }
+ }
+
+ if (count) {
+ pattern += options.shorthand === true ? '\\d' : '[0-9]';
+ }
+
+ return { pattern, count: [count], digits };
+}
+
+function splitToPatterns(min, max, tok, options) {
+ let ranges = splitToRanges(min, max);
+ let tokens = [];
+ let start = min;
+ let prev;
+
+ for (let i = 0; i < ranges.length; i++) {
+ let max = ranges[i];
+ let obj = rangeToPattern(String(start), String(max), options);
+ let zeros = '';
+
+ if (!tok.isPadded && prev && prev.pattern === obj.pattern) {
+ if (prev.count.length > 1) {
+ prev.count.pop();
+ }
+
+ prev.count.push(obj.count[0]);
+ prev.string = prev.pattern + toQuantifier(prev.count);
+ start = max + 1;
+ continue;
+ }
+
+ if (tok.isPadded) {
+ zeros = padZeros(max, tok, options);
+ }
+
+ obj.string = zeros + obj.pattern + toQuantifier(obj.count);
+ tokens.push(obj);
+ start = max + 1;
+ prev = obj;
+ }
+
+ return tokens;
+}
+
+function filterPatterns(arr, comparison, prefix, intersection, options) {
+ let result = [];
+
+ for (let ele of arr) {
+ let { string } = ele;
+
+ // only push if _both_ are negative...
+ if (!intersection && !contains(comparison, 'string', string)) {
+ result.push(prefix + string);
+ }
+
+ // or _both_ are positive
+ if (intersection && contains(comparison, 'string', string)) {
+ result.push(prefix + string);
+ }
+ }
+ return result;
+}
+
+/**
+ * Zip strings
+ */
+
+function zip(a, b) {
+ let arr = [];
+ for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]);
+ return arr;
+}
+
+function compare(a, b) {
+ return a > b ? 1 : b > a ? -1 : 0;
+}
+
+function contains(arr, key, val) {
+ return arr.some(ele => ele[key] === val);
+}
+
+function countNines(min, len) {
+ return Number(String(min).slice(0, -len) + '9'.repeat(len));
+}
+
+function countZeros(integer, zeros) {
+ return integer - (integer % Math.pow(10, zeros));
+}
+
+function toQuantifier(digits) {
+ let [start = 0, stop = ''] = digits;
+ if (stop || start > 1) {
+ return `{${start + (stop ? ',' + stop : '')}}`;
+ }
+ return '';
+}
+
+function toCharacterClass(a, b, options) {
+ return `[${a}${(b - a === 1) ? '' : '-'}${b}]`;
+}
+
+function hasPadding(str) {
+ return /^-?(0+)\d/.test(str);
+}
+
+function padZeros(value, tok, options) {
+ if (!tok.isPadded) {
+ return value;
+ }
+
+ let diff = Math.abs(tok.maxLen - String(value).length);
+ let relax = options.relaxZeros !== false;
+
+ switch (diff) {
+ case 0:
+ return '';
+ case 1:
+ return relax ? '0?' : '0';
+ case 2:
+ return relax ? '0{0,2}' : '00';
+ default: {
+ return relax ? `0{0,${diff}}` : `0{${diff}}`;
+ }
+ }
+}
+
+/**
+ * Cache
+ */
+
+toRegexRange.cache = {};
+toRegexRange.clearCache = () => (toRegexRange.cache = {});
+
+/**
+ * Expose `toRegexRange`
+ */
+
+module.exports = toRegexRange;
+
+
/***/ }),
/***/ 4256:
@@ -17952,6 +22210,7 @@ __nccwpck_require__.d(core_dist_namespaceObject, {
"Avatar": () => (Avatar),
"Branches": () => (Branches),
"BroadcastMessages": () => (BroadcastMessages),
+ "CodeSuggestions": () => (CodeSuggestions),
"CommitDiscussions": () => (CommitDiscussions),
"Commits": () => (Commits),
"Composer": () => (Composer),
@@ -17981,6 +22240,7 @@ __nccwpck_require__.d(core_dist_namespaceObject, {
"FeatureFlags": () => (FeatureFlags),
"FreezePeriods": () => (FreezePeriods),
"GeoNodes": () => (GeoNodes),
+ "GeoSites": () => (GeoSites),
"GitLabCIYMLTemplates": () => (GitLabCIYMLTemplates),
"GitignoreTemplates": () => (GitignoreTemplates),
"Gitlab": () => (Gitlab),
@@ -17992,6 +22252,7 @@ __nccwpck_require__.d(core_dist_namespaceObject, {
"GroupBadges": () => (GroupBadges),
"GroupCustomAttributes": () => (GroupCustomAttributes),
"GroupDORA4Metrics": () => (GroupDORA4Metrics),
+ "GroupEpicBoards": () => (GroupEpicBoards),
"GroupHooks": () => (GroupHooks),
"GroupImportExports": () => (GroupImportExports),
"GroupInvitations": () => (GroupInvitations),
@@ -18008,6 +22269,7 @@ __nccwpck_require__.d(core_dist_namespaceObject, {
"GroupReleases": () => (GroupReleases),
"GroupRepositoryStorageMoves": () => (GroupRepositoryStorageMoves),
"GroupSAMLIdentities": () => (GroupSAMLIdentities),
+ "GroupSAMLLinks": () => (GroupSAMLLinks),
"GroupSCIMIdentities": () => (GroupSCIMIdentities),
"GroupVariables": () => (GroupVariables),
"GroupWikis": () => (GroupWikis),
@@ -18104,6 +22366,7 @@ __nccwpck_require__.d(core_dist_namespaceObject, {
"RubyGems": () => (RubyGems),
"Runners": () => (Runners),
"Search": () => (Search),
+ "SearchAdmin": () => (SearchAdmin),
"SecureFiles": () => (SecureFiles),
"ServiceData": () => (ServiceData),
"SidekiqMetrics": () => (SidekiqMetrics),
@@ -18124,17 +22387,83 @@ __nccwpck_require__.d(core_dist_namespaceObject, {
"Users": () => (Users)
});
-// EXTERNAL MODULE: ./node_modules/dotenv/lib/main.js
-var main = __nccwpck_require__(2437);
+;// CONCATENATED MODULE: ./adapters/logger/logger.js
+// logger.js
+
+function getCurrentTimestamp() {
+ const now = new Date();
+ return now.toISOString();
+}
+
+function logInfo(message, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "ERROR",
+ timestamp,
+ method,
+ message,
+ };
+ console.error(logEntry);
+}
+
+function withInfo(message, vcs, sha, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "INFO",
+ timestamp,
+ vcs,
+ sha,
+ method,
+ message,
+ };
+ console.log(logEntry);
+}
+
+function withError(message, vcs, sha, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "ERROR",
+ timestamp,
+ vcs,
+ sha,
+ method,
+ message,
+ };
+ console.error(logEntry);
+}
+
+function debug(message, vcs, sha, method) {
+ const timestamp = getCurrentTimestamp();
+ const logEntry = {
+ level: "DEBUG",
+ timestamp,
+ vcs,
+ sha,
+ method,
+ message,
+ };
+ console.debug(logEntry);
+}
+
+const logger = {
+ withInfo,
+ withError,
+ debug,
+ logInfo,
+};
+
+/* harmony default export */ const logger_logger = (logger);
+
;// CONCATENATED MODULE: ./adapters/gateway.js
// Common Gateway for all integrations
+
async function runAction(token, integrationModule) {
if (token === undefined) {
- console.log("Token not provided.");
+ logger_logger.logInfo("Token not provided.", "runAction");
return;
}
const integration = new integrationModule(token);
- await integration.run(); // Add error part
+ await integration.run();
}
;// CONCATENATED MODULE: ./adapters/integrations/contract/contract.js
@@ -18195,62 +22524,29 @@ class IntegrationInterface {
// EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js
var github = __nccwpck_require__(5438);
-// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js
-var core = __nccwpck_require__(2186);
-;// CONCATENATED MODULE: ./src/utils/get-environment-variables.js
-
-
-
-main.config();
-
-const {
- IS_DEV,
- ATLAN_INSTANCE_URL,
- ATLAN_API_TOKEN,
- IGNORE_MODEL_ALIAS_MATCHING,
-} = process.env;
-
-const isDev = () => IS_DEV === "true";
-const getInstanceUrl = () => {
- if (ATLAN_INSTANCE_URL) return new URL(ATLAN_INSTANCE_URL).origin;
- return new URL(core.getInput("ATLAN_INSTANCE_URL")).origin;
-};
-const getAPIToken = () => {
- if (ATLAN_API_TOKEN) return ATLAN_API_TOKEN;
- return core.getInput("ATLAN_API_TOKEN");
-};
-const getEnvironments = () => {
- return core.getInput("DBT_ENVIRONMENT_BRANCH_MAP")
- ? core.getInput("DBT_ENVIRONMENT_BRANCH_MAP")
- .trim()
- ?.split("\n")
- ?.map((i) => i.split(":").map((i) => i.trim()))
- : [];
-};
-const isIgnoreModelAliasMatching = () =>
- core.getInput("IGNORE_MODEL_ALIAS_MATCHING") === "true";
+// EXTERNAL MODULE: ./node_modules/json-stringify-safe/stringify.js
+var stringify = __nccwpck_require__(7073);
+;// CONCATENATED MODULE: ./adapters/utils/get-image-url.js
-function getGitLabEnvironments() {
- const { DBT_ENVIRONMENT_BRANCH_MAP } = process.env;
- if (DBT_ENVIRONMENT_BRANCH_MAP) {
- const environmentLines = DBT_ENVIRONMENT_BRANCH_MAP.split("\n");
- const environmentMap = {};
+function getImageURL(name, height = 20, width = 20) {
+ try {
+ return ``;
+ } catch (e) {
+ console.log(name);
+ return '';
+ }
+}
- environmentLines.forEach((line) => {
- const [environment, branch] = line.split(":").map((item) => item.trim());
- if (environment && branch) {
- environmentMap[environment] = branch;
- }
- });
+function getConnectorImage(connectorName) {
+ return getImageURL(`connector-${connectorName.toLowerCase()}`, 15, 15);
+}
- return environmentMap;
- } else {
- return {};
- }
+function getCertificationImage(certificationStatus) {
+ return getImageURL(`certification-${certificationStatus.toLowerCase()}`, 15, 15);
}
-;// CONCATENATED MODULE: ./src/utils/hosted-images.js
+;// CONCATENATED MODULE: ./adapters/utils/hosted-images.js
/* harmony default export */ const hosted_images = ({
"atlan-logo": {
alt: "Atlan Logo",
@@ -18373,197 +22669,24 @@ function getGitLabEnvironments() {
url: "https://assets.atlan.com/assets/tableau.svg",
},
"connector-mode": {
- alt: "Connector Mode",
- url: "https://iili.io/HVTAlgs.png"
- },
- "connector-sigma": {
- alt: "Connector Sigma",
- url: "https://iili.io/HVTA1dG.png"
- }
-});
-
-;// CONCATENATED MODULE: ./src/utils/create-comment.js
-
-
-
-const create_comment_IS_DEV = isDev();
-const create_comment_ATLAN_INSTANCE_URL =
- getInstanceUrl();
-
-function truncate(value) {
- if (typeof value === 'string')
- return value.length > 100 ? value.substring(0, 100) + "..." : value;
- if (Array.isArray(value))
- return value.length > 10 ? value.slice(0, 10).join(", ") + "..." : value.join(", ");
- return ""
-}
-
-async function renderDownstreamAssetsComment(
- octokit,
- context,
- asset,
- materialisedAsset,
- downstreamAssets,
- classifications
-) {
- // Mapping the downstream assets data
- let impactedData = downstreamAssets.entities.map(
- ({
- displayText,
- guid,
- typeName,
- attributes,
- meanings,
- classificationNames
- }) => {
- // Modifying the typeName and getting the readableTypeName
- let readableTypeName = typeName
- .toLowerCase()
- .replace(attributes.connectorName, "")
- .toUpperCase();
-
- // Filtering classifications based on classificationNames
- let classificationsObj = classifications.filter(({name}) =>
- classificationNames.includes(name)
- );
-
- // Modifying the readableTypeName
- readableTypeName = readableTypeName.charAt(0).toUpperCase() + readableTypeName.slice(1).toLowerCase();
-
- return [
- guid,
- truncate(displayText),
- truncate(attributes.connectorName),
- truncate(readableTypeName),
- truncate(attributes?.userDescription || attributes?.description || ""),
- attributes?.certificateStatus || "",
- truncate([...attributes?.ownerUsers, ...attributes?.ownerGroups] || []),
- truncate(meanings.map(({displayText, termGuid}) =>
- `[${displayText}](${create_comment_ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_github_action)`
- )),
- truncate(classificationsObj?.map(({name, displayName}) =>
- `\`${displayName}\``
- )),
- attributes?.sourceURL || ""
- ];
- }
- );
-
- // Sorting the impactedData first by typeName and then by connectorName
- impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
- impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
-
- // Creating rows for the downstream table
- let rows = impactedData.map(
- ([guid, displayText, connectorName, typeName, description, certificateStatus, owners, meanings, classifications, sourceUrl]) => {
- // Getting connector and certification images
- const connectorImage = getConnectorImage(connectorName);
- const certificationImage = certificateStatus ? getCertificationImage(certificateStatus) : "";
-
- return [
- `${connectorImage} [${displayText}](${create_comment_ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_github_action) ${certificationImage}`,
- `\`${typeName}\``,
- description,
- owners,
- meanings,
- classifications,
- sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " "
- ];
- }
- );
-
- const environmentName = materialisedAsset?.attributes?.assetDbtEnvironmentName
- const projectName = materialisedAsset?.attributes?.assetDbtProjectName
- // Generating asset information
- const assetInfo = `### ${getConnectorImage(asset.attributes.connectorName)} [${
- asset.displayText
- }](${create_comment_ATLAN_INSTANCE_URL}/assets/${asset.guid}/overview?utm_source=dbt_github_action) ${
- asset.attributes?.certificateStatus
- ? getCertificationImage(asset.attributes.certificateStatus)
- : ""
- }
-Materialised asset: ${getConnectorImage(materialisedAsset.attributes.connectorName)} [${
- materialisedAsset.attributes.name
- }](${create_comment_ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/overview?utm_source=dbt_github_action) ${
- materialisedAsset.attributes?.certificateStatus
- ? getCertificationImage(materialisedAsset.attributes.certificateStatus)
- : ""
- }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ''}${projectName ? ` | Project Name: \`${projectName}\`` : ''}`;
-
- // Generating the downstream table
- const downstreamTable = `${downstreamAssets.entityCount} downstream assets 👇
-
-Name | Type | Description | Owners | Terms | Classifications | Source URL
---- | --- | --- | --- | --- | --- | ---
-${rows.map((row) => row.map(i => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")).join("\n")}
-
-${downstreamAssets.hasMore ? `[See more downstream assets at Atlan](${create_comment_ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_github_action)` : ""}
-
- `;
-
- // Generating the "View asset in Atlan" button
- const viewAssetButton = `${getImageURL("atlan-logo", 15, 15)} [View asset in Atlan](${create_comment_ATLAN_INSTANCE_URL}/assets/${asset.guid}/overview?utm_source=dbt_github_action)`;
-
- // Generating the final comment based on the presence of downstream assets
- if (downstreamAssets.entities.length > 0) {
- return `${assetInfo}
-
-${downstreamTable}
-
-${viewAssetButton}`;
- } else {
- return `${assetInfo}
-
-No downstream assets found.
-
-${viewAssetButton}`;
+ alt: "Connector Mode",
+ url: "https://iili.io/HVTAlgs.png"
+ },
+ "connector-sigma": {
+ alt: "Connector Sigma",
+ url: "https://iili.io/HVTA1dG.png"
}
-}
-
-
-async function checkCommentExists(octokit, context) {
- if (create_comment_IS_DEV) return null;
-
- const {pull_request} = context.payload;
-
- const comments = await octokit.rest.issues.listComments({
- ...context.repo,
- issue_number: pull_request.number,
- });
-
- return comments.data.find(
- (comment) => comment.user.login === "github-actions[bot]" && comment.body.includes("")
- );
-}
-
-async function createIssueComment(octokit, context, content, comment_id = null, forceNewComment = false) {
- const {pull_request} = context.payload;
-
- content = `
-${content}`
-
- const commentObj = {
- ...context.repo,
- issue_number: pull_request.number,
- body: content,
- };
-
- console.log(content, content.length)
-
- if (create_comment_IS_DEV) return content;
-
- if (comment_id && !forceNewComment) return octokit.rest.issues.updateComment({...commentObj, comment_id});
- return octokit.rest.issues.createComment(commentObj);
-}
-
-async function deleteComment(octokit, context, comment_id) {
- const {pull_request} = context.payload;
+});
- return octokit.rest.issues.deleteComment({
- ...context.repo,
- issue_number: pull_request.number,
- comment_id,
- });
+;// CONCATENATED MODULE: ./adapters/utils/create-comment.js
+function truncate(value) {
+ if (typeof value === "string")
+ return value.length > 100 ? value.substring(0, 100) + "..." : value;
+ if (Array.isArray(value))
+ return value.length > 10
+ ? value.slice(0, 10).join(", ") + "..."
+ : value.join(", ");
+ return "";
}
;// CONCATENATED MODULE: external "node:http"
@@ -20715,23 +24838,102 @@ function fixResponseChunkedTransferBadEnding(request, errorCallback) {
});
}
-;// CONCATENATED MODULE: ./src/utils/auth.js
+// EXTERNAL MODULE: ./node_modules/dotenv/lib/main.js
+var main = __nccwpck_require__(2437);
+// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js
+var core = __nccwpck_require__(2186);
+;// CONCATENATED MODULE: ./adapters/utils/get-environment-variables.js
+
+
+main.config();
+//Common env variables
+const ATLAN_INSTANCE_URL = new URL(
+ process.env.ATLAN_INSTANCE_URL || core.getInput("ATLAN_INSTANCE_URL")
+).origin;
+const ATLAN_API_TOKEN =
+ process.env.ATLAN_API_TOKEN || core.getInput("ATLAN_API_TOKEN");
+const IS_DEV = process.env.IS_DEV;
+
+const IGNORE_MODEL_ALIAS_MATCHING =
+ (process.env.IGNORE_MODEL_ALIAS_MATCHING ||
+ core.getInput("IGNORE_MODEL_ALIAS_MATCHING")) == "true";
+
+//GITLAB SPECIFIC ENV VARIABLES
+async function getCIMergeRequestIID(
+ gitlab,
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+) {
+ if (!process.env.CI_MERGE_REQUEST_IID) {
+ const mergeRequestCommit = await gitlab.Commits.allMergeRequests(
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+ );
+
+ const firstMergeRequest = mergeRequestCommit[0];
+ if (firstMergeRequest) {
+ return firstMergeRequest.iid;
+ }
+ }
+
+ return process.env.CI_MERGE_REQUEST_IID;
+}
+
+const {
+ CI_PROJECT_PATH,
+ CI_PROJECT_ID,
+ CI_JOB_URL,
+ GITLAB_TOKEN,
+ CI_COMMIT_MESSAGE,
+ GITLAB_USER_LOGIN,
+ CI_PROJECT_NAME,
+ CI_COMMIT_SHA,
+ CI_PROJECT_NAMESPACE,
+} = process.env;
+
+function getGitLabEnvironments() {
+ const { DBT_ENVIRONMENT_BRANCH_MAP } = process.env;
+
+ if (DBT_ENVIRONMENT_BRANCH_MAP) {
+ const environmentLines = DBT_ENVIRONMENT_BRANCH_MAP.split("\n");
+ const environmentMap = {};
+
+ environmentLines.forEach((line) => {
+ const [environment, branch] = line.split(":").map((item) => item.trim());
+ if (environment && branch) {
+ environmentMap[environment] = branch;
+ }
+ });
+
+ return environmentMap;
+ } else {
+ return {};
+ }
+}
+
+//GITHUB SPECIFIC ENV VARIABLES
+const GITHUB_TOKEN =
+ core.getInput("GITHUB_TOKEN") || process.env.GITHUB_TOKEN;
+
+const getEnvironments = () => {
+ return (
+ core.getInput("DBT_ENVIRONMENT_BRANCH_MAP")
+ ?.trim()
+ ?.split("\n")
+ ?.map((i) => i.split(":").map((i) => i.trim())) ?? []
+ );
+};
+
+;// CONCATENATED MODULE: ./adapters/utils/auth.js
-main.config();
-const auth_ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const auth_ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
async function auth() {
- //Done
- console.log("Inside auth in utils.js");
var myHeaders = {
- authorization: `Bearer ${auth_ATLAN_API_TOKEN}`,
+ authorization: `Bearer ${ATLAN_API_TOKEN}`,
"content-type": "application/json",
};
@@ -20741,59 +24943,29 @@ async function auth() {
};
var response = await src_fetch(
- `${auth_ATLAN_INSTANCE_URL}/api/meta`,
+ `${ATLAN_INSTANCE_URL}/api/meta`,
requestOptions
).catch((err) => {});
- console.log("Completed auth in utils.js");
+
return response;
}
-;// CONCATENATED MODULE: ./src/utils/index.js
-
-
-
-
-
-
-;// CONCATENATED MODULE: ./src/utils/get-image-url.js
-
-
-function get_image_url_getImageURL(name, height = 20, width = 20) {
- try {
- return ``;
- } catch (e) {
- console.log(name);
- return '';
- }
-}
+;// CONCATENATED MODULE: ./adapters/utils/index.js
-function get_image_url_getConnectorImage(connectorName) {
- return get_image_url_getImageURL(`connector-${connectorName.toLowerCase()}`, 15, 15);
-}
-function get_image_url_getCertificationImage(certificationStatus) {
- return get_image_url_getImageURL(`certification-${certificationStatus.toLowerCase()}`, 15, 15);
-}
-// EXTERNAL MODULE: ./node_modules/json-stringify-safe/stringify.js
-var stringify = __nccwpck_require__(7073);
-;// CONCATENATED MODULE: ./src/api/get-downstream-assets.js
+;// CONCATENATED MODULE: ./adapters/api/get-downstream-assets.js
-main.config();
-const get_downstream_assets_ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const get_downstream_assets_ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
const ASSETS_LIMIT = 100;
-async function getDownstreamAssets( //Done
+async function getDownstreamAssets(
asset,
guid,
totalModifiedFiles,
@@ -20801,7 +24973,7 @@ async function getDownstreamAssets( //Done
integration
) {
var myHeaders = {
- authorization: `Bearer ${get_downstream_assets_ATLAN_API_TOKEN}`,
+ authorization: `Bearer ${ATLAN_API_TOKEN}`,
"content-type": "application/json",
};
@@ -20852,39 +25024,42 @@ async function getDownstreamAssets( //Done
};
var handleError = (err) => {
- const comment = `### ${get_image_url_getConnectorImage(
+ const comment = `### ${getConnectorImage(
asset.attributes.connectorName
- )} [${asset.displayText}](${get_downstream_assets_ATLAN_INSTANCE_URL}/assets/${
+ )} [${asset.displayText}](${ATLAN_INSTANCE_URL}/assets/${
asset.guid
}/overview?utm_source=dbt_${integration}_action) ${
asset.attributes?.certificateStatus
- ? get_image_url_getCertificationImage(asset.attributes.certificateStatus)
+ ? getCertificationImage(asset.attributes.certificateStatus)
: ""
}
_Failed to fetch impacted assets._
-${get_image_url_getImageURL(
+${getImageURL(
"atlan-logo",
15,
15
-)} [View lineage in Atlan](${get_downstream_assets_ATLAN_INSTANCE_URL}/assets/${
+)} [View lineage in Atlan](${ATLAN_INSTANCE_URL}/assets/${
asset.guid
}/lineage/overview?utm_source=dbt_${integration}_action)`;
- sendSegmentEventOfIntegration("dbt_ci_action_failure", {
- reason: "failed_to_fetch_lineage",
- asset_guid: asset.guid,
- asset_name: asset.name,
- asset_typeName: asset.typeName,
- msg: err,
+ sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_failure",
+ properties: {
+ reason: "failed_to_fetch_lineage",
+ asset_guid: asset.guid,
+ asset_name: asset.name,
+ asset_typeName: asset.typeName,
+ msg: err,
+ },
});
return comment;
};
var response = await src_fetch(
- `${get_downstream_assets_ATLAN_INSTANCE_URL}/api/meta/lineage/list`,
+ `${ATLAN_INSTANCE_URL}/api/meta/lineage/list`,
requestOptions
)
.then((e) => {
@@ -20899,34 +25074,58 @@ ${get_image_url_getImageURL(
error: handleError(err),
};
});
-
if (response.error) return response;
return response;
}
-;// CONCATENATED MODULE: ./src/api/get-asset.js
+;// CONCATENATED MODULE: ./adapters/templates/atlan.js
+
+
+function getErrorModelNotFound(name) {
+ return `
+
❌ Model with name **${name}** could not be found or is deleted
+ `;
+}
+
+function getErrorDoesNotMaterialize(
+ name,
+ ATLAN_INSTANCE_URL,
+ response,
+ integration
+) {
+
+ return `
+
❌ Model with name [${name}](${ATLAN_INSTANCE_URL}/assets/${response.entities[0].guid}/overview?utm_source=dbt_${integration}_action) does not materialise any asset
`;
+}
+function getNewModelAddedComment(fileName) {
+ return `### ${getConnectorImage("dbt")} ${fileName} 🆕
+ Its a new model and not present in Atlan yet, you'll see the downstream impact for it after its present in Atlan.`
+}
+function getBaseComment(totalChangedFiles, comments) {
+ return `### ${getImageURL("atlan-logo", 15, 15)} Atlan impact analysis
+ Here is your downstream impact analysis for **${totalChangedFiles} ${
+ totalChangedFiles > 1 ? "models" : "model"
+ }** you have edited.
+
+ ${comments}`
+}
+;// CONCATENATED MODULE: ./adapters/api/get-asset.js
-main.config();
-const get_asset_ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const get_asset_ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
async function getAsset({
- //Done
name,
sendSegmentEventOfIntegration,
environment,
integration,
}) {
var myHeaders = {
- Authorization: `Bearer ${get_asset_ATLAN_API_TOKEN}`,
+ Authorization: `Bearer ${ATLAN_API_TOKEN}`,
"Content-Type": "application/json",
};
@@ -20996,9 +25195,9 @@ async function getAsset({
headers: myHeaders,
body: raw,
};
- console.log("Before SendSegmentEventOfIntegration");
+
var response = await src_fetch(
- `${get_asset_ATLAN_INSTANCE_URL}/api/meta/search/indexsearch#findAssetByExactName`,
+ `${ATLAN_INSTANCE_URL}/api/meta/search/indexsearch#findAssetByExactName`,
requestOptions
)
.then((e) => e.json())
@@ -21012,35 +25211,61 @@ async function getAsset({
},
});
});
- console.log("<><><><><><><><><><><><><>");
- console.log(response);
- if (!response?.entities?.length)
+
+ if (!response?.entities?.length) {
return {
- error: `❌ Model with name **${name}** could not be found or is deleted
`,
+ error: getErrorModelNotFound(name),
};
+ }
+
+ if (Array.isArray(response.entities)) {
+ response.entities.sort((entityA, entityB) => {
+ const hasDbtModelSqlAssetsA =
+ entityA.attributes.dbtModelSqlAssets &&
+ entityA.attributes.dbtModelSqlAssets.length > 0;
+ const hasDbtModelSqlAssetsB =
+ entityB.attributes.dbtModelSqlAssets &&
+ entityB.attributes.dbtModelSqlAssets.length > 0;
+
+ if (hasDbtModelSqlAssetsA && !hasDbtModelSqlAssetsB) {
+ return -1; // entityA comes before entityB
+ } else if (!hasDbtModelSqlAssetsA && hasDbtModelSqlAssetsB) {
+ return 1; // entityB comes before entityA
+ }
+
+ // Primary sorting criterion: Latest createTime comes first
+ if (entityA.createTime > entityB.createTime) {
+ return -1;
+ } else if (entityA.createTime < entityB.createTime) {
+ return 1;
+ }
+
+ return 0; // No difference in sorting for these two entities
+ });
+ }
if (!response?.entities[0]?.attributes?.dbtModelSqlAssets?.length > 0)
return {
- error: `❌ Model with name [${name}](${get_asset_ATLAN_INSTANCE_URL}/assets/${response.entities[0].guid}/overview?utm_source=dbt_${integration}_action) does not materialise any asset
`,
+ error: getErrorDoesNotMaterialize(
+ name,
+ ATLAN_INSTANCE_URL,
+ response,
+ integration
+ ),
};
return response.entities[0];
}
-;// CONCATENATED MODULE: ./src/api/get-classifications.js
-
-
-
+;// CONCATENATED MODULE: ./adapters/api/get-classifications.js
-const get_classifications_ATLAN_INSTANCE_URL = getInstanceUrl();
-const get_classifications_ATLAN_API_TOKEN = getAPIToken();
async function getClassifications({
sendSegmentEventOfIntegration,
}) {
var myHeaders = {
- Authorization: `Bearer ${get_classifications_ATLAN_API_TOKEN}`,
+ Authorization: `Bearer ${ATLAN_API_TOKEN}`,
"Content-Type": "application/json",
};
@@ -21051,14 +25276,17 @@ async function getClassifications({
};
var response = await src_fetch(
- `${get_classifications_ATLAN_INSTANCE_URL}/api/meta/types/typedefs?type=classification`,
+ `${ATLAN_INSTANCE_URL}/api/meta/types/typedefs?type=classification`,
requestOptions
)
.then((e) => e.json())
.catch((err) => {
- sendSegmentEventOfIntegration("dbt_ci_action_failure", {
- reason: "failed_to_get_classifications",
- msg: err,
+ sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_failure",
+ properties: {
+ reason: "failed_to_get_classifications",
+ msg: err,
+ },
});
});
@@ -21079,23 +25307,20 @@ const validate = uuid_dist/* validate */.Gu;
const wrapper_stringify = uuid_dist/* stringify */.Pz;
const parse = uuid_dist/* parse */.Qc;
-;// CONCATENATED MODULE: ./src/api/create-resource.js
+;// CONCATENATED MODULE: ./adapters/api/create-resource.js
-const create_resource_ATLAN_INSTANCE_URL = getInstanceUrl();
-const create_resource_ATLAN_API_TOKEN = getAPIToken();
-
-async function createResource( //Done
+async function createResource(
guid,
name,
link,
sendSegmentEventOfIntegration
) {
var myHeaders = {
- Authorization: `Bearer ${create_resource_ATLAN_API_TOKEN}`,
+ Authorization: `Bearer ${ATLAN_API_TOKEN}`,
"Content-Type": "application/json",
};
@@ -21125,40 +25350,32 @@ async function createResource( //Done
};
var response = await src_fetch(
- `${create_resource_ATLAN_INSTANCE_URL}/api/meta/entity/bulk`,
+ `${ATLAN_INSTANCE_URL}/api/meta/entity/bulk`,
requestOptions
)
.then((e) => e.json())
.catch((err) => {
console.log(err);
- sendSegmentEventOfIntegration("dbt_ci_action_failure", {
- reason: "failed_to_create_resource",
- asset_name: name,
- msg: err,
+ sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_failure",
+ properties: {
+ reason: "failed_to_create_resource",
+ asset_name: name, // This should change
+ msg: err,
+ },
});
});
- console.log("Created Resource:", response);
-
return response;
}
-;// CONCATENATED MODULE: ./src/api/segment.js
-
-
+;// CONCATENATED MODULE: ./adapters/api/segment.js
-main.config();
-
-const { IS_DEV: segment_IS_DEV } = process.env;
-const segment_ATLAN_INSTANCE_URL =
- core.getInput("ATLAN_INSTANCE_URL") || process.env.ATLAN_INSTANCE_URL;
-const segment_ATLAN_API_TOKEN =
- core.getInput("ATLAN_API_TOKEN") || process.env.ATLAN_API_TOKEN;
async function sendSegmentEvent(action, body) {
const myHeaders = {
- authorization: `Bearer ${segment_ATLAN_API_TOKEN}`,
+ authorization: `Bearer ${ATLAN_API_TOKEN}`,
"content-type": "application/json",
};
@@ -21169,9 +25386,9 @@ async function sendSegmentEvent(action, body) {
};
var response = null;
- if (!segment_IS_DEV) {
+ if (!IS_DEV) {
response = await src_fetch(
- `${segment_ATLAN_INSTANCE_URL}/api/service/segment/track`,
+ `${ATLAN_INSTANCE_URL}/api/service/segment/track`,
requestOptions
)
.then(() => {
@@ -21187,7 +25404,7 @@ async function sendSegmentEvent(action, body) {
return response;
}
-;// CONCATENATED MODULE: ./src/api/index.js
+;// CONCATENATED MODULE: ./adapters/api/index.js
@@ -21195,14 +25412,111 @@ async function sendSegmentEvent(action, body) {
-;// CONCATENATED MODULE: ./adapters/integrations/github-integration.js
-// githubIntegration.js
- // Check do we actually need it or not
+;// CONCATENATED MODULE: ./adapters/templates/github-integration.js
+function getErrorResponseStatus401 (ATLAN_INSTANCE_URL, context) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` as this repository's action secret.
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+function getErrorResponseStatusUndefined(ATLAN_INSTANCE_URL, context) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` as this repository's action secret.
+
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Make sure your Atlan Instance URL is set in the following format.
+\`https://tenant.atlan.com\`
+
+Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+function getSetResourceOnAssetComment(tableMd, setResourceFailed) {
+ return `## 🎊 Congrats on the merge!
+
+This pull request has been added as a resource to the following assets:
+Name | Resource set successfully
+--- | ---
+${tableMd}
+${setResourceFailed ? '> Seems like we were unable to set the resources for some of the assets due to insufficient permissions. To ensure that the pull request is linked as a resource, you will need to assign the right persona with requisite permissions to the API token.' : ''}
+`
+}
+
+function getAssetInfo(ATLAN_INSTANCE_URL, asset, materialisedAsset, environmentName, projectName) {
+ return `### ${getConnectorImage(
+ asset.attributes.connectorName
+ )} [${asset.displayText}](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_github_action) ${
+ asset.attributes?.certificateStatus
+ ? getCertificationImage(asset.attributes.certificateStatus)
+ : ""
+ }
+ Materialised asset: ${getConnectorImage(
+ materialisedAsset.attributes.connectorName
+ )} [${materialisedAsset.attributes.name}](${ATLAN_INSTANCE_URL}/assets/${
+ materialisedAsset.guid
+ }/overview?utm_source=dbt_github_action) ${
+ materialisedAsset.attributes?.certificateStatus
+ ? getCertificationImage(materialisedAsset.attributes.certificateStatus)
+ : ""
+ }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ""}${
+ projectName ? ` | Project Name: \`${projectName}\`` : ""
+ }`
+}
+
+function getDownstreamTable(ATLAN_INSTANCE_URL, downstreamAssets, rows, materialisedAsset) {
+ return `${
+ downstreamAssets.entityCount
+ } downstream assets 👇
+
+ Name | Type | Description | Owners | Terms | Classifications | Source URL
+ --- | --- | --- | --- | --- | --- | ---
+ ${rows
+ .map((row) =>
+ row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
+ )
+ .join("\n")}
+
+ ${
+ downstreamAssets.hasMore
+ ? `[See more downstream assets at Atlan](${ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_github_action)`
+ : ""
+ }
+
+ `
+}
+
+function getViewAssetButton(ATLAN_INSTANCE_URL, asset) {
+ return `${getImageURL(
+ "atlan-logo",
+ 15,
+ 15
+ )} [View asset in Atlan](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_github_action)`
+}
+function getMDCommentForModel(ATLAN_INSTANCE_URL, model) {
+ return `${getConnectorImage(model?.attributes?.connectorName)} [${
+ model?.displayText
+ }](${ATLAN_INSTANCE_URL}/assets/${model?.guid}/overview?utm_source=dbt_github_action)`
+}
+
+function getMDCommentForMaterialisedView(ATLAN_INSTANCE_URL, materialisedView) {
+ return `${getConnectorImage(materialisedView?.attributes?.connectorName)} [${
+ materialisedView?.attributes?.name
+ }](${ATLAN_INSTANCE_URL}/assets/${materialisedView?.guid}/overview?utm_source=dbt_github_action)`
+}
+function getTableMD(md, resp) {
+ return `${md} | ${resp ? '✅' : '❌'} \n`
+}
+;// CONCATENATED MODULE: ./adapters/integrations/github-integration.js
+// githubIntegration.js
@@ -21210,470 +25524,816 @@ async function sendSegmentEvent(action, body) {
-const github_integration_IS_DEV = isDev();
-const github_integration_ATLAN_INSTANCE_URL = getInstanceUrl();
-main.config();
+var headSHA;
+const integrationName = "github";
class GitHubIntegration extends IntegrationInterface {
constructor(token) {
super(token);
}
async run() {
- //Done
- //Complete
- console.log("Run Github");
- console.log(github_integration_IS_DEV);
- const timeStart = Date.now();
- const { context } = github;
- console.log("Context:", context);
- const octokit = github.getOctokit(this.token);
- const { pull_request } = context?.payload;
- console.log(pull_request, "hii");
-
- console.log("Interesting");
- const { state, merged } = pull_request;
- console.log("state", state);
- console.log("merged", merged);
- if (!(await this.authIntegration({ octokit, context }))) {
- //DONE
- //Complete
- throw { message: "Wrong API Token" };
- }
-
- let total_assets = 0;
- console.log("After auth Integration");
- if (state === "open") {
- total_assets = await this.printDownstreamAssets({ octokit, context });
- } else if (state === "closed" && merged) {
- console.log("Hmm");
- total_assets = await this.setResourceOnAsset({ octokit, context });
- }
-
- if (total_assets !== 0) {
- this.sendSegmentEventOfIntegration("dbt_ci_action_run", {
- //Complete
- asset_count: total_assets,
- total_time: Date.now() - timeStart,
- });
- }
- }
+ try {
+ const timeStart = Date.now();
+ const { context } = github;
- async printDownstreamAssets({ octokit, context }) {
- //Done
- console.log("Brother");
- // const changedFiles = await this.getChangedFiles({ octokit, context }); //Complete
- var changedFiles = [
- {
- fileName: "instacart_beverages_order_customer",
- filePath: "instacart_beverages_order_customer.sql",
- status: "modified",
- },
- ];
- let comments = ``;
- let totalChangedFiles = 0;
+ const octokit = github.getOctokit(this.token);
+ const { pull_request } = context?.payload;
+ const { state, merged } = pull_request;
+ headSHA = pull_request?.head?.sha;
- for (const { fileName, filePath, status } of changedFiles) {
- const aliasName = await this.getAssetName({
- //Complete
- octokit,
- context,
- fileName,
- filePath,
- });
- const assetName = isIgnoreModelAliasMatching() ? fileName : aliasName; //Complete
- console.log("acha2");
- const environments = getEnvironments();
-
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === context.payload.pull_request.base.ref) {
- environment = environmentName;
- break;
- }
+ logger_logger.withInfo(
+ "GitHub Integration is running...",
+ integrationName,
+ headSHA,
+ "run"
+ );
+
+ if (!(await this.authIntegration({ octokit, context }))) {
+ logger_logger.withError(
+ "Authentication failed. Wrong API Token.",
+ integrationName,
+ headSHA,
+ "run"
+ );
+ throw { message: "Wrong API Token" };
}
- console.log("Before getAsset");
- const asset = await getAsset({
- //Done
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "github",
- });
- console.log("After getAsset");
- if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
- console.log("Status: ", status);
- if (status === "added") {
- comments += `### ${get_image_url_getConnectorImage("dbt")} ${fileName} 🆕
-Its a new model and not present in Atlan yet, you'll see the downstream impact for it after its present in Atlan.`;
- totalChangedFiles++;
- continue;
+
+ let total_assets = 0;
+
+ if (state === "open") {
+ total_assets = await this.printDownstreamAssets({ octokit, context });
+ } else if (state === "closed" && merged) {
+ total_assets = await this.setResourceOnAsset({ octokit, context });
}
- console.log("Before filtering");
- console.log("Asset", asset);
- if (asset.error) {
- comments += asset.error;
- totalChangedFiles++;
- continue;
+
+ if (total_assets !== 0) {
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_run",
+ properties: {
+ asset_count: total_assets,
+ total_time: Date.now() - timeStart,
+ },
+ });
}
- const materialisedAsset = asset.attributes.dbtModelSqlAssets[0];
- const timeStart = Date.now();
- const totalModifiedFiles = changedFiles.filter(
- (i) => i.status === "modified"
- ).length;
- console.log("Before getDownstreamAssets");
- const downstreamAssets = await getDownstreamAssets(
- //Complete
- asset,
- materialisedAsset.guid,
- totalModifiedFiles
+
+ logger_logger.withInfo(
+ "Successfully Completed DBT_CI_ACTION",
+ integrationName,
+ headSHA,
+ "run"
);
- console.log("After getDownstreamAssets");
- if (downstreamAssets.error) {
- comments += downstreamAssets.error;
- totalChangedFiles++;
- continue;
- }
- console.log("At line 139 after getDownstreamAssets in printDownstream");
- this.sendSegmentEventOfIntegration("dbt_ci_action_downstream_unfurl", {
- //Complete
- asset_guid: asset.guid,
- asset_type: asset.typeName,
- downstream_count: downstreamAssets.entities.length,
- total_fetch_time: Date.now() - timeStart,
- });
- console.log("At line 147 after getDownstreamAssets in printDownstream");
+ } catch (error) {
+ logger_logger.withError(
+ `Error in run(): ${error.message}`,
+ integrationName,
+ headSHA,
+ "run"
+ );
+ throw error;
+ }
+ }
- const classifications = await getClassifications({
- //Complete
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- });
+ async printDownstreamAssets({ octokit, context }) {
+ logger_logger.withInfo(
+ "Printing downstream assets...",
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
- const comment = await this.renderDownstreamAssetsComment({
- //Done
- //Complete
- octokit,
- context,
- asset,
- materialisedAsset,
- downstreamAssets,
- classifications,
- });
+ try {
+ const changedFiles = await this.getChangedFiles({ octokit, context });
+ let comments = ``;
+ let totalChangedFiles = 0;
+
+ for (const { fileName, filePath, status } of changedFiles) {
+ logger_logger.withInfo(
+ `Processing file: ${fileName}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ const aliasName = await this.getAssetName({
+ octokit,
+ context,
+ fileName,
+ filePath,
+ });
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
+
+ const environments = getEnvironments();
+ let environment = null;
+ for (const [baseBranchName, environmentName] of environments) {
+ if (baseBranchName === context.payload.pull_request.base.ref) {
+ environment = environmentName;
+ break;
+ }
+ }
- comments += comment;
+ logger_logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "github",
+ });
- totalChangedFiles++;
- }
+ if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
+
+ if (status === "added") {
+ logger_logger.withInfo(
+ `New model added: ${fileName}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ comments += getNewModelAddedComment(fileName);
+ totalChangedFiles++;
+ continue;
+ }
+
+ if (asset.error) {
+ logger_logger.withError(
+ `Asset error for ${assetName}: ${asset.error}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ comments += asset.error;
+ totalChangedFiles++;
+ continue;
+ }
+
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
+
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
+
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "github"
+ );
+
+ if (downstreamAssets.error) {
+ logger_logger.withError(
+ `Downstream assets error for ${assetName}: ${downstreamAssets.error}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ comments += downstreamAssets.error;
+ totalChangedFiles++;
+ continue;
+ }
+
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
- comments = `### ${get_image_url_getImageURL("atlan-logo", 15, 15)} Atlan impact analysis
-Here is your downstream impact analysis for **${totalChangedFiles} ${
- totalChangedFiles > 1 ? "models" : "model"
- }** you have edited.
+ const classifications = await getClassifications({
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ });
-${comments}`;
+ const comment = await this.renderDownstreamAssetsComment({
+ octokit,
+ context,
+ asset,
+ materialisedAsset,
+ downstreamAssets,
+ classifications,
+ });
- const existingComment = await this.checkCommentExists({ octokit, context }); //Complete
+ comments += comment;
- if (totalChangedFiles > 0)
- await this.createIssueComment({
- //Complete
- octokit,
- context,
- content: comments,
- comment_id: existingComment?.id,
- });
+ totalChangedFiles++;
+ }
- if (totalChangedFiles === 0 && existingComment)
- await this.deleteComment({
- //Complete
+ comments = getBaseComment(totalChangedFiles, comments);
+
+ const existingComment = await this.checkCommentExists({
octokit,
context,
- comment_id: existingComment.id,
});
- return totalChangedFiles;
- }
+ logger_logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
- async setResourceOnAsset({ octokit, context }) {
- //Done
- //Complete
- const changedFiles = await this.getChangedFiles({ octokit, context }); //Complete
- const { pull_request } = context.payload;
- var totalChangedFiles = 0;
+ if (totalChangedFiles > 0)
+ await this.createIssueComment({
+ octokit,
+ context,
+ content: comments,
+ comment_id: existingComment?.id,
+ });
+
+ if (totalChangedFiles === 0 && existingComment)
+ await this.deleteComment({
+ octokit,
+ context,
+ comment_id: existingComment?.id,
+ });
- if (changedFiles.length === 0) return;
+ logger_logger.withInfo(
+ "Successfully printed Downstream Assets",
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
- for (const { fileName, filePath } of changedFiles) {
- const assetName = await this.getAssetName({
- //Complete
- octokit,
- context,
- fileName,
- filePath,
- });
+ return totalChangedFiles;
+ } catch (error) {
+ logger_logger.withError(
+ `Error in printDownstreamAssets: ${error.message}`,
+ integrationName,
+ headSHA,
+ "printDownstreamAssets"
+ );
+ throw error;
+ }
+ }
- const environments = getEnvironments();
+ async setResourceOnAsset({ octokit, context }) {
+ logger_logger.withInfo(
+ "Setting resources on assets...",
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === context.payload.pull_request.base.ref) {
- environment = environmentName;
- break;
- }
+ try {
+ const changedFiles = await this.getChangedFiles({ octokit, context });
+ const { pull_request } = context.payload;
+ var totalChangedFiles = 0;
+ let tableMd = ``;
+ let setResourceFailed = false;
+
+ if (changedFiles.length === 0) {
+ logger_logger.withInfo(
+ "No changed files found. Skipping resource setup.",
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ return totalChangedFiles;
}
- const asset = await getAsset({
- //Done
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "github",
- });
+ for (const { fileName, filePath } of changedFiles) {
+ logger_logger.withInfo(
+ `Processing file: ${fileName}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ const aliasName = await this.getAssetName({
+ octokit,
+ context,
+ fileName,
+ filePath,
+ });
+
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
- if (asset.error) continue;
+ logger_logger.withInfo(
+ `Resolved asset name: ${assetName}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
- const { guid: modelGuid } = asset;
- const { guid: tableAssetGuid } =
- asset?.attributes?.dbtModelSqlAssets?.[0];
+ const environments = getEnvironments();
+ let environment = null;
+ for (const [baseBranchName, environmentName] of environments) {
+ if (baseBranchName === context.payload.pull_request.base.ref) {
+ environment = environmentName;
+ break;
+ }
+ }
- if (modelGuid)
- await createResource(
- //Complete
- modelGuid,
- "Pull Request on GitHub",
- pull_request.html_url,
- this.sendSegmentEventOfIntegration
+ logger_logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
);
- if (tableAssetGuid)
- await createResource(
- //Complete
- tableAssetGuid,
- "Pull Request on GitHub",
- pull_request.html_url,
- this.sendSegmentEventOfIntegration
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "github",
+ });
+
+ if (asset.error) {
+ logger_logger.withError(
+ `Failed to retrieve asset: ${assetName}, Error: ${asset.error}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
+
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
+
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
+
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "github"
);
- totalChangedFiles++;
- }
+ if (downstreamAssets.error) {
+ logger_logger.withError(
+ `Failed to retrieve downstream assets for: ${assetName}, Error: ${downstreamAssets.error}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
+
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
- const comment = await this.createIssueComment({
- //Complete
- octokit,
- context,
- content: `🎊 Congrats on the merge!
+ const model = asset;
+ const materialisedView = asset?.attributes?.dbtModelSqlAssets?.[0];
-This pull request has been added as a resource to all the assets modified. ✅
-`,
- comment_id: null,
- forceNewComment: true,
- });
+ let PR_TITLE = pull_request.title;
- return totalChangedFiles;
- }
+ if (downstreamAssets.entityCount != 0) {
+ if (model) {
+ const { guid: modelGuid } = model;
+ const resp = await createResource(
+ modelGuid,
+ PR_TITLE,
+ pull_request.html_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = getMDCommentForModel(ATLAN_INSTANCE_URL, model);
+ tableMd += getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger_logger.withError(
+ `Setting resource failed for model: ${modelGuid}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
- async authIntegration({ octokit, context }) {
- //DONE
- //COMPLETE
- console.log("Here is Context:", context);
- const response = await auth();
- console.log("Inside authIntegration befor comment exists");
- const existingComment = await this.checkCommentExists({ octokit, context });
-
- console.log("Existing Comment", existingComment);
-
- if (response?.status === 401) {
- console.log("Inside authIntegration befor createIssueComment");
- await this.createIssueComment({
+ if (materialisedView) {
+ const { guid: tableAssetGuid } = materialisedView;
+ const resp = await createResource(
+ tableAssetGuid,
+ PR_TITLE,
+ pull_request.html_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = getMDCommentForMaterialisedView(
+ ATLAN_INSTANCE_URL,
+ materialisedView
+ );
+ tableMd += getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger_logger.withError(
+ `Setting resource failed for materialized view: ${tableAssetGuid}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
+ }
+ totalChangedFiles++;
+ }
+
+ const comment = await this.createIssueComment({
octokit,
context,
- content: `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` as this repository's action secret.
+ content: getSetResourceOnAssetComment(tableMd, setResourceFailed),
+ comment_id: null,
+ forceNewComment: true,
+ });
-Atlan Instance URL: ${github_integration_ATLAN_INSTANCE_URL}
+ logger_logger.withInfo(
+ "Successfully set the resource on the asset",
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
-Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`,
- comment_id: existingComment?.id,
- });
- return false;
+ return totalChangedFiles;
+ } catch (error) {
+ logger_logger.withError(
+ `Error in setResourceOnAsset: ${error}`,
+ integrationName,
+ headSHA,
+ "setResourceOnAsset"
+ );
+ throw error;
}
+ }
- if (response === undefined) {
- await this.createIssueComment({
+ async authIntegration({ octokit, context }) {
+ logger_logger.withInfo(
+ "Authenticating with Atlan",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+
+ try {
+ const response = await auth();
+
+ const existingComment = await this.checkCommentExists({
octokit,
context,
- content: `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` as this repository's action secret.
+ });
-Atlan Instance URL: ${github_integration_ATLAN_INSTANCE_URL}
+ logger_logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
-Make sure your Atlan Instance URL is set in the following format.
-\`https://tenant.atlan.com\`
+ if (response?.status === 401) {
+ logger_logger.withError(
+ "Authentication failed: Status 401",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ octokit,
+ context,
+ content: getErrorResponseStatus401(ATLAN_INSTANCE_URL, context),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
-Set your repository action secrets [here](https://github.com/${context.payload.repository.full_name}/settings/secrets/actions). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`,
- comment_id: existingComment?.id,
- });
- return false;
+ if (response === undefined) {
+ logger_logger.withError(
+ "Authentication failed: Undefined response",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ octokit,
+ context,
+ content: getErrorResponseStatusUndefined(ATLAN_INSTANCE_URL, context),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
+ logger_logger.withInfo(
+ "Successfully Authenticated with Atlan",
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ return true;
+ } catch (error) {
+ logger_logger.withError(
+ `Error in authIntegration: ${error.message}`,
+ integrationName,
+ headSHA,
+ "authIntegration"
+ );
+ throw error;
}
-
- return true;
}
async sendSegmentEventOfIntegration({ action, properties }) {
- //Done
- //FullyComplete
- // IMPORT ATLAN_INSTANCE_URL.
- const domain = new URL(github_integration_ATLAN_INSTANCE_URL).hostname;
-
- const raw = stringify({
- category: "integration",
- object: "github",
- action,
- userId: "atlan-annonymous-github",
- properties: {
- ...properties,
- //get context for this
- // github_action_id: `https://github.com/${context.payload.repository.full_name}/actions/runs/${context.runId}`,
- domain,
- },
- });
+ try {
+ const domain = new URL(ATLAN_INSTANCE_URL).hostname;
+ const { context } = github; //confirm this
+ logger_logger.withInfo(
+ `Sending Segment event for action: ${action}`,
+ integrationName,
+ headSHA,
+ "sendSegmentEventOfIntegration"
+ );
+
+ const raw = stringify({
+ category: "integration",
+ object: "github",
+ action,
+ userId: "atlan-annonymous-github",
+ properties: {
+ ...properties,
+ github_action_id: `https://github.com/${context?.payload?.repository?.full_name}/actions/runs/${context?.runId}`,
+ domain,
+ },
+ });
- return sendSegmentEvent(action, raw);
+ return sendSegmentEvent(action, raw);
+ } catch (error) {
+ logger_logger.withError(
+ `Error sending Segment event for action: ${action} - ${error.message}`,
+ integrationName,
+ headSHA,
+ "sendSegmentEventOfIntegration"
+ );
+ throw error;
+ }
}
async getChangedFiles({ octokit, context }) {
- //Done
- //FullyComplete
- const { repository, pull_request } = context.payload,
- owner = repository.owner.login,
- repo = repository.name,
- pull_number = pull_request.number;
-
- const res = await octokit.request(
- `GET /repos/${owner}/${repo}/pulls/${pull_number}/files`,
- {
- owner,
- repo,
- pull_number,
- }
- );
+ try {
+ logger_logger.withInfo(
+ "Fetching changed files...",
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
- var changedFiles = res.data
- .map(({ filename, status }) => {
- try {
- const [modelName] = filename
- .match(/.*models\/(.*)\.sql/)[1]
- .split("/")
- .reverse()[0]
- .split(".");
+ const { repository, pull_request } = context.payload,
+ owner = repository.owner.login,
+ repo = repository.name,
+ pull_number = pull_request.number;
- if (modelName) {
- return {
- fileName: modelName,
- filePath: filename,
- status,
- };
+ const res = await octokit.request(
+ `GET /repos/${owner}/${repo}/pulls/${pull_number}/files`,
+ {
+ owner,
+ repo,
+ pull_number,
+ }
+ );
+
+ var changedFiles = res.data
+ .map(({ filename, status }) => {
+ try {
+ const [modelName] = filename
+ .match(/.*models\/(.*)\.sql/)[1]
+ .split("/")
+ .reverse()[0]
+ .split(".");
+
+ if (modelName) {
+ return {
+ fileName: modelName,
+ filePath: filename,
+ status,
+ };
+ }
+ } catch (e) {
+ logger_logger.withError(
+ `Error processing file: ${filename} - ${e.message}`,
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
}
- } catch (e) {}
- })
- .filter((i) => i !== undefined);
+ })
+ .filter((i) => i !== undefined);
- changedFiles = changedFiles.filter((item, index) => {
- return (
- changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
- index
- );
- });
+ changedFiles = changedFiles.filter((item, index) => {
+ return (
+ changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
+ index
+ );
+ });
- console.log("Changed Files: ", changedFiles);
+ logger_logger.withInfo(
+ "Successfully fetched changed files",
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
- return changedFiles;
+ return changedFiles;
+ } catch (error) {
+ logger_logger.withError(
+ `Error fetching changed files - ${error.message}`,
+ integrationName,
+ headSHA,
+ "getChangedFiles"
+ );
+ throw error;
+ }
}
async getAssetName({ octokit, context, fileName, filePath }) {
- //Done
- // FullyComplete
- var regExp =
- /{{\s*config\s*\(\s*(?:[^,]*,)*\s*alias\s*=\s*['"]([^'"]+)['"](?:\s*,[^,]*)*\s*\)\s*}}/im;
- var fileContents = await this.getFileContents({
- octokit,
- context,
- filePath,
- });
+ try {
+ logger_logger.withInfo(
+ "Getting asset name...",
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
- if (fileContents) {
- var matches = regExp.exec(fileContents);
+ var regExp =
+ /{{\s*config\s*\(\s*(?:[^,]*,)*\s*alias\s*=\s*['"]([^'"]+)['"](?:\s*,[^,]*)*\s*\)\s*}}/im;
+ var fileContents = await this.getFileContents({
+ octokit,
+ context,
+ filePath,
+ });
- if (matches) {
- return matches[1].trim();
+ if (fileContents) {
+ var matches = regExp.exec(fileContents);
+ if (matches) {
+ logger_logger.withInfo(
+ `Found a match: ${matches[1].trim()}`,
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
+ return matches[1].trim();
+ }
}
+ logger_logger.withInfo(
+ `Using filename as asset name: ${fileName}`,
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
+ return fileName;
+ } catch (error) {
+ logger_logger.withError(
+ `Error getting asset name - ${error.message}`,
+ integrationName,
+ headSHA,
+ "getAssetName"
+ );
+ throw error;
}
-
- return fileName;
}
async getFileContents({ octokit, context, filePath }) {
- //Done
- // FullyComplete
- const { repository, pull_request } = context.payload,
- owner = repository.owner.login,
- repo = repository.name,
- head_sha = pull_request.head.sha;
-
- const res = await octokit
- .request(
- `GET /repos/${owner}/${repo}/contents/${filePath}?ref=${head_sha}`,
- {
- owner,
- repo,
- path: filePath,
- }
- )
- .catch((e) => {
- console.log("Error fetching file contents: ", e);
- return null;
- });
+ try {
+ logger_logger.withInfo(
+ "Fetching file contents...",
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
- if (!res) return null;
+ const { repository, pull_request } = context.payload,
+ owner = repository.owner.login,
+ repo = repository.name,
+ head_sha = pull_request.head.sha;
+
+ const res = await octokit
+ .request(
+ `GET /repos/${owner}/${repo}/contents/${filePath}?ref=${head_sha}`,
+ {
+ owner,
+ repo,
+ path: filePath,
+ }
+ )
+ .catch((e) => {
+ logger_logger.withError(
+ `Error fetching file contents: ${e.message}`,
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
+ return null;
+ });
+
+ if (!res) return null;
- const buff = Buffer.from(res.data.content, "base64");
+ const buff = Buffer.from(res.data.content, "base64");
- return buff.toString("utf8");
+ logger_logger.withInfo(
+ "Successfully fetched file contents",
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
+
+ return buff.toString("utf8");
+ } catch (error) {
+ logger_logger.withError(
+ `Error in getFileContents: ${error.message}`,
+ integrationName,
+ headSHA,
+ "getFileContents"
+ );
+ throw error;
+ }
}
async checkCommentExists({ octokit, context }) {
- //Done
- //FullyComplete
- if (github_integration_IS_DEV) return null;
+ logger_logger.withInfo(
+ "Checking for existing comments...",
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+
+ if (IS_DEV) {
+ logger_logger.withInfo(
+ "Development mode enabled. Skipping comment check.",
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ return null;
+ }
const { pull_request } = context.payload;
- const comments = await octokit.rest.issues.listComments({
- ...context.repo,
- issue_number: pull_request.number,
- });
+ try {
+ const comments = await octokit.rest.issues.listComments({
+ ...context.repo,
+ issue_number: pull_request.number,
+ });
- return comments.data.find(
- (comment) =>
- comment.user.login === "github-actions[bot]" &&
- comment.body.includes(
- ""
- )
- );
+ const existingComment = comments.data.find(
+ (comment) =>
+ comment.user.login === "github-actions[bot]" &&
+ comment.body.includes(
+ ""
+ )
+ );
+ if (existingComment) {
+ logger_logger.withInfo(
+ "Found existing comment: " + existingComment?.id,
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ } else {
+ logger_logger.withInfo(
+ "No existing comment found",
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ }
+
+ return existingComment;
+ } catch (error) {
+ logger_logger.withError(
+ "Error checking for existing comments: " + error.message,
+ integrationName,
+ headSHA,
+ "checkCommentExists"
+ );
+ throw error;
+ }
}
async createIssueComment({
- //Done
- // FullyComplete
octokit,
context,
content,
comment_id = null,
forceNewComment = false,
}) {
- console.log("Inside CreateIssue:", context);
- console.log("Inside CreateIssue Comment");
+ logger_logger.withInfo(
+ "Creating an issue comment...",
+ integrationName,
+ headSHA,
+ "createIssueComment"
+ );
+
const { pull_request } = context?.payload || {};
- console.log("Inside CreateIssue Comment");
+
content = `
${content}`;
@@ -21683,10 +26343,15 @@ ${content}`;
body: content,
};
- console.log(content, content.length);
- console.log("Inside CreateIssue Comment Complete");
-
- if (github_integration_IS_DEV) return content;
+ if (IS_DEV) {
+ logger_logger.withInfo(
+ "Development mode enabled. Skipping comment creation.",
+ integrationName,
+ headSHA,
+ "createIssueComment"
+ );
+ return content;
+ }
if (comment_id && !forceNewComment)
return octokit.rest.issues.updateComment({ ...commentObj, comment_id });
@@ -21694,8 +26359,13 @@ ${content}`;
}
async deleteComment({ octokit, context, comment_id }) {
- //Done
- //FullyComplete
+ logger_logger.withInfo(
+ `Deleted comment with ID ${comment_id}`,
+ integrationName,
+ headSHA,
+ "deleteComment"
+ );
+
const { pull_request } = context.payload;
return octokit.rest.issues.deleteComment({
@@ -21706,8 +26376,6 @@ ${content}`;
}
async renderDownstreamAssetsComment({
- //Done
- //FullyComplete
octokit,
context,
asset,
@@ -21715,163 +26383,148 @@ ${content}`;
downstreamAssets,
classifications,
}) {
- let impactedData = downstreamAssets.entities.map(
- ({
- displayText,
- guid,
- typeName,
- attributes,
- meanings,
- classificationNames,
- }) => {
- // Modifying the typeName and getting the readableTypeName
- let readableTypeName = typeName
- .toLowerCase()
- .replace(attributes.connectorName, "")
- .toUpperCase();
-
- // Filtering classifications based on classificationNames
- let classificationsObj = classifications.filter(({ name }) =>
- classificationNames.includes(name)
- );
-
- // Modifying the readableTypeName
- readableTypeName =
- readableTypeName.charAt(0).toUpperCase() +
- readableTypeName.slice(1).toLowerCase();
-
- return [
- guid,
- truncate(displayText),
- truncate(attributes.connectorName),
- truncate(readableTypeName),
- truncate(
- attributes?.userDescription || attributes?.description || ""
- ),
- attributes?.certificateStatus || "",
- truncate(
- [...attributes?.ownerUsers, ...attributes?.ownerGroups] || []
- ),
- truncate(
- meanings.map(
- ({ displayText, termGuid }) =>
- `[${displayText}](${github_integration_ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_github_action)`
- )
- ),
- truncate(
- classificationsObj?.map(
- ({ name, displayName }) => `\`${displayName}\``
- )
- ),
- attributes?.sourceURL || "",
- ];
- }
+ logger_logger.withInfo(
+ "Rendering Downstream Assets...",
+ integrationName,
+ headSHA,
+ "renderDownstreamAssetsComment"
);
-
- // Sorting the impactedData first by typeName and then by connectorName
- impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
- impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
-
- // Creating rows for the downstream table
- let rows = impactedData.map(
- ([
- guid,
- displayText,
- connectorName,
- typeName,
- description,
- certificateStatus,
- owners,
- meanings,
- classifications,
- sourceUrl,
- ]) => {
- // Getting connector and certification images
- const connectorImage = get_image_url_getConnectorImage(connectorName);
- const certificationImage = certificateStatus
- ? get_image_url_getCertificationImage(certificateStatus)
- : "";
-
- return [
- `${connectorImage} [${displayText}](${github_integration_ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_github_action) ${certificationImage}`,
- `\`${typeName}\``,
- description,
- owners,
+ try {
+ let impactedData = downstreamAssets.entities.map(
+ ({
+ displayText,
+ guid,
+ typeName,
+ attributes,
meanings,
- classifications,
- sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
- ];
- }
- );
+ classificationNames,
+ }) => {
+ // Modifying the typeName and getting the readableTypeName
+ let readableTypeName = typeName
+ .toLowerCase()
+ .replace(attributes.connectorName, "")
+ .toUpperCase();
+
+ // Filtering classifications based on classificationNames
+ let classificationsObj = classifications.filter(({ name }) =>
+ classificationNames.includes(name)
+ );
+
+ // Modifying the readableTypeName
+ readableTypeName =
+ readableTypeName.charAt(0).toUpperCase() +
+ readableTypeName.slice(1).toLowerCase();
+
+ return [
+ guid,
+ truncate(displayText),
+ truncate(attributes.connectorName),
+ truncate(readableTypeName),
+ truncate(
+ attributes?.userDescription || attributes?.description || ""
+ ),
+ attributes?.certificateStatus || "",
+ truncate(
+ [...attributes?.ownerUsers, ...attributes?.ownerGroups] || []
+ ),
+ truncate(
+ meanings.map(
+ ({ displayText, termGuid }) =>
+ `[${displayText}](${ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_github_action)`
+ )
+ ),
+ truncate(
+ classificationsObj?.map(
+ ({ name, displayName }) => `\`${displayName}\``
+ )
+ ),
+ attributes?.sourceURL || "",
+ ];
+ }
+ );
- const environmentName =
- materialisedAsset?.attributes?.assetDbtEnvironmentName;
- const projectName = materialisedAsset?.attributes?.assetDbtProjectName;
- // Generating asset information
- const assetInfo = `### ${get_image_url_getConnectorImage(
- asset.attributes.connectorName
- )} [${asset.displayText}](${github_integration_ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }/overview?utm_source=dbt_github_action) ${
- asset.attributes?.certificateStatus
- ? get_image_url_getCertificationImage(asset.attributes.certificateStatus)
- : ""
- }
-Materialised asset: ${get_image_url_getConnectorImage(
- materialisedAsset.attributes.connectorName
- )} [${materialisedAsset.attributes.name}](${github_integration_ATLAN_INSTANCE_URL}/assets/${
- materialisedAsset.guid
- }/overview?utm_source=dbt_github_action) ${
- materialisedAsset.attributes?.certificateStatus
- ? get_image_url_getCertificationImage(materialisedAsset.attributes.certificateStatus)
- : ""
- }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ""}${
- projectName ? ` | Project Name: \`${projectName}\`` : ""
- }`;
+ // Sorting the impactedData first by typeName and then by connectorName
+ impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
+ impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
+
+ // Creating rows for the downstream table
+ let rows = impactedData.map(
+ ([
+ guid,
+ displayText,
+ connectorName,
+ typeName,
+ description,
+ certificateStatus,
+ owners,
+ meanings,
+ classifications,
+ sourceUrl,
+ ]) => {
+ // Getting connector and certification images
+ const connectorImage = getConnectorImage(connectorName);
+ const certificationImage = certificateStatus
+ ? getCertificationImage(certificateStatus)
+ : "";
- // Generating the downstream table
- const downstreamTable = `${
- downstreamAssets.entityCount
- } downstream assets 👇
+ return [
+ `${connectorImage} [${displayText}](${ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_github_action) ${certificationImage}`,
+ `\`${typeName}\``,
+ description,
+ owners,
+ meanings,
+ classifications,
+ sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
+ ];
+ }
+ );
-Name | Type | Description | Owners | Terms | Classifications | Source URL
---- | --- | --- | --- | --- | --- | ---
-${rows
- .map((row) =>
- row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
- )
- .join("\n")}
+ const environmentName =
+ materialisedAsset?.attributes?.assetDbtEnvironmentName;
+ const projectName = materialisedAsset?.attributes?.assetDbtProjectName;
+ // Generating asset information
-${
- downstreamAssets.hasMore
- ? `[See more downstream assets at Atlan](${github_integration_ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_github_action)`
- : ""
-}
+ const assetInfo = getAssetInfo(
+ ATLAN_INSTANCE_URL,
+ asset,
+ materialisedAsset,
+ environmentName,
+ projectName
+ );
- `;
+ // Generating the downstream table
+ const downstreamTable = getDownstreamTable(
+ ATLAN_INSTANCE_URL,
+ downstreamAssets,
+ rows,
+ materialisedAsset
+ );
- // Generating the "View asset in Atlan" button
- const viewAssetButton = `${get_image_url_getImageURL(
- "atlan-logo",
- 15,
- 15
- )} [View asset in Atlan](${github_integration_ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }/overview?utm_source=dbt_github_action)`;
+ // Generating the "View asset in Atlan" button
+ const viewAssetButton = getViewAssetButton(ATLAN_INSTANCE_URL, asset);
- // Generating the final comment based on the presence of downstream assets
- if (downstreamAssets.entities.length > 0) {
- return `${assetInfo}
+ // Generating the final comment based on the presence of downstream assets
+ if (downstreamAssets.entities.length > 0) {
+ return `${assetInfo}
${downstreamTable}
${viewAssetButton}`;
- } else {
- return `${assetInfo}
+ } else {
+ return `${assetInfo}
No downstream assets found.
${viewAssetButton}`;
+ }
+ } catch (error) {
+ logger_logger.withError(
+ `Error rendering Downstream Assets: ${error.message}`,
+ integrationName,
+ headSHA,
+ "renderDownstreamAssetsComment"
+ );
+ throw error;
}
}
}
@@ -21880,10 +26533,16 @@ ${viewAssetButton}`;
var lib = __nccwpck_require__(2760);
// EXTERNAL MODULE: ./node_modules/xcase/es5/index.js
var es5 = __nccwpck_require__(7020);
+// EXTERNAL MODULE: ./node_modules/async-sema/lib/index.js
+var async_sema_lib = __nccwpck_require__(1884);
+// EXTERNAL MODULE: ./node_modules/micromatch/index.js
+var micromatch = __nccwpck_require__(6228);
;// CONCATENATED MODULE: ./node_modules/@gitbeaker/requester-utils/dist/index.mjs
+
+
// src/RequesterUtils.ts
function formatQuery(params = {}) {
const decamelized = (0,es5/* decamelizeKeys */.iF)(params);
@@ -21926,10 +26585,24 @@ async function defaultOptionsHandler(resourceOptions, {
defaultOptions.searchParams = q;
return Promise.resolve(defaultOptions);
}
+function createRateLimiters(rateLimitOptions = {}) {
+ const rateLimiters = {};
+ Object.entries(rateLimitOptions).forEach(([key, config]) => {
+ if (typeof config === "number")
+ rateLimiters[key] = (0,async_sema_lib.RateLimit)(config, { timeUnit: 6e4 });
+ else
+ rateLimiters[key] = {
+ method: config.method.toUpperCase(),
+ limit: (0,async_sema_lib.RateLimit)(config.limit, { timeUnit: 6e4 })
+ };
+ });
+ return rateLimiters;
+}
function createRequesterFn(optionsHandler, requestHandler) {
const methods = ["get", "post", "put", "patch", "delete"];
return (serviceOptions) => {
const requester = {};
+ const rateLimiters = createRateLimiters(serviceOptions.rateLimits);
methods.forEach((m) => {
requester[m] = async (endpoint, options) => {
const defaultRequestOptions = await defaultOptionsHandler(serviceOptions, {
@@ -21937,13 +26610,13 @@ function createRequesterFn(optionsHandler, requestHandler) {
method: m.toUpperCase()
});
const requestOptions = await optionsHandler(serviceOptions, defaultRequestOptions);
- return requestHandler(endpoint, requestOptions);
+ return requestHandler(endpoint, { ...requestOptions, rateLimiters });
};
});
return requester;
};
}
-function extendClass(Base, customConfig = {}) {
+function extendClass(Base, customConfig) {
return class extends Base {
constructor(...options) {
const [config, ...opts] = options;
@@ -21958,11 +26631,58 @@ function presetResourceArguments(resources, customConfig = {}) {
});
return updated;
}
+function getMatchingRateLimiter(endpoint, rateLimiters = {}, method = "GET") {
+ const sortedEndpoints = Object.keys(rateLimiters).sort().reverse();
+ const match = sortedEndpoints.find((ep) => micromatch.isMatch(endpoint, ep));
+ const rateLimitConfig = match && rateLimiters[match];
+ if (rateLimitConfig && typeof rateLimitConfig !== "object") {
+ return rateLimitConfig;
+ }
+ if (rateLimitConfig && rateLimitConfig.method.toUpperCase() === method.toUpperCase()) {
+ return rateLimitConfig.limit;
+ }
+ return (0,async_sema_lib.RateLimit)(3e3, { timeUnit: 6e4 });
+}
// src/BaseResource.ts
function getDynamicToken(tokenArgument) {
return tokenArgument instanceof Function ? tokenArgument() : Promise.resolve(tokenArgument);
}
+var DEFAULT_RATE_LIMITS = Object.freeze({
+ // Default rate limit
+ "**": 3e3,
+ // Import/Export
+ "projects/import": 6,
+ "projects/*/export": 6,
+ "projects/*/download": 1,
+ "groups/import": 6,
+ "groups/*/export": 6,
+ "groups/*/download": 1,
+ // Note creation
+ "projects/*/issues/*/notes": {
+ method: "post",
+ limit: 300
+ },
+ "projects/*/snippets/*/notes": {
+ method: "post",
+ limit: 300
+ },
+ "projects/*/merge_requests/*/notes": {
+ method: "post",
+ limit: 300
+ },
+ "groups/*/epics/*/notes": {
+ method: "post",
+ limit: 300
+ },
+ // Repositories - get file archive
+ "projects/*/repository/archive*": 5,
+ // Project Jobs
+ "projects/*/jobs": 600,
+ // Member deletion
+ "projects/*/members": 60,
+ "groups/*/members": 60
+});
var BaseResource = class {
url;
requester;
@@ -21981,6 +26701,7 @@ var BaseResource = class {
prefixUrl = "",
rejectUnauthorized = true,
queryTimeout = 3e5,
+ rateLimits = DEFAULT_RATE_LIMITS,
...tokens
}) {
if (!requesterFn)
@@ -22009,7 +26730,7 @@ var BaseResource = class {
}
if (sudo)
this.headers.Sudo = `${sudo}`;
- this.requester = requesterFn({ ...this });
+ this.requester = requesterFn({ ...this, rateLimits });
}
};
@@ -22371,6 +27092,7 @@ var ApplicationPlanLimits = class extends BaseResource {
...opts
} = options;
return RequestHelper.put()(this, "application/plan_limits", {
+ ...opts,
searchParams: {
planName,
ciPipelineSize,
@@ -22390,8 +27112,7 @@ var ApplicationPlanLimits = class extends BaseResource {
pypiMaxFileSize,
terraformModuleMaxFileSize,
storageSizeLimit
- },
- opts
+ }
});
}
};
@@ -22487,6 +27208,18 @@ var BroadcastMessages = class extends BaseResource {
);
}
};
+var CodeSuggestions = class extends BaseResource {
+ createAccessToken(options) {
+ return RequestHelper.post()(this, "code_suggestions/tokens", options);
+ }
+ generateCompletion(options) {
+ return RequestHelper.post()(
+ this,
+ "code_suggestions/completions",
+ options
+ );
+ }
+};
var Composer = class extends BaseResource {
create(projectId, options) {
return RequestHelper.post()(
@@ -23881,6 +28614,35 @@ var GeoNodes = class extends BaseResource {
return RequestHelper.get()(this, `geo_nodes/${geonodeId}/status`, options);
}
};
+var GeoSites = class extends BaseResource {
+ all(options) {
+ return RequestHelper.get()(this, "geo_sites", options);
+ }
+ allStatuses(options) {
+ return RequestHelper.get()(this, "geo_sites/statuses", options);
+ }
+ allFailures(options) {
+ return RequestHelper.get()(this, "geo_sites/current/failures", options);
+ }
+ create(name, url12, options) {
+ return RequestHelper.post()(this, "geo_sites", { name, url: url12, ...options });
+ }
+ edit(geositeId, options) {
+ return RequestHelper.put()(this, `geo_sites/${geositeId}`, options);
+ }
+ repair(geositeId, options) {
+ return RequestHelper.post()(this, `geo_sites/${geositeId}/repair`, options);
+ }
+ remove(geositeId, options) {
+ return RequestHelper.del()(this, `geo_sites/${geositeId}`, options);
+ }
+ show(geositeId, options) {
+ return RequestHelper.get()(this, `geo_sites/${geositeId}`, options);
+ }
+ showStatus(geositeId, options) {
+ return RequestHelper.get()(this, `geo_sites/${geositeId}/status`, options);
+ }
+};
// src/resources/GitignoreTemplates.ts
var GitignoreTemplates = class extends ResourceTemplates {
@@ -24391,6 +29153,18 @@ var Search = class extends BaseResource {
});
}
};
+var SearchAdmin = class extends BaseResource {
+ all(options) {
+ return RequestHelper.get()(this, "admin/search/migrations", options);
+ }
+ show(versionOrName, options) {
+ return RequestHelper.get()(
+ this,
+ endpoint`admin/search/migrations/${versionOrName}`,
+ options
+ );
+ }
+};
var ServiceData = class extends BaseResource {
showMetricDefinitions(options) {
return RequestHelper.get()(this, "usage_data/metric_definitions", options);
@@ -27905,6 +32679,36 @@ var GroupDORA4Metrics = class extends ResourceDORA4Metrics {
super("groups", options);
}
};
+var GroupEpicBoards = class extends BaseResource {
+ all(groupId, options) {
+ return RequestHelper.get()(
+ this,
+ endpoint`groups/${groupId}/epic_boards`,
+ options
+ );
+ }
+ allLists(groupId, boardId, options) {
+ return RequestHelper.get()(
+ this,
+ endpoint`groups/${groupId}/epic_boards/${boardId}/lists`,
+ options
+ );
+ }
+ show(groupId, boardId, options) {
+ return RequestHelper.get()(
+ this,
+ endpoint`groups/${groupId}/epic_boards/${boardId}`,
+ options
+ );
+ }
+ showList(groupId, boardId, listId, options) {
+ return RequestHelper.get()(
+ this,
+ endpoint`groups/${groupId}/epic_boards/${boardId}/lists/${listId}`,
+ options
+ );
+ }
+};
// src/resources/GroupHooks.ts
var GroupHooks = class extends ResourceHooks {
@@ -28259,6 +33063,44 @@ var GroupSAMLIdentities = class extends BaseResource {
);
}
};
+var GroupSAMLLinks = class extends BaseResource {
+ all(groupId, options) {
+ return RequestHelper.get()(
+ this,
+ endpoint`groups/${groupId}/saml_group_links`,
+ options
+ );
+ }
+ create(groupId, samlGroupName, accessLevel, options) {
+ return RequestHelper.post()(
+ this,
+ endpoint`groups/${groupId}/saml_group_links`,
+ {
+ accessLevel,
+ samlGroupName,
+ ...options
+ }
+ );
+ }
+ remove(groupId, samlGroupName, options) {
+ return RequestHelper.del()(this, endpoint`groups/${groupId}/saml_group_links`, {
+ searchParams: {
+ samlGroupName
+ },
+ ...options
+ });
+ }
+ show(groupId, samlGroupName, options) {
+ return RequestHelper.get()(
+ this,
+ endpoint`groups/${groupId}/saml_group_links`,
+ {
+ samlGroupName,
+ ...options
+ }
+ );
+ }
+};
var GroupSCIMIdentities = class extends BaseResource {
all(groupId, options) {
return RequestHelper.get()(
@@ -28620,6 +33462,7 @@ var resources = {
AuditEvents,
Avatar,
BroadcastMessages,
+ CodeSuggestions,
Composer,
Conan,
DashboardAnnotations,
@@ -28631,6 +33474,7 @@ var resources = {
Events,
Experiments,
GeoNodes,
+ GeoSites,
GitignoreTemplates,
GitLabCIYMLTemplates,
Import,
@@ -28651,6 +33495,7 @@ var resources = {
PyPI,
RubyGems,
Search,
+ SearchAdmin,
ServiceData,
SidekiqMetrics,
SidekiqQueues,
@@ -28763,6 +33608,7 @@ var resources = {
GroupBadges,
GroupCustomAttributes,
GroupDORA4Metrics,
+ GroupEpicBoards,
GroupHooks,
GroupImportExports,
GroupInvitations,
@@ -28780,6 +33626,7 @@ var resources = {
GroupRepositoryStorageMoves,
Groups,
GroupSAMLIdentities,
+ GroupSAMLLinks,
GroupSCIMIdentities,
GroupVariables,
GroupWikis,
@@ -28871,7 +33718,8 @@ function getConditionalMode(endpoint) {
async function defaultRequestHandler(endpoint, options) {
const retryCodes = [429, 502];
const maxRetries = 10;
- const { prefixUrl, asStream, searchParams, ...opts } = options || {};
+ const { prefixUrl, asStream, searchParams, rateLimiters, method, ...opts } = options || {};
+ const endpointRateLimit = getMatchingRateLimiter(endpoint, rateLimiters, method);
let baseUrl;
if (prefixUrl)
baseUrl = prefixUrl.endsWith("/") ? prefixUrl : `${prefixUrl}/`;
@@ -28879,7 +33727,8 @@ async function defaultRequestHandler(endpoint, options) {
url.search = searchParams || "";
const mode = getConditionalMode(endpoint);
for (let i = 0; i < maxRetries; i += 1) {
- const request = new Request(url, { ...opts, mode });
+ const request = new Request(url, { ...opts, method, mode });
+ await endpointRateLimit();
const response = await fetch(request).catch((e) => {
if (e.name === "TimeoutError" || e.name === "AbortError") {
throw new Error("Query timeout was reached");
@@ -28912,6 +33761,7 @@ var {
AuditEvents: dist_AuditEvents,
Avatar: dist_Avatar,
BroadcastMessages: dist_BroadcastMessages,
+ CodeSuggestions: dist_CodeSuggestions,
Composer: dist_Composer,
Conan: dist_Conan,
DashboardAnnotations: dist_DashboardAnnotations,
@@ -28923,6 +33773,7 @@ var {
Events: dist_Events,
Experiments: dist_Experiments,
GeoNodes: dist_GeoNodes,
+ GeoSites: dist_GeoSites,
GitignoreTemplates: dist_GitignoreTemplates,
GitLabCIYMLTemplates: dist_GitLabCIYMLTemplates,
Import: dist_Import,
@@ -28943,6 +33794,7 @@ var {
PyPI: dist_PyPI,
RubyGems: dist_RubyGems,
Search: dist_Search,
+ SearchAdmin: dist_SearchAdmin,
ServiceData: dist_ServiceData,
SidekiqMetrics: dist_SidekiqMetrics,
SidekiqQueues: dist_SidekiqQueues,
@@ -29055,6 +33907,7 @@ var {
GroupBadges: dist_GroupBadges,
GroupCustomAttributes: dist_GroupCustomAttributes,
GroupDORA4Metrics: dist_GroupDORA4Metrics,
+ GroupEpicBoards: dist_GroupEpicBoards,
GroupHooks: dist_GroupHooks,
GroupImportExports: dist_GroupImportExports,
GroupInvitations: dist_GroupInvitations,
@@ -29072,6 +33925,7 @@ var {
GroupRepositoryStorageMoves: dist_GroupRepositoryStorageMoves,
Groups: dist_Groups,
GroupSAMLIdentities: dist_GroupSAMLIdentities,
+ GroupSAMLLinks: dist_GroupSAMLLinks,
GroupSCIMIdentities: dist_GroupSCIMIdentities,
GroupVariables: dist_GroupVariables,
GroupWikis: dist_GroupWikis,
@@ -29087,10 +33941,111 @@ var {
-;// CONCATENATED MODULE: ./adapters/integrations/gitlab-integration.js
-// gitlabIntegration.js
+;// CONCATENATED MODULE: ./adapters/templates/gitlab-integration.js
+
+
+function gitlab_integration_getErrorResponseStatus401 (ATLAN_INSTANCE_URL, CI_PROJECT_NAME, CI_PROJECT_NAMESPACE) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` as this repository's CI/CD variable.
+
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Set your CI/CD variables [here](https://gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/-/settings/ci_cd). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+function gitlab_integration_getErrorResponseStatusUndefined(ATLAN_INSTANCE_URL, CI_PROJECT_NAME, CI_PROJECT_NAMESPACE) {
+ return `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` as this repository's CI/CD variable.
+
+Atlan Instance URL: ${ATLAN_INSTANCE_URL}
+
+Make sure your Atlan Instance URL is set in the following format.
+\`https://tenant.atlan.com\`
+
+Set your CI/CD variables [here](https://gitlab.com/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}/-/settings/ci_cd). For more information on how to setup the Atlan dbt Action, please read the [setup documentation here](https://github.com/atlanhq/dbt-action/blob/main/README.md).`
+}
+
+function gitlab_integration_getSetResourceOnAssetComment(tableMd, setResourceFailed) {
+ return `## 🎊 Congrats on the merge!
+
+ This pull request has been added as a resource to the following assets:
+ Name | Resource set successfully
+ --- | ---
+ ${tableMd}
+ ${setResourceFailed ? '> Seems like we were unable to set the resources for some of the assets due to insufficient permissions. To ensure that the pull request is linked as a resource, you will need to assign the right persona with requisite permissions to the API token.' : ''}
+ `
+}
+
+function gitlab_integration_getAssetInfo(ATLAN_INSTANCE_URL, asset, materialisedAsset, environmentName, projectName) {
+ return `### ${getConnectorImage(
+ asset.attributes.connectorName
+ )} [${asset.displayText}](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_gitlab_action) ${
+ asset.attributes?.certificateStatus
+ ? getCertificationImage(asset.attributes.certificateStatus)
+ : ""
+ }
+Materialised asset: ${getConnectorImage(
+ materialisedAsset.attributes.connectorName
+ )} [${materialisedAsset.attributes.name}](${ATLAN_INSTANCE_URL}/assets/${
+ materialisedAsset.guid
+ }/overview?utm_source=dbt_gitlab_action) ${
+ materialisedAsset.attributes?.certificateStatus
+ ? getCertificationImage(materialisedAsset.attributes.certificateStatus)
+ : ""
+ }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ""}${
+ projectName ? ` | Project Name: \`${projectName}\`` : ""
+ }`
+}
+
+function gitlab_integration_getDownstreamTable(ATLAN_INSTANCE_URL, downstreamAssets, rows, materialisedAsset) {
+ return `${
+ downstreamAssets.entityCount
+ } downstream assets 👇
+
+Name | Type | Description | Owners | Terms | Classifications | Source URL
+--- | --- | --- | --- | --- | --- | ---
+${rows
+ .map((row) =>
+ row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
+ )
+ .join("\n")}
+
+${
+ downstreamAssets.hasMore
+ ? `[See more downstream assets at Atlan](${ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_gitlab_action)`
+ : ""
+}
+
+ `
+}
+function gitlab_integration_getViewAssetButton(ATLAN_INSTANCE_URL, asset) {
+ return `${getImageURL(
+ "atlan-logo",
+ 15,
+ 15
+ )} [View asset in Atlan](${ATLAN_INSTANCE_URL}/assets/${
+ asset.guid
+ }/overview?utm_source=dbt_gitlab_action)`
+}
+
+function gitlab_integration_getMDCommentForModel(ATLAN_INSTANCE_URL, model) {
+ return `${getConnectorImage(model?.attributes?.connectorName)} [${
+ model?.displayText
+ }](${ATLAN_INSTANCE_URL}/assets/${model?.guid}/overview?utm_source=dbt_gitlab_action)`
+}
+
+function gitlab_integration_getMDCommentForMaterialisedView(ATLAN_INSTANCE_URL, materialisedView) {
+ return `${getConnectorImage(materialisedView?.attributes?.connectorName)} [${
+ materialisedView?.attributes?.name
+ }](${ATLAN_INSTANCE_URL}/assets/${materialisedView?.guid}/overview?utm_source=dbt_gitlab_action)`
+}
+function gitlab_integration_getTableMD(md, resp) {
+ return `${md} | ${resp ? '✅' : '❌'} \n`
+}
+;// CONCATENATED MODULE: ./adapters/integrations/gitlab-integration.js
+// gitlabIntegration.js
@@ -29100,9 +34055,8 @@ var {
-main.config();
-const gitlab_integration_ATLAN_INSTANCE_URL = process.env.ATLAN_INSTANCE_URL;
-const { IS_DEV: gitlab_integration_IS_DEV } = process.env;
+const gitlab_integration_integrationName = "gitlab";
+var CI_MERGE_REQUEST_IID;
class GitLabIntegration extends IntegrationInterface {
constructor(token) {
@@ -29110,288 +34064,576 @@ class GitLabIntegration extends IntegrationInterface {
}
async run() {
- //Done
- console.log("Run Gitlab");
- const timeStart = Date.now();
+ try {
+ const timeStart = Date.now();
+ const gitlab = new dist_Gitlab({
+ host: "https://gitlab.com",
+ token: this.token,
+ });
- const gitlab = new dist_Gitlab({
- host: "https://gitlab.com",
- token: this.token,
- });
+ CI_MERGE_REQUEST_IID = await getCIMergeRequestIID(
+ gitlab,
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+ );
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ var mergeRequestCommit = await gitlab.Commits.allMergeRequests(
+ CI_PROJECT_ID,
+ CI_COMMIT_SHA
+ );
- if (!(await this.authIntegration({ gitlab })))
- //Done
- throw { message: "Wrong API Token" };
+ logger_logger.withInfo(
+ "GitLab Integration is running...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
- const { state, web_url, source_branch } = await gitlab.MergeRequests.show(
- CI_PROJECT_PATH,
- CI_MERGE_REQUEST_IID
- );
+ if (!(await this.authIntegration({ gitlab }))) {
+ logger_logger.withError(
+ "Authentication failed. Wrong API Token.",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
+ throw { message: "Wrong API Token" };
+ }
- let total_assets = 0;
+ let total_assets = 0;
+
+ if (
+ mergeRequestCommit.length &&
+ mergeRequestCommit[0]?.state == "merged"
+ ) {
+ const { web_url, target_branch, diff_refs } =
+ await gitlab.MergeRequests.show(
+ CI_PROJECT_PATH,
+ mergeRequestCommit[0]?.iid
+ );
+ total_assets = await this.setResourceOnAsset({
+ gitlab,
+ web_url,
+ target_branch,
+ diff_refs,
+ });
+ } else {
+ const { target_branch, diff_refs } = await gitlab.MergeRequests.show(
+ CI_PROJECT_PATH,
+ CI_MERGE_REQUEST_IID
+ );
- if (state === "opened") {
- total_assets = await this.printDownstreamAssets({
- gitlab,
- source_branch,
- });
- } else if (state === "merged") {
- total_assets = await this.setResourceOnAsset({
- gitlab,
- web_url,
- source_branch,
- });
- }
+ total_assets = await this.printDownstreamAssets({
+ gitlab,
+ target_branch,
+ diff_refs,
+ });
+ }
- if (total_assets !== 0)
- this.sendSegmentEventOfIntegration("dbt_ci_action_run", {
- asset_count: total_assets,
- total_time: Date.now() - timeStart,
- });
- }
+ if (total_assets !== 0)
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_run",
+ properties: {
+ asset_count: total_assets,
+ total_time: Date.now() - timeStart,
+ },
+ });
- async printDownstreamAssets({ gitlab, source_branch }) {
- //Done
- // Implementation for printing impact on GitHub
- // Use this.token to access the token
- const changedFiles = await this.getChangedFiles({ gitlab }); //Complete
+ logger_logger.withInfo(
+ "Successfully Completed DBT_CI_PIPELINE",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
+ } catch (error) {
+ logger_logger.withError(
+ `Error in run(): ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "run"
+ );
+ throw error;
+ }
+ }
- let comments = ``;
- let totalChangedFiles = 0;
+ async printDownstreamAssets({ gitlab, target_branch, diff_refs }) {
+ logger_logger.withInfo(
+ "Printing downstream assets...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
- for (const { fileName, filePath, headSHA } of changedFiles) {
- const assetName = await this.getAssetName({
- //Complete
- gitlab,
- fileName,
- filePath,
- headSHA,
- });
+ try {
+ const changedFiles = await this.getChangedFiles({ gitlab, diff_refs });
- const environments = getGitLabEnvironments();
+ let comments = ``;
+ let totalChangedFiles = 0;
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === source_branch) {
- environment = environmentName;
- break;
+ for (const { fileName, filePath, headSHA, status } of changedFiles) {
+ logger_logger.withInfo(
+ `Processing file: ${fileName}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ const aliasName = await this.getAssetName({
+ gitlab,
+ fileName,
+ filePath,
+ headSHA,
+ });
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
+
+ const environments = getGitLabEnvironments();
+ let environment = null;
+ for (const baseBranchName of Object.keys(environments)) {
+ const environmentName = environments[baseBranchName];
+ if (baseBranchName === target_branch) {
+ environment = environmentName;
+ break;
+ }
}
- }
- const asset = await getAsset({
- //Complete
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "gitlab",
- });
+ logger_logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "gitlab",
+ });
+
+ if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
+
+ if (status === "added") {
+ logger_logger.withInfo(
+ `New model added: ${fileName}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ comments += getNewModelAddedComment(fileName);
+ totalChangedFiles++;
+ continue;
+ }
+
+ if (asset.error) {
+ logger_logger.withError(
+ `Asset error for ${assetName}: ${asset.error}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ comments += asset.error;
+ totalChangedFiles++;
+ continue;
+ }
+
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
+
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
+
+ const { guid } = asset;
+
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "gitlab"
+ );
+
+ if (downstreamAssets.error) {
+ logger_logger.withError(
+ `Downstream assets error for ${assetName}: ${downstreamAssets.error}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+ comments += downstreamAssets.error;
+ totalChangedFiles++;
+ continue;
+ }
+
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
+
+ const classifications = await getClassifications({
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ });
+
+ const comment = await this.renderDownstreamAssetsComment({
+ asset,
+ downstreamAssets,
+ classifications,
+ materialisedAsset,
+ });
+
+ comments += comment;
- if (asset.error) {
- comments += asset.error;
totalChangedFiles++;
- continue;
}
- //Cross-check this part once with Jaagrav.
+ comments = getBaseComment(totalChangedFiles, comments);
- const totalModifiedFiles = changedFiles.filter(
- (i) => i.status === "modified"
- ).length;
+ const existingComment = await this.checkCommentExists({ gitlab });
- const { guid } = asset.attributes.sqlAsset;
- const timeStart = Date.now();
- const downstreamAssets = await getDownstreamAssets(
- //Done
- asset,
- guid,
- totalModifiedFiles,
- this.sendSegmentEventOfIntegration,
- "gitlab"
+ logger_logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+
+ if (totalChangedFiles > 0)
+ await this.createIssueComment({
+ gitlab,
+ content: comments,
+ comment_id: existingComment?.id,
+ });
+
+ if (totalChangedFiles === 0 && existingComment)
+ await this.deleteComment({ gitlab, comment_id: existingComment?.id });
+
+ logger_logger.withInfo(
+ "Successfully printed Downstream Assets",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
+ );
+
+ return totalChangedFiles;
+ } catch (error) {
+ logger_logger.withError(
+ `Error in printDownstreamAssets: ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "printDownstreamAssets"
);
+ throw error;
+ }
+ }
- if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
+ async setResourceOnAsset({ gitlab, web_url, target_branch, diff_refs }) {
+ logger_logger.withInfo(
+ "Setting resources on assets...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
- if (downstreamAssets.error) {
- comments += downstreamAssets.error;
- totalChangedFiles++;
- continue;
+ try {
+ const changedFiles = await this.getChangedFiles({ gitlab, diff_refs });
+
+ var totalChangedFiles = 0;
+ let tableMd = ``;
+ let setResourceFailed = false;
+ if (changedFiles.length === 0) {
+ logger_logger.withInfo(
+ "No changed files found. Skipping resource setup.",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ return totalChangedFiles;
}
- this.sendSegmentEventOfIntegration("dbt_ci_action_downstream_unfurl", {
- //Complete
- asset_guid: asset.guid,
- asset_type: asset.typeName,
- downstream_count: downstreamAssets.length,
- total_fetch_time: Date.now() - timeStart,
- });
+ for (const { fileName, filePath, headSHA } of changedFiles) {
+ const aliasName = await this.getAssetName({
+ gitlab,
+ fileName,
+ filePath,
+ headSHA,
+ });
- const comment = await this.renderDownstreamAssetsComment({
- //Complete
- asset,
- downstreamAssets,
- });
+ const assetName = IGNORE_MODEL_ALIAS_MATCHING ? fileName : aliasName;
- comments += comment;
+ logger_logger.withInfo(
+ `Resolved asset name: ${assetName}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
- totalChangedFiles++;
- }
+ const environments = getGitLabEnvironments();
+ let environment = null;
+ for (const baseBranchName of Object.keys(environments)) {
+ const environmentName = environments[baseBranchName];
+ if (baseBranchName === target_branch) {
+ environment = environmentName;
+ break;
+ }
+ }
- comments = `### ${get_image_url_getImageURL("atlan-logo", 15, 15)} Atlan impact analysis
-Here is your downstream impact analysis for **${totalChangedFiles} ${
- totalChangedFiles > 1 ? "models" : "model"
- }** you have edited.
+ logger_logger.withInfo(
+ `Processing asset: ${assetName} in environment: ${environment}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
-${comments}`;
+ const asset = await getAsset({
+ name: assetName,
+ sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
+ environment: environment,
+ integration: "gitlab",
+ });
- const existingComment = await this.checkCommentExists({ gitlab }); //Complete
+ if (asset.error) {
+ logger_logger.withError(
+ `Failed to retrieve asset: ${assetName}, Error: ${asset.error}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
- if (totalChangedFiles > 0)
- await this.createIssueComment({
- //Complete
- gitlab,
- comments,
- comment_id: existingComment?.id,
- });
+ const materialisedAsset = asset?.attributes?.dbtModelSqlAssets?.[0];
+ const timeStart = Date.now();
- if (totalChangedFiles === 0 && existingComment)
- await this.deleteComment({ gitlab, comment_id: existingComment.id }); //Complete
+ const totalModifiedFiles = changedFiles.filter(
+ (i) => i.status === "modified"
+ ).length;
- return totalChangedFiles;
- }
+ const { guid } = asset;
- async setResourceOnAsset({ gitlab, web_url, source_branch }) {
- //Done
- // Implementation for setting resources on GitHub
- // Use this.token to access the token
- const changedFiles = await this.getChangedFiles({ gitlab }); //Done
- var totalChangedFiles = 0;
+ const downstreamAssets = await getDownstreamAssets(
+ asset,
+ materialisedAsset.guid,
+ totalModifiedFiles,
+ this.sendSegmentEventOfIntegration,
+ "gitlab"
+ );
- if (changedFiles.length === 0) return;
+ if (downstreamAssets.error) {
+ logger_logger.withError(
+ `Failed to retrieve downstream assets for: ${assetName}, Error: ${downstreamAssets.error}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ continue;
+ }
+
+ this.sendSegmentEventOfIntegration({
+ action: "dbt_ci_action_downstream_unfurl",
+ properties: {
+ asset_guid: asset.guid,
+ asset_type: asset.typeName,
+ downstream_count: downstreamAssets.entities.length,
+ total_fetch_time: Date.now() - timeStart,
+ },
+ });
- for (const { fileName, filePath, headSHA } of changedFiles) {
- const assetName = await this.getAssetName({
- gitlab,
- fileName,
- filePath,
- headSHA,
- });
+ const model = asset;
+ const materialisedView = asset?.attributes?.dbtModelSqlAssets?.[0];
- const environments = getGitLabEnvironments();
+ var lines = CI_COMMIT_MESSAGE.split("\n");
+ var CI_MERGE_REQUEST_TITLE = lines[2];
- let environment = null;
- for (const [baseBranchName, environmentName] of environments) {
- if (baseBranchName === source_branch) {
- environment = environmentName;
- break;
+ if (downstreamAssets.entityCount != 0) {
+ if (model) {
+ const { guid: modelGuid } = model;
+ const resp = await createResource(
+ modelGuid,
+ CI_MERGE_REQUEST_TITLE,
+ web_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = gitlab_integration_getMDCommentForModel(ATLAN_INSTANCE_URL, model);
+ tableMd += gitlab_integration_getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger_logger.withError(
+ `Setting resource failed for model: ${modelGuid}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
+
+ if (materialisedView) {
+ const { guid: tableAssetGuid } = materialisedView;
+ const resp = await createResource(
+ tableAssetGuid,
+ CI_MERGE_REQUEST_TITLE,
+ web_url,
+ this.sendSegmentEventOfIntegration
+ );
+ const md = gitlab_integration_getMDCommentForMaterialisedView(
+ ATLAN_INSTANCE_URL,
+ materialisedView
+ );
+ tableMd += gitlab_integration_getTableMD(md, resp);
+ if (!resp) {
+ setResourceFailed = true;
+ logger_logger.withError(
+ `Setting resource failed for materialized view: ${tableAssetGuid}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ }
+ }
}
+
+ totalChangedFiles++;
}
- const asset = await getAsset({
- //Done
- name: assetName,
- sendSegmentEventOfIntegration: this.sendSegmentEventOfIntegration,
- environment: environment,
- integration: "gitlab",
+ const comment = await this.createIssueComment({
+ gitlab,
+ content: gitlab_integration_getSetResourceOnAssetComment(tableMd, setResourceFailed),
+ comment_id: null,
+ forceNewComment: true,
});
- if (!asset) continue;
-
- const { guid: modelGuid } = asset;
- const { guid: tableAssetGuid } = asset.attributes.sqlAsset;
-
- await createResource(
- //Done
- //Complete
- modelGuid,
- "Pull Request on GitLab",
- web_url,
- this.sendSegmentEventOfIntegration
- );
- await createResource(
- //Done
- tableAssetGuid,
- "Pull Request on GitLab",
- web_url,
- this.sendSegmentEventOfIntegration
+ logger_logger.withInfo(
+ "Successfully set the resource on the asset",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
);
- totalChangedFiles++;
+ return totalChangedFiles;
+ } catch (error) {
+ logger_logger.withError(
+ `Error in setResourceOnAsset: ${error}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "setResourceOnAsset"
+ );
+ throw error;
}
-
- const comment = await this.createIssueComment({
- //Done
- //Complete
- gitlab,
- content: `🎊 Congrats on the merge!
-
-This pull request has been added as a resource to all the assets modified. ✅
-`,
- comment_id: null,
- forceNewComment: true,
- });
-
- return totalChangedFiles;
}
async authIntegration({ gitlab }) {
- //Done
- const response = await auth();
-
- if (response?.status === 401) {
- //Complete
- await this.createIssueComment(
- gitlab,
- `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Bearer Token as \`ATLAN_API_TOKEN\` in your .gitlab-ci.yml file.
+ logger_logger.withInfo(
+ "Authenticating with Atlan",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
-Atlan Instance URL: ${gitlab_integration_ATLAN_INSTANCE_URL}`
- );
- return false;
- }
+ try {
+ const response = await auth();
- if (response === undefined) {
- await this.createIssueComment(
- gitlab,
- `We couldn't connect to your Atlan Instance, please make sure to set the valid Atlan Instance URL as \`ATLAN_INSTANCE_URL\` in your .gitlab-ci.yml file.
+ const existingComment = await this.checkCommentExists({ gitlab });
-Atlan Instance URL: ${gitlab_integration_ATLAN_INSTANCE_URL}
+ logger_logger.withInfo(
+ `Existing Comment: ${existingComment?.id}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
-Make sure your Atlan Instance URL is set in the following format.
-\`https://tenant.atlan.com\`
+ if (response?.status === 401) {
+ logger_logger.withError(
+ "Authentication failed: Status 401",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ gitlab,
+ content: gitlab_integration_getErrorResponseStatus401(
+ ATLAN_INSTANCE_URL,
+ CI_PROJECT_NAME,
+ CI_PROJECT_NAMESPACE
+ ),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
-`
+ if (response === undefined) {
+ logger_logger.withError(
+ "Authentication failed: Undefined response",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
+ await this.createIssueComment({
+ gitlab,
+ content: gitlab_integration_getErrorResponseStatusUndefined(
+ ATLAN_INSTANCE_URL,
+ CI_PROJECT_NAME,
+ CI_PROJECT_NAMESPACE
+ ),
+ comment_id: existingComment?.id,
+ });
+ return false;
+ }
+ logger_logger.withInfo(
+ "Successfully Authenticated with Atlan",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
);
- return false;
+ return true;
+ } catch (error) {
+ logger_logger.withError(
+ `Error in authIntegration: ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "authIntegration"
+ );
+ throw error;
}
-
- return true;
}
async createIssueComment({
- //Done
- //Complete
gitlab,
content,
comment_id = null,
forceNewComment = false,
}) {
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ logger_logger.withInfo(
+ "Creating an issue comment...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "createIssueComment"
+ );
content = `
${content}`;
- console.log(content);
-
- if (gitlab_integration_IS_DEV) return content;
+ if (IS_DEV) {
+ logger_logger.withInfo(
+ "Development mode enabled. Skipping comment creation.",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "createIssueComment"
+ );
+ return content;
+ }
- if (comment_id && !forceNewComment)
+ if (comment_id && !forceNewComment) {
return await gitlab.MergeRequestNotes.edit(
- CI_PROJECT_PATH,
+ CI_PROJECT_ID,
CI_MERGE_REQUEST_IID,
comment_id,
- content
+ {
+ body: content,
+ }
);
+ }
return await gitlab.MergeRequestNotes.create(
CI_PROJECT_PATH,
CI_MERGE_REQUEST_IID,
@@ -29400,147 +34642,277 @@ ${content}`;
}
async sendSegmentEventOfIntegration({ action, properties }) {
- //Done
- //Complete
- // Implement your sendSegmentEvent logic here
- // IMPORT ATLAN_INSTANCE_URL.
- const domain = new URL(gitlab_integration_ATLAN_INSTANCE_URL).hostname;
- const { CI_PROJECT_PATH, CI_JOB_URL } = process.env;
-
- const raw = stringify({
- category: "integration",
- object: "gitlab",
- action,
- userId: "atlan-annonymous-github",
- properties: {
- ...properties,
- gitlab_job_id: CI_JOB_URL,
- domain,
- },
- });
- // IMPORT SEGMENTEVENT
- return sendSegmentEvent(action, raw);
+ try {
+ const domain = new URL(ATLAN_INSTANCE_URL).hostname;
+ logger_logger.withInfo(
+ `Sending Segment event for action: ${action}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "sendSegmentEventOfIntegration"
+ );
+
+ const raw = stringify({
+ category: "integration",
+ object: "gitlab",
+ action,
+ userId: "atlan-annonymous-github",
+ properties: {
+ ...properties,
+ gitlab_job_id: CI_JOB_URL,
+ domain,
+ },
+ });
+
+ return sendSegmentEvent(action, raw);
+ } catch (error) {
+ logger_logger.withError(
+ `Error sending Segment event for action: ${action} - ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "sendSegmentEventOfIntegration"
+ );
+ throw error;
+ }
}
- async getChangedFiles({ gitlab }) {
- //Done
- //Complete
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ async getChangedFiles({ gitlab, diff_refs }) {
+ try {
+ logger_logger.withInfo(
+ "Fetching changed files...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
+ );
- const { changes, diff_refs } = await gitlab.MergeRequests.changes(
- CI_PROJECT_PATH,
- CI_MERGE_REQUEST_IID
- );
- var changedFiles = changes
- .map(({ new_path, old_path }) => {
- try {
- const [modelName] = new_path
- .match(/.*models\/(.*)\.sql/)[1]
- .split("/")
- .reverse()[0]
- .split(".");
-
- //Cross-check this with Jaagrav. ###
- if (modelName) {
- if (old_path === null) {
- return {
- fileName: modelName,
- filePath: new_path,
- headSHA: diff_refs.head_sha,
- status: "added",
- };
- } else if (new_path !== old_path) {
- // File is renamed or moved
- return {
- fileName: modelName,
- filePath: new_path,
- headSHA: diff_refs.head_sha,
- status: "renamed_or_moved",
- };
- } else {
- // File is modified
- return {
- fileName: modelName,
- filePath: new_path,
- headSHA: diff_refs.head_sha,
- status: "modified",
- };
+ var changes = await gitlab.MergeRequests.allDiffs(
+ CI_PROJECT_PATH,
+ CI_MERGE_REQUEST_IID
+ );
+
+ var changedFiles = changes
+ .map(({ new_path, old_path, new_file }) => {
+ try {
+ const [modelName] = new_path
+ .match(/.*models\/(.*)\.sql/)[1]
+ .split("/")
+ .reverse()[0]
+ .split(".");
+
+ if (modelName) {
+ if (new_file) {
+ return {
+ fileName: modelName,
+ filePath: new_path,
+ headSHA: diff_refs.head_sha,
+ status: "added",
+ };
+ } else if (new_path !== old_path) {
+ // File is renamed or moved
+ return {
+ fileName: modelName,
+ filePath: new_path,
+ headSHA: diff_refs.head_sha,
+ status: "renamed_or_moved",
+ };
+ } else {
+ // File is modified
+ return {
+ fileName: modelName,
+ filePath: new_path,
+ headSHA: diff_refs.head_sha,
+ status: "modified",
+ };
+ }
}
+ } catch (e) {
+ logger_logger.withError(
+ `Error processing file`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
+ );
}
- } catch (e) {}
- })
- .filter((i) => i !== undefined);
+ })
+ .filter((i) => i !== undefined);
- changedFiles = changedFiles.filter((item, index) => {
- return (
- changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
- index
- );
- });
+ changedFiles = changedFiles.filter((item, index) => {
+ return (
+ changedFiles.findIndex((obj) => obj.fileName === item.fileName) ===
+ index
+ );
+ });
- console.log(changedFiles);
+ logger_logger.withInfo(
+ "Successfully fetched changed files",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
+ );
- return changedFiles;
+ return changedFiles;
+ } catch (error) {
+ logger_logger.withError(
+ `Error fetching changed files - ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getChangedFiles"
+ );
+ throw error;
+ }
}
async getAssetName({ gitlab, fileName, filePath, headSHA }) {
- //Done
- //Complete
- var regExp = /config\(.*alias=\'([^']+)\'.*\)/im;
- var fileContents = await this.getFileContents({
- gitlab,
- filePath,
- headSHA,
- });
+ try {
+ logger_logger.withInfo(
+ "Getting asset name...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
- var matches = regExp.exec(fileContents);
+ var regExp =
+ /{{\s*config\s*\(\s*(?:[^,]*,)*\s*alias\s*=\s*['"]([^'"]+)['"](?:\s*,[^,]*)*\s*\)\s*}}/im;
+ var fileContents = await this.getFileContents({
+ gitlab,
+ filePath,
+ headSHA,
+ });
- if (matches) {
- return matches[1];
- }
+ if (fileContents) {
+ var matches = regExp.exec(fileContents);
+ if (matches) {
+ logger_logger.withInfo(
+ `Found a match: ${matches[1].trim()}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
+ return matches[1].trim();
+ }
+ }
+
+ logger_logger.withInfo(
+ `Using filename as asset name: ${fileName}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
- return fileName;
+ return fileName;
+ } catch (error) {
+ logger_logger.withError(
+ `Error getting asset name - ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getAssetName"
+ );
+ throw error;
+ }
}
async getFileContents({ gitlab, filePath, headSHA }) {
- //Done
- //Complete
- const { CI_PROJECT_PATH } = process.env;
- const { content } = await gitlab.RepositoryFiles.show(
- CI_PROJECT_PATH,
- filePath,
- headSHA
- );
- const buff = Buffer.from(content, "base64");
+ try {
+ logger_logger.withInfo(
+ "Fetching file contents...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getFileContents"
+ );
+
+ const { content } = await gitlab.RepositoryFiles.show(
+ CI_PROJECT_PATH,
+ filePath,
+ headSHA
+ );
+ const buff = Buffer.from(content, "base64");
+
+ logger_logger.withInfo(
+ "Successfully fetched file contents",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getFileContents"
+ );
- return buff.toString("utf8");
+ return buff.toString("utf8");
+ } catch (error) {
+ logger_logger.withError(
+ `Error in getFileContents: ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "getFileContents"
+ );
+ throw error;
+ }
}
async checkCommentExists({ gitlab }) {
- //Done
- //Complete
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
- if (gitlab_integration_IS_DEV) return null;
+ logger_logger.withInfo(
+ "Checking for existing comments...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+
+ if (IS_DEV) {
+ logger_logger.withInfo(
+ "Development mode enabled. Skipping comment check.",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ return null;
+ }
- const comments = await gitlab.MergeRequestNotes.all(
- CI_PROJECT_PATH,
- CI_MERGE_REQUEST_IID
- );
+ try {
+ const comments = await gitlab.MergeRequestNotes.all(
+ CI_PROJECT_PATH,
+ CI_MERGE_REQUEST_IID
+ );
- return comments.find(
- // Why here we have hardocded value? What should be over here inplace of this.
- (comment) =>
- comment.author.username === "Jaagrav" &&
- comment.body.includes(
- ""
- )
- );
+ const identifier = `project_${CI_PROJECT_ID}_bot_`;
+
+ const existingComment = comments.find(
+ (comment) =>
+ comment.author.username.includes(identifier) &&
+ comment.body.includes(
+ ""
+ )
+ );
+ if (existingComment) {
+ logger_logger.withInfo(
+ "Found existing comment: " + existingComment?.id,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ } else {
+ logger_logger.withInfo(
+ "No existing comment found",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ }
+
+ return existingComment;
+ } catch (error) {
+ logger_logger.withError(
+ "Error checking for existing comments: " + error.message,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "checkCommentExists"
+ );
+ throw error;
+ }
}
async deleteComment({ gitlab, comment_id }) {
- //Done
- //Complete
- const { CI_PROJECT_PATH, CI_MERGE_REQUEST_IID } = process.env;
+ logger_logger.withInfo(
+ `Deleted comment with ID ${comment_id}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "deleteComment"
+ );
return await gitlab.MergeRequestNotes.remove(
CI_PROJECT_PATH,
@@ -29549,95 +34921,155 @@ ${content}`;
);
}
- async renderDownstreamAssetsComment({ asset, downstreamAssets }) {
- //Done
- let impactedData = downstreamAssets.map(
- ({ displayText, guid, typeName, attributes, meanings }) => {
- let readableTypeName = typeName
- .toLowerCase()
- .replace(attributes.connectorName, "")
- .toUpperCase();
- readableTypeName =
- readableTypeName.charAt(0).toUpperCase() +
- readableTypeName.slice(1).toLowerCase();
- return [
- guid,
- displayText,
- attributes.connectorName,
- readableTypeName,
- attributes?.userDescription || attributes?.description || "",
- attributes?.certificateStatus || "",
- [...attributes?.ownerUsers, ...attributes?.ownerGroups] || [],
- meanings
- .map(
- ({ displayText, termGuid }) =>
- `[${displayText}](${gitlab_integration_ATLAN_INSTANCE_URL}/assets/${termGuid}?utm_source=dbt_gitlab_action)`
- )
- ?.join(", ") || " ",
- attributes?.sourceURL || "",
- ];
- }
+ async renderDownstreamAssetsComment({
+ asset,
+ downstreamAssets,
+ classifications,
+ materialisedAsset,
+ }) {
+ logger_logger.withInfo(
+ "Rendering Downstream Assets...",
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "renderDownstreamAssetsComment"
);
- impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3])); // Sort by typeName
- impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2])); // Sort by connectorName
+ try {
+ let impactedData = downstreamAssets.entities.map(
+ ({
+ displayText,
+ guid,
+ typeName,
+ attributes,
+ meanings,
+ classificationNames,
+ }) => {
+ // Modifying the typeName and getting the readableTypeName
+ let readableTypeName = typeName
+ .toLowerCase()
+ .replace(attributes.connectorName, "")
+ .toUpperCase();
+
+ // Filtering classifications based on classificationNames
+ let classificationsObj = classifications.filter(({ name }) =>
+ classificationNames.includes(name)
+ );
+
+ // Modifying the readableTypeName
+ readableTypeName =
+ readableTypeName.charAt(0).toUpperCase() +
+ readableTypeName.slice(1).toLowerCase();
+
+ return [
+ guid,
+ truncate(displayText),
+ truncate(attributes.connectorName),
+ truncate(readableTypeName),
+ truncate(
+ attributes?.userDescription || attributes?.description || ""
+ ),
+ attributes?.certificateStatus || "",
+ truncate(
+ [...attributes?.ownerUsers, ...attributes?.ownerGroups] || []
+ ),
+ truncate(
+ meanings.map(
+ ({ displayText, termGuid }) =>
+ `[${displayText}](${ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_gitlab_action)`
+ )
+ ),
+ truncate(
+ classificationsObj?.map(
+ ({ name, displayName }) => `\`${displayName}\``
+ )
+ ),
+ attributes?.sourceURL || "",
+ ];
+ }
+ );
- let rows = impactedData.map(
- ([
- guid,
- displayText,
- connectorName,
- typeName,
- description,
- certificateStatus,
- owners,
- meanings,
- sourceUrl,
- ]) => {
- const connectorImage = get_image_url_getConnectorImage(connectorName),
- certificationImage = certificateStatus
- ? get_image_url_getCertificationImage(certificateStatus)
- : "";
+ // Sorting the impactedData first by typeName and then by connectorName
+ impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
+ impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
- return [
- `${connectorImage} [${displayText}](${gitlab_integration_ATLAN_INSTANCE_URL}/assets/${guid}?utm_source=dbt_gitlab_action) ${certificationImage}`,
- `\`${typeName}\``,
+ // Creating rows for the downstream table
+ let rows = impactedData.map(
+ ([
+ guid,
+ displayText,
+ connectorName,
+ typeName,
description,
- owners.join(", ") || " ",
+ certificateStatus,
+ owners,
meanings,
- sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
- ];
- }
- );
+ classifications,
+ sourceUrl,
+ ]) => {
+ // Getting connector and certification images
+ const connectorImage = getConnectorImage(connectorName);
+ const certificationImage = certificateStatus
+ ? getCertificationImage(certificateStatus)
+ : "";
- const comment = `### ${get_image_url_getConnectorImage(
- asset.attributes.connectorName
- )} [${asset.displayText}](${gitlab_integration_ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }?utm_source=dbt_gitlab_action) ${
- asset.attributes?.certificateStatus
- ? get_image_url_getCertificationImage(asset.attributes.certificateStatus)
- : ""
- }
+ return [
+ `${connectorImage} [${displayText}](${ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_gitlab_action) ${certificationImage}`,
+ `\`${typeName}\``,
+ description,
+ owners,
+ meanings,
+ classifications,
+ sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " ",
+ ];
+ }
+ );
- **${downstreamAssets.length} downstream assets** 👇
- Name | Type | Description | Owners | Terms | Source URL
- --- | --- | --- | --- | --- | ---
- ${rows
- .map((row) =>
- row.map((i) => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")
- )
- .join("\n")}
+ const environmentName =
+ materialisedAsset?.attributes?.assetDbtEnvironmentName;
+ const projectName = materialisedAsset?.attributes?.assetDbtProjectName;
+ // Generating asset information
+ const assetInfo = gitlab_integration_getAssetInfo(
+ ATLAN_INSTANCE_URL,
+ asset,
+ materialisedAsset,
+ environmentName,
+ projectName
+ );
- ${get_image_url_getImageURL(
- "atlan-logo",
- 15,
- 15
- )} [View asset in Atlan](${gitlab_integration_ATLAN_INSTANCE_URL}/assets/${
- asset.guid
- }?utm_source=dbt_gitlab_action)`;
+ // Generating the downstream table
+ const downstreamTable = gitlab_integration_getDownstreamTable(
+ ATLAN_INSTANCE_URL,
+ downstreamAssets,
+ rows,
+ materialisedAsset
+ );
- return comment;
+ // Generating the "View asset in Atlan" button
+ const viewAssetButton = gitlab_integration_getViewAssetButton(ATLAN_INSTANCE_URL, asset);
+
+ // Generating the final comment based on the presence of downstream assets
+ if (downstreamAssets.entities.length > 0) {
+ return `${assetInfo}
+
+${downstreamTable}
+
+${viewAssetButton}`;
+ } else {
+ return `${assetInfo}
+
+No downstream assets found.
+
+${viewAssetButton}`;
+ }
+ } catch (error) {
+ logger_logger.withError(
+ `Error rendering Downstream Assets: ${error.message}`,
+ gitlab_integration_integrationName,
+ CI_COMMIT_SHA,
+ "renderDownstreamAssetsComment"
+ );
+ throw error;
+ }
}
}
@@ -29648,15 +35080,8 @@ ${content}`;
-
-main.config();
-
-const GITHUB_TOKEN = core.getInput("GITHUB_TOKEN") || process.env.GITHUB_TOKEN;
-const GITLAB_TOKEN = process.env.GITLAB_TOKEN;
-
async function run() {
//Add new integrations over here
- console.log("oii");
await runAction(GITHUB_TOKEN, GitHubIntegration);
await runAction(GITLAB_TOKEN, GitLabIntegration);
}
diff --git a/package-lock.json b/package-lock.json
index 880e022..5d68496 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,12 +11,18 @@
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1",
- "@gitbeaker/rest": "^39.17.0",
+ "@gitbeaker/cli": "^39.19.0",
+ "@gitbeaker/core": "^39.19.0",
+ "@gitbeaker/requester-utils": "^39.19.0",
+ "@gitbeaker/rest": "^39.19.0",
"@vercel/ncc": "^0.34.0",
"dotenv": "^16.0.3",
"json-stringify-safe": "^5.0.1",
"node-fetch": "^3.3.0",
"uuid": "^9.0.0"
+ },
+ "devDependencies": {
+ "@types/json-stringify-safe": "^5.0.2"
}
},
"node_modules/@actions/core": {
@@ -55,12 +61,31 @@
"tunnel": "^0.0.6"
}
},
+ "node_modules/@gitbeaker/cli": {
+ "version": "39.19.0",
+ "resolved": "https://registry.npmjs.org/@gitbeaker/cli/-/cli-39.19.0.tgz",
+ "integrity": "sha512-NW3VND/3hZL0g350hB/x5B0q1cDgpxfVel0VefPvlYSwrh0g2BFCqDV/UDCfqWwoLGXNxf/gZfqCZfjWbmJYfw==",
+ "dependencies": {
+ "@gitbeaker/core": "^39.19.0",
+ "@gitbeaker/rest": "^39.19.0",
+ "chalk": "4.1.2",
+ "sywac": "^1.3.0",
+ "xcase": "^2.0.1"
+ },
+ "bin": {
+ "gb": "dist/index.mjs",
+ "gitbeaker": "dist/index.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@gitbeaker/core": {
- "version": "39.17.0",
- "resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-39.17.0.tgz",
- "integrity": "sha512-yKlI2qpi6k+aQsfNwlRjmeiKyDcB2xf3NHp5XzMpHdiXUMjwFmNrlmEv8TLj5mdrwDgZWGpUHVHX9xKwHri8eA==",
+ "version": "39.19.0",
+ "resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-39.19.0.tgz",
+ "integrity": "sha512-v8zZY5S1RsKDAMl0iqjwYwPpLPLYyPfRyYmWxyqyxqkB9SoB3Eqb7LPLMgtTFu2rZ6Atk2N/MXjMYl/f8x10fw==",
"dependencies": {
- "@gitbeaker/requester-utils": "^39.17.0",
+ "@gitbeaker/requester-utils": "^39.19.0",
"qs": "^6.11.2",
"xcase": "^2.0.1"
},
@@ -69,10 +94,12 @@
}
},
"node_modules/@gitbeaker/requester-utils": {
- "version": "39.17.0",
- "resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-39.17.0.tgz",
- "integrity": "sha512-ymy3xA9HZTdZ7GJMR7ewdGQa4JoLAmIdN6T8F5FEvLB4AYBwVqwIyitX4mrnukqI4FlGF/Lt5IUIp4zUDmJXQQ==",
+ "version": "39.19.0",
+ "resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-39.19.0.tgz",
+ "integrity": "sha512-cRPz469TaGUMaxpz/Yht6BlVTrNlWkYiXSuE+vfyo/jyDajeiI+8fswKR3nZO7tRkMu/VAotEb0QXw1MAF+V3w==",
"dependencies": {
+ "async-sema": "^3.1.1",
+ "micromatch": "^4.0.5",
"qs": "^6.11.2",
"xcase": "^2.0.1"
},
@@ -81,12 +108,12 @@
}
},
"node_modules/@gitbeaker/rest": {
- "version": "39.17.0",
- "resolved": "https://registry.npmjs.org/@gitbeaker/rest/-/rest-39.17.0.tgz",
- "integrity": "sha512-P5mg66aKJrMfZag3DXJlqnrFjtRjg6gQgrT3AotN0A7TDQyxXNAOtE19k+etXkXzecaNA01HYNp9aIxXpa5y9A==",
+ "version": "39.19.0",
+ "resolved": "https://registry.npmjs.org/@gitbeaker/rest/-/rest-39.19.0.tgz",
+ "integrity": "sha512-4MaekE0zcelImkM+QbZiuNTDGnBFOd8m/Sge5jjEsQG588B+rjDTCkR4pvmIqRQgkpu5aM8+HSgEFxZ+VRtbmg==",
"dependencies": {
- "@gitbeaker/core": "^39.17.0",
- "@gitbeaker/requester-utils": "^39.17.0"
+ "@gitbeaker/core": "^39.19.0",
+ "@gitbeaker/requester-utils": "^39.19.0"
},
"engines": {
"node": ">=18.0.0"
@@ -212,6 +239,12 @@
"@octokit/openapi-types": "^12.11.0"
}
},
+ "node_modules/@types/json-stringify-safe": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@types/json-stringify-safe/-/json-stringify-safe-5.0.2.tgz",
+ "integrity": "sha512-NJdNTdatSiYvxdPLwgQImChxTfPECXYkdB6wC71dO3GCz2z/s/ZkkHXHaUlSVvnbsRUQg8Al3cT8Wp08wMF3zA==",
+ "dev": true
+ },
"node_modules/@vercel/ncc": {
"version": "0.34.0",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.34.0.tgz",
@@ -220,11 +253,41 @@
"ncc": "dist/ncc/cli.js"
}
},
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/async-sema": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz",
+ "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg=="
+ },
"node_modules/before-after-hook": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
},
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
@@ -237,6 +300,37 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
"node_modules/data-uri-to-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
@@ -280,6 +374,17 @@
"node": "^12.20 || >= 14.13"
}
},
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
@@ -311,16 +416,21 @@
}
},
"node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dependencies": {
- "function-bind": "^1.1.1"
- },
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+ "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
"engines": {
"node": ">= 0.4.0"
}
},
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
@@ -343,6 +453,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
@@ -356,6 +474,18 @@
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
},
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
@@ -407,6 +537,17 @@
"wrappy": "1"
}
},
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/qs": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
@@ -434,6 +575,36 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sywac": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/sywac/-/sywac-1.3.0.tgz",
+ "integrity": "sha512-LDt2stNTp4bVPMgd70Jj9PWrSa4batl+bv+Ea5NLNGT7ufc4oQPtRfQ73wbddNV6RilaPqnEt6y1Wkm5FVTNEg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
diff --git a/package.json b/package.json
index 6d68730..cf55044 100644
--- a/package.json
+++ b/package.json
@@ -29,11 +29,17 @@
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1",
- "@gitbeaker/rest": "^39.17.0",
+ "@gitbeaker/cli": "^39.19.0",
+ "@gitbeaker/core": "^39.19.0",
+ "@gitbeaker/requester-utils": "^39.19.0",
+ "@gitbeaker/rest": "^39.19.0",
"@vercel/ncc": "^0.34.0",
"dotenv": "^16.0.3",
"json-stringify-safe": "^5.0.1",
"node-fetch": "^3.3.0",
"uuid": "^9.0.0"
+ },
+ "devDependencies": {
+ "@types/json-stringify-safe": "^5.0.2"
}
}
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index 02b54ac..0000000
--- a/src/index.js
+++ /dev/null
@@ -1,45 +0,0 @@
-// import dotenv from "dotenv";
-// import core from "@actions/core";
-// import github from "@actions/github";
-
-// import { printDownstreamAssets, setResourceOnAsset } from "./main/index.js";
-// import { sendSegmentEvent } from "./api/index.js";
-// import { auth } from "./utils/index.js";
-
-// dotenv.config();
-
-// const GITHUB_TOKEN = core.getInput("GITHUB_TOKEN") || process.env.GITHUB_TOKEN;
-
-// async function run() {
-// console.log("Hmm");
-// const timeStart = Date.now();
-// const { context } = github;
-// const octokit = github.getOctokit(GITHUB_TOKEN);
-// const { pull_request } = context.payload;
-// const { state, merged } = pull_request;
-
-// if (!(await auth(octokit, context))) throw { message: "Wrong API Token" };
-
-// let total_assets = 0;
-
-// if (state === "open") {
-// total_assets = await printDownstreamAssets({ octokit, context });
-// } else if (state === "closed") {
-// if (merged) total_assets = await setResourceOnAsset({ octokit, context });
-// }
-
-// if (total_assets !== 0)
-// sendSegmentEvent("dbt_ci_action_run", {
-// asset_count: total_assets,
-// total_time: Date.now() - timeStart,
-// });
-// }
-
-// run().catch((err) => {
-// sendSegmentEvent("dbt_ci_action_failure", {
-// reason: "failed_to_run_action",
-// msg: err,
-// });
-
-// core.setFailed(err.message);
-// });
diff --git a/src/main/index.js b/src/main/index.js
deleted file mode 100644
index fd65f4b..0000000
--- a/src/main/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export { default as printDownstreamAssets } from "./print-downstream-assets.js";
-export { default as setResourceOnAsset } from "./set-resource-on-asset.js";
diff --git a/src/main/print-downstream-assets.js b/src/main/print-downstream-assets.js
deleted file mode 100644
index e24f2d3..0000000
--- a/src/main/print-downstream-assets.js
+++ /dev/null
@@ -1,105 +0,0 @@
-import {
- getAsset,
- getClassifications,
- getDownstreamAssets,
- sendSegmentEvent,
-} from "../api/index.js";
-import {
- renderDownstreamAssetsComment,
- getChangedFiles,
- getAssetName,
- createIssueComment,
- checkCommentExists,
- deleteComment,
- getImageURL,
- getConnectorImage,
-} from "../utils/index.js";
-import { isIgnoreModelAliasMatching } from "../utils/get-environment-variables.js";
-
-export default async function printDownstreamAssets({ octokit, context }) {
- const changedFiles = await getChangedFiles(octokit, context);
- let comments = ``;
- let totalChangedFiles = 0;
-
- for (const { fileName, filePath, status } of changedFiles) {
- const aliasName = await getAssetName({
- octokit,
- context,
- fileName,
- filePath,
- });
- const assetName = isIgnoreModelAliasMatching() ? fileName : aliasName;
- const asset = await getAsset({ name: assetName });
-
- if (totalChangedFiles !== 0) comments += "\n\n---\n\n";
-
- if (status === "added") {
- comments += `### ${getConnectorImage("dbt")} ${fileName} 🆕
-Its a new model and not present in Atlan yet, you'll see the downstream impact for it after its present in Atlan.`;
- totalChangedFiles++;
- continue;
- }
-
- if (asset.error) {
- comments += asset.error;
- totalChangedFiles++;
- continue;
- }
-
- const materialisedAsset = asset.attributes.dbtModelSqlAssets[0];
- const timeStart = Date.now();
- const totalModifiedFiles = changedFiles.filter(
- (i) => i.status === "modified"
- ).length;
- const downstreamAssets = await getDownstreamAssets(
- asset,
- materialisedAsset.guid,
- totalModifiedFiles
- );
-
- if (downstreamAssets.error) {
- comments += downstreamAssets.error;
- totalChangedFiles++;
- continue;
- }
-
- sendSegmentEvent("dbt_ci_action_downstream_unfurl", {
- asset_guid: asset.guid,
- asset_type: asset.typeName,
- downstream_count: downstreamAssets.entities.length,
- total_fetch_time: Date.now() - timeStart,
- });
-
- const classifications = await getClassifications();
-
- const comment = await renderDownstreamAssetsComment(
- octokit,
- context,
- asset,
- materialisedAsset,
- downstreamAssets,
- classifications
- );
-
- comments += comment;
-
- totalChangedFiles++;
- }
-
- comments = `### ${getImageURL("atlan-logo", 15, 15)} Atlan impact analysis
-Here is your downstream impact analysis for **${totalChangedFiles} ${
- totalChangedFiles > 1 ? "models" : "model"
- }** you have edited.
-
-${comments}`;
-
- const existingComment = await checkCommentExists(octokit, context);
-
- if (totalChangedFiles > 0)
- await createIssueComment(octokit, context, comments, existingComment?.id);
-
- if (totalChangedFiles === 0 && existingComment)
- await deleteComment(octokit, context, existingComment.id);
-
- return totalChangedFiles;
-}
diff --git a/src/main/set-resource-on-asset.js b/src/main/set-resource-on-asset.js
deleted file mode 100644
index db493bc..0000000
--- a/src/main/set-resource-on-asset.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import { getAsset, createResource } from "../api/index.js";
-import {
- createIssueComment,
- getChangedFiles,
- getAssetName,
-} from "../utils/index.js";
-
-export default async function setResourceOnAsset({ octokit, context }) {
- const changedFiles = await getChangedFiles(octokit, context);
- const { pull_request } = context.payload;
- var totalChangedFiles = 0;
-
- if (changedFiles.length === 0) return;
-
- for (const { fileName, filePath } of changedFiles) {
- const assetName = await getAssetName({
- octokit,
- context,
- fileName,
- filePath,
- });
- const asset = await getAsset({ name: assetName });
-
- if (asset.error) continue;
-
- const { guid: modelGuid } = asset;
- const { guid: tableAssetGuid } = asset?.attributes?.dbtModelSqlAssets?.[0];
-
- if (modelGuid)
- await createResource(
- modelGuid,
- "Pull Request on GitHub",
- pull_request.html_url
- );
-
- if (tableAssetGuid)
- await createResource(
- tableAssetGuid,
- "Pull Request on GitHub",
- pull_request.html_url
- );
-
- totalChangedFiles++;
- }
-
- const comment = await createIssueComment(
- octokit,
- context,
- `🎊 Congrats on the merge!
-
-This pull request has been added as a resource to all the assets modified. ✅
-`,
- null,
- true
- );
-
- return totalChangedFiles;
-}
diff --git a/src/utils/create-comment.js b/src/utils/create-comment.js
deleted file mode 100644
index 1ed05d9..0000000
--- a/src/utils/create-comment.js
+++ /dev/null
@@ -1,182 +0,0 @@
-import {getCertificationImage, getConnectorImage, getImageURL,} from "./index.js";
-import {getInstanceUrl, isDev} from "./get-environment-variables.js";
-
-const IS_DEV = isDev();
-const ATLAN_INSTANCE_URL =
- getInstanceUrl();
-
-export function truncate(value) {
- if (typeof value === 'string')
- return value.length > 100 ? value.substring(0, 100) + "..." : value;
- if (Array.isArray(value))
- return value.length > 10 ? value.slice(0, 10).join(", ") + "..." : value.join(", ");
- return ""
-}
-
-export default async function renderDownstreamAssetsComment(
- octokit,
- context,
- asset,
- materialisedAsset,
- downstreamAssets,
- classifications
-) {
- // Mapping the downstream assets data
- let impactedData = downstreamAssets.entities.map(
- ({
- displayText,
- guid,
- typeName,
- attributes,
- meanings,
- classificationNames
- }) => {
- // Modifying the typeName and getting the readableTypeName
- let readableTypeName = typeName
- .toLowerCase()
- .replace(attributes.connectorName, "")
- .toUpperCase();
-
- // Filtering classifications based on classificationNames
- let classificationsObj = classifications.filter(({name}) =>
- classificationNames.includes(name)
- );
-
- // Modifying the readableTypeName
- readableTypeName = readableTypeName.charAt(0).toUpperCase() + readableTypeName.slice(1).toLowerCase();
-
- return [
- guid,
- truncate(displayText),
- truncate(attributes.connectorName),
- truncate(readableTypeName),
- truncate(attributes?.userDescription || attributes?.description || ""),
- attributes?.certificateStatus || "",
- truncate([...attributes?.ownerUsers, ...attributes?.ownerGroups] || []),
- truncate(meanings.map(({displayText, termGuid}) =>
- `[${displayText}](${ATLAN_INSTANCE_URL}/assets/${termGuid}/overview?utm_source=dbt_github_action)`
- )),
- truncate(classificationsObj?.map(({name, displayName}) =>
- `\`${displayName}\``
- )),
- attributes?.sourceURL || ""
- ];
- }
- );
-
- // Sorting the impactedData first by typeName and then by connectorName
- impactedData = impactedData.sort((a, b) => a[3].localeCompare(b[3]));
- impactedData = impactedData.sort((a, b) => a[2].localeCompare(b[2]));
-
- // Creating rows for the downstream table
- let rows = impactedData.map(
- ([guid, displayText, connectorName, typeName, description, certificateStatus, owners, meanings, classifications, sourceUrl]) => {
- // Getting connector and certification images
- const connectorImage = getConnectorImage(connectorName);
- const certificationImage = certificateStatus ? getCertificationImage(certificateStatus) : "";
-
- return [
- `${connectorImage} [${displayText}](${ATLAN_INSTANCE_URL}/assets/${guid}/overview?utm_source=dbt_github_action) ${certificationImage}`,
- `\`${typeName}\``,
- description,
- owners,
- meanings,
- classifications,
- sourceUrl ? `[Open in ${connectorName}](${sourceUrl})` : " "
- ];
- }
- );
-
- const environmentName = materialisedAsset?.attributes?.assetDbtEnvironmentName
- const projectName = materialisedAsset?.attributes?.assetDbtProjectName
- // Generating asset information
- const assetInfo = `### ${getConnectorImage(asset.attributes.connectorName)} [${
- asset.displayText
- }](${ATLAN_INSTANCE_URL}/assets/${asset.guid}/overview?utm_source=dbt_github_action) ${
- asset.attributes?.certificateStatus
- ? getCertificationImage(asset.attributes.certificateStatus)
- : ""
- }
-Materialised asset: ${getConnectorImage(materialisedAsset.attributes.connectorName)} [${
- materialisedAsset.attributes.name
- }](${ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/overview?utm_source=dbt_github_action) ${
- materialisedAsset.attributes?.certificateStatus
- ? getCertificationImage(materialisedAsset.attributes.certificateStatus)
- : ""
- }${environmentName ? ` | Environment Name: \`${environmentName}\`` : ''}${projectName ? ` | Project Name: \`${projectName}\`` : ''}`;
-
- // Generating the downstream table
- const downstreamTable = `${downstreamAssets.entityCount} downstream assets 👇
-
-Name | Type | Description | Owners | Terms | Classifications | Source URL
---- | --- | --- | --- | --- | --- | ---
-${rows.map((row) => row.map(i => i.replace(/\|/g, "•").replace(/\n/g, "")).join(" | ")).join("\n")}
-
-${downstreamAssets.hasMore ? `[See more downstream assets at Atlan](${ATLAN_INSTANCE_URL}/assets/${materialisedAsset.guid}/lineage?utm_source=dbt_github_action)` : ""}
-
- `;
-
- // Generating the "View asset in Atlan" button
- const viewAssetButton = `${getImageURL("atlan-logo", 15, 15)} [View asset in Atlan](${ATLAN_INSTANCE_URL}/assets/${asset.guid}/overview?utm_source=dbt_github_action)`;
-
- // Generating the final comment based on the presence of downstream assets
- if (downstreamAssets.entities.length > 0) {
- return `${assetInfo}
-
-${downstreamTable}
-
-${viewAssetButton}`;
- } else {
- return `${assetInfo}
-
-No downstream assets found.
-
-${viewAssetButton}`;
- }
-}
-
-
-export async function checkCommentExists(octokit, context) {
- if (IS_DEV) return null;
-
- const {pull_request} = context.payload;
-
- const comments = await octokit.rest.issues.listComments({
- ...context.repo,
- issue_number: pull_request.number,
- });
-
- return comments.data.find(
- (comment) => comment.user.login === "github-actions[bot]" && comment.body.includes("")
- );
-}
-
-export async function createIssueComment(octokit, context, content, comment_id = null, forceNewComment = false) {
- const {pull_request} = context.payload;
-
- content = `
-${content}`
-
- const commentObj = {
- ...context.repo,
- issue_number: pull_request.number,
- body: content,
- };
-
- console.log(content, content.length)
-
- if (IS_DEV) return content;
-
- if (comment_id && !forceNewComment) return octokit.rest.issues.updateComment({...commentObj, comment_id});
- return octokit.rest.issues.createComment(commentObj);
-}
-
-export async function deleteComment(octokit, context, comment_id) {
- const {pull_request} = context.payload;
-
- return octokit.rest.issues.deleteComment({
- ...context.repo,
- issue_number: pull_request.number,
- comment_id,
- });
-}
diff --git a/src/utils/file-system.js b/src/utils/file-system.js
deleted file mode 100644
index e799587..0000000
--- a/src/utils/file-system.js
+++ /dev/null
@@ -1,82 +0,0 @@
-export async function getFileContents(octokit, context, filePath) {
- const {repository, pull_request} = context.payload,
- owner = repository.owner.login,
- repo = repository.name,
- head_sha = pull_request.head.sha;
-
- const res = await octokit.request(
- `GET /repos/${owner}/${repo}/contents/${filePath}?ref=${head_sha}`,
- {
- owner,
- repo,
- path: filePath,
- }
- ).catch(e => {
- console.log("Error fetching file contents: ", e)
- return null
- });
-
- if (!res) return null
-
- const buff = Buffer.from(res.data.content, "base64");
-
- return buff.toString("utf8");
-}
-
-export async function getChangedFiles(octokit, context) {
- const {repository, pull_request} = context.payload,
- owner = repository.owner.login,
- repo = repository.name,
- pull_number = pull_request.number;
-
- const res = await octokit.request(
- `GET /repos/${owner}/${repo}/pulls/${pull_number}/files`,
- {
- owner,
- repo,
- pull_number,
- }
- );
-
- var changedFiles = res.data
- .map(({filename, status}) => {
- try {
- const [modelName] = filename.match(/.*models\/(.*)\.sql/)[1].split('/').reverse()[0].split('.');
-
- if (modelName) {
- return {
- fileName: modelName,
- filePath: filename,
- status
- };
- }
- } catch (e) {
-
- }
- })
- .filter((i) => i !== undefined)
-
- changedFiles = changedFiles
- .filter((item, index) => {
- return changedFiles.findIndex(obj => obj.fileName === item.fileName) === index;
- })
-
- console.log("Changed Files: ", changedFiles)
-
- return changedFiles
-}
-
-export async function getAssetName({octokit, context, fileName, filePath}) {
- var regExp = /{{\s*config\s*\(\s*(?:[^,]*,)*\s*alias\s*=\s*['"]([^'"]+)['"](?:\s*,[^,]*)*\s*\)\s*}}/im;
- var fileContents = await getFileContents(octokit, context, filePath);
-
- if (fileContents) {
- var matches = regExp.exec(fileContents);
-
- if (matches) {
- return matches[1].trim();
- }
- }
-
- return fileName;
-}
diff --git a/src/utils/get-environment-variables.js b/src/utils/get-environment-variables.js
deleted file mode 100644
index ba30ead..0000000
--- a/src/utils/get-environment-variables.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import dotenv from "dotenv";
-import core from "@actions/core";
-
-dotenv.config();
-
-const {
- IS_DEV,
- ATLAN_INSTANCE_URL,
- ATLAN_API_TOKEN,
- IGNORE_MODEL_ALIAS_MATCHING,
-} = process.env;
-
-export const isDev = () => IS_DEV === "true";
-export const getInstanceUrl = () => {
- if (ATLAN_INSTANCE_URL) return new URL(ATLAN_INSTANCE_URL).origin;
- return new URL(core.getInput("ATLAN_INSTANCE_URL")).origin;
-};
-export const getAPIToken = () => {
- if (ATLAN_API_TOKEN) return ATLAN_API_TOKEN;
- return core.getInput("ATLAN_API_TOKEN");
-};
-export const getEnvironments = () => {
- return core.getInput("DBT_ENVIRONMENT_BRANCH_MAP")
- ? core
- .getInput("DBT_ENVIRONMENT_BRANCH_MAP")
- .trim()
- ?.split("\n")
- ?.map((i) => i.split(":").map((i) => i.trim()))
- : [];
-};
-export const isIgnoreModelAliasMatching = () =>
- core.getInput("IGNORE_MODEL_ALIAS_MATCHING") === "true";
-
-export function getGitLabEnvironments() {
- const { DBT_ENVIRONMENT_BRANCH_MAP } = process.env;
-
- if (DBT_ENVIRONMENT_BRANCH_MAP) {
- const environmentLines = DBT_ENVIRONMENT_BRANCH_MAP.split("\n");
- const environmentMap = {};
-
- environmentLines.forEach((line) => {
- const [environment, branch] = line.split(":").map((item) => item.trim());
- if (environment && branch) {
- environmentMap[environment] = branch;
- }
- });
-
- return environmentMap;
- } else {
- return {};
- }
-}
diff --git a/src/utils/index.js b/src/utils/index.js
deleted file mode 100644
index fc6889a..0000000
--- a/src/utils/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-export {
- getImageURL,
- getConnectorImage,
- getCertificationImage,
-} from "./get-image-url.js";
-export {default as hostedImages} from "./hosted-images.js";
-export {
- default as renderDownstreamAssetsComment,
- createIssueComment, checkCommentExists, deleteComment
-} from "./create-comment.js";
-export {
- getFileContents,
- getChangedFiles,
- getAssetName,
-} from "./file-system.js";
-export {
- auth
-} from "./auth.js"
-export {
- getAPIToken,
- getInstanceUrl,
- isDev
-} from "./get-environment-variables.js"
\ No newline at end of file