├── .node-version ├── .prettierignore ├── .eslintignore ├── CODEOWNERS ├── .gitattributes ├── src ├── index.ts ├── wait.ts └── main.ts ├── .github ├── linters │ ├── .yaml-lint.yml │ ├── tsconfig.json │ ├── .markdown-lint.yml │ └── .eslintrc.yml ├── dependabot.yml └── workflows │ ├── codeql-analysis.yml │ ├── linter.yml │ ├── ci.yml │ └── check-dist.yml ├── .prettierrc.json ├── __tests__ ├── index.test.ts ├── wait.test.ts └── main.test.ts ├── tsconfig.json ├── action.yml ├── badges └── coverage.svg ├── LICENSE ├── .devcontainer └── devcontainer.json ├── script └── release ├── .gitignore ├── package.json ├── dist ├── licenses.txt └── sourcemap-register.js └── README.md /.node-version: -------------------------------------------------------------------------------- 1 | 20.6.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | coverage/ 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | dist/ 3 | node_modules/ 4 | coverage/ 5 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Repository CODEOWNERS 2 | 3 | * @actions/actions-oss-maintainers 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | dist/** -diff linguist-generated=true 4 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The entrypoint for the action. 3 | */ 4 | import { run } from './main' 5 | 6 | // eslint-disable-next-line @typescript-eslint/no-floating-promises 7 | run() 8 | -------------------------------------------------------------------------------- /.github/linters/.yaml-lint.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | document-end: disable 3 | document-start: 4 | level: warning 5 | present: false 6 | line-length: 7 | level: warning 8 | max: 80 9 | allow-non-breakable-words: true 10 | allow-non-breakable-inline-mappings: true 11 | -------------------------------------------------------------------------------- /.github/linters/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "noEmit": true 6 | }, 7 | "include": ["../../__tests__/**/*", "../../src/**/*"], 8 | "exclude": ["../../dist", "../../node_modules", "../../coverage", "*.json"] 9 | } 10 | -------------------------------------------------------------------------------- /.github/linters/.markdown-lint.yml: -------------------------------------------------------------------------------- 1 | # Unordered list style 2 | MD004: 3 | style: dash 4 | 5 | # Ordered list item prefix 6 | MD029: 7 | style: one 8 | 9 | # Spaces after list markers 10 | MD030: 11 | ul_single: 1 12 | ol_single: 1 13 | ul_multi: 1 14 | ol_multi: 1 15 | 16 | # Code block style 17 | MD046: 18 | style: fenced 19 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": false, 6 | "singleQuote": true, 7 | "quoteProps": "as-needed", 8 | "jsxSingleQuote": false, 9 | "trailingComma": "none", 10 | "bracketSpacing": true, 11 | "bracketSameLine": true, 12 | "arrowParens": "avoid", 13 | "proseWrap": "always", 14 | "htmlWhitespaceSensitivity": "css", 15 | "endOfLine": "lf" 16 | } 17 | -------------------------------------------------------------------------------- /src/wait.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Wait for a number of milliseconds. 3 | * @param milliseconds The number of milliseconds to wait. 4 | * @returns {Promise} Resolves with 'done!' after the wait is over. 5 | */ 6 | export async function wait(milliseconds: number): Promise { 7 | return new Promise(resolve => { 8 | if (isNaN(milliseconds)) { 9 | throw new Error('milliseconds not a number') 10 | } 11 | 12 | setTimeout(() => resolve('done!'), milliseconds) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Unit tests for the action's entrypoint, src/index.ts 3 | */ 4 | 5 | import * as main from '../src/main' 6 | 7 | // Mock the action's entrypoint 8 | const runMock = jest.spyOn(main, 'run').mockImplementation() 9 | 10 | describe('index', () => { 11 | it('calls run when imported', async () => { 12 | // eslint-disable-next-line @typescript-eslint/no-require-imports 13 | require('../src/index') 14 | 15 | expect(runMock).toHaveBeenCalled() 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "target": "ES2022", 5 | "module": "NodeNext", 6 | "rootDir": "./src", 7 | "moduleResolution": "NodeNext", 8 | "baseUrl": "./", 9 | "sourceMap": true, 10 | "outDir": "./dist", 11 | "noImplicitAny": true, 12 | "esModuleInterop": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "strict": true, 15 | "skipLibCheck": true, 16 | "newLine": "lf" 17 | }, 18 | "exclude": ["./dist", "./node_modules", "./__tests__", "./coverage"] 19 | } 20 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'The name of your action here' 2 | description: 'Provide a description here' 3 | author: 'Your name or organization here' 4 | 5 | # Add your action's branding here. This will appear on the GitHub Marketplace. 6 | branding: 7 | icon: 'heart' 8 | color: 'red' 9 | 10 | # Define your inputs here. 11 | inputs: 12 | milliseconds: 13 | description: 'Your input description here' 14 | required: true 15 | default: '1000' 16 | 17 | # Define your outputs here. 18 | outputs: 19 | time: 20 | description: 'Your output description here' 21 | 22 | runs: 23 | using: node20 24 | main: dist/index.js 25 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | groups: 8 | actions-minor: 9 | update-types: 10 | - minor 11 | - patch 12 | 13 | - package-ecosystem: npm 14 | directory: / 15 | schedule: 16 | interval: weekly 17 | groups: 18 | npm-development: 19 | dependency-type: development 20 | update-types: 21 | - minor 22 | - patch 23 | npm-production: 24 | dependency-type: production 25 | update-types: 26 | - patch 27 | -------------------------------------------------------------------------------- /__tests__/wait.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Unit tests for src/wait.ts 3 | */ 4 | 5 | import { wait } from '../src/wait' 6 | import { expect } from '@jest/globals' 7 | 8 | describe('wait.ts', () => { 9 | it('throws an invalid number', async () => { 10 | const input = parseInt('foo', 10) 11 | expect(isNaN(input)).toBe(true) 12 | 13 | await expect(wait(input)).rejects.toThrow('milliseconds not a number') 14 | }) 15 | 16 | it('waits with a valid number', async () => { 17 | const start = new Date() 18 | await wait(500) 19 | const end = new Date() 20 | 21 | const delta = Math.abs(end.getTime() - start.getTime()) 22 | 23 | expect(delta).toBeGreaterThan(450) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core' 2 | import { wait } from './wait' 3 | 4 | /** 5 | * The main function for the action. 6 | * @returns {Promise} Resolves when the action is complete. 7 | */ 8 | export async function run(): Promise { 9 | try { 10 | const ms: string = core.getInput('milliseconds') 11 | 12 | // Debug logs are only output if the `ACTIONS_STEP_DEBUG` secret is true 13 | core.debug(`Waiting ${ms} milliseconds ...`) 14 | 15 | // Log the current timestamp, wait, then log the new timestamp 16 | core.debug(new Date().toTimeString()) 17 | await wait(parseInt(ms, 10)) 18 | core.debug(new Date().toTimeString()) 19 | 20 | // Set outputs for other workflow steps to use 21 | core.setOutput('time', new Date().toTimeString()) 22 | } catch (error) { 23 | // Fail the workflow run if an error occurs 24 | if (error instanceof Error) core.setFailed(error.message) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: CodeQL 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - main 10 | schedule: 11 | - cron: '31 7 * * 3' 12 | 13 | permissions: 14 | actions: read 15 | checks: write 16 | contents: read 17 | security-events: write 18 | 19 | jobs: 20 | analyze: 21 | name: Analyze 22 | runs-on: ubuntu-latest 23 | 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | language: 28 | - TypeScript 29 | 30 | steps: 31 | - name: Checkout 32 | id: checkout 33 | uses: actions/checkout@v4 34 | 35 | - name: Initialize CodeQL 36 | id: initialize 37 | uses: github/codeql-action/init@v3 38 | with: 39 | languages: ${{ matrix.language }} 40 | source-root: src 41 | 42 | - name: Autobuild 43 | id: autobuild 44 | uses: github/codeql-action/autobuild@v3 45 | 46 | - name: Perform CodeQL Analysis 47 | id: analyze 48 | uses: github/codeql-action/analyze@v3 49 | -------------------------------------------------------------------------------- /badges/coverage.svg: -------------------------------------------------------------------------------- 1 | Coverage: 100%Coverage100% -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright GitHub 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: Lint Codebase 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - main 10 | 11 | permissions: 12 | contents: read 13 | packages: read 14 | statuses: write 15 | 16 | jobs: 17 | lint: 18 | name: Lint Codebase 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout 23 | id: checkout 24 | uses: actions/checkout@v4 25 | with: 26 | fetch-depth: 0 27 | 28 | - name: Setup Node.js 29 | id: setup-node 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version-file: .node-version 33 | cache: npm 34 | 35 | - name: Install Dependencies 36 | id: install 37 | run: npm ci 38 | 39 | - name: Lint Codebase 40 | id: super-linter 41 | uses: super-linter/super-linter/slim@v6 42 | env: 43 | DEFAULT_BRANCH: main 44 | FILTER_REGEX_EXCLUDE: dist/**/* 45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | TYPESCRIPT_DEFAULT_STYLE: prettier 47 | VALIDATE_ALL_CODEBASE: true 48 | VALIDATE_JAVASCRIPT_STANDARD: false 49 | VALIDATE_JSCPD: false 50 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GitHub Actions (TypeScript)", 3 | "image": "mcr.microsoft.com/devcontainers/typescript-node:20", 4 | "postCreateCommand": "npm install", 5 | "customizations": { 6 | "codespaces": { 7 | "openFiles": ["README.md"] 8 | }, 9 | "vscode": { 10 | "extensions": [ 11 | "bierner.markdown-preview-github-styles", 12 | "davidanson.vscode-markdownlint", 13 | "dbaeumer.vscode-eslint", 14 | "esbenp.prettier-vscode", 15 | "github.copilot", 16 | "github.copilot-chat", 17 | "github.vscode-github-actions", 18 | "github.vscode-pull-request-github", 19 | "me-dutour-mathieu.vscode-github-actions", 20 | "redhat.vscode-yaml", 21 | "rvest.vs-code-prettier-eslint", 22 | "yzhang.markdown-all-in-one" 23 | ], 24 | "settings": { 25 | "editor.defaultFormatter": "esbenp.prettier-vscode", 26 | "editor.tabSize": 2, 27 | "editor.formatOnSave": true, 28 | "markdown.extension.list.indentationSize": "adaptive", 29 | "markdown.extension.italic.indicator": "_", 30 | "markdown.extension.orderedList.marker": "one" 31 | } 32 | } 33 | }, 34 | "remoteEnv": { 35 | "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}" 36 | }, 37 | "features": { 38 | "ghcr.io/devcontainers/features/github-cli:1": {}, 39 | "ghcr.io/devcontainers-contrib/features/prettier:1": {} 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - main 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | test-typescript: 16 | name: TypeScript Tests 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout 21 | id: checkout 22 | uses: actions/checkout@v4 23 | 24 | - name: Setup Node.js 25 | id: setup-node 26 | uses: actions/setup-node@v4 27 | with: 28 | node-version-file: .node-version 29 | cache: npm 30 | 31 | - name: Install Dependencies 32 | id: npm-ci 33 | run: npm ci 34 | 35 | - name: Check Format 36 | id: npm-format-check 37 | run: npm run format:check 38 | 39 | - name: Lint 40 | id: npm-lint 41 | run: npm run lint 42 | 43 | - name: Test 44 | id: npm-ci-test 45 | run: npm run ci-test 46 | 47 | test-action: 48 | name: GitHub Actions Test 49 | runs-on: ubuntu-latest 50 | 51 | steps: 52 | - name: Checkout 53 | id: checkout 54 | uses: actions/checkout@v4 55 | 56 | - name: Test Local Action 57 | id: test-action 58 | uses: ./ 59 | with: 60 | milliseconds: 2000 61 | 62 | - name: Print Output 63 | id: output 64 | run: echo "${{ steps.test-action.outputs.time }}" 65 | -------------------------------------------------------------------------------- /script/release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # About: 4 | # 5 | # This is a helper script to tag and push a new release. GitHub Actions use 6 | # release tags to allow users to select a specific version of the action to use. 7 | # 8 | # See: https://github.com/actions/typescript-action#publishing-a-new-release 9 | # 10 | # This script will do the following: 11 | # 12 | # 1. Get the latest release tag 13 | # 2. Prompt the user for a new release tag 14 | # 3. Tag the new release 15 | # 4. Push the new tag to the remote 16 | # 17 | # Usage: 18 | # 19 | # script/release 20 | 21 | # Terminal colors 22 | OFF='\033[0m' 23 | RED='\033[0;31m' 24 | GREEN='\033[0;32m' 25 | BLUE='\033[0;34m' 26 | 27 | # Get the latest release tag 28 | latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)") 29 | 30 | if [[ -z "$latest_tag" ]]; then 31 | # There are no existing release tags 32 | echo -e "No tags found (yet) - Continue to create and push your first tag" 33 | latest_tag="[unknown]" 34 | fi 35 | 36 | # Display the latest release tag 37 | echo -e "The latest release tag is: ${BLUE}${latest_tag}${OFF}" 38 | 39 | # Prompt the user for the new release tag 40 | read -r -p 'Enter a new release tag (vX.X.X format): ' new_tag 41 | 42 | # Validate the new release tag 43 | tag_regex='v[0-9]+\.[0-9]+\.[0-9]+$' 44 | if echo "$new_tag" | grep -q -E "$tag_regex"; then 45 | echo -e "Tag: ${BLUE}$new_tag${OFF} is valid" 46 | else 47 | # Release tag is not `vX.X.X` format 48 | echo -e "Tag: ${BLUE}$new_tag${OFF} is ${RED}not valid${OFF} (must be in vX.X.X format)" 49 | exit 1 50 | fi 51 | 52 | # Tag the new release 53 | git tag -a "$new_tag" -m "$new_tag Release" 54 | echo -e "${GREEN}Tagged: $new_tag${OFF}" 55 | 56 | # Push the new tag to the remote 57 | git push --tags 58 | echo -e "${GREEN}Release tag pushed to remote${OFF}" 59 | echo -e "${GREEN}Done!${OFF}" 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules 3 | 4 | # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variables file 69 | .env 70 | .env.test 71 | 72 | # parcel-bundler cache (https://parceljs.org/) 73 | .cache 74 | 75 | # next.js build output 76 | .next 77 | 78 | # nuxt.js build output 79 | .nuxt 80 | 81 | # vuepress build output 82 | .vuepress/dist 83 | 84 | # Serverless directories 85 | .serverless/ 86 | 87 | # FuseBox cache 88 | .fusebox/ 89 | 90 | # DynamoDB Local files 91 | .dynamodb/ 92 | 93 | # OS metadata 94 | .DS_Store 95 | Thumbs.db 96 | 97 | # Ignore built ts files 98 | __tests__/runner/* 99 | 100 | # IDE files 101 | .idea 102 | .vscode 103 | *.code-workspace 104 | -------------------------------------------------------------------------------- /.github/workflows/check-dist.yml: -------------------------------------------------------------------------------- 1 | # In TypeScript actions, `dist/` is a special directory. When you reference 2 | # an action with the `uses:` property, `dist/index.js` is the code that will be 3 | # run. For this project, the `dist/index.js` file is transpiled from other 4 | # source files. This workflow ensures the `dist/` directory contains the 5 | # expected transpiled code. 6 | # 7 | # If this workflow is run from a feature branch, it will act as an additional CI 8 | # check and fail if the checked-in `dist/` directory does not match what is 9 | # expected from the build. 10 | name: Check Transpiled JavaScript 11 | 12 | on: 13 | pull_request: 14 | branches: 15 | - main 16 | push: 17 | branches: 18 | - main 19 | 20 | permissions: 21 | contents: read 22 | 23 | jobs: 24 | check-dist: 25 | name: Check dist/ 26 | runs-on: ubuntu-latest 27 | 28 | steps: 29 | - name: Checkout 30 | id: checkout 31 | uses: actions/checkout@v4 32 | 33 | - name: Setup Node.js 34 | id: setup-node 35 | uses: actions/setup-node@v4 36 | with: 37 | node-version-file: .node-version 38 | cache: npm 39 | 40 | - name: Install Dependencies 41 | id: install 42 | run: npm ci 43 | 44 | - name: Build dist/ Directory 45 | id: build 46 | run: npm run bundle 47 | 48 | # This will fail the workflow if the PR wasn't created by Dependabot. 49 | - name: Compare Directories 50 | id: diff 51 | run: | 52 | if [ "$(git diff --ignore-space-at-eol --text dist/ | wc -l)" -gt "0" ]; then 53 | echo "Detected uncommitted changes after build. See status below:" 54 | git diff --ignore-space-at-eol --text dist/ 55 | exit 1 56 | fi 57 | 58 | # If `dist/` was different than expected, and this was not a Dependabot 59 | # PR, upload the expected version as a workflow artifact. 60 | - if: ${{ failure() && steps.diff.outcome == 'failure' }} 61 | name: Upload Artifact 62 | id: upload 63 | uses: actions/upload-artifact@v4 64 | with: 65 | name: dist 66 | path: dist/ 67 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-action", 3 | "description": "GitHub Actions TypeScript template", 4 | "version": "0.0.0", 5 | "author": "", 6 | "private": true, 7 | "homepage": "https://github.com/actions/typescript-action", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/actions/typescript-action.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/actions/typescript-action/issues" 14 | }, 15 | "keywords": [ 16 | "actions", 17 | "node", 18 | "setup" 19 | ], 20 | "exports": { 21 | ".": "./dist/index.js" 22 | }, 23 | "engines": { 24 | "node": ">=20" 25 | }, 26 | "scripts": { 27 | "bundle": "npm run format:write && npm run package", 28 | "ci-test": "npx jest", 29 | "coverage": "npx make-coverage-badge --output-path ./badges/coverage.svg", 30 | "format:write": "npx prettier --write .", 31 | "format:check": "npx prettier --check .", 32 | "lint": "npx eslint . -c ./.github/linters/.eslintrc.yml", 33 | "package": "npx ncc build src/index.ts -o dist --source-map --license licenses.txt", 34 | "package:watch": "npm run package -- --watch", 35 | "test": "npx jest", 36 | "all": "npm run format:write && npm run lint && npm run test && npm run coverage && npm run package" 37 | }, 38 | "license": "MIT", 39 | "jest": { 40 | "preset": "ts-jest", 41 | "verbose": true, 42 | "clearMocks": true, 43 | "testEnvironment": "node", 44 | "moduleFileExtensions": [ 45 | "js", 46 | "ts" 47 | ], 48 | "testMatch": [ 49 | "**/*.test.ts" 50 | ], 51 | "testPathIgnorePatterns": [ 52 | "/node_modules/", 53 | "/dist/" 54 | ], 55 | "transform": { 56 | "^.+\\.ts$": "ts-jest" 57 | }, 58 | "coverageReporters": [ 59 | "json-summary", 60 | "text", 61 | "lcov" 62 | ], 63 | "collectCoverage": true, 64 | "collectCoverageFrom": [ 65 | "./src/**" 66 | ] 67 | }, 68 | "dependencies": { 69 | "@actions/core": "^1.10.1" 70 | }, 71 | "devDependencies": { 72 | "@types/jest": "^29.5.12", 73 | "@types/node": "^20.11.25", 74 | "@typescript-eslint/eslint-plugin": "^7.0.2", 75 | "@typescript-eslint/parser": "^7.1.1", 76 | "@vercel/ncc": "^0.38.1", 77 | "eslint": "^8.57.0", 78 | "eslint-plugin-github": "^4.10.2", 79 | "eslint-plugin-jest": "^27.9.0", 80 | "eslint-plugin-jsonc": "^2.13.0", 81 | "eslint-plugin-prettier": "^5.1.3", 82 | "jest": "^29.7.0", 83 | "make-coverage-badge": "^1.2.0", 84 | "prettier": "^3.2.5", 85 | "prettier-eslint": "^16.3.0", 86 | "ts-jest": "^29.1.2", 87 | "typescript": "^5.4.2" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /__tests__/main.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Unit tests for the action's main functionality, src/main.ts 3 | * 4 | * These should be run as if the action was called from a workflow. 5 | * Specifically, the inputs listed in `action.yml` should be set as environment 6 | * variables following the pattern `INPUT_`. 7 | */ 8 | 9 | import * as core from '@actions/core' 10 | import * as main from '../src/main' 11 | 12 | // Mock the action's main function 13 | const runMock = jest.spyOn(main, 'run') 14 | 15 | // Other utilities 16 | const timeRegex = /^\d{2}:\d{2}:\d{2}/ 17 | 18 | // Mock the GitHub Actions core library 19 | let debugMock: jest.SpiedFunction 20 | let errorMock: jest.SpiedFunction 21 | let getInputMock: jest.SpiedFunction 22 | let setFailedMock: jest.SpiedFunction 23 | let setOutputMock: jest.SpiedFunction 24 | 25 | describe('action', () => { 26 | beforeEach(() => { 27 | jest.clearAllMocks() 28 | 29 | debugMock = jest.spyOn(core, 'debug').mockImplementation() 30 | errorMock = jest.spyOn(core, 'error').mockImplementation() 31 | getInputMock = jest.spyOn(core, 'getInput').mockImplementation() 32 | setFailedMock = jest.spyOn(core, 'setFailed').mockImplementation() 33 | setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation() 34 | }) 35 | 36 | it('sets the time output', async () => { 37 | // Set the action's inputs as return values from core.getInput() 38 | getInputMock.mockImplementation(name => { 39 | switch (name) { 40 | case 'milliseconds': 41 | return '500' 42 | default: 43 | return '' 44 | } 45 | }) 46 | 47 | await main.run() 48 | expect(runMock).toHaveReturned() 49 | 50 | // Verify that all of the core library functions were called correctly 51 | expect(debugMock).toHaveBeenNthCalledWith(1, 'Waiting 500 milliseconds ...') 52 | expect(debugMock).toHaveBeenNthCalledWith( 53 | 2, 54 | expect.stringMatching(timeRegex) 55 | ) 56 | expect(debugMock).toHaveBeenNthCalledWith( 57 | 3, 58 | expect.stringMatching(timeRegex) 59 | ) 60 | expect(setOutputMock).toHaveBeenNthCalledWith( 61 | 1, 62 | 'time', 63 | expect.stringMatching(timeRegex) 64 | ) 65 | expect(errorMock).not.toHaveBeenCalled() 66 | }) 67 | 68 | it('sets a failed status', async () => { 69 | // Set the action's inputs as return values from core.getInput() 70 | getInputMock.mockImplementation(name => { 71 | switch (name) { 72 | case 'milliseconds': 73 | return 'this is not a number' 74 | default: 75 | return '' 76 | } 77 | }) 78 | 79 | await main.run() 80 | expect(runMock).toHaveReturned() 81 | 82 | // Verify that all of the core library functions were called correctly 83 | expect(setFailedMock).toHaveBeenNthCalledWith( 84 | 1, 85 | 'milliseconds not a number' 86 | ) 87 | expect(errorMock).not.toHaveBeenCalled() 88 | }) 89 | }) 90 | -------------------------------------------------------------------------------- /.github/linters/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | es6: true 4 | jest: true 5 | 6 | globals: 7 | Atomics: readonly 8 | SharedArrayBuffer: readonly 9 | 10 | ignorePatterns: 11 | - '!.*' 12 | - '**/node_modules/.*' 13 | - '**/dist/.*' 14 | - '**/coverage/.*' 15 | - '*.json' 16 | 17 | parser: '@typescript-eslint/parser' 18 | 19 | parserOptions: 20 | ecmaVersion: 2023 21 | sourceType: module 22 | project: 23 | - './.github/linters/tsconfig.json' 24 | - './tsconfig.json' 25 | 26 | plugins: 27 | - jest 28 | - '@typescript-eslint' 29 | 30 | extends: 31 | - eslint:recommended 32 | - plugin:@typescript-eslint/eslint-recommended 33 | - plugin:@typescript-eslint/recommended 34 | - plugin:github/recommended 35 | - plugin:jest/recommended 36 | 37 | rules: 38 | { 39 | 'camelcase': 'off', 40 | 'eslint-comments/no-use': 'off', 41 | 'eslint-comments/no-unused-disable': 'off', 42 | 'i18n-text/no-en': 'off', 43 | 'import/no-namespace': 'off', 44 | 'no-console': 'off', 45 | 'no-unused-vars': 'off', 46 | 'prettier/prettier': 'error', 47 | 'semi': 'off', 48 | '@typescript-eslint/array-type': 'error', 49 | '@typescript-eslint/await-thenable': 'error', 50 | '@typescript-eslint/ban-ts-comment': 'error', 51 | '@typescript-eslint/consistent-type-assertions': 'error', 52 | '@typescript-eslint/explicit-member-accessibility': 53 | ['error', { 'accessibility': 'no-public' }], 54 | '@typescript-eslint/explicit-function-return-type': 55 | ['error', { 'allowExpressions': true }], 56 | '@typescript-eslint/func-call-spacing': ['error', 'never'], 57 | '@typescript-eslint/no-array-constructor': 'error', 58 | '@typescript-eslint/no-empty-interface': 'error', 59 | '@typescript-eslint/no-explicit-any': 'error', 60 | '@typescript-eslint/no-extraneous-class': 'error', 61 | '@typescript-eslint/no-for-in-array': 'error', 62 | '@typescript-eslint/no-inferrable-types': 'error', 63 | '@typescript-eslint/no-misused-new': 'error', 64 | '@typescript-eslint/no-namespace': 'error', 65 | '@typescript-eslint/no-non-null-assertion': 'warn', 66 | '@typescript-eslint/no-require-imports': 'error', 67 | '@typescript-eslint/no-unnecessary-qualifier': 'error', 68 | '@typescript-eslint/no-unnecessary-type-assertion': 'error', 69 | '@typescript-eslint/no-unused-vars': 'error', 70 | '@typescript-eslint/no-useless-constructor': 'error', 71 | '@typescript-eslint/no-var-requires': 'error', 72 | '@typescript-eslint/prefer-for-of': 'warn', 73 | '@typescript-eslint/prefer-function-type': 'warn', 74 | '@typescript-eslint/prefer-includes': 'error', 75 | '@typescript-eslint/prefer-string-starts-ends-with': 'error', 76 | '@typescript-eslint/promise-function-async': 'error', 77 | '@typescript-eslint/require-array-sort-compare': 'error', 78 | '@typescript-eslint/restrict-plus-operands': 'error', 79 | '@typescript-eslint/semi': ['error', 'never'], 80 | '@typescript-eslint/space-before-function-paren': 'off', 81 | '@typescript-eslint/type-annotation-spacing': 'error', 82 | '@typescript-eslint/unbound-method': 'error' 83 | } 84 | -------------------------------------------------------------------------------- /dist/licenses.txt: -------------------------------------------------------------------------------- 1 | @actions/core 2 | MIT 3 | The MIT License (MIT) 4 | 5 | Copyright 2019 GitHub 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | 13 | @actions/http-client 14 | MIT 15 | Actions Http Client for Node.js 16 | 17 | Copyright (c) GitHub, Inc. 18 | 19 | All rights reserved. 20 | 21 | MIT License 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 24 | associated documentation files (the "Software"), to deal in the Software without restriction, 25 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 26 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 27 | subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 32 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 33 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 34 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 35 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | 38 | @fastify/busboy 39 | MIT 40 | Copyright Brian White. All rights reserved. 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy 43 | of this software and associated documentation files (the "Software"), to 44 | deal in the Software without restriction, including without limitation the 45 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 46 | sell copies of the Software, and to permit persons to whom the Software is 47 | furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in 50 | all copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 57 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 58 | IN THE SOFTWARE. 59 | 60 | tunnel 61 | MIT 62 | The MIT License (MIT) 63 | 64 | Copyright (c) 2012 Koichi Kobayashi 65 | 66 | Permission is hereby granted, free of charge, to any person obtaining a copy 67 | of this software and associated documentation files (the "Software"), to deal 68 | in the Software without restriction, including without limitation the rights 69 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 70 | copies of the Software, and to permit persons to whom the Software is 71 | furnished to do so, subject to the following conditions: 72 | 73 | The above copyright notice and this permission notice shall be included in 74 | all copies or substantial portions of the Software. 75 | 76 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 77 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 78 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 79 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 80 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 81 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 82 | THE SOFTWARE. 83 | 84 | 85 | undici 86 | MIT 87 | MIT License 88 | 89 | Copyright (c) Matteo Collina and Undici contributors 90 | 91 | Permission is hereby granted, free of charge, to any person obtaining a copy 92 | of this software and associated documentation files (the "Software"), to deal 93 | in the Software without restriction, including without limitation the rights 94 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 95 | copies of the Software, and to permit persons to whom the Software is 96 | furnished to do so, subject to the following conditions: 97 | 98 | The above copyright notice and this permission notice shall be included in all 99 | copies or substantial portions of the Software. 100 | 101 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 102 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 103 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 104 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 105 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 106 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 107 | SOFTWARE. 108 | 109 | 110 | uuid 111 | MIT 112 | The MIT License (MIT) 113 | 114 | Copyright (c) 2010-2020 Robert Kieffer and other contributors 115 | 116 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 117 | 118 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 119 | 120 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Create a GitHub Action Using TypeScript 2 | 3 | [![GitHub Super-Linter](https://github.com/actions/typescript-action/actions/workflows/linter.yml/badge.svg)](https://github.com/super-linter/super-linter) 4 | ![CI](https://github.com/actions/typescript-action/actions/workflows/ci.yml/badge.svg) 5 | [![Check dist/](https://github.com/actions/typescript-action/actions/workflows/check-dist.yml/badge.svg)](https://github.com/actions/typescript-action/actions/workflows/check-dist.yml) 6 | [![CodeQL](https://github.com/actions/typescript-action/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/actions/typescript-action/actions/workflows/codeql-analysis.yml) 7 | [![Coverage](./badges/coverage.svg)](./badges/coverage.svg) 8 | 9 | Use this template to bootstrap the creation of a TypeScript action. :rocket: 10 | 11 | This template includes compilation support, tests, a validation workflow, 12 | publishing, and versioning guidance. 13 | 14 | If you are new, there's also a simpler introduction in the 15 | [Hello world JavaScript action repository](https://github.com/actions/hello-world-javascript-action). 16 | 17 | ## Create Your Own Action 18 | 19 | To create your own action, you can use this repository as a template! Just 20 | follow the below instructions: 21 | 22 | 1. Click the **Use this template** button at the top of the repository 23 | 1. Select **Create a new repository** 24 | 1. Select an owner and name for your new repository 25 | 1. Click **Create repository** 26 | 1. Clone your new repository 27 | 28 | > [!IMPORTANT] 29 | > 30 | > Make sure to remove or update the [`CODEOWNERS`](./CODEOWNERS) file! For 31 | > details on how to use this file, see 32 | > [About code owners](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners). 33 | 34 | ## Initial Setup 35 | 36 | After you've cloned the repository to your local machine or codespace, you'll 37 | need to perform some initial setup steps before you can develop your action. 38 | 39 | > [!NOTE] 40 | > 41 | > You'll need to have a reasonably modern version of 42 | > [Node.js](https://nodejs.org) handy (20.x or later should work!). If you are 43 | > using a version manager like [`nodenv`](https://github.com/nodenv/nodenv) or 44 | > [`nvm`](https://github.com/nvm-sh/nvm), this template has a `.node-version` 45 | > file at the root of the repository that will be used to automatically switch 46 | > to the correct version when you `cd` into the repository. Additionally, this 47 | > `.node-version` file is used by GitHub Actions in any `actions/setup-node` 48 | > actions. 49 | 50 | 1. :hammer_and_wrench: Install the dependencies 51 | 52 | ```bash 53 | npm install 54 | ``` 55 | 56 | 1. :building_construction: Package the TypeScript for distribution 57 | 58 | ```bash 59 | npm run bundle 60 | ``` 61 | 62 | 1. :white_check_mark: Run the tests 63 | 64 | ```bash 65 | $ npm test 66 | 67 | PASS ./index.test.js 68 | ✓ throws invalid number (3ms) 69 | ✓ wait 500 ms (504ms) 70 | ✓ test runs (95ms) 71 | 72 | ... 73 | ``` 74 | 75 | ## Update the Action Metadata 76 | 77 | The [`action.yml`](action.yml) file defines metadata about your action, such as 78 | input(s) and output(s). For details about this file, see 79 | [Metadata syntax for GitHub Actions](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions). 80 | 81 | When you copy this repository, update `action.yml` with the name, description, 82 | inputs, and outputs for your action. 83 | 84 | ## Update the Action Code 85 | 86 | The [`src/`](./src/) directory is the heart of your action! This contains the 87 | source code that will be run when your action is invoked. You can replace the 88 | contents of this directory with your own code. 89 | 90 | There are a few things to keep in mind when writing your action code: 91 | 92 | - Most GitHub Actions toolkit and CI/CD operations are processed asynchronously. 93 | In `main.ts`, you will see that the action is run in an `async` function. 94 | 95 | ```javascript 96 | import * as core from '@actions/core' 97 | //... 98 | 99 | async function run() { 100 | try { 101 | //... 102 | } catch (error) { 103 | core.setFailed(error.message) 104 | } 105 | } 106 | ``` 107 | 108 | For more information about the GitHub Actions toolkit, see the 109 | [documentation](https://github.com/actions/toolkit/blob/master/README.md). 110 | 111 | So, what are you waiting for? Go ahead and start customizing your action! 112 | 113 | 1. Create a new branch 114 | 115 | ```bash 116 | git checkout -b releases/v1 117 | ``` 118 | 119 | 1. Replace the contents of `src/` with your action code 120 | 1. Add tests to `__tests__/` for your source code 121 | 1. Format, test, and build the action 122 | 123 | ```bash 124 | npm run all 125 | ``` 126 | 127 | > This step is important! It will run [`ncc`](https://github.com/vercel/ncc) 128 | > to build the final JavaScript action code with all dependencies included. 129 | > If you do not run this step, your action will not work correctly when it is 130 | > used in a workflow. This step also includes the `--license` option for 131 | > `ncc`, which will create a license file for all of the production node 132 | > modules used in your project. 133 | 134 | 1. Commit your changes 135 | 136 | ```bash 137 | git add . 138 | git commit -m "My first action is ready!" 139 | ``` 140 | 141 | 1. Push them to your repository 142 | 143 | ```bash 144 | git push -u origin releases/v1 145 | ``` 146 | 147 | 1. Create a pull request and get feedback on your action 148 | 1. Merge the pull request into the `main` branch 149 | 150 | Your action is now published! :rocket: 151 | 152 | For information about versioning your action, see 153 | [Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) 154 | in the GitHub Actions toolkit. 155 | 156 | ## Validate the Action 157 | 158 | You can now validate the action by referencing it in a workflow file. For 159 | example, [`ci.yml`](./.github/workflows/ci.yml) demonstrates how to reference an 160 | action in the same repository. 161 | 162 | ```yaml 163 | steps: 164 | - name: Checkout 165 | id: checkout 166 | uses: actions/checkout@v4 167 | 168 | - name: Test Local Action 169 | id: test-action 170 | uses: ./ 171 | with: 172 | milliseconds: 1000 173 | 174 | - name: Print Output 175 | id: output 176 | run: echo "${{ steps.test-action.outputs.time }}" 177 | ``` 178 | 179 | For example workflow runs, check out the 180 | [Actions tab](https://github.com/actions/typescript-action/actions)! :rocket: 181 | 182 | ## Usage 183 | 184 | After testing, you can create version tag(s) that developers can use to 185 | reference different stable versions of your action. For more information, see 186 | [Versioning](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) 187 | in the GitHub Actions toolkit. 188 | 189 | To include the action in a workflow in another repository, you can use the 190 | `uses` syntax with the `@` symbol to reference a specific branch, tag, or commit 191 | hash. 192 | 193 | ```yaml 194 | steps: 195 | - name: Checkout 196 | id: checkout 197 | uses: actions/checkout@v4 198 | 199 | - name: Test Local Action 200 | id: test-action 201 | uses: actions/typescript-action@v1 # Commit with the `v1` tag 202 | with: 203 | milliseconds: 1000 204 | 205 | - name: Print Output 206 | id: output 207 | run: echo "${{ steps.test-action.outputs.time }}" 208 | ``` 209 | 210 | ## Publishing a New Release 211 | 212 | This project includes a helper script, [`script/release`](./script/release) 213 | designed to streamline the process of tagging and pushing new releases for 214 | GitHub Actions. 215 | 216 | GitHub Actions allows users to select a specific version of the action to use, 217 | based on release tags. This script simplifies this process by performing the 218 | following steps: 219 | 220 | 1. **Retrieving the latest release tag:** The script starts by fetching the most 221 | recent release tag by looking at the local data available in your repository. 222 | 1. **Prompting for a new release tag:** The user is then prompted to enter a new 223 | release tag. To assist with this, the script displays the latest release tag 224 | and provides a regular expression to validate the format of the new tag. 225 | 1. **Tagging the new release:** Once a valid new tag is entered, the script tags 226 | the new release. 227 | 1. **Pushing the new tag to the remote:** Finally, the script pushes the new tag 228 | to the remote repository. From here, you will need to create a new release in 229 | GitHub and users can easily reference the new tag in their workflows. 230 | -------------------------------------------------------------------------------- /dist/sourcemap-register.js: -------------------------------------------------------------------------------- 1 | (()=>{var e={650:e=>{var r=Object.prototype.toString;var n=typeof Buffer.alloc==="function"&&typeof Buffer.allocUnsafe==="function"&&typeof Buffer.from==="function";function isArrayBuffer(e){return r.call(e).slice(8,-1)==="ArrayBuffer"}function fromArrayBuffer(e,r,t){r>>>=0;var o=e.byteLength-r;if(o<0){throw new RangeError("'offset' is out of bounds")}if(t===undefined){t=o}else{t>>>=0;if(t>o){throw new RangeError("'length' is out of bounds")}}return n?Buffer.from(e.slice(r,r+t)):new Buffer(new Uint8Array(e.slice(r,r+t)))}function fromString(e,r){if(typeof r!=="string"||r===""){r="utf8"}if(!Buffer.isEncoding(r)){throw new TypeError('"encoding" must be a valid string encoding')}return n?Buffer.from(e,r):new Buffer(e,r)}function bufferFrom(e,r,t){if(typeof e==="number"){throw new TypeError('"value" argument must not be a number')}if(isArrayBuffer(e)){return fromArrayBuffer(e,r,t)}if(typeof e==="string"){return fromString(e,r)}return n?Buffer.from(e):new Buffer(e)}e.exports=bufferFrom},274:(e,r,n)=>{var t=n(339);var o=Object.prototype.hasOwnProperty;var i=typeof Map!=="undefined";function ArraySet(){this._array=[];this._set=i?new Map:Object.create(null)}ArraySet.fromArray=function ArraySet_fromArray(e,r){var n=new ArraySet;for(var t=0,o=e.length;t=0){return r}}else{var n=t.toSetString(e);if(o.call(this._set,n)){return this._set[n]}}throw new Error('"'+e+'" is not in the set.')};ArraySet.prototype.at=function ArraySet_at(e){if(e>=0&&e{var t=n(190);var o=5;var i=1<>1;return r?-n:n}r.encode=function base64VLQ_encode(e){var r="";var n;var i=toVLQSigned(e);do{n=i&a;i>>>=o;if(i>0){n|=u}r+=t.encode(n)}while(i>0);return r};r.decode=function base64VLQ_decode(e,r,n){var i=e.length;var s=0;var l=0;var c,p;do{if(r>=i){throw new Error("Expected more digits in base 64 VLQ value.")}p=t.decode(e.charCodeAt(r++));if(p===-1){throw new Error("Invalid base64 digit: "+e.charAt(r-1))}c=!!(p&u);p&=a;s=s+(p<{var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");r.encode=function(e){if(0<=e&&e{r.GREATEST_LOWER_BOUND=1;r.LEAST_UPPER_BOUND=2;function recursiveSearch(e,n,t,o,i,a){var u=Math.floor((n-e)/2)+e;var s=i(t,o[u],true);if(s===0){return u}else if(s>0){if(n-u>1){return recursiveSearch(u,n,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return n1){return recursiveSearch(e,u,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return u}else{return e<0?-1:e}}}r.search=function search(e,n,t,o){if(n.length===0){return-1}var i=recursiveSearch(-1,n.length,e,n,t,o||r.GREATEST_LOWER_BOUND);if(i<0){return-1}while(i-1>=0){if(t(n[i],n[i-1],true)!==0){break}--i}return i}},680:(e,r,n)=>{var t=n(339);function generatedPositionAfter(e,r){var n=e.generatedLine;var o=r.generatedLine;var i=e.generatedColumn;var a=r.generatedColumn;return o>n||o==n&&a>=i||t.compareByGeneratedPositionsInflated(e,r)<=0}function MappingList(){this._array=[];this._sorted=true;this._last={generatedLine:-1,generatedColumn:0}}MappingList.prototype.unsortedForEach=function MappingList_forEach(e,r){this._array.forEach(e,r)};MappingList.prototype.add=function MappingList_add(e){if(generatedPositionAfter(this._last,e)){this._last=e;this._array.push(e)}else{this._sorted=false;this._array.push(e)}};MappingList.prototype.toArray=function MappingList_toArray(){if(!this._sorted){this._array.sort(t.compareByGeneratedPositionsInflated);this._sorted=true}return this._array};r.H=MappingList},758:(e,r)=>{function swap(e,r,n){var t=e[r];e[r]=e[n];e[n]=t}function randomIntInRange(e,r){return Math.round(e+Math.random()*(r-e))}function doQuickSort(e,r,n,t){if(n{var t;var o=n(339);var i=n(345);var a=n(274).I;var u=n(449);var s=n(758).U;function SourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}return n.sections!=null?new IndexedSourceMapConsumer(n,r):new BasicSourceMapConsumer(n,r)}SourceMapConsumer.fromSourceMap=function(e,r){return BasicSourceMapConsumer.fromSourceMap(e,r)};SourceMapConsumer.prototype._version=3;SourceMapConsumer.prototype.__generatedMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_generatedMappings",{configurable:true,enumerable:true,get:function(){if(!this.__generatedMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__generatedMappings}});SourceMapConsumer.prototype.__originalMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_originalMappings",{configurable:true,enumerable:true,get:function(){if(!this.__originalMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__originalMappings}});SourceMapConsumer.prototype._charIsMappingSeparator=function SourceMapConsumer_charIsMappingSeparator(e,r){var n=e.charAt(r);return n===";"||n===","};SourceMapConsumer.prototype._parseMappings=function SourceMapConsumer_parseMappings(e,r){throw new Error("Subclasses must implement _parseMappings")};SourceMapConsumer.GENERATED_ORDER=1;SourceMapConsumer.ORIGINAL_ORDER=2;SourceMapConsumer.GREATEST_LOWER_BOUND=1;SourceMapConsumer.LEAST_UPPER_BOUND=2;SourceMapConsumer.prototype.eachMapping=function SourceMapConsumer_eachMapping(e,r,n){var t=r||null;var i=n||SourceMapConsumer.GENERATED_ORDER;var a;switch(i){case SourceMapConsumer.GENERATED_ORDER:a=this._generatedMappings;break;case SourceMapConsumer.ORIGINAL_ORDER:a=this._originalMappings;break;default:throw new Error("Unknown order of iteration.")}var u=this.sourceRoot;a.map((function(e){var r=e.source===null?null:this._sources.at(e.source);r=o.computeSourceURL(u,r,this._sourceMapURL);return{source:r,generatedLine:e.generatedLine,generatedColumn:e.generatedColumn,originalLine:e.originalLine,originalColumn:e.originalColumn,name:e.name===null?null:this._names.at(e.name)}}),this).forEach(e,t)};SourceMapConsumer.prototype.allGeneratedPositionsFor=function SourceMapConsumer_allGeneratedPositionsFor(e){var r=o.getArg(e,"line");var n={source:o.getArg(e,"source"),originalLine:r,originalColumn:o.getArg(e,"column",0)};n.source=this._findSourceIndex(n.source);if(n.source<0){return[]}var t=[];var a=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,i.LEAST_UPPER_BOUND);if(a>=0){var u=this._originalMappings[a];if(e.column===undefined){var s=u.originalLine;while(u&&u.originalLine===s){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}else{var l=u.originalColumn;while(u&&u.originalLine===r&&u.originalColumn==l){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}}return t};r.SourceMapConsumer=SourceMapConsumer;function BasicSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sources");var u=o.getArg(n,"names",[]);var s=o.getArg(n,"sourceRoot",null);var l=o.getArg(n,"sourcesContent",null);var c=o.getArg(n,"mappings");var p=o.getArg(n,"file",null);if(t!=this._version){throw new Error("Unsupported version: "+t)}if(s){s=o.normalize(s)}i=i.map(String).map(o.normalize).map((function(e){return s&&o.isAbsolute(s)&&o.isAbsolute(e)?o.relative(s,e):e}));this._names=a.fromArray(u.map(String),true);this._sources=a.fromArray(i,true);this._absoluteSources=this._sources.toArray().map((function(e){return o.computeSourceURL(s,e,r)}));this.sourceRoot=s;this.sourcesContent=l;this._mappings=c;this._sourceMapURL=r;this.file=p}BasicSourceMapConsumer.prototype=Object.create(SourceMapConsumer.prototype);BasicSourceMapConsumer.prototype.consumer=SourceMapConsumer;BasicSourceMapConsumer.prototype._findSourceIndex=function(e){var r=e;if(this.sourceRoot!=null){r=o.relative(this.sourceRoot,r)}if(this._sources.has(r)){return this._sources.indexOf(r)}var n;for(n=0;n1){v.source=l+_[1];l+=_[1];v.originalLine=i+_[2];i=v.originalLine;v.originalLine+=1;v.originalColumn=a+_[3];a=v.originalColumn;if(_.length>4){v.name=c+_[4];c+=_[4]}}m.push(v);if(typeof v.originalLine==="number"){d.push(v)}}}s(m,o.compareByGeneratedPositionsDeflated);this.__generatedMappings=m;s(d,o.compareByOriginalPositions);this.__originalMappings=d};BasicSourceMapConsumer.prototype._findMapping=function SourceMapConsumer_findMapping(e,r,n,t,o,a){if(e[n]<=0){throw new TypeError("Line must be greater than or equal to 1, got "+e[n])}if(e[t]<0){throw new TypeError("Column must be greater than or equal to 0, got "+e[t])}return i.search(e,r,o,a)};BasicSourceMapConsumer.prototype.computeColumnSpans=function SourceMapConsumer_computeColumnSpans(){for(var e=0;e=0){var t=this._generatedMappings[n];if(t.generatedLine===r.generatedLine){var i=o.getArg(t,"source",null);if(i!==null){i=this._sources.at(i);i=o.computeSourceURL(this.sourceRoot,i,this._sourceMapURL)}var a=o.getArg(t,"name",null);if(a!==null){a=this._names.at(a)}return{source:i,line:o.getArg(t,"originalLine",null),column:o.getArg(t,"originalColumn",null),name:a}}}return{source:null,line:null,column:null,name:null}};BasicSourceMapConsumer.prototype.hasContentsOfAllSources=function BasicSourceMapConsumer_hasContentsOfAllSources(){if(!this.sourcesContent){return false}return this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some((function(e){return e==null}))};BasicSourceMapConsumer.prototype.sourceContentFor=function SourceMapConsumer_sourceContentFor(e,r){if(!this.sourcesContent){return null}var n=this._findSourceIndex(e);if(n>=0){return this.sourcesContent[n]}var t=e;if(this.sourceRoot!=null){t=o.relative(this.sourceRoot,t)}var i;if(this.sourceRoot!=null&&(i=o.urlParse(this.sourceRoot))){var a=t.replace(/^file:\/\//,"");if(i.scheme=="file"&&this._sources.has(a)){return this.sourcesContent[this._sources.indexOf(a)]}if((!i.path||i.path=="/")&&this._sources.has("/"+t)){return this.sourcesContent[this._sources.indexOf("/"+t)]}}if(r){return null}else{throw new Error('"'+t+'" is not in the SourceMap.')}};BasicSourceMapConsumer.prototype.generatedPositionFor=function SourceMapConsumer_generatedPositionFor(e){var r=o.getArg(e,"source");r=this._findSourceIndex(r);if(r<0){return{line:null,column:null,lastColumn:null}}var n={source:r,originalLine:o.getArg(e,"line"),originalColumn:o.getArg(e,"column")};var t=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,o.getArg(e,"bias",SourceMapConsumer.GREATEST_LOWER_BOUND));if(t>=0){var i=this._originalMappings[t];if(i.source===n.source){return{line:o.getArg(i,"generatedLine",null),column:o.getArg(i,"generatedColumn",null),lastColumn:o.getArg(i,"lastGeneratedColumn",null)}}}return{line:null,column:null,lastColumn:null}};t=BasicSourceMapConsumer;function IndexedSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sections");if(t!=this._version){throw new Error("Unsupported version: "+t)}this._sources=new a;this._names=new a;var u={line:-1,column:0};this._sections=i.map((function(e){if(e.url){throw new Error("Support for url field in sections not implemented.")}var n=o.getArg(e,"offset");var t=o.getArg(n,"line");var i=o.getArg(n,"column");if(t{var t=n(449);var o=n(339);var i=n(274).I;var a=n(680).H;function SourceMapGenerator(e){if(!e){e={}}this._file=o.getArg(e,"file",null);this._sourceRoot=o.getArg(e,"sourceRoot",null);this._skipValidation=o.getArg(e,"skipValidation",false);this._sources=new i;this._names=new i;this._mappings=new a;this._sourcesContents=null}SourceMapGenerator.prototype._version=3;SourceMapGenerator.fromSourceMap=function SourceMapGenerator_fromSourceMap(e){var r=e.sourceRoot;var n=new SourceMapGenerator({file:e.file,sourceRoot:r});e.eachMapping((function(e){var t={generated:{line:e.generatedLine,column:e.generatedColumn}};if(e.source!=null){t.source=e.source;if(r!=null){t.source=o.relative(r,t.source)}t.original={line:e.originalLine,column:e.originalColumn};if(e.name!=null){t.name=e.name}}n.addMapping(t)}));e.sources.forEach((function(t){var i=t;if(r!==null){i=o.relative(r,t)}if(!n._sources.has(i)){n._sources.add(i)}var a=e.sourceContentFor(t);if(a!=null){n.setSourceContent(t,a)}}));return n};SourceMapGenerator.prototype.addMapping=function SourceMapGenerator_addMapping(e){var r=o.getArg(e,"generated");var n=o.getArg(e,"original",null);var t=o.getArg(e,"source",null);var i=o.getArg(e,"name",null);if(!this._skipValidation){this._validateMapping(r,n,t,i)}if(t!=null){t=String(t);if(!this._sources.has(t)){this._sources.add(t)}}if(i!=null){i=String(i);if(!this._names.has(i)){this._names.add(i)}}this._mappings.add({generatedLine:r.line,generatedColumn:r.column,originalLine:n!=null&&n.line,originalColumn:n!=null&&n.column,source:t,name:i})};SourceMapGenerator.prototype.setSourceContent=function SourceMapGenerator_setSourceContent(e,r){var n=e;if(this._sourceRoot!=null){n=o.relative(this._sourceRoot,n)}if(r!=null){if(!this._sourcesContents){this._sourcesContents=Object.create(null)}this._sourcesContents[o.toSetString(n)]=r}else if(this._sourcesContents){delete this._sourcesContents[o.toSetString(n)];if(Object.keys(this._sourcesContents).length===0){this._sourcesContents=null}}};SourceMapGenerator.prototype.applySourceMap=function SourceMapGenerator_applySourceMap(e,r,n){var t=r;if(r==null){if(e.file==null){throw new Error("SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, "+'or the source map\'s "file" property. Both were omitted.')}t=e.file}var a=this._sourceRoot;if(a!=null){t=o.relative(a,t)}var u=new i;var s=new i;this._mappings.unsortedForEach((function(r){if(r.source===t&&r.originalLine!=null){var i=e.originalPositionFor({line:r.originalLine,column:r.originalColumn});if(i.source!=null){r.source=i.source;if(n!=null){r.source=o.join(n,r.source)}if(a!=null){r.source=o.relative(a,r.source)}r.originalLine=i.line;r.originalColumn=i.column;if(i.name!=null){r.name=i.name}}}var l=r.source;if(l!=null&&!u.has(l)){u.add(l)}var c=r.name;if(c!=null&&!s.has(c)){s.add(c)}}),this);this._sources=u;this._names=s;e.sources.forEach((function(r){var t=e.sourceContentFor(r);if(t!=null){if(n!=null){r=o.join(n,r)}if(a!=null){r=o.relative(a,r)}this.setSourceContent(r,t)}}),this)};SourceMapGenerator.prototype._validateMapping=function SourceMapGenerator_validateMapping(e,r,n,t){if(r&&typeof r.line!=="number"&&typeof r.column!=="number"){throw new Error("original.line and original.column are not numbers -- you probably meant to omit "+"the original mapping entirely and only map the generated position. If so, pass "+"null for the original mapping instead of an object with empty or null values.")}if(e&&"line"in e&&"column"in e&&e.line>0&&e.column>=0&&!r&&!n&&!t){return}else if(e&&"line"in e&&"column"in e&&r&&"line"in r&&"column"in r&&e.line>0&&e.column>=0&&r.line>0&&r.column>=0&&n){return}else{throw new Error("Invalid mapping: "+JSON.stringify({generated:e,source:n,original:r,name:t}))}};SourceMapGenerator.prototype._serializeMappings=function SourceMapGenerator_serializeMappings(){var e=0;var r=1;var n=0;var i=0;var a=0;var u=0;var s="";var l;var c;var p;var f;var g=this._mappings.toArray();for(var h=0,d=g.length;h0){if(!o.compareByGeneratedPositionsInflated(c,g[h-1])){continue}l+=","}}l+=t.encode(c.generatedColumn-e);e=c.generatedColumn;if(c.source!=null){f=this._sources.indexOf(c.source);l+=t.encode(f-u);u=f;l+=t.encode(c.originalLine-1-i);i=c.originalLine-1;l+=t.encode(c.originalColumn-n);n=c.originalColumn;if(c.name!=null){p=this._names.indexOf(c.name);l+=t.encode(p-a);a=p}}s+=l}return s};SourceMapGenerator.prototype._generateSourcesContent=function SourceMapGenerator_generateSourcesContent(e,r){return e.map((function(e){if(!this._sourcesContents){return null}if(r!=null){e=o.relative(r,e)}var n=o.toSetString(e);return Object.prototype.hasOwnProperty.call(this._sourcesContents,n)?this._sourcesContents[n]:null}),this)};SourceMapGenerator.prototype.toJSON=function SourceMapGenerator_toJSON(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};if(this._file!=null){e.file=this._file}if(this._sourceRoot!=null){e.sourceRoot=this._sourceRoot}if(this._sourcesContents){e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)}return e};SourceMapGenerator.prototype.toString=function SourceMapGenerator_toString(){return JSON.stringify(this.toJSON())};r.h=SourceMapGenerator},351:(e,r,n)=>{var t;var o=n(591).h;var i=n(339);var a=/(\r?\n)/;var u=10;var s="$$$isSourceNode$$$";function SourceNode(e,r,n,t,o){this.children=[];this.sourceContents={};this.line=e==null?null:e;this.column=r==null?null:r;this.source=n==null?null:n;this.name=o==null?null:o;this[s]=true;if(t!=null)this.add(t)}SourceNode.fromStringWithSourceMap=function SourceNode_fromStringWithSourceMap(e,r,n){var t=new SourceNode;var o=e.split(a);var u=0;var shiftNextLine=function(){var e=getNextLine();var r=getNextLine()||"";return e+r;function getNextLine(){return u=0;r--){this.prepend(e[r])}}else if(e[s]||typeof e==="string"){this.children.unshift(e)}else{throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e)}return this};SourceNode.prototype.walk=function SourceNode_walk(e){var r;for(var n=0,t=this.children.length;n0){r=[];for(n=0;n{function getArg(e,r,n){if(r in e){return e[r]}else if(arguments.length===3){return n}else{throw new Error('"'+r+'" is a required argument.')}}r.getArg=getArg;var n=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;var t=/^data:.+\,.+$/;function urlParse(e){var r=e.match(n);if(!r){return null}return{scheme:r[1],auth:r[2],host:r[3],port:r[4],path:r[5]}}r.urlParse=urlParse;function urlGenerate(e){var r="";if(e.scheme){r+=e.scheme+":"}r+="//";if(e.auth){r+=e.auth+"@"}if(e.host){r+=e.host}if(e.port){r+=":"+e.port}if(e.path){r+=e.path}return r}r.urlGenerate=urlGenerate;function normalize(e){var n=e;var t=urlParse(e);if(t){if(!t.path){return e}n=t.path}var o=r.isAbsolute(n);var i=n.split(/\/+/);for(var a,u=0,s=i.length-1;s>=0;s--){a=i[s];if(a==="."){i.splice(s,1)}else if(a===".."){u++}else if(u>0){if(a===""){i.splice(s+1,u);u=0}else{i.splice(s,2);u--}}}n=i.join("/");if(n===""){n=o?"/":"."}if(t){t.path=n;return urlGenerate(t)}return n}r.normalize=normalize;function join(e,r){if(e===""){e="."}if(r===""){r="."}var n=urlParse(r);var o=urlParse(e);if(o){e=o.path||"/"}if(n&&!n.scheme){if(o){n.scheme=o.scheme}return urlGenerate(n)}if(n||r.match(t)){return r}if(o&&!o.host&&!o.path){o.host=r;return urlGenerate(o)}var i=r.charAt(0)==="/"?r:normalize(e.replace(/\/+$/,"")+"/"+r);if(o){o.path=i;return urlGenerate(o)}return i}r.join=join;r.isAbsolute=function(e){return e.charAt(0)==="/"||n.test(e)};function relative(e,r){if(e===""){e="."}e=e.replace(/\/$/,"");var n=0;while(r.indexOf(e+"/")!==0){var t=e.lastIndexOf("/");if(t<0){return r}e=e.slice(0,t);if(e.match(/^([^\/]+:\/)?\/*$/)){return r}++n}return Array(n+1).join("../")+r.substr(e.length+1)}r.relative=relative;var o=function(){var e=Object.create(null);return!("__proto__"in e)}();function identity(e){return e}function toSetString(e){if(isProtoString(e)){return"$"+e}return e}r.toSetString=o?identity:toSetString;function fromSetString(e){if(isProtoString(e)){return e.slice(1)}return e}r.fromSetString=o?identity:fromSetString;function isProtoString(e){if(!e){return false}var r=e.length;if(r<9){return false}if(e.charCodeAt(r-1)!==95||e.charCodeAt(r-2)!==95||e.charCodeAt(r-3)!==111||e.charCodeAt(r-4)!==116||e.charCodeAt(r-5)!==111||e.charCodeAt(r-6)!==114||e.charCodeAt(r-7)!==112||e.charCodeAt(r-8)!==95||e.charCodeAt(r-9)!==95){return false}for(var n=r-10;n>=0;n--){if(e.charCodeAt(n)!==36){return false}}return true}function compareByOriginalPositions(e,r,n){var t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0||n){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0){return t}t=e.generatedLine-r.generatedLine;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByOriginalPositions=compareByOriginalPositions;function compareByGeneratedPositionsDeflated(e,r,n){var t=e.generatedLine-r.generatedLine;if(t!==0){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0||n){return t}t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsDeflated=compareByGeneratedPositionsDeflated;function strcmp(e,r){if(e===r){return 0}if(e===null){return 1}if(r===null){return-1}if(e>r){return 1}return-1}function compareByGeneratedPositionsInflated(e,r){var n=e.generatedLine-r.generatedLine;if(n!==0){return n}n=e.generatedColumn-r.generatedColumn;if(n!==0){return n}n=strcmp(e.source,r.source);if(n!==0){return n}n=e.originalLine-r.originalLine;if(n!==0){return n}n=e.originalColumn-r.originalColumn;if(n!==0){return n}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsInflated=compareByGeneratedPositionsInflated;function parseSourceMapInput(e){return JSON.parse(e.replace(/^\)]}'[^\n]*\n/,""))}r.parseSourceMapInput=parseSourceMapInput;function computeSourceURL(e,r,n){r=r||"";if(e){if(e[e.length-1]!=="/"&&r[0]!=="/"){e+="/"}r=e+r}if(n){var t=urlParse(n);if(!t){throw new Error("sourceMapURL could not be parsed")}if(t.path){var o=t.path.lastIndexOf("/");if(o>=0){t.path=t.path.substring(0,o+1)}}r=join(urlGenerate(t),r)}return normalize(r)}r.computeSourceURL=computeSourceURL},997:(e,r,n)=>{n(591).h;r.SourceMapConsumer=n(952).SourceMapConsumer;n(351)},284:(e,r,n)=>{e=n.nmd(e);var t=n(997).SourceMapConsumer;var o=n(17);var i;try{i=n(147);if(!i.existsSync||!i.readFileSync){i=null}}catch(e){}var a=n(650);function dynamicRequire(e,r){return e.require(r)}var u=false;var s=false;var l=false;var c="auto";var p={};var f={};var g=/^data:application\/json[^,]+base64,/;var h=[];var d=[];function isInBrowser(){if(c==="browser")return true;if(c==="node")return false;return typeof window!=="undefined"&&typeof XMLHttpRequest==="function"&&!(window.require&&window.module&&window.process&&window.process.type==="renderer")}function hasGlobalProcessEventEmitter(){return typeof process==="object"&&process!==null&&typeof process.on==="function"}function globalProcessVersion(){if(typeof process==="object"&&process!==null){return process.version}else{return""}}function globalProcessStderr(){if(typeof process==="object"&&process!==null){return process.stderr}}function globalProcessExit(e){if(typeof process==="object"&&process!==null&&typeof process.exit==="function"){return process.exit(e)}}function handlerExec(e){return function(r){for(var n=0;n"}var n=this.getLineNumber();if(n!=null){r+=":"+n;var t=this.getColumnNumber();if(t){r+=":"+t}}}var o="";var i=this.getFunctionName();var a=true;var u=this.isConstructor();var s=!(this.isToplevel()||u);if(s){var l=this.getTypeName();if(l==="[object Object]"){l="null"}var c=this.getMethodName();if(i){if(l&&i.indexOf(l)!=0){o+=l+"."}o+=i;if(c&&i.indexOf("."+c)!=i.length-c.length-1){o+=" [as "+c+"]"}}else{o+=l+"."+(c||"")}}else if(u){o+="new "+(i||"")}else if(i){o+=i}else{o+=r;a=false}if(a){o+=" ("+r+")"}return o}function cloneCallSite(e){var r={};Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach((function(n){r[n]=/^(?:is|get)/.test(n)?function(){return e[n].call(e)}:e[n]}));r.toString=CallSiteToString;return r}function wrapCallSite(e,r){if(r===undefined){r={nextPosition:null,curPosition:null}}if(e.isNative()){r.curPosition=null;return e}var n=e.getFileName()||e.getScriptNameOrSourceURL();if(n){var t=e.getLineNumber();var o=e.getColumnNumber()-1;var i=/^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;var a=i.test(globalProcessVersion())?0:62;if(t===1&&o>a&&!isInBrowser()&&!e.isEval()){o-=a}var u=mapSourcePosition({source:n,line:t,column:o});r.curPosition=u;e=cloneCallSite(e);var s=e.getFunctionName;e.getFunctionName=function(){if(r.nextPosition==null){return s()}return r.nextPosition.name||s()};e.getFileName=function(){return u.source};e.getLineNumber=function(){return u.line};e.getColumnNumber=function(){return u.column+1};e.getScriptNameOrSourceURL=function(){return u.source};return e}var l=e.isEval()&&e.getEvalOrigin();if(l){l=mapEvalOrigin(l);e=cloneCallSite(e);e.getEvalOrigin=function(){return l};return e}return e}function prepareStackTrace(e,r){if(l){p={};f={}}var n=e.name||"Error";var t=e.message||"";var o=n+": "+t;var i={nextPosition:null,curPosition:null};var a=[];for(var u=r.length-1;u>=0;u--){a.push("\n at "+wrapCallSite(r[u],i));i.nextPosition=i.curPosition}i.curPosition=i.nextPosition=null;return o+a.reverse().join("")}function getErrorSource(e){var r=/\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(e.stack);if(r){var n=r[1];var t=+r[2];var o=+r[3];var a=p[n];if(!a&&i&&i.existsSync(n)){try{a=i.readFileSync(n,"utf8")}catch(e){a=""}}if(a){var u=a.split(/(?:\r\n|\r|\n)/)[t-1];if(u){return n+":"+t+"\n"+u+"\n"+new Array(o).join(" ")+"^"}}}return null}function printErrorAndExit(e){var r=getErrorSource(e);var n=globalProcessStderr();if(n&&n._handle&&n._handle.setBlocking){n._handle.setBlocking(true)}if(r){console.error();console.error(r)}console.error(e.stack);globalProcessExit(1)}function shimEmitUncaughtException(){var e=process.emit;process.emit=function(r){if(r==="uncaughtException"){var n=arguments[1]&&arguments[1].stack;var t=this.listeners(r).length>0;if(n&&!t){return printErrorAndExit(arguments[1])}}return e.apply(this,arguments)}}var S=h.slice(0);var _=d.slice(0);r.wrapCallSite=wrapCallSite;r.getErrorSource=getErrorSource;r.mapSourcePosition=mapSourcePosition;r.retrieveSourceMap=v;r.install=function(r){r=r||{};if(r.environment){c=r.environment;if(["node","browser","auto"].indexOf(c)===-1){throw new Error("environment "+c+" was unknown. Available options are {auto, browser, node}")}}if(r.retrieveFile){if(r.overrideRetrieveFile){h.length=0}h.unshift(r.retrieveFile)}if(r.retrieveSourceMap){if(r.overrideRetrieveSourceMap){d.length=0}d.unshift(r.retrieveSourceMap)}if(r.hookRequire&&!isInBrowser()){var n=dynamicRequire(e,"module");var t=n.prototype._compile;if(!t.__sourceMapSupport){n.prototype._compile=function(e,r){p[r]=e;f[r]=undefined;return t.call(this,e,r)};n.prototype._compile.__sourceMapSupport=true}}if(!l){l="emptyCacheBetweenOperations"in r?r.emptyCacheBetweenOperations:false}if(!u){u=true;Error.prepareStackTrace=prepareStackTrace}if(!s){var o="handleUncaughtExceptions"in r?r.handleUncaughtExceptions:true;try{var i=dynamicRequire(e,"worker_threads");if(i.isMainThread===false){o=false}}catch(e){}if(o&&hasGlobalProcessEventEmitter()){s=true;shimEmitUncaughtException()}}};r.resetRetrieveHandlers=function(){h.length=0;d.length=0;h=S.slice(0);d=_.slice(0);v=handlerExec(d);m=handlerExec(h)}},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")}};var r={};function __webpack_require__(n){var t=r[n];if(t!==undefined){return t.exports}var o=r[n]={id:n,loaded:false,exports:{}};var i=true;try{e[n](o,o.exports,__webpack_require__);i=false}finally{if(i)delete r[n]}o.loaded=true;return o.exports}(()=>{__webpack_require__.nmd=e=>{e.paths=[];if(!e.children)e.children=[];return e}})();if(typeof __webpack_require__!=="undefined")__webpack_require__.ab=__dirname+"/";var n={};(()=>{__webpack_require__(284).install()})();module.exports=n})(); --------------------------------------------------------------------------------