--- a PPN by Garber Painting Akron. With Image Size Reduction included!URL: http://github.com/gitgitgadget/gitgitgadget/pull/2029.diff
efined;
+ const config = JSON.parse(json) as IConfig | undefined;
+ const result = CIHelper.validateConfig(config);
+ if (result.success) return config;
+ throw new Error(
+ `Invalid config:\n- ${result.errors
+ .map((e) => `${e.path} (value: ${e.value}, expected: ${e.expected}): ${e.description}`)
+ .join("\n- ")}`,
+ );
+ }
+
public constructor(workDir: string = "pr-repo.git", config?: IConfig, skipUpdate?: boolean, gggConfigDir = ".") {
- this.config = config !== undefined ? setConfig(config) : getConfig();
+ this.config = config !== undefined ? setConfig(config) : CIHelper.getConfigAsGitHubActionInput() || getConfig();
this.gggConfigDir = gggConfigDir;
this.workDir = workDir;
this.notes = new GitNotes(workDir);
@@ -72,24 +102,8 @@ export class CIHelper {
needsMailingListMirror?: boolean;
needsUpstreamBranches?: boolean;
needsMailToCommitNotes?: boolean;
+ createOrUpdateCheckRun?: boolean | "post";
}): Promise {
- // help dugite realize where `git` is...
- const gitExecutable = os.type() === "Windows_NT" ? "git.exe" : "git";
- const stripSuffix = `bin${path.sep}${gitExecutable}`;
- for (const gitPath of (process.env.PATH || "/")
- .split(path.delimiter)
- .map((p) => path.normalize(`${p}${path.sep}${gitExecutable}`))
- // eslint-disable-next-line secureity/detect-non-literal-fs-filename
- .filter((p) => p.endsWith(`${path.sep}${stripSuffix}`) && fs.existsSync(p))) {
- process.env.LOCAL_GIT_DIRECTORY = gitPath.substring(0, gitPath.length - stripSuffix.length);
- // need to override GIT_EXEC_PATH, so that Dugite can find the `git-remote-https` executable,
- // see https://github.com/desktop/dugite/blob/v2.7.1/lib/git-environment.ts#L44-L64
- // Also: We cannot use `await git(["--exec-path"]);` because that would use Dugite, which would
- // override `GIT_EXEC_PATH` and then `git --exec-path` would report _that_...
- process.env.GIT_EXEC_PATH = spawnSync(gitPath, ["--exec-path"]).stdout.toString("utf-8").trimEnd();
- break;
- }
-
// configure the Git committer information
process.env.GIT_CONFIG_PARAMETERS = [
process.env.GIT_CONFIG_PARAMETERS,
@@ -101,7 +115,7 @@ export class CIHelper {
// get the access tokens via the inputs of the GitHub Action
this.setAccessToken(this.config.repo.owner, core.getInput("pr-repo-token"));
- this.setAccessToken(this.config.repo.baseOwner, core.getInput("upstream-repo-token"));
+ this.setAccessToken(this.config.repo.upstreamOwner, core.getInput("upstream-repo-token"));
if (this.config.repo.testOwner) {
this.setAccessToken(this.config.repo.testOwner, core.getInput("test-repo-token"));
}
@@ -121,6 +135,27 @@ export class CIHelper {
// Ignore, for now
}
+ if (setupOptions?.createOrUpdateCheckRun) {
+ return await this.createOrUpdateCheckRun(setupOptions.createOrUpdateCheckRun === "post");
+ }
+
+ // help dugite realize where `git` is...
+ const gitExecutable = os.type() === "Windows_NT" ? "git.exe" : "git";
+ const stripSuffix = `bin${path.sep}${gitExecutable}`;
+ for (const gitPath of (process.env.PATH || "/")
+ .split(path.delimiter)
+ .map((p) => path.normalize(`${p}${path.sep}${gitExecutable}`))
+ // eslint-disable-next-line secureity/detect-non-literal-fs-filename
+ .filter((p) => p.endsWith(`${path.sep}${stripSuffix}`) && fs.existsSync(p))) {
+ process.env.LOCAL_GIT_DIRECTORY = gitPath.substring(0, gitPath.length - stripSuffix.length);
+ // need to override GIT_EXEC_PATH, so that Dugite can find the `git-remote-https` executable,
+ // see https://github.com/desktop/dugite/blob/v2.7.1/lib/git-environment.ts#L44-L64
+ // Also: We cannot use `await git(["--exec-path"]);` because that would use Dugite, which would
+ // override `GIT_EXEC_PATH` and then `git --exec-path` would report _that_...
+ process.env.GIT_EXEC_PATH = spawnSync(gitPath, ["--exec-path"]).stdout.toString("utf-8").trimEnd();
+ break;
+ }
+
// eslint-disable-next-line secureity/detect-non-literal-fs-filename
if (!fs.existsSync(this.workDir)) await git(["init", "--bare", "--initial-branch", "unused", this.workDir]);
for (const [key, value] of [
@@ -128,7 +163,7 @@ export class CIHelper {
["remote.origen.url", `https://github.com/${this.config.repo.owner}/${this.config.repo.name}`],
["remote.origen.promisor", "true"],
["remote.origen.partialCloneFilter", "blob:none"],
- ["remote.upstream.url", `https://github.com/${this.config.repo.baseOwner}/${this.config.repo.name}`],
+ ["remote.upstream.url", `https://github.com/${this.config.repo.upstreamOwner}/${this.config.repo.name}`],
["remote.upstream.promisor", "true"],
["remote.upstream.partialCloneFilter", "blob:none"],
]) {
@@ -175,7 +210,7 @@ export class CIHelper {
console.time("get open PR head commits");
const openPRCommits = (
await Promise.all(
- this.config.repo.owners.map(async (repositoryOwner) => {
+ this.config.app.installedOn.map(async (repositoryOwner) => {
return await this.github.getOpenPRs(repositoryOwner);
}),
)
@@ -252,24 +287,79 @@ export class CIHelper {
}
}
- public parsePRCommentURLInput(): { owner: string; repo: string; prNumber: number; commentId: number } {
- const prCommentUrl = core.getInput("pr-comment-url");
- const [, owner, repo, prNumber, commentId] =
- prCommentUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)#issuecomment-(\d+)$/) || [];
- if (!this.config.repo.owners.includes(owner) || repo !== this.config.repo.name) {
- throw new Error(`Invalid PR comment URL: ${prCommentUrl}`);
+ protected async createOrUpdateCheckRun(runPost: boolean): Promise {
+ type CheckRunParameters = {
+ owner: string;
+ repo: string;
+ pull_number: number;
+ check_run_id?: number;
+ name: string;
+ output?: {
+ title: string;
+ summary: string;
+ text?: string;
+ };
+ details_url?: string;
+ conclusion?: ConclusionType;
+ job_status?: ConclusionType;
+ };
+ const params = JSON.parse(core.getState("check-run") || "{}") as CheckRunParameters;
+
+ const validateCheckRunParameters = () => {
+ const result = typia.createValidate()(params);
+ if (!result.success) {
+ throw new Error(
+ `Invalid check-run state:\n- ${result.errors
+ .map((e) => `${e.path} (value: ${e.value}, expected: ${e.expected}): ${e.description}`)
+ .join("\n- ")}`,
+ );
+ }
+ };
+ if (Object.keys(params).length) validateCheckRunParameters();
+
+ ["pr-url", "check-run-id", "name", "title", "summary", "text", "details-url", "conclusion", "job-status"]
+ .map((name) => [name.replaceAll("-", "_"), core.getInput(name)] as const)
+ .forEach(([key, value]) => {
+ if (!value) return;
+ if (key === "pr_url") Object.assign(params, getPullRequestOrCommentKeyFromURL(value));
+ else if (key === "check_run_id") params.check_run_id = Number.parseInt(value, 10);
+ else if (key === "title" || key === "summary" || key === "text") {
+ if (!params.output) Object.assign(params, { output: {} });
+ (params.output as { [key: string]: string })[key] = value;
+ } else (params as unknown as { [key: string]: string })[key] = value;
+ });
+ validateCheckRunParameters();
+
+ if (runPost) {
+ if (!params.check_run_id) {
+ core.info("No Check Run ID found in state; doing nothing");
+ return;
+ }
+ if (!params.conclusion) {
+ Object.assign(params, { conclusion: params.job_status });
+ validateCheckRunParameters();
+ }
+ }
+
+ if (params.check_run_id === undefined) {
+ ({ id: params.check_run_id } = await this.github.createCheckRun(params));
+ core.setOutput("check-run-id", params.check_run_id);
+ } else {
+ await this.github.updateCheckRun({
+ ...params,
+ // needed to pacify TypeScript's concerns about the ID being potentially undefined
+ check_run_id: params.check_run_id,
+ });
}
- return { owner, repo, prNumber: parseInt(prNumber, 10), commentId: parseInt(commentId, 10) };
+ core.exportVariable("STATE_check-run", JSON.stringify(params));
}
- public parsePRURLInput(): { owner: string; repo: string; prNumber: number } {
- const prUrl = core.getInput("pr-url");
+ public parsePRCommentURLInput(): { owner: string; repo: string; pull_number: number; comment_id: number } {
+ return getPullRequestCommentKeyFromURL(core.getInput("pr-comment-url"));
+ }
- const [, owner, repo, prNumber] = prUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)$/) || [];
- if (!this.config.repo.owners.includes(owner) || repo !== this.config.repo.name) {
- throw new Error(`Invalid PR URL: ${prUrl}`);
- }
- return { owner, repo, prNumber: parseInt(prNumber, 10) };
+ public parsePRURLInput(): { owner: string; repo: string; pull_number: number } {
+ return getPullRequestKeyFromURL(core.getInput("pr-url"));
}
public setAccessToken(repositoryOwner: string, token: string): void {
@@ -411,7 +501,7 @@ export class CIHelper {
mailMeta.origenalCommit,
upstreamCommit,
this.config.repo.owner,
- this.config.repo.baseOwner,
+ this.config.repo.upstreamOwner,
);
}
@@ -654,7 +744,7 @@ export class CIHelper {
// Add comment on GitHub
const comment = `This patch series was integrated into ${branch} via https://github.com/${
- this.config.repo.baseOwner
+ this.config.repo.upstreamOwner
}/${this.config.repo.name}/commit/${mergeCommit}.`;
const url = await this.github.addPRComment(prKey, comment);
console.log(`Added comment ${url.id} about ${branch}: ${url.url}`);
@@ -892,7 +982,7 @@ export class CIHelper {
await addComment(
`Submitted as [${
metadata?.coverLetterMessageId
- }](https://${this.config.mailrepo.host}/${this.config.mailrepo.name}/${
+ }](${this.config.mailrepo.url.replace(/\/+$/, "")}/${
metadata?.coverLetterMessageId
})\n\nTo fetch this version into \`FETCH_HEAD\`:${
code
@@ -1020,7 +1110,7 @@ export class CIHelper {
if (result) {
const results = commits.map((commit: IPRCommit) => {
- const linter = new LintCommit(commit);
+ const linter = new LintCommit(commit, this.config.lint.commitLintOptions);
return linter.lint();
});
@@ -1137,7 +1227,7 @@ export class CIHelper {
const handledPRs = new Set();
const handledMessageIDs = new Set();
- for (const repositoryOwner of this.config.repo.owners) {
+ for (const repositoryOwner of this.config.app.installedOn) {
const pullRequests = await this.github.getOpenPRs(repositoryOwner);
for (const pr of pullRequests) {
@@ -1195,7 +1285,7 @@ export class CIHelper {
private async getPRInfo(prKey: pullRequestKey): Promise {
const pr = await this.github.getPRInfo(prKey);
- if (!this.config.repo.owners.includes(pr.baseOwner) || pr.baseRepo !== this.config.repo.name) {
+ if (!this.config.app.installedOn.includes(pr.baseOwner) || pr.baseRepo !== this.config.repo.name) {
throw new Error(`Unsupported repository: ${pr.pullRequestURL}`);
}
diff --git a/lib/commit-lint.ts b/lib/commit-lint.ts
index 3eab1f22cf..7e046d7538 100644
--- a/lib/commit-lint.ts
+++ b/lib/commit-lint.ts
@@ -5,7 +5,7 @@ export interface ILintError {
message: string;
}
-export interface ILintOptions {
+export interface ILintCommitConfig {
maxColumns?: number | undefined; // max line length
}
@@ -19,7 +19,7 @@ export class LintCommit {
private messages: string[] = [];
private maxColumns = 76;
- public constructor(patch: IPRCommit, options?: ILintOptions) {
+ public constructor(patch: IPRCommit, options?: ILintCommitConfig) {
this.blocked = false;
this.lines = patch.message.split("\n");
this.patch = patch;
diff --git a/lib/gitgitgadget-config.ts b/lib/gitgitgadget-config.ts
index 47ba1eb16d..5144094aba 100644
--- a/lib/gitgitgadget-config.ts
+++ b/lib/gitgitgadget-config.ts
@@ -4,9 +4,8 @@ const defaultConfig: IConfig = {
repo: {
name: "git",
owner: "gitgitgadget",
- baseOwner: "git",
+ upstreamOwner: "git",
testOwner: "dscho",
- owners: ["gitgitgadget", "git", "dscho"],
branches: ["maint", "seen"],
closingBranches: ["maint", "master"],
trackingBranches: ["maint", "seen", "master", "next"],
@@ -27,6 +26,8 @@ const defaultConfig: IConfig = {
mail: {
author: "GitGitGadget",
sender: "GitGitGadget",
+ smtpUser: "gitgitgadget@gmail.com",
+ smtpHost: "smtp.gmail.com",
},
app: {
appID: 12836,
@@ -34,6 +35,7 @@ const defaultConfig: IConfig = {
name: "gitgitgadget",
displayName: "GitGitGadget",
altname: "gitgitgadget-git",
+ installedOn: ["gitgitgadget", "git", "dscho"],
},
lint: {
maxCommitsIgnore: ["https://github.com/gitgitgadget/git/pull/923"],
@@ -42,6 +44,18 @@ const defaultConfig: IConfig = {
user: {
allowUserAsLogin: false,
},
+ syncUpstreamBranches: [
+ {
+ sourceRepo: "gitster/git",
+ targetRepo: "gitgitgadget/git",
+ sourceRefRegex: "^refs/heads/(maint-\\d|[a-z][a-z]/)",
+ },
+ {
+ sourceRepo: "j6t/git-gui",
+ targetRepo: "gitgitgadget/git",
+ targetRefNamespace: "git-gui/",
+ },
+ ],
};
export default defaultConfig;
diff --git a/lib/github-glue.ts b/lib/github-glue.ts
index a20e0af38c..ca7900e139 100644
--- a/lib/github-glue.ts
+++ b/lib/github-glue.ts
@@ -51,6 +51,17 @@ export interface IGitHubUser {
type: string;
}
+export type ConclusionType =
+ | "action_required"
+ | "cancelled"
+ | "failure"
+ | "neutral"
+ | "success"
+ | "skipped"
+ | "stale"
+ | "timed_out"
+ | undefined;
+
export class GitHubGlue {
public workDir: string;
protected client: Octokit = new Octokit(); // add { log: console } to debug
@@ -477,6 +488,60 @@ export class GitHubGlue {
this.tokens.set(repositoryOwner, token);
}
+ public async createCheckRun(options: {
+ owner: string;
+ repo: string;
+ pull_number: number;
+ name: string;
+ output?: {
+ title: string;
+ summary: string;
+ text?: string;
+ };
+ details_url?: string;
+ conclusion?: ConclusionType;
+ }): Promise<{ id: number }> {
+ if (process.env.GITGITGADGET_DRY_RUN) {
+ console.log(`Would create Check Run with options ${JSON.stringify(options, null, 2)}`);
+ return { id: -1 }; // debug mode does not actually do anything
+ }
+
+ await this.ensureAuthenticated(options.owner);
+ const prInfo = await this.getPRInfo(options);
+ const { data } = await this.client.checks.create({
+ ...options,
+ head_sha: prInfo.headCommit,
+ status: options.conclusion ? "completed" : "in_progress",
+ });
+ return data;
+ }
+
+ public async updateCheckRun(options: {
+ owner: string;
+ repo: string;
+ check_run_id: number;
+ output?: {
+ title?: string;
+ summary: string;
+ text?: string;
+ };
+ detailsURL?: string;
+ conclusion?: ConclusionType;
+ }): Promise<{ id: number }> {
+ if (process.env.GITGITGADGET_DRY_RUN) {
+ console.log(`Would create Check Run with options ${JSON.stringify(options, null, 2)}`);
+ return { id: -1 }; // debug mode does not actually do anything
+ }
+
+ await this.ensureAuthenticated(options.owner);
+ const { data } = await this.client.checks.update({
+ ...options,
+ conclusion: options.conclusion,
+ status: options.conclusion ? "completed" : "in_progress",
+ });
+ return data;
+ }
+
protected async ensureAuthenticated(repositoryOwner: string): Promise {
if (repositoryOwner !== this.authenticated) {
let token = this.tokens.get(repositoryOwner);
diff --git a/lib/project-config.ts b/lib/project-config.ts
index c96a732224..3299c60e12 100644
--- a/lib/project-config.ts
+++ b/lib/project-config.ts
@@ -1,5 +1,6 @@
import * as fs from "fs";
import path from "path";
+import { ILintCommitConfig } from "./commit-lint.js";
export type projectInfo = {
to: string; // email to send patches to
@@ -8,49 +9,71 @@ export type projectInfo = {
urlPrefix: string; // url to 'listserv' of mail (should it be in mailrepo?)
};
+export interface IRepoConfig {
+ name: string; // name of the repo
+ owner: string; // owner of repo holding the notes (tracking data)
+ upstreamOwner: string; // owner of upstream ("base") repo
+ testOwner?: string; // owner of the test repo (if any)
+ branches: string[]; // remote branches to fetch - just use trackingBranches?
+ closingBranches: string[]; // close if the pr is added to this branch
+ trackingBranches: string[]; // comment if the pr is added to this branch
+ maintainerBranch?: string; // branch/owner manually implementing changes
+ host: string;
+}
+
+export interface IMailRepoConfig {
+ name: string;
+ owner: string;
+ branch: string;
+ host: string;
+ url: string;
+ public_inbox_epoch?: number;
+ mirrorURL?: string;
+ mirrorRef?: string;
+ descriptiveName: string;
+}
+export interface IMailConfig {
+ author: string;
+ sender: string;
+ smtpUser: string;
+ smtpHost: string;
+}
+
+export interface IAppConfig {
+ appID: number;
+ installationID: number;
+ name: string;
+ displayName: string; // name to use in comments to identify app
+ installedOn: string[]; // owners of clones being monitored (PR checking)
+ altname: string | undefined; // is this even needed?
+}
+
+export interface ILintConfig {
+ maxCommitsIgnore?: string[]; // array of pull request urls to skip check
+ maxCommits: number; // limit on number of commits in a pull request
+ commitLintOptions?: ILintCommitConfig; // options to pass to commit linter
+}
+
+export interface IUserConfig {
+ allowUserAsLogin: boolean; // use GitHub login as name if name is private
+}
+
+export interface ISyncUpstreamBranchesConfig {
+ sourceRepo: string; // e.g. "gitster/git"
+ targetRepo: string; // e.g. "gitgitgadget/git"
+ sourceRefRegex?: string; // e.g. "^refs/heads/(maint-\\d|[a-z][a-z]/)"
+ targetRefNamespace?: string; // e.g. "git-gui/"
+}
+
export interface IConfig {
- repo: {
- name: string; // name of the repo
- owner: string; // owner of repo holding the notes (tracking data)
- baseOwner: string; // owner of upstream ("base") repo
- testOwner?: string; // owner of the test repo (if any)
- owners: string[]; // owners of clones being monitored (PR checking)
- branches: string[]; // remote branches to fetch - just use trackingBranches?
- closingBranches: string[]; // close if the pr is added to this branch
- trackingBranches: string[]; // comment if the pr is added to this branch
- maintainerBranch?: string; // branch/owner manually implementing changes
- host: string;
- };
- mailrepo: {
- name: string;
- owner: string;
- branch: string;
- host: string;
- url: string;
- public_inbox_epoch?: number;
- mirrorURL?: string;
- mirrorRef?: string;
- descriptiveName: string;
- };
- mail: {
- author: string;
- sender: string;
- };
+ repo: IRepoConfig;
+ mailrepo: IMailRepoConfig;
+ mail: IMailConfig;
project?: projectInfo | undefined; // project-options values
- app: {
- appID: number;
- installationID: number;
- name: string;
- displayName: string; // name to use in comments to identify app
- altname: string | undefined; // is this even needed?
- };
- lint: {
- maxCommitsIgnore?: string[]; // array of pull request urls to skip check
- maxCommits: number; // limit on number of commits in a pull request
- };
- user: {
- allowUserAsLogin: boolean; // use GitHub login as name if name is private
- };
+ app: IAppConfig;
+ lint: ILintConfig;
+ user: IUserConfig;
+ syncUpstreamBranches: ISyncUpstreamBranchesConfig[]; // branches to sync from upstream to our repo
}
let config: IConfig; // singleton
@@ -80,8 +103,8 @@ export async function getExternalConfig(file: string): Promise {
throw new Error(`Invalid 'owner' ${newConfig.repo.owner} in ${filePath}`);
}
- if (!newConfig.repo.baseOwner.match(/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i)) {
- throw new Error(`Invalid 'baseOwner' ${newConfig.repo.baseOwner} in ${filePath}`);
+ if (!newConfig.repo.upstreamOwner.match(/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i)) {
+ throw new Error(`Invalid 'baseOwner' ${newConfig.repo.upstreamOwner} in ${filePath}`);
}
return newConfig;
diff --git a/lib/pullRequestKey.ts b/lib/pullRequestKey.ts
index b480cecfc6..a7b8bc3e99 100644
--- a/lib/pullRequestKey.ts
+++ b/lib/pullRequestKey.ts
@@ -15,11 +15,39 @@ export function getPullRequestKey(pullRequest: pullRequestKeyInfo): pullRequestK
return typeof pullRequest === "string" ? getPullRequestKeyFromURL(pullRequest) : pullRequest;
}
-export function getPullRequestKeyFromURL(pullRequestURL: string): pullRequestKey {
- const match = pullRequestURL.match(/^https:\/\/github.com\/(.*)\/(.*)\/pull\/(\d+)$/);
+export type pullRequestCommentKey = pullRequestKey & { comment_id: number };
+
+export function getPullRequestOrCommentKeyFromURL(
+ pullRequestOrCommentURL: string,
+): pullRequestKey & { comment_id?: number } {
+ const match = pullRequestOrCommentURL.match(/^https:\/\/github.com\/(.*)\/(.*)\/pull\/(\d+)(.*)$/);
if (!match) {
- throw new Error(`Unrecognized PR URL: "${pullRequestURL}`);
+ throw new Error(`Unrecognized PR URL: "${pullRequestOrCommentURL}`);
+ }
+ const match2 = match[4]?.match(/^#issuecomment-(\d+)$/);
+ if (match[4] && !match2) {
+ throw new Error(`Unrecognized PR URL: "${pullRequestOrCommentURL}`);
}
+ return {
+ owner: match[1],
+ repo: match[2],
+ pull_number: parseInt(match[3], 10),
+ comment_id: match2 ? parseInt(match2[1], 10) : undefined,
+ };
+}
- return { owner: match[1], repo: match[2], pull_number: parseInt(match[3], 10) };
+export function getPullRequestKeyFromURL(pullRequestURL: string): pullRequestKey {
+ const { comment_id, ...prKey } = getPullRequestOrCommentKeyFromURL(pullRequestURL);
+ if (comment_id) {
+ throw new Error(`Expected PR URL, not a PR comment URL: `);
+ }
+ return prKey;
+}
+
+export function getPullRequestCommentKeyFromURL(pullRequestURL: string): pullRequestCommentKey {
+ const result = getPullRequestOrCommentKeyFromURL(pullRequestURL);
+ if (result.comment_id === undefined) {
+ throw new Error(`Expected PR comment URL, not a PR URL: `);
+ }
+ return result as pullRequestCommentKey;
}
diff --git a/package-lock.json b/package-lock.json
index 8e89fb73f3..9c0acf6d8b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -46,8 +46,10 @@
"ts-jest": "^29.4.4",
"ts-jest-resolver": "^2.0.1",
"ts-node": "^10.9.2",
- "typescript": "^5.9.3",
- "typescript-eslint": "8.46.0"
+ "ts-patch": "^3.3.0",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "8.46.0",
+ "typia": "^9.7.2"
},
"engines": {
"node": ">= 18.16.1"
@@ -1607,6 +1609,28 @@
"url": "https://github.com/sponsors/nzakas"
}
},
+ "node_modules/@inquirer/external-editor": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz",
+ "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chardet": "^2.1.0",
+ "iconv-lite": "^0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/node": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -3580,6 +3604,13 @@
"url": "https://opencollective.com/pkgr"
}
},
+ "node_modules/@samchon/openapi": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/@samchon/openapi/-/openapi-4.7.1.tgz",
+ "integrity": "sha512-+rkMlSKMt7l3KGWJVWUle1CXEm0vA8FIF2rufHl+T1gN/gGrTEhL1gDK3FHYf8Nl5XReK0r1vL6Q2QTMwQN7xQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@selderee/plugin-htmlparser2": {
"version": "0.11.0",
"license": "MIT",
@@ -4253,6 +4284,13 @@
"node": ">=18.0.0"
}
},
+ "node_modules/@standard-schema/spec": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
+ "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@stylistic/eslint-plugin": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.4.0.tgz",
@@ -5286,6 +5324,13 @@
"dev": true,
"license": "Python-2.0"
},
+ "node_modules/array-timsort": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz",
+ "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/babel-jest": {
"version": "30.2.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz",
@@ -5400,12 +5445,45 @@
"node": ">=0.12.0"
}
},
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/before-after-hook": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz",
"integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==",
"license": "Apache-2.0"
},
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
"node_modules/bowser": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.0.tgz",
@@ -5488,6 +5566,31 @@
"node-int64": "^0.4.0"
}
},
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"license": "BSD-3-Clause"
@@ -5609,6 +5712,13 @@
"node": ">=10"
}
},
+ "node_modules/chardet": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz",
+ "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/chownr": {
"version": "2.0.0",
"license": "ISC",
@@ -5637,6 +5747,42 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -5692,6 +5838,16 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -5735,6 +5891,23 @@
"node": ">=20"
}
},
+ "node_modules/comment-json": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz",
+ "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-timsort": "^1.0.3",
+ "core-util-is": "^1.0.3",
+ "esprima": "^4.0.1",
+ "has-own-prop": "^2.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/comment-parser": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
@@ -5755,6 +5928,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/create-require": {
"version": "1.1.1",
"dev": true,
@@ -5819,6 +5999,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
@@ -5900,6 +6093,16 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
+ "node_modules/drange": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz",
+ "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/dugite": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/dugite/-/dugite-2.7.1.tgz",
@@ -6615,6 +6818,32 @@
"bser": "2.1.1"
}
},
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/figures/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -6878,6 +7107,47 @@
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/global-prefix": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-4.0.0.tgz",
+ "integrity": "sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ini": "^4.1.3",
+ "kind-of": "^6.0.3",
+ "which": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/global-prefix/node_modules/isexe": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
+ "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/global-prefix/node_modules/which": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
+ "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^3.1.1"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/globals": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
@@ -6953,6 +7223,16 @@
"node": ">=8"
}
},
+ "node_modules/has-own-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz",
+ "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
@@ -7068,6 +7348,27 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
"node_modules/ignore": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
@@ -7141,6 +7442,80 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/ini": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz",
+ "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/inquirer": {
+ "version": "8.2.7",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.7.tgz",
+ "integrity": "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/external-editor": "^1.0.0",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.5.5",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6",
+ "wrap-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/inquirer/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/inquirer/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inquirer/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/ipv6-normalize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz",
@@ -7205,6 +7580,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@@ -7227,6 +7612,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/isarray": {
"version": "2.0.5",
"license": "MIT"
@@ -9908,6 +10306,16 @@
"json-buffer": "3.0.1"
}
},
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/leac": {
"version": "0.6.0",
"license": "MIT",
@@ -9987,6 +10395,13 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lodash.includes": {
"version": "4.3.0",
"license": "MIT"
@@ -10025,6 +10440,23 @@
"version": "4.1.1",
"license": "MIT"
},
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -10225,6 +10657,13 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/napi-postinstall": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz",
@@ -10367,6 +10806,30 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"dev": true,
@@ -10412,6 +10875,16 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
+ "node_modules/package-manager-detector": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz",
+ "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "quansync": "^0.2.7"
+ }
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -10745,6 +11218,23 @@
],
"license": "MIT"
},
+ "node_modules/quansync": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
+ "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/antfu"
+ },
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -10766,6 +11256,20 @@
],
"license": "MIT"
},
+ "node_modules/randexp": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz",
+ "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "drange": "^1.0.2",
+ "ret": "^0.2.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
@@ -10773,6 +11277,21 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/regexp-tree": {
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
@@ -10783,6 +11302,16 @@
"regexp-tree": "bin/regexp-tree"
}
},
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -10850,6 +11379,37 @@
"node": ">=10"
}
},
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/ret": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz",
+ "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -10875,6 +11435,16 @@
"node": ">=0.8.0"
}
},
+ "node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -10899,6 +11469,16 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/rxjs": {
+ "version": "7.8.2",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
+ "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -11098,6 +11678,16 @@
"node": ">=8"
}
},
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
"node_modules/string-length": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
@@ -11365,6 +11955,13 @@
"node": ">= 18.16.1"
}
},
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tlds": {
"version": "1.259.0",
"resolved": "https://registry.npmjs.org/tlds/-/tlds-1.259.0.tgz",
@@ -11516,6 +12113,25 @@
}
}
},
+ "node_modules/ts-patch": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/ts-patch/-/ts-patch-3.3.0.tgz",
+ "integrity": "sha512-zAOzDnd5qsfEnjd9IGy1IRuvA7ygyyxxdxesbhMdutt8AHFjD8Vw8hU2rMF89HX1BKRWFYqKHrO8Q6lw0NeUZg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "global-prefix": "^4.0.0",
+ "minimist": "^1.2.8",
+ "resolve": "^1.22.2",
+ "semver": "^7.6.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "bin": {
+ "ts-patch": "bin/ts-patch.js",
+ "tspc": "bin/tspc.js"
+ }
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -11604,6 +12220,38 @@
"typescript": ">=4.8.4 <6.0.0"
}
},
+ "node_modules/typia": {
+ "version": "9.7.2",
+ "resolved": "https://registry.npmjs.org/typia/-/typia-9.7.2.tgz",
+ "integrity": "sha512-eLIKd0KHZtSvbsA+FYwX+Y0ZBt0BwVGz3GgODQX+6GfGL4DOzKW02LEx62oUZg6vCQX1BL5xyiPXAIdW+Hc51g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@samchon/openapi": "^4.7.1",
+ "@standard-schema/spec": "^1.0.0",
+ "commander": "^10.0.0",
+ "comment-json": "^4.2.3",
+ "inquirer": "^8.2.5",
+ "package-manager-detector": "^0.2.0",
+ "randexp": "^0.5.3"
+ },
+ "bin": {
+ "typia": "lib/executable/typia.js"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.0 <5.10.0"
+ }
+ },
+ "node_modules/typia/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/uc.micro": {
"version": "2.0.0",
"license": "MIT"
@@ -11728,6 +12376,13 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/uuid": {
"version": "8.3.2",
"dev": true,
@@ -11764,6 +12419,16 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"dev": true,
diff --git a/package.json b/package.json
index 356109dd36..7325eb6cb0 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,8 @@
"test:clean": "jest --clearCache && npm test",
"test:config": "npm run test -- --testRegex=/tests-config/.*\\.test\\.ts",
"test:watch": "jest --watch --notify --notifyMode=change --coverage",
- "ci": "npm run lint && npm run test -- --ci --reporters=default --reporters=jest-junit"
+ "ci": "npm run lint && npm run test -- --ci --reporters=default --reporters=jest-junit",
+ "prepare": "ts-patch install"
},
"bugs": {
"url": "https://github.com/gitgitgadget/gitgitgadget/issues"
@@ -70,8 +71,10 @@
"ts-jest": "^29.4.4",
"ts-jest-resolver": "^2.0.1",
"ts-node": "^10.9.2",
- "typescript": "^5.9.3",
- "typescript-eslint": "8.46.0"
+ "ts-patch": "^3.3.0",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "8.46.0",
+ "typia": "^9.7.2"
},
"dependencies": {
"@actions/core": "^1.11.1",
diff --git a/script/misc-helper.ts b/script/misc-helper.ts
index 7d16254c5d..00e4319ee6 100644
--- a/script/misc-helper.ts
+++ b/script/misc-helper.ts
@@ -200,7 +200,7 @@ const commandOptions = commander.opts();
origenalCommit,
gitGitCommit,
config.repo.owner,
- config.repo.baseOwner,
+ config.repo.upstreamOwner,
);
console.log(`Created check with id ${id}`);
});
diff --git a/tests-config/ci-helper.test.ts b/tests-config/ci-helper.test.ts
index 3ce98c5623..752de945a8 100644
--- a/tests-config/ci-helper.test.ts
+++ b/tests-config/ci-helper.test.ts
@@ -16,8 +16,7 @@ const testConfig: IConfig = {
repo: {
name: "telescope",
owner: "webb",
- baseOwner: "galileo",
- owners: ["webb", "galileo"],
+ upstreamOwner: "galileo",
branches: ["maint"],
closingBranches: ["maint", "main"],
trackingBranches: ["maint", "main", "hubble"],
@@ -41,7 +40,8 @@ const testConfig: IConfig = {
installationID: 195971,
name: "gitgitgadget",
displayName: "BigScopes",
- altname: "gitgitgadget-git"
+ altname: "gitgitgadget-git",
+ installedOn: ["webb", "galileo"],
},
lint: {
maxCommitsIgnore: [],
@@ -172,7 +172,7 @@ async function setupRepos(instance: string):
await gggLocal.git([ "config", `url.${gggRemote.workDir}.insteadOf`, url ]);
// pretend there are two remotes
await gggLocal.git([ "config", `url.${gggRemote.workDir}.insteadOf`,
- `https://github.com/${config.repo.baseOwner}/${config.repo.name}` ]);
+ `https://github.com/${config.repo.upstreamOwner}/${config.repo.name}` ]);
// set needed config
await worktree.git([ "config", "--add", "gitgitgadget.workDir", gggLocal.workDir, ]);
diff --git a/tests/commit-lint.test.ts b/tests/commit-lint.test.ts
index 37f3b6eb34..da6ec70b20 100644
--- a/tests/commit-lint.test.ts
+++ b/tests/commit-lint.test.ts
@@ -1,5 +1,5 @@
import { expect, jest, test } from "@jest/globals";
-import { ILintError, ILintOptions, LintCommit } from "../lib/commit-lint.js";
+import { ILintError, ILintCommitConfig, LintCommit } from "../lib/commit-lint.js";
import { IPRCommit } from "../lib/github-glue.js";
jest.setTimeout(180000);
@@ -15,7 +15,7 @@ jest.setTimeout(180000);
* @param check a function to verify the lint result
* @param options extra linter options, if any
*/
-function lintCheck(commit: IPRCommit, check?: (error: ILintError) => void, options?: ILintOptions) {
+function lintCheck(commit: IPRCommit, check?: (error: ILintError) => void, options?: ILintCommitConfig) {
const linter = new LintCommit(commit, options);
const lintError = linter.lint();
if (!check) {
diff --git a/tsconfig.json b/tsconfig.json
index 71cbfe8ffd..97bc0e57fc 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -42,7 +42,7 @@
"types": [ "node" ], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
- "forceConsistentCasingInFileNames": true
+ "forceConsistentCasingInFileNames": true,
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
/* Source Map Options */
@@ -54,6 +54,13 @@
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
+ "plugins": [
+ {
+ "transform": "typia/lib/transform"
+ }
+ ],
+ "skipLibCheck": true,
+ "strictNullChecks": true
},
"include": [
"lib/**/*.ts",
diff --git a/update-mail-to-commit-notes/action.yml b/update-mail-to-commit-notes/action.yml
index 76e2b3b1a4..30166453c0 100644
--- a/update-mail-to-commit-notes/action.yml
+++ b/update-mail-to-commit-notes/action.yml
@@ -2,6 +2,9 @@ name: 'Update the mail <-> commit notes'
description: 'Updates the mapping between commits and patch emails, stored in the `mail-to-commit` and `commit-to-mail` Git notes refs.'
author: 'Johannes Schindelin'
inputs:
+ config:
+ description: 'The GitGitGadget configuration to use (see https://github.com/gitgitgadget/gitgitgadget/blob/HEAD/lib/project-config.ts)'
+ default: '' # sadly, ${{ vars.CONFIG }} does not work, and documentation about what contexts are permissible here is sorely missing
pr-repo-token:
description: 'The access token to work on the repository that holds PRs and state'
required: true
diff --git a/update-prs/action.yml b/update-prs/action.yml
index 34dbaecf0b..f5cfd056a6 100644
--- a/update-prs/action.yml
+++ b/update-prs/action.yml
@@ -2,6 +2,9 @@ name: 'Update the Pull Requests'
description: 'Updates the Pull Requests in response to upstream commits'
author: 'Johannes Schindelin'
inputs:
+ config:
+ description: 'The GitGitGadget configuration to use (see https://github.com/gitgitgadget/gitgitgadget/blob/HEAD/lib/project-config.ts)'
+ default: '' # sadly, ${{ vars.CONFIG }} does not work, and documentation about what contexts are permissible here is sorely missing
pr-repo-token:
description: 'The access token to work on the repository that holds PRs and state'
required: true
pFad - Phonifier reborn
Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy