@theholocron/holocron-plugin-github 5.0.0-alpha.371 → 5.0.0-alpha.373

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Auth, AuthError, BoardItem, BoardState, BoardSummary, BoardTemplate, Ci, CiRun, CiRunFilter, EnsureReport, Environment, Environments, ImportOptions, ImportResult, Issue, IssueRecord, IssueSearchFilter, IssueSelector, Issues, LabelDef, LifecycleResult, LifecycleSlot, MoveReport, PagesConfig, PluginToken, Projects, PullRequest, RepoRef, RepoSettings, ResolveTokenInput, Ruleset, SecretScope, Secrets, Source, SourceBranch, SourceFile, SourceRepoInfo, SourceRulesetDetail, SourceSecurity, SourceTeamMember, TeamEntry, TeamEntry as TeamEntry$1, TeamPermission, TeamPermission as TeamPermission$1, TrackerDoctorReport, TrackerUser, VerifyTokenFailure, VerifyTokenResult, VerifyTokenResult as VerifyTokenResult$1, VerifyTokenSuccess, createFeatureResolver } from "@theholocron/cli";
1
+ import { AddedItem, Auth, AuthError, BoardItem, BoardItemInput, BoardState, BoardSummary, BoardTemplate, Ci, CiRun, CiRunFilter, EnsureReport, Environment, Environments, ImportOptions, ImportResult, Issue, IssueRecord, IssueSearchFilter, IssueSelector, Issues, LabelDef, LifecycleResult, LifecycleSlot, MoveReport, PagesConfig, PluginToken, Projects, PullRequest, RepoRef, RepoSettings, ResolveTokenInput, Ruleset, SecretScope, Secrets, Source, SourceBranch, SourceFile, SourceRepoInfo, SourceRulesetDetail, SourceSecurity, SourceTeamMember, TeamEntry, TeamEntry as TeamEntry$1, TeamPermission, TeamPermission as TeamPermission$1, TrackerDoctorReport, TrackerUser, VerifyTokenFailure, VerifyTokenResult, VerifyTokenResult as VerifyTokenResult$1, VerifyTokenSuccess, createFeatureResolver } from "@theholocron/cli";
2
2
  import { GitHubClient, GitHubClientOptions, GraphQLClient, createGitHubClient } from "@theholocron/github-client";
3
3
  /** Resolves the token for read-only GitHub access (`HOLOCRON_READ_TOKEN`, keyring key `github.read`). */
4
4
  export declare const resolveReadToken: import("@theholocron/cli").FeatureResolver;
