diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index f6846c2..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,39 +0,0 @@ -module.exports = { - env: { - es2022: true - }, - extends: [ - 'xo' - ], - overrides: [ - { - extends: [ - 'xo-typescript', - ], - files: [ - 'sources/**/*.ts', - 'index.ts' - ], - rules: - { - '@typescript-eslint/naming-convention': ['error', { - selector: ['variableLike', 'parameterProperty', 'classProperty', 'typeProperty'], - format: ['PascalCase'] - }], - '@typescript-eslint/semi': ['error', 'never'], - '@typescript-eslint/prefer-nullish-coalescing': 'off', - 'new-cap': 'off' - } - } - ], - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module' - }, - rules: { - 'no-var': 'off', - 'comma-dangle': 'off', - indent: ['off', 'tab'], - semi: 'off' - } -} diff --git a/.github/workflows/dependency.yml b/.github/workflows/dependency.yml new file mode 100644 index 0000000..f0b0eb0 --- /dev/null +++ b/.github/workflows/dependency.yml @@ -0,0 +1,14 @@ +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v4 \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..31728f2 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,27 @@ +import tsPlugin from "@typescript-eslint/eslint-plugin" +import tsParser from "@typescript-eslint/parser" + +const config = [ + { + files: ["**/*.ts", "**/*.tsx"], // Target TypeScript files + languageOptions: { + parser: tsParser, + sourceType: "module", + }, + plugins: { + "@typescript-eslint": tsPlugin, + }, + rules: { + ...tsPlugin.configs.recommended.rules, + "semi": ["error", "never"], + "quotes": ["error", "single"], + "@typescript-eslint/no-unused-vars": "warn", + '@typescript-eslint/naming-convention': ['error', { + selector: ['variableLike', 'parameterProperty', 'classProperty', 'typeProperty'], + format: ['PascalCase'] + }] + } + } +] + +export default config \ No newline at end of file diff --git a/index.ts b/index.ts index 6c280be..8961767 100644 --- a/index.ts +++ b/index.ts @@ -51,7 +51,7 @@ var ChangedFiles: Array<{Branch: string; Filename: string}> = [] for (const Branch of Branches.Branches) { const CommitManagerInstance = new CommitManager(ProgramOptions) // eslint-disable-next-line no-await-in-loop - const CommitSHA = await CommitManagerInstance.GetCommitSHAFromLatestWorkflowTime(LatestWorkflowRunTime, Branch).then(CommitSHA => CommitSHA) + const CommitSHA = await CommitManagerInstance.GetCommitSHAFromLatestWorkflowTime(LatestWorkflowRunTime).then(CommitSHA => CommitSHA) if (CommitSHA.length === 0) { continue } diff --git a/package.json b/package.json index 079d291..3f3b954 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jsdelivr-purge", - "version": "5.6.0", + "version": "6.0.0", "author": { "name": "PiQuark6046", "email": "piquark6046@proton.me", @@ -18,27 +18,25 @@ "type": "module", "scripts": { "ci": "tsx index.ts", - "lint": "tsc && eslint . --ext .ts" + "lint": "tsc --noEmit && eslint ." }, "dependencies": { "@actions/core": "^1.10.1", - "@octokit/rest": "^20.0.2", + "@octokit/rest": "^21.0.2", "@types/luxon": "^3.4.2", - "@types/node": "^20.11.24", - "commander": "^12.0.0", - "got": "^14.2.0", + "@types/node": "^22.5.1", + "commander": "^12.1.0", + "es-toolkit": "^1.17.0", + "got": "^14.4.2", "ip-regex": "^5.0.0", - "luxon": "^3.4.4", + "luxon": "^3.5.0", "p-queue": "^8.0.1", - "simple-git": "^3.22.0", - "tsx": "^4.7.1", - "typescript": "^5.3.3" + "simple-git": "^3.25.0", + "tsx": "^4.19.0", + "typescript": "^5.5.4" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.0", - "@typescript-eslint/parser": "^7.1.0", - "eslint": "^8.57.0", - "eslint-config-xo": "^0.44.0", - "eslint-config-xo-typescript": "^3.0.0" + "eslint": "^9.9.1", + "typescript-eslint": "^8.3.0" } } diff --git a/sources/actions.ts b/sources/actions.ts index d7b802a..c02270e 100644 --- a/sources/actions.ts +++ b/sources/actions.ts @@ -2,6 +2,17 @@ import * as GitHub from '@octokit/rest' import {DateTime} from 'luxon' import type {ProgramOptionsType} from './types.js' +async function ListWorkflowRuns(ProgramOptions: ProgramOptionsType, EventType: string) { + const GitHubInstance = new GitHub.Octokit({auth: ProgramOptions.ghToken}) + const [RepoOwner, RepoName] = ProgramOptions.repo.split('/') + const WorkflowRuns = await GitHubInstance.actions.listWorkflowRuns({ + event: EventType, + owner: RepoOwner, repo: RepoName, + workflow_id: /(?<=^[A-Za-z0-9-_.]+\/[A-Za-z0-9-_.]+\/\.github\/workflows\/).+\.yml(?=@refs\/)/.exec(ProgramOptions.workflowRef)[0] + }).then(WorkflowRuns => WorkflowRuns.data.workflow_runs) + return WorkflowRuns +} + /** * @name GetLatestWorkflowTime * @description Get the latest workflow time. @@ -9,14 +20,18 @@ import type {ProgramOptionsType} from './types.js' * @returns {Promise} The latest workflow time in milliseconds. */ export async function GetLatestWorkflowTime(ProgramOptions: ProgramOptionsType): Promise { - const GitHubInstance = new GitHub.Octokit({auth: ProgramOptions.ghToken}) - const [RepoOwner, RepoName] = ProgramOptions.repo.split('/') var LatestWorkflowRunTime = 0 - const WorkflowRuns = await GitHubInstance.actions.listWorkflowRuns({ - owner: RepoOwner, repo: RepoName, - workflow_id: /(?<=^[A-Za-z0-9-_.]+\/[A-Za-z0-9-_.]+\/\.github\/workflows\/).+\.yml(?=@refs\/)/.exec(ProgramOptions.workflowRef)[0], - }).then(WorkflowRuns => WorkflowRuns.data.workflow_runs) - for (const WorkflowRun of WorkflowRuns) { + let WorkflowRuns: ReturnType = null + for (const EventType of ['push', 'release']) { + if (WorkflowRuns === null) { + WorkflowRuns = ListWorkflowRuns(ProgramOptions, EventType) + } else { + // eslint-disable-next-line no-await-in-loop + (await WorkflowRuns).push(...await ListWorkflowRuns(ProgramOptions, EventType)) + } + } + + for (const WorkflowRun of await WorkflowRuns) { if (WorkflowRun.status === 'completed' && WorkflowRun.conclusion === 'success' && DateTime.fromISO(WorkflowRun.updated_at).toMillis() > LatestWorkflowRunTime) { LatestWorkflowRunTime = DateTime.fromISO(WorkflowRun.updated_at).toMillis() diff --git a/sources/branches.ts b/sources/branches.ts index 6f7aeae..630c572 100644 --- a/sources/branches.ts +++ b/sources/branches.ts @@ -18,7 +18,7 @@ function CreateGitInstance(BasePath: string): Git.SimpleGit { export async function ListBranches(ProgramOptions: Types.ProgramOptionsType): Promise<{Branches: string[]; Default: string}> { var Branches: {Branches: string[]; Default: string} = { Branches: [], - Default: '', + Default: '' } const GitInstance = CreateGitInstance(ProgramOptions.ciWorkspacePath) Branches.Default = await GitInstance.branchLocal().then(Branches => Branches.current) diff --git a/sources/commits.ts b/sources/commits.ts index 14ddc6a..c733820 100644 --- a/sources/commits.ts +++ b/sources/commits.ts @@ -18,7 +18,7 @@ export class CommitManager { * @param {string} Branch The branch or tag name. * @returns {Promise} SHA of the latest commit. */ - async GetCommitSHAFromLatestWorkflowTime(LatestWorkflowRunTime: number, Branch: string): Promise { + async GetCommitSHAFromLatestWorkflowTime(LatestWorkflowRunTime: number): Promise { var MatchedCommitTimeAddress = 0 const GitInstance = CreateGitInstance(this.ProgramOptions.ciWorkspacePath) const GitLog = (await GitInstance.log(['--date=iso-strict'])).all diff --git a/sources/ipcheck.ts b/sources/ipcheck.ts index 5881e49..f77afc7 100644 --- a/sources/ipcheck.ts +++ b/sources/ipcheck.ts @@ -5,12 +5,12 @@ export async function GetIPAddress(): Promise { const ResponseRAW = await got('https://checkip.amazonaws.com/', { https: { minVersion: 'TLSv1.3', - ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256', + ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256' }, http2: true, headers: { - 'user-agent': 'jsdelivr-purge', - }, + 'user-agent': 'jsdelivr-purge' + } }).text() return (ipRegex().exec(ResponseRAW))?.[0] ?? 'UNKNWON' diff --git a/sources/requests.ts b/sources/requests.ts index 74b91bf..b465e42 100644 --- a/sources/requests.ts +++ b/sources/requests.ts @@ -10,12 +10,12 @@ async function GetCDNResponse(ProgramOptions: Types.ProgramOptionsType, ID: stri const ResponseRaw: Types.CDNStatusResponseType = await got(`https://purge.jsdelivr.net/status/${ID}`, { https: { minVersion: 'TLSv1.3', - ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256', + ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256' }, http2: true, headers: { - 'user-agent': 'jsdelivr-purge', - }, + 'user-agent': 'jsdelivr-purge' + } }).json() for (const [Key, Value] of Object.entries(ResponseRaw.paths)) { @@ -34,16 +34,16 @@ async function PostPurgeRequest(ProgramOptions: Types.ProgramOptionsType, Branch const ResponseRaw: Types.CDNPostResponseType = await got.post('https://purge.jsdelivr.net/', { headers: { 'cache-control': 'no-cache', - 'user-agent': 'jsdelivr-purge', + 'user-agent': 'jsdelivr-purge' }, json: { - path: new Array(Filenames.length).fill(null, 0, Filenames.length).map((Filename, Index) => `/gh/${ProgramOptions.repo}@${BranchOrTag[Index]}/${Filenames[Index]}`), + path: new Array(Filenames.length).fill(null, 0, Filenames.length).map((Filename, Index) => `/gh/${ProgramOptions.repo}@${BranchOrTag[Index]}/${Filenames[Index]}`) } satisfies Types.CDNPostRequestType, https: { minVersion: 'TLSv1.3', - ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256', + ciphers: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256' }, - http2: true, + http2: true }).json() Actions.startGroup(`PostPurgeRequest called: ${ResponseRaw.id}`) Actions.info(JSON.stringify(ResponseRaw)) diff --git a/sources/utility.ts b/sources/utility.ts index 5fa81c2..e388cd8 100644 --- a/sources/utility.ts +++ b/sources/utility.ts @@ -1,3 +1,4 @@ +import {chunk} from 'es-toolkit' import type * as Types from './types.js' /** @@ -38,30 +39,21 @@ export function IncludePropertiesInObject(CustomObjectArray: unknown[], CompareO return CustomObjectArray.some(CustomObject => Object.entries(CompareObject).every(([Key, Value]) => CustomObject[Key] === Value)) } -function GroupObjectByNumber(StringOrObject: unknown[], GroupSize: number): unknown[][] { - const SplittedArray = new Array(Math.ceil(StringOrObject.length / GroupSize)) - for (var I = 0; I < SplittedArray.length; I++) { - SplittedArray[I] = StringOrObject.slice(I === 0 ? I : I * GroupSize, (I + 1) * GroupSize > StringOrObject.length ? StringOrObject.length : (I + 1) * GroupSize) - } - - return SplittedArray -} - /** * @name GroupStringsByNumber * @description Groups a RemainingFilenamesArray into subarrays based on a specified group size. A group with latest tag will be separated from others. * @param {Types.RemainingFilenamesArrayType[]} RemainingObjectArray A RemainingFilenamesArray to group. - * @param {number} GroupSize The maximum number of elements in each subarray. + * @param {number} {Count} The maximum number of elements in each subarray. * @returns {Types.RemainingFilenamesArrayType[][]} A RemainingFilenamesArray of subarrays. */ -export function GroupRequestsByNumberWithBranch(RemainingObjectArray: Types.RemainingFilenamesArrayType[], GroupSize: number): Types.RemainingFilenamesArrayType[][] { +export function GroupRequestsByNumberWithBranch(RemainingObjectArray: Types.RemainingFilenamesArrayType[], Count: number): Types.RemainingFilenamesArrayType[][] { if (RemainingObjectArray.every(RemainingObject => RemainingObject.BranchOrTag === RemainingObjectArray[0].BranchOrTag)) { - return GroupObjectByNumber(RemainingObjectArray, GroupSize) as Types.RemainingFilenamesArrayType[][] + return chunk(RemainingObjectArray, Count) as Types.RemainingFilenamesArrayType[][] } const SplittedArray: Types.RemainingFilenamesArrayType[][] = [] - SplittedArray.push(...GroupObjectByNumber(RemainingObjectArray.filter(RemainingObject => RemainingObject.BranchOrTag === 'latest'), GroupSize) as Types.RemainingFilenamesArrayType[][]) - SplittedArray.push(...GroupObjectByNumber(RemainingObjectArray.filter(RemainingObject => RemainingObject.BranchOrTag !== 'latest'), GroupSize) as Types.RemainingFilenamesArrayType[][]) + SplittedArray.push(...chunk(RemainingObjectArray.filter(RemainingObject => RemainingObject.BranchOrTag === 'latest'), Count) as Types.RemainingFilenamesArrayType[][]) + SplittedArray.push(...chunk(RemainingObjectArray.filter(RemainingObject => RemainingObject.BranchOrTag !== 'latest'), Count) as Types.RemainingFilenamesArrayType[][]) return SplittedArray }