Repository: AlaskaAirlines/auro-cli
Pull request #39: Add wca-script-update
Author: login: jyang81
Labels: name: released
description: Completed work has been released
Created: 2025-04-02T20:19:01Z | Merged: 2025-04-10T21:25:01Z

# Alaska Airlines Pull Request

## Type of change:

Please delete options that are not relevant.

- [x] New capability
- [ ] Revision of an existing capability
- [ ] Infrastructure change (automation, etc.)
- [ ] Other (please elaborate)

## Checklist:

- [ ] My update follows the CONTRIBUTING guidelines of this project
- [ ] I have performed a self-review of my own update

**By submitting this Pull Request, I confirm that my contribution is made under the terms of the Apache 2.0 license.**

_Pull Requests will be evaluated by their quality of update and whether it is consistent with the goals and values of this project. Any submission is to be considered a conversation between the submitter and the maintainers of this project and may require changes to your submission._

**Thank you for your submission!**<br>
-- Auro Design System Team

## Summary by Sourcery

Add Web Component Analyzer (WCA) setup and migration script for Auro design system components

New Features:
- Introduce a new 'wca-setup' command to prepare Web Component Analyzer compatible scripts for Auro components

Enhancements:
- Create a script to generate WCA-compatible component wrappers
- Update build:api script in package.json to use WCA for generating API documentation

Chores:
- Add migration script to set up WCA infrastructure
- Create multi-gitter configuration for applying changes across Auro repositories


Diff:
diff --git a/src/commands/wca-setup.js b/src/commands/wca-setup.js
new file mode 100644
index 0000000..0a5d79a
--- /dev/null
+++ b/src/commands/wca-setup.js
@@ -0,0 +1,61 @@
+/* eslint-disable no-await-in-loop, line-comment-position, no-inline-comments, jsdoc/require-jsdoc, no-undef */
+
+import { program } from "commander";
+import fs from "fs";
+import path from "path";
+import glob from "glob";
+import util from "util";
+import getTemplatedComponentCode from "../scripts/prepWcaCompatibleCode.mjs";
+import { Logger } from "@aurodesignsystem/auro-library/scripts/utils/logger.mjs";
+
+const promisifiedGlob = util.promisify(glob);
+
+const WAC_DIR = path.resolve(process.cwd(), "./scripts/wca");
+
+async function globPath(sources) {
+  try {
+    const fileArrays = await Promise.all(
+      sources.map((source) => promisifiedGlob(source)),
+    );
+    return fileArrays.flat();
+  } catch (err) {
+    console.error("Error processing glob patterns:", err);
+    throw err; // Re-throw to handle failure at caller
+  }
+}
+
+async function createExtendsFile(filePaths) {
+  if (!fs.existsSync(WAC_DIR)) {
+    await fs.promises.mkdir(WAC_DIR, { recursive: true });
+  }
+
+  for (const filePath of filePaths) {
+    const resolvedPath = path.resolve(process.cwd(), filePath);
+    const fileContent = await fs.promises.readFile(resolvedPath, "utf-8");
+    const newPath = path.resolve(WAC_DIR, `${path.basename(filePath)}`);
+    const newCode = getTemplatedComponentCode(
+      fileContent,
+      path.relative(WAC_DIR, filePath),
+    );
+    await fs.promises.writeFile(newPath, newCode);
+  }
+}
+
+async function main() {
+  // files to analyze
+  const filePaths = await globPath(["./src/auro-*.js"]);
+  await createExtendsFile(filePaths);
+}
+
+export default program
+  .command("wca-setup")
+  .description("Set up WCA (Web Component Analyzer) for the project")
+  .action(() => {
+    main()
+      .then(() => {
+        Logger.success("WCA setup completed successfully.");
+      })
+      .catch((error) => {
+        Logger.error(`WCA setup failed: ${error.message}`);
+      });
+  });
diff --git a/src/index.ts b/src/index.ts
index 0feb342..93ed560 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -10,6 +10,7 @@ import "./commands/dev.js";
 import "./commands/migrate.js";
 import "./commands/sync.js";
 import "./commands/demo.js";
+import "./commands/wca-setup.js";
 
 auroSplash();
 
