@@ -229599,12 +229599,202 @@ var membershipCycle = {
229599229599 }
229600229600};
229601229601
229602+ // src/cycles/teams.ts
229603+ var PER_PAGE2 = 100;
229604+ var VALID_PRIVACY = /* @__PURE__ */ new Set(["secret", "closed"]);
229605+ var VALID_TEAM_PERMISSIONS = ["admin", "maintain", "push", "triage", "pull"];
229606+ async function paginate(client, makePath, budget) {
229607+ const out = [];
229608+ let page = 1;
229609+ for (; ; ) {
229610+ if (budget.exhausted) break;
229611+ budget.use(1);
229612+ const batch = await client.request("GET", makePath(page));
229613+ if (!Array.isArray(batch) || batch.length === 0) break;
229614+ out.push(...batch);
229615+ if (batch.length < PER_PAGE2) break;
229616+ page++;
229617+ }
229618+ return out;
229619+ }
229620+ function mapTeamRepoPermission(repo) {
229621+ if (repo.role_name && VALID_TEAM_PERMISSIONS.includes(repo.role_name)) {
229622+ return repo.role_name;
229623+ }
229624+ const p = repo.permissions ?? {};
229625+ if (p.admin) return "admin";
229626+ if (p.maintain) return "maintain";
229627+ if (p.push) return "push";
229628+ if (p.triage) return "triage";
229629+ return "pull";
229630+ }
229631+ async function fetchTeamMembers(client, org, slug, budget) {
229632+ const maintainers = await paginate(
229633+ client,
229634+ (page) => `/orgs/${org}/teams/${slug}/members?role=maintainer&per_page=${PER_PAGE2}&page=${page}`,
229635+ budget
229636+ );
229637+ const members = await paginate(
229638+ client,
229639+ (page) => `/orgs/${org}/teams/${slug}/members?role=member&per_page=${PER_PAGE2}&page=${page}`,
229640+ budget
229641+ );
229642+ return [
229643+ ...maintainers.map((m) => ({ login: m.login, role: "maintainer" })),
229644+ ...members.map((m) => ({ login: m.login, role: "member" }))
229645+ ];
229646+ }
229647+ async function fetchTeamRepos(client, org, slug, budget) {
229648+ const repos = await paginate(
229649+ client,
229650+ (page) => `/orgs/${org}/teams/${slug}/repos?per_page=${PER_PAGE2}&page=${page}`,
229651+ budget
229652+ );
229653+ return repos.map((r) => ({ name: r.name, permission: mapTeamRepoPermission(r) }));
229654+ }
229655+ async function buildTeamBody(client, org, slug, desired, includeName, budget) {
229656+ const body = {};
229657+ if (includeName) body.name = slug;
229658+ if (desired.description !== void 0) body.description = desired.description;
229659+ if (desired.privacy !== void 0) body.privacy = desired.privacy;
229660+ if (desired.parentTeamSlug !== void 0) {
229661+ if (desired.parentTeamSlug === "") {
229662+ body.parent_team_id = null;
229663+ } else {
229664+ budget.use(1);
229665+ const parent = await client.request(
229666+ "GET",
229667+ `/orgs/${org}/teams/${desired.parentTeamSlug}`
229668+ );
229669+ body.parent_team_id = parent.id;
229670+ }
229671+ }
229672+ return body;
229673+ }
229674+ function splitKey(key, resourceType) {
229675+ const idx = key.indexOf("/");
229676+ if (idx === -1) {
229677+ throw new Error(`teams: malformed ${resourceType} key "${key}" \u2014 expected "<slug>/<child>"`);
229678+ }
229679+ return [key.slice(0, idx), key.slice(idx + 1)];
229680+ }
229681+ var teamsCycle = {
229682+ name: "teams",
229683+ // ── Part 2: fetchLive ──────────────────────────────────────────────────────
229684+ async fetchLive(client, orgLogin, scope, budget) {
229685+ if (budget.exhausted) {
229686+ const { BudgetExhaustedError: BudgetExhaustedError2 } = await Promise.resolve().then(() => (init_runner(), runner_exports));
229687+ throw new BudgetExhaustedError2();
229688+ }
229689+ const ghTeams = await paginate(
229690+ client,
229691+ (page) => `/orgs/${orgLogin}/teams?per_page=${PER_PAGE2}&page=${page}`,
229692+ budget
229693+ );
229694+ const teams = {};
229695+ for (const t of ghTeams) {
229696+ if (!t || typeof t.slug !== "string") continue;
229697+ const live = {};
229698+ if (t.description != null) live.description = t.description;
229699+ if (t.privacy != null && VALID_PRIVACY.has(t.privacy)) {
229700+ live.privacy = t.privacy;
229701+ }
229702+ if (t.parent?.slug) live.parentTeamSlug = t.parent.slug;
229703+ const scopeTeam = scope.teams?.[t.slug];
229704+ if (scopeTeam?.members !== void 0 && !budget.exhausted) {
229705+ live.members = await fetchTeamMembers(client, orgLogin, t.slug, budget);
229706+ }
229707+ if (scopeTeam?.repos !== void 0 && !budget.exhausted) {
229708+ live.repos = await fetchTeamRepos(client, orgLogin, t.slug, budget);
229709+ }
229710+ teams[t.slug] = live;
229711+ }
229712+ return { teams };
229713+ },
229714+ // ── Part 3: buildDesired ───────────────────────────────────────────────────
229715+ buildDesired(orgConfig, _orgLogin, _scope) {
229716+ if (!orgConfig.teams) return {};
229717+ return { teams: orgConfig.teams };
229718+ },
229719+ // ── Part 4: apply ──────────────────────────────────────────────────────────
229720+ async apply(client, entry, orgLogin, _scope, budget) {
229721+ switch (entry.resourceType) {
229722+ case "team":
229723+ return applyTeam(client, entry, orgLogin, budget);
229724+ case "team-member":
229725+ return applyTeamMember(client, entry, orgLogin, budget);
229726+ case "team-repo":
229727+ return applyTeamRepo(client, entry, orgLogin, budget);
229728+ default:
229729+ return;
229730+ }
229731+ }
229732+ };
229733+ async function applyTeam(client, entry, org, budget) {
229734+ const slug = entry.key;
229735+ if (entry.kind === "delete") {
229736+ budget.use(1);
229737+ await client.request("DELETE", `/orgs/${org}/teams/${slug}`);
229738+ return;
229739+ }
229740+ const desired = entry.after;
229741+ if (entry.kind === "create") {
229742+ const body2 = await buildTeamBody(client, org, slug, desired, true, budget);
229743+ budget.use(1);
229744+ await client.request("POST", `/orgs/${org}/teams`, body2);
229745+ for (const m of desired.members ?? []) {
229746+ budget.use(1);
229747+ await client.request(
229748+ "PUT",
229749+ `/orgs/${org}/teams/${slug}/memberships/${encodeURIComponent(m.login)}`,
229750+ { role: m.role ?? "member" }
229751+ );
229752+ }
229753+ for (const r of desired.repos ?? []) {
229754+ budget.use(1);
229755+ await client.request("PUT", `/orgs/${org}/teams/${slug}/repos/${org}/${r.name}`, {
229756+ permission: r.permission
229757+ });
229758+ }
229759+ return;
229760+ }
229761+ const body = await buildTeamBody(client, org, slug, desired, false, budget);
229762+ if (Object.keys(body).length === 0) return;
229763+ budget.use(1);
229764+ await client.request("PATCH", `/orgs/${org}/teams/${slug}`, body);
229765+ }
229766+ async function applyTeamMember(client, entry, org, budget) {
229767+ const [slug, login] = splitKey(entry.key, "team-member");
229768+ const path = `/orgs/${org}/teams/${slug}/memberships/${encodeURIComponent(login)}`;
229769+ if (entry.kind === "delete") {
229770+ budget.use(1);
229771+ await client.request("DELETE", path);
229772+ return;
229773+ }
229774+ const after = entry.after;
229775+ budget.use(1);
229776+ await client.request("PUT", path, { role: after.role ?? "member" });
229777+ }
229778+ async function applyTeamRepo(client, entry, org, budget) {
229779+ const [slug, repo] = splitKey(entry.key, "team-repo");
229780+ const path = `/orgs/${org}/teams/${slug}/repos/${org}/${repo}`;
229781+ if (entry.kind === "delete") {
229782+ budget.use(1);
229783+ await client.request("DELETE", path);
229784+ return;
229785+ }
229786+ const after = entry.after;
229787+ budget.use(1);
229788+ await client.request("PUT", path, { permission: after.permission });
229789+ }
229790+
229602229791// src/cli/registry.ts
229603229792var CYCLE_REGISTRY = {
229604229793 [branchProtectionCycle.name]: branchProtectionCycle,
229605229794 [orgSettingsCycle.name]: orgSettingsCycle,
229606229795 [repoSettingsCycle.name]: repoSettingsCycle,
229607- [membershipCycle.name]: membershipCycle
229796+ [membershipCycle.name]: membershipCycle,
229797+ [teamsCycle.name]: teamsCycle
229608229798};
229609229799
229610229800// node_modules/@intentius/chant/src/audit/fetch.ts
0 commit comments