@@ -179,6 +179,16 @@ export declare class GitHubProjects implements Projects {
179
179
  * closed and merged ones stay, and are set to the template's done status when theirs is not a done one.
180
180
  */
181
181
  move(_owner: string, from: BoardSummary, to: BoardSummary, template: BoardTemplate): Promise<MoveReport>;
182
+ /**
183
+ * Puts issues on the board (`addProjectV2ItemById`, the content id the issue's node id) and sets Status and Priority
184
+ * through the single select update, only where the item has no value yet. A status or priority with no option on
185
+ * the board is reported in `dropped`; no option is ever created, so no value is cleared.
186
+ */
187
+ addItems(_owner: string, board: BoardSummary, items: BoardItemInput[], template: BoardTemplate): Promise<AddedItem[]>;
188
+ /** The board's own status for an input: the option named like its status, else the template's status of its category. */
189
+ private statusFor;
190
+ /** The node id of an issue, which `addProjectV2ItemById` takes as the content id. */
191
+ private nodeId;
182
192
  /** A `holocron doctor` smoke check: how many boards the token sees in the configured repository's organization. */
183
193
  whoami(): Promise<{
184
194
  ok: boolean;
package/dist/index.mjs CHANGED
@@ -957,6 +957,72 @@ var GitHubProjects = class {
957
957
  }
958
958
  return report;
959
959
  }
960
+ /**
961
+ * Puts issues on the board (`addProjectV2ItemById`, the content id the issue's node id) and sets Status and Priority
962
+ * through the single select update, only where the item has no value yet. A status or priority with no option on
963
+ * the board is reported in `dropped`; no option is ever created, so no value is cleared.
964
+ */
965
+ async addItems(_owner, board, items, template) {
966
+ const raw = await this.readRaw(board.id);
967
+ const onBoard = await this.fetchItems(board.id);
968
+ const statusField = raw.fields.find((f) => f.name === STATUS_FIELD && f.options);
969
+ const priorityField = raw.fields.find((f) => f.name === PRIORITY_FIELD && f.options);
970
+ const results = [];
971
+ for (const input of items) {
972
+ const ref = this.parseKey(input.key);
973
+ let current = onBoard.find((i) => i.repo === ref.repo && i.number === ref.number);
974
+ const added = !current;
975
+ if (!current) current = {
976
+ id: (await this.graphql.query(`mutation($project: ID!, $content: ID!) { addProjectV2ItemById(input: { projectId: $project, contentId: $content }) { item { id } } }`, {
977
+ project: board.id,
978
+ content: await this.nodeId(ref)
979
+ })).addProjectV2ItemById.item.id,
980
+ contentId: "",
981
+ repo: ref.repo,
982
+ number: ref.number,
983
+ title: "",
984
+ open: true,
985
+ values: {},
986
+ blockers: []
987
+ };
988
+ const dropped = [];
989
+ if (input.status !== void 0 || input.category !== void 0) {
990
+ const name = this.statusFor(input, template, statusField?.options);
991
+ if (!name) dropped.push(`status ${input.status ?? input.category} (no matching option on the board)`);
992
+ else if (!current.values[STATUS_FIELD]) await this.setOption(board.id, raw, current.id, STATUS_FIELD, name);
993
+ }
994
+ if (input.priority !== void 0 && input.priority !== "none") {
995
+ const option = priorityField?.options?.find((o) => priorityOf(o.name) === input.priority);
996
+ if (!option) dropped.push(`priority ${input.priority} (no matching option on the board)`);
997
+ else if (!current.values[PRIORITY_FIELD]) await this.setOption(board.id, raw, current.id, PRIORITY_FIELD, option.name);
998
+ }
999
+ results.push({
1000
+ key: input.key,
1001
+ added,
1002
+ dropped
1003
+ });
1004
+ }
1005
+ return results;
1006
+ }
1007
+ /** The board's own status for an input: the option named like its status, else the template's status of its category. */
1008
+ statusFor(input, template, options) {
1009
+ const has = (name) => options?.find((o) => o.name.toLowerCase() === name.toLowerCase())?.name;
1010
+ const named = input.status === void 0 ? void 0 : has(input.status);
1011
+ if (named) return named;
1012
+ const byCategory = template.statuses.find((s) => s.category === input.category);
1013
+ return byCategory ? has(byCategory.name) : void 0;
1014
+ }
1015
+ /** The node id of an issue, which `addProjectV2ItemById` takes as the content id. */
1016
+ async nodeId(ref) {
1017
+ const [owner, name] = ref.repo.split("/");
1018
+ const id = (await this.graphql.query(`query($owner: String!, $name: String!, $number: Int!) { repository(owner: $owner, name: $name) { issue(number: $number) { id } } }`, {
1019
+ owner,
1020
+ name,
1021
+ number: ref.number
1022
+ })).repository?.issue?.id;
1023
+ if (!id) throw new Error(`issue ${ref.repo}#${ref.number} not found`);
1024
+ return id;
1025
+ }
960
1026
  /** A `holocron doctor` smoke check: how many boards the token sees in the configured repository's organization. */
961
1027
  async whoami() {
962
1028
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/holocron-plugin-github",
3
- "version": "5.0.0-alpha.371",
3
+ "version": "5.0.0-alpha.373",
4
4
  "description": "Holocron plugin for GitHub. Implements source, ci, secrets, environments, and issues capabilities against the GitHub REST API.",
5
5
  "keywords": [
6
6
  "ci",
@@ -44,21 +44,21 @@
44
44
  "tsx": "4.23.15",
45
45
  "typescript": "^5.9.3",
46
46
  "vitest": "^5.1.0",
47
- "@theholocron/cli": "5.0.0-alpha.371",
48
- "@theholocron/eslint-config": "^8.9.0-alpha.11",
47
+ "@theholocron/cli": "5.0.0-alpha.373",
49
48
  "@theholocron/fs-utils": "^1.17.0-alpha.2",
50
- "@theholocron/github-client": "^1.58.0-alpha.18",
49
+ "@theholocron/eslint-config": "^8.9.0-alpha.12",
50
+ "@theholocron/http-client": "^1.58.0-alpha.20",
51
+ "@theholocron/github-client": "^1.58.0-alpha.20",
51
52
  "@theholocron/misc-utils": "^1.17.0-alpha.2",
52
- "@theholocron/http-client": "^1.58.0-alpha.18",
53
- "@theholocron/tsconfig": "^8.9.0-alpha.11",
54
- "@theholocron/vitest-config": "^8.9.0-alpha.11",
55
- "@theholocron/tsdown-config": "^8.9.0-alpha.11"
53
+ "@theholocron/tsconfig": "^8.9.0-alpha.12",
54
+ "@theholocron/tsdown-config": "^8.9.0-alpha.12",
55
+ "@theholocron/vitest-config": "^8.9.0-alpha.12"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "@theholocron/fs-utils": "^1.16.0",
59
59
  "@theholocron/github-client": "^1.58.0",
60
60
  "@theholocron/misc-utils": "^1.16.0",
61
- "@theholocron/cli": "5.0.0-alpha.371"
61
+ "@theholocron/cli": "5.0.0-alpha.373"
62
62
  },
63
63
  "engines": {
64
64
  "node": ">=22"