diff --git a/src/migrations/wca-script-update/migration.js b/src/migrations/wca-script-update/migration.js
new file mode 100644
index 0000000..c7b1ce6
--- /dev/null
+++ b/src/migrations/wca-script-update/migration.js
@@ -0,0 +1,28 @@
+/* eslint-disable jsdoc/require-jsdoc, no-magic-numbers */
+
+import { Logger } from "@aurodesignsystem/auro-library/scripts/utils/logger.mjs";
+
+import fs from "fs";
+
+function updateBuildApiScript() {
+  try {
+    const newScript = "wca analyze 'scripts/wca/*' --outFiles docs/api.md";
+    const packageJsonPath = "package.json";
+
+    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
+
+    packageJson.scripts["build:api"] = newScript;
+
+    // Write the updated package.json back to the file
+    fs.writeFileSync(
+      packageJsonPath,
+      `${JSON.stringify(packageJson, null, 2)}\n`,
+      "utf8",
+    );
+    Logger.success(`build:api script updated in package.json`);
+  } catch (error) {
+    Logger.error(`Failed to update build:api script in package.json: ${error}`);
+  }
+}
+
+updateBuildApiScript();
diff --git a/src/migrations/wca-script-update/multi-gitter.yml b/src/migrations/wca-script-update/multi-gitter.yml
new file mode 100644
index 0000000..263ec93
--- /dev/null
+++ b/src/migrations/wca-script-update/multi-gitter.yml
@@ -0,0 +1,164 @@
+# The username of the assignees to be added on the pull request.
+assignees:
+  - jyang81
+
+# The authentication type. Used only for Bitbucket cloud. Available values: app-password, workspace-token.
+auth-type: workspace-token
+
+# Email of the committer. If not set, the global git config setting will be used.
+author-email: 
+
+# Name of the committer. If not set, the global git config setting will be used.
+author-name:
+
+# The branch which the changes will be based on.
+base-branch:
+
+# Base URL of the target platform, needs to be changed for GitHub enterprise, a self-hosted GitLab instance, Gitea or BitBucket.
+base-url:
+
+# The name of the branch where changes are committed.
+branch: migration/wca-script-update
+
+# The temporary directory where the repositories will be cloned. If not set, the default os temporary directory will be used.
+clone-dir: .gitter-temp
+
+# Use a code search to find a set of repositories to target (GitHub only). Repeated results from a given repository will be ignored, forks are NOT included by default (use `fork:true` to include them). See the GitHub documentation for full syntax: https://docs.github.com/en/search-github/searching-on-github/searching-code.
+code-search:
+
+# The commit message. Will default to title + body if none is set.
+commit-message: "perf: add wca script for docs api"
+
+# The maximum number of concurrent runs.
+concurrent: 1
+
+# What should happen if the branch already exist.
+# Available values:
+#   skip: Skip making any changes to the existing branch and do not create a new pull request.
+#   replace: Replace the existing content of the branch by force pushing any new changes, then reuse any existing pull request, or create a new one if none exist.
+conflict-strategy: skip
+
+# Create pull request(s) as draft.
+draft: false
+
+# Run without pushing changes or creating pull requests.
+dry-run: false
+
+# Limit fetching to the specified number of commits. Set to 0 for no limit.
+fetch-depth: 1
+
+# Fork the repository instead of creating a new branch on the same owner.
+fork: false
+
+# If set, make the fork to the defined value. Default behavior is for the fork to be on the logged in user.
+fork-owner:
+
+# The type of git implementation to use.
+# Available values:
+#   go: Uses go-git, a Go native implementation of git. This is compiled with the multi-gitter binary, and no extra dependencies are needed.
+#   cmd: Calls out to the git command. This requires git to be installed and available with by calling "git".
+git-type: go
+
+# The name of a GitLab organization. All repositories in that group will be used.
+group:
+
+# Include GitLab subgroups when using the --group flag.
+include-subgroups: false
+
+# Insecure controls whether a client verifies the server certificate chain and host name. Used only for Bitbucket server.
+insecure: false
+
+# Take manual decision before committing any change. Requires git to be installed.
+interactive: false
+
+# Labels to be added to any created pull request.
+labels:
+
+# The file where all logs should be printed to. "-" means stdout.
+log-file: "-"
+
+# The formatting of the logs. Available values: text, json, json-pretty.
+log-format: text
+
+# The level of logging that should be made. Available values: trace, debug, info, error.
+log-level: info
+
+# If this value is set, reviewers will be randomized.
+max-reviewers: 0
+
+# If this value is set, team reviewers will be randomized
+max-team-reviewers: 0
+
+# The name of a GitHub organization. All repositories in that organization will be used.
+org:
+
+# The file that the output of the script should be outputted to. "-" means stdout.
+output: "-"
+
+# Don't use any terminal formatting when printing the output.
+plain-output: false
+
+# The platform that is used. Available values: github, gitlab, gitea, bitbucket_server, bitbucket_cloud. Note: bitbucket_cloud is in Beta
+platform: github
+
+# The body of the commit message. Will default to everything but the first line of the commit message if none is set.
+pr-body: "Resolves AlaskaAirlines/auro-cli#38"
+
+# The title of the PR. Will default to the first line of the commit message if none is set.
+pr-title: "AURO MIGRATION: WCA Script Update"
+
+# The name, including owner of a GitLab project in the format "ownerName/repoName".
+project: 
+
+# Skip pull request and only push the feature branch.
+push-only: false
+
+# The name, including owner of a GitHub repository in the format "ownerName/repoName".
+repo:
+  # - AlaskaAirlines/auro-button
+  # - AlaskaAirlines/auro-hyperlink
+  # - AlaskaAirlines/auro-table
+  # - AlaskaAirlines/auro-carousel
+  # - AlaskaAirlines/auro-popover
+  # - AlaskaAirlines/auro-alert
+  # - AlaskaAirlines/auro-accordion
+  # - AlaskaAirlines/auro-pane
+  # - AlaskaAirlines/auro-avatar
+  # - AlaskaAirlines/auro-datetime
+  # - AlaskaAirlines/auro-loader
+  # - AlaskaAirlines/auro-badge
+  # - AlaskaAirlines/auro-flightline
+  # - AlaskaAirlines/auro-card
+  # - AlaskaAirlines/auro-backtotop
+  # - AlaskaAirlines/auro-skeleton
+  # - AlaskaAirlines/auro-banner
+  # - AlaskaAirlines/auro-background
+  # - AlaskaAirlines/auro-sidenav
+  # - AlaskaAirlines/auro-dialog
+
+# Exclude repositories that match with a given Regular Expression
+repo-exclude:
+
+# Include repositories that match with a given Regular Expression
+repo-include:
+
+# Use a repository search to find repositories to target (GitHub only). Forks are NOT included by default, use `fork:true` to include them. See the GitHub documentation for full syntax: https://docs.github.com/en/search-github/searching-on-github/searching-for-repositories.
+repo-search:
+
+# The username of the reviewers to be added on the pull request.
+reviewers:
+
+# Skip repositories which are forks.
+skip-forks: false
+
+# Skip pull request and directly push to the branch.
+skip-pr: false
+
+# Skip changes on specified repositories, the name is including the owner of repository in the format "ownerName/repoName".
+skip-repo:
+
+# Use SSH cloning URL instead of HTTPS + token. This requires that a setup with ssh keys that have access to all repos and that the server is already in known_hosts.
+ssh-auth: false
+
+# Github team names of the reviewers, in format: 'org/team'
+team-reviewers:
diff --git a/src/migrations/wca-script-update/script.sh b/src/migrations/wca-script-update/script.sh
new file mode 100755
index 0000000..ead5fd3
--- /dev/null
+++ b/src/migrations/wca-script-update/script.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+auro wca-setup
+node "$(dirname "$0")/migration.js"
+npm install
+npm run build:api
+npm run build:docs
+npm run build
+
diff --git a/src/scripts/prepWcaCompatibleCode.mjs b/src/scripts/prepWcaCompatibleCode.mjs
new file mode 100644
index 0000000..d154c46
--- /dev/null
+++ b/src/scripts/prepWcaCompatibleCode.mjs
@@ -0,0 +1,21 @@
+/* eslint-disable require-unicode-regexp, prefer-named-capture-group, prefer-destructuring, prettier/prettier */
+
+export default (code, sourcePath) => {
+  const defaultTag = (code.match(/static register\(name \= (.+)\)/) || code.match(/customElements.get\((.+?)\)/))[1];
+  const className = code.match(/export class (.+) extends/)?.[1];
+  const classDesc = code.match(/\/\*\*((.|\n)*?)(\*\n|\*\/|[@])/)?.[1] || '';
+
+  if (!defaultTag || !className) {
+    return code;
+  }
+  return `
+import { ${className} } from '${sourcePath}';
+
+/**${classDesc}*/
+class ${className}WCA extends ${className} {}
+
+if (!customElements.get(${defaultTag})) {
+  customElements.define(${defaultTag}, ${className}WCA);
+}
+`;
+};
\ No newline at end of file


Reviews:
user: login: sourcery-ai[bot]
body: Hey @jyang81 - I've reviewed your changes - here's some feedback:

**Overall Comments**:
- Consider using a more descriptive name for the `wca-setup.js` command to better reflect its purpose.
- The `multi-gitter.yml` file contains a lot of configuration - consider breaking it up into smaller files.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 3 issues found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟢 **Complexity**: all looks good
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-02T20:19:53Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-07T18:26:16Z
user: login: sourcery-ai[bot]
body: Hey @jyang81 - I've reviewed your changes - here's some feedback:

**Overall Comments**:
- Consider adding a rollback strategy in case the migration script fails.
- The multi-gitter.yml file has a lot of commented-out repos; consider removing them to reduce clutter.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 2 issues found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟡 **Complexity**: 1 issue found
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-07T18:27:22Z
user: login: sourcery-ai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-07T18:27:25Z
user: login: sourcery-ai[bot]
body: Hey @jyang81 - I've reviewed your changes - here's some feedback:

**Overall Comments**:
- Consider adding a rollback strategy in case the migration script fails.
- The multi-gitter.yml file has a lot of commented-out repos; consider removing them to reduce clutter.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 1 issue found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟢 **Complexity**: all looks good
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-07T18:27:47Z
user: login: jyang81
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T21:28:48Z
user: login: rmenner
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-10T21:24:52Z

Review comments:
diff_hunk: @@ -0,0 +1,21 @@
+/* eslint-disable require-unicode-regexp, prefer-named-capture-group, prefer-destructuring, prettier/prettier */
+
+export default (code, sourcePath) => {
+  const defaultTag = (code.match(/static register\(name \= (.+)\)/) || code.match(/customElements.get\((.+?)\)/))[1];
path: src/scripts/prepWcaCompatibleCode.mjs
user: login: sourcery-ai[bot]
body: **suggestion (bug_risk):** Add a null-check to the regex match result before accessing [1].

Currently, the code directly accesses [1] from the match result for 'defaultTag'. If neither regex matches, this will throw an error. Consider verifying that the match is not null before accessing the capturing group to avoid potential runtime issues.

```suggestion
  const defaultTagMatch = code.match(/static register\(name \= (.+)\)/) || code.match(/customElements.get\((.+?)\)/);
  const defaultTag = defaultTagMatch ? defaultTagMatch[1] : null;
```
created_at: 2025-04-02T20:19:52Z
author_association: NONE
diff_hunk: @@ -0,0 +1,61 @@
+/* eslint-disable no-await-in-loop, line-comment-position, no-inline-comments, jsdoc/require-jsdoc, no-undef, prettier/prettier */
+
+import { program } from "commander";
+import fs from "fs";
+import path from "path";
+import glob from "glob";
+import util from "util";
+import getTemplatedComponentCode from "../scripts/prepWcaCompatibleCode.mjs";
+import { Logger } from "@aurodesignsystem/auro-library/scripts/utils/logger.mjs";
+
+const promisifiedGlob = util.promisify(glob);
+
+const WAC_DIR = path.resolve(process.cwd(), "./scripts/wca");
+
+async function globPath(sources) {
+  try {
+    const fileArrays = await Promise.all(
+      sources.map((source) => promisifiedGlob(source)),
+    );
+    return fileArrays.flat();
+  } catch (err) {
+    console.error("Error processing glob patterns:", err);
+    throw err; // Re-throw to handle failure at caller
+  }
+}
+
+async function createExtendsFile(filePaths) {
+  if (!fs.existsSync(WAC_DIR)) {
+    await fs.promises.mkdir(WAC_DIR, { recursive: true });
+  }
+
+  for (const filePath of filePaths) {
+    const resolvedPath = path.resolve(process.cwd(), filePath);
+    const fileContent = await fs.promises.readFile(resolvedPath, "utf-8");
+    const newPath = path.resolve(WAC_DIR, `${path.basename(filePath)}`);
+    const newCode = getTemplatedComponentCode(
+      fileContent,
+      path.relative(WAC_DIR, filePath),
+    );
+    await fs.promises.writeFile(newPath, newCode);
+  }
+}
+
+async function main() {
+  // files to analyze
+  const filePaths = await globPath(["./src/auro-*.js"]);
+  await createExtendsFile(filePaths);
+}
+
+export default program
+  .command("wca-setup")
+  .description("Set up WCA (Web Component Analyzer) for the project")
+  .action(() => {
+    main()
+      .then(() => {
+        Logger.success("WCA setup completed successfully.");
+      })
+      .catch((error) => {
+        Logger.error(`WCA setup failed: ${error.message}`);
+      });
path: src/commands/wca-setup.js
user: login: sourcery-ai[bot]
body: **suggestion (bug_risk):** Consider ensuring proper process exit on failure.

While the error is logged using Logger.error on a failure in the async main() function, it might be beneficial for CLI commands to call process.exit with a non-zero exit code. This helps in scenarios where the command’s exit status is used programmatically to indicate failure.

```suggestion
      .catch((error) => {
        Logger.error(`WCA setup failed: ${error.message}`);
        process.exit(1);
      });
```
created_at: 2025-04-02T20:19:52Z
author_association: NONE
diff_hunk: @@ -0,0 +1,9 @@
+#!/bin/bash
+
+auro wca-setup
path: src/migrations/wca-script-update/script.sh
user: login: sourcery-ai[bot]
body: **suggestion (bug_risk):** Consider adding stricter error handling in the bash script.

Adding a 'set -e' command after the shebang can help ensure that the script exits on any error, preventing subsequent commands from running in an inconsistent state.

```suggestion
#!/bin/bash
set -e

auro wca-setup
```
created_at: 2025-04-02T20:19:53Z
author_association: NONE
diff_hunk: @@ -0,0 +1,21 @@
+/* eslint-disable require-unicode-regexp, prefer-named-capture-group, prefer-destructuring, prettier/prettier */
+
+export default (code, sourcePath) => {
+  const defaultTag = (code.match(/static register\(name \= (.+)\)/) || code.match(/customElements.get\((.+?)\)/))[1];
path: src/scripts/prepWcaCompatibleCode.mjs
user: login: sourcery-ai[bot]
body: Sure! I'm generating a new review now.
created_at: 2025-04-07T18:26:16Z
author_association: NONE
diff_hunk: @@ -0,0 +1,29 @@
+/* eslint-disable jsdoc/require-jsdoc, no-magic-numbers */
+
+import { Logger } from "@aurodesignsystem/auro-library/scripts/utils/logger.mjs";
+
+import fs from "fs";
+
+function updateBuildApiScript() {
+  try {
+    const newScript = "wca analyze 'scripts/wca/*' --outFiles docs/api.md";
+    const packageJsonPath = "package.json";
+
+    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
+
+    packageJson.scripts["build:api"] = newScript;
+
+    // Write the updated package.json back to the file
+    fs.writeFileSync(
+      packageJsonPath,
+      `${JSON.stringify(packageJson, null, 2)}\n`,
+      "utf8",
+    );
+  } catch (error) {
+    Logger.error(`Failed to update build:api script in package.json: ${error}`);
+  }
+
+  Logger.success(`build:api script updated in package.json`);
path: src/migrations/wca-script-update/migration.js
user: login: sourcery-ai[bot]
body: **issue (bug_risk):** Success log is printed even if an error occurs.

If an error is caught in the try block, the script still logs a success message afterward. Consider conditionally logging success only when the update actually completes without error.
created_at: 2025-04-07T18:27:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,21 @@
+/* eslint-disable require-unicode-regexp, prefer-named-capture-group, prefer-destructuring, prettier/prettier */
+
+export default (code, sourcePath) => {
path: src/scripts/prepWcaCompatibleCode.mjs
user: login: sourcery-ai[bot]
body: **suggestion (bug_risk):** Regexes may be too strict for varied code formatting.

The regular expressions used to extract elements (e.g., default tag and class name) assume a specific format. It would be beneficial to review or extend these patterns to handle optional whitespaces or alternative syntax variations reliably.

Suggested implementation:

```javascript
  const defaultTag = (code.match(/static\s+register\s*\(\s*name\s*=\s*(['"])(.*?)\1/) || code.match(/customElements\.get\s*\(\s*(['"])(.*?)\1/))?.[2];

```

```javascript
  const className = code.match(/export\s+class\s+([A-Za-z0-9_$]+)\s+extends/)?.[1];

```
created_at: 2025-04-07T18:27:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,61 @@
+/* eslint-disable no-await-in-loop, line-comment-position, no-inline-comments, jsdoc/require-jsdoc, no-undef */
+
+import { program } from "commander";
+import fs from "fs";
+import path from "path";
+import glob from "glob";
+import util from "util";
+import getTemplatedComponentCode from "../scripts/prepWcaCompatibleCode.mjs";
+import { Logger } from "@aurodesignsystem/auro-library/scripts/utils/logger.mjs";
+
+const promisifiedGlob = util.promisify(glob);
+
+const WAC_DIR = path.resolve(process.cwd(), "./scripts/wca");
+
+async function globPath(sources) {
+  try {
+    const fileArrays = await Promise.all(
+      sources.map((source) => promisifiedGlob(source)),
+    );
+    return fileArrays.flat();
+  } catch (err) {
+    console.error("Error processing glob patterns:", err);
+    throw err; // Re-throw to handle failure at caller
+  }
+}
+
+async function createExtendsFile(filePaths) {
path: src/commands/wca-setup.js
user: login: sourcery-ai[bot]
body: **issue (complexity):** Consider using concurrent file processing with Promise.all and asynchronous directory creation to simplify the function and improve performance

Consider moving to a concurrent file processing pattern instead of a sequential loop. This reduces the nesting of asynchronous calls and avoids mixing sync and async operations. For example, you can replace the synchronous `existsSync` check and the `for…of` loop with the asynchronous `mkdir` and `Promise.all`:

```js
async function createExtendsFile(filePaths) {
  // Create the directory asynchronously; mkdir with { recursive: true } handles it if already exists.
  await fs.promises.mkdir(WAC_DIR, { recursive: true });

  await Promise.all(
    filePaths.map(async (filePath) => {
      const resolvedPath = path.resolve(process.cwd(), filePath);
      const fileContent = await fs.promises.readFile(resolvedPath, "utf-8");
      const newPath = path.resolve(WAC_DIR, `${path.basename(filePath)}`);
      const newCode = getTemplatedComponentCode(
        fileContent,
        path.relative(WAC_DIR, filePath)
      );
      await fs.promises.writeFile(newPath, newCode);
    })
  );
}
```

This refactoring concurrently handles file operations while keeping all functionality intact.
created_at: 2025-04-07T18:27:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,21 @@
+/* eslint-disable require-unicode-regexp, prefer-named-capture-group, prefer-destructuring, prettier/prettier */
+
+export default (code, sourcePath) => {
+  const defaultTag = (code.match(/static register\(name \= (.+)\)/) || code.match(/customElements.get\((.+?)\)/))[1];
path: src/scripts/prepWcaCompatibleCode.mjs
user: login: sourcery-ai[bot]
body: Hey @jyang81, I've posted a new review for you!
created_at: 2025-04-07T18:27:25Z
author_association: NONE
diff_hunk: @@ -0,0 +1,29 @@
+/* eslint-disable jsdoc/require-jsdoc, no-magic-numbers */
+
+import { Logger } from "@aurodesignsystem/auro-library/scripts/utils/logger.mjs";
+
+import fs from "fs";
+
+function updateBuildApiScript() {
+  try {
+    const newScript = "wca analyze 'scripts/wca/*' --outFiles docs/api.md";
+    const packageJsonPath = "package.json";
+
+    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
+
+    packageJson.scripts["build:api"] = newScript;
+
+    // Write the updated package.json back to the file
+    fs.writeFileSync(
+      packageJsonPath,
+      `${JSON.stringify(packageJson, null, 2)}\n`,
+      "utf8",
+    );
+  } catch (error) {
+    Logger.error(`Failed to update build:api script in package.json: ${error}`);
+  }
+
+  Logger.success(`build:api script updated in package.json`);
path: src/migrations/wca-script-update/migration.js
user: login: sourcery-ai[bot]
body: **issue (bug_risk):** Success logging is executed even if an error occurs.

Since the try block catches and logs errors but still proceeds to log success, it might be better to either rethrow the error or only log the success message when the update completes without errors.
created_at: 2025-04-07T18:27:47Z
author_association: NONE
diff_hunk: @@ -0,0 +1,29 @@
+/* eslint-disable jsdoc/require-jsdoc, no-magic-numbers */
+
+import { Logger } from "@aurodesignsystem/auro-library/scripts/utils/logger.mjs";
+
+import fs from "fs";
+
+function updateBuildApiScript() {
+  try {
+    const newScript = "wca analyze 'scripts/wca/*' --outFiles docs/api.md";
+    const packageJsonPath = "package.json";
+
+    const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
+
+    packageJson.scripts["build:api"] = newScript;
+
+    // Write the updated package.json back to the file
+    fs.writeFileSync(
+      packageJsonPath,
+      `${JSON.stringify(packageJson, null, 2)}\n`,
+      "utf8",
+    );
+  } catch (error) {
+    Logger.error(`Failed to update build:api script in package.json: ${error}`);
+  }
+
+  Logger.success(`build:api script updated in package.json`);
path: src/migrations/wca-script-update/migration.js
user: login: jyang81
body: moved into the try block
created_at: 2025-04-07T21:28:48Z
author_association: CONTRIBUTOR

PR comments:
user: login: sourcery-ai[bot]
created_at: 2025-04-02T20:19:06Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## Reviewer's Guide by Sourcery

This pull request introduces a new WCA setup command, a script to generate WCA-compatible component wrappers, and updates the build process to generate component API documentation. It also includes a migration script and a multi-gitter configuration file for automating the WCA script update across multiple repositories.

_No diagrams generated as the changes look simple and do not need a visual representation._

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Introduces a new command `wca-setup` to prepare components for web component analysis. | <ul><li>Adds a new command to the program using `commander`.</li><li>Defines the logic to find component files using glob patterns.</li><li>Creates a directory for WCA-compatible files.</li><li>Generates WCA-compatible component wrappers using `prepWcaCompatibleCode.mjs`.</li><li>Writes the generated wrappers to the WCA directory.</li></ul> | `src/commands/wca-setup.js` |
| Adds a script to generate WCA-compatible component wrappers. | <ul><li>The script takes component code and its source path as input.</li><li>It extracts the component's tag name, class name, and description from the code.</li><li>It generates a new class extending the original component class.</li><li>It defines the new class with the original component's tag name.</li></ul> | `src/scripts/prepWcaCompatibleCode.mjs` |
| Updates the build process to generate component API documentation using WCA. | <ul><li>Adds a migration script to update the `build:api` script in `package.json`.</li><li>The migration script sets the `build:api` script to run WCA against the generated component wrappers.</li><li>The migration script outputs the API documentation to `docs/api.md`.</li></ul> | `src/migrations/wca-script-update/migration.js` |
| Adds a shell script to execute the WCA setup, migration, and build commands. | <ul><li>The script executes the `wca-setup` command.</li><li>The script executes the migration script to update the `package.json`.</li><li>The script installs dependencies, builds the API documentation, builds the documentation, and builds the project.</li></ul> | `src/migrations/wca-script-update/script.sh` |
| Adds a multi-gitter configuration file for automating the WCA script update across multiple repositories. | <ul><li>Specifies the target repositories.</li><li>Configures the branch name, commit message, and pull request title.</li><li>Sets the pull request body and assignees.</li><li>Configures the platform, conflict strategy, and other settings for the multi-gitter tool.</li></ul> | `src/migrations/wca-script-update/multi-gitter.yml` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!
- **Generate a plan of action for an issue:** Comment `@sourcery-ai plan` on
  an issue to generate a plan of action for it.

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: NONE
user: login: jyang81
created_at: 2025-04-07T18:26:40Z
body: @sourcery-ai review
author_association: CONTRIBUTOR
user: login: jason-capsule42
created_at: 2025-04-10T21:26:00Z
body: :tada: This PR is included in version 1.2.0 :tada:

The release is available on:
- [npm package (@latest dist-tag)](https://www.npmjs.com/package/@aurodesignsystem/auro-cli/v/1.2.0)
- [GitHub release](https://github.com/AlaskaAirlines/auro-cli/releases/tag/v1.2.0)

Your **[semantic-release](https://github.com/semantic-release/semantic-release)** bot :package::rocket:
author_association: MEMBER