diff --git a/pkgs/structures/src/entities/channel-managers.ts b/pkgs/structures/src/entities/channel-managers.ts index cbbdb26..2d8a2e6 100644 --- a/pkgs/structures/src/entities/channel-managers.ts +++ b/pkgs/structures/src/entities/channel-managers.ts @@ -19,16 +19,16 @@ export interface PermissionOverwriteEditOptions { export function permissionOverwritePayload( permissions: Partial>, -): { allow: number | null; deny: number | null } { - let allow = 0; - let deny = 0; +): { allow: string | null; deny: string | null } { + let allow = 0n; + let deny = 0n; for (const [key, value] of Object.entries(permissions)) { const bit = PermissionFlags[key as PermissionFlag]; if (bit === undefined) continue; - if (value) allow |= Number(bit); - else deny |= Number(bit); + if (value) allow |= bit; + else deny |= bit; } - return { allow: allow === 0 ? null : allow, deny: deny === 0 ? null : deny }; + return { allow: allow === 0n ? null : String(allow), deny: deny === 0n ? null : String(deny) }; } export class ChannelPermissionOverwritesManager { @@ -48,7 +48,10 @@ export class ChannelPermissionOverwritesManager { allow, deny, }; - const res = await this.ctx.rest.channels(this.channelId).permissions(userId).put(body); + const res = await this.ctx.rest + .channels(this.channelId) + .permissions(userId) + .put(body as unknown as never); throwIfError(res, body); } } diff --git a/pkgs/structures/src/entities/guild-managers.ts b/pkgs/structures/src/entities/guild-managers.ts index bce60bb..529ec38 100644 --- a/pkgs/structures/src/entities/guild-managers.ts +++ b/pkgs/structures/src/entities/guild-managers.ts @@ -59,10 +59,10 @@ function toPermissionOverwrites( overwrites: NonNullable, ) { return overwrites.map((ow) => { - const toBits = (val: bigint[] | bigint | undefined): number | null => { + const toBits = (val: bigint[] | bigint | undefined): string | null => { if (val === undefined) return null; - if (Array.isArray(val)) return val.reduce((a, b) => a | Number(b), 0); - return Number(val); + const bits = Array.isArray(val) ? val.reduce((a, b) => a | b, 0n) : val; + return bits === 0n ? "0" : String(bits); }; return { id: ow.id, @@ -89,9 +89,10 @@ export class GuildChannelsManager { const res = await this.ctx.rest.channels(id).get(); if (!res.ok) return undefined; const data = res.data as GuildChannelResponse | ThreadResponse; - const channel = "guild_id" in data - ? channelFromData(data as GuildChannelResponse, this.ctx) - : new ThreadChannel(data as unknown as ThreadResponse, this.ctx); + const channel = + "guild_id" in data + ? channelFromData(data as GuildChannelResponse, this.ctx) + : new ThreadChannel(data as unknown as ThreadResponse, this.ctx); this.ctx.caches?.channels?.set(id, channel); return channel; } @@ -107,7 +108,9 @@ export class GuildChannelsManager { position: options.position, }; if (options.permissionOverwrites) { - body.permission_overwrites = toPermissionOverwrites(options.permissionOverwrites); + body.permission_overwrites = toPermissionOverwrites( + options.permissionOverwrites, + ) as unknown as CreateGuildChannelRequest["permission_overwrites"]; } const res = await this.ctx.rest.guilds(this.guildId).channels.post(body); const data = throwIfError(res, body); diff --git a/scripts/publish.ts b/scripts/publish.ts index 5e0799f..f798f02 100644 --- a/scripts/publish.ts +++ b/scripts/publish.ts @@ -2,7 +2,8 @@ import { readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { execSync } from "node:child_process"; -const PKGS_DIR = join(import.meta.dir, "..", "pkgs"); +const ROOT = join(import.meta.dir, ".."); +const PKGS_DIR = join(ROOT, "pkgs"); const BUILD_ORDER = [ "types", @@ -30,6 +31,30 @@ interface Pkg { path: string; } +const isDryRun = process.argv.includes("--dry-run") || process.argv.includes("-d"); + +function git(cmd: string): string { + return execSync(`git ${cmd}`, { cwd: ROOT, encoding: "utf-8" }).trim(); +} + +function run(cmd: string, cwd = ROOT, prefix = "\t") { + if (isDryRun) { + console.log(`${prefix} $ ${cmd}`); + return; + } + try { + execSync(cmd, { cwd, stdio: "inherit" }); + } catch { + rollback(); + } +} + +function rollback() { + console.error("\nfailed. reverting changes..."); + git("checkout -- pkgs/*/package.json"); + process.exit(1); +} + function loadPackages(): Map { const pkgs = new Map(); for (const short of BUILD_ORDER) { @@ -63,7 +88,6 @@ function findAffected(pkgs: Map, target: PkgShort): PkgShort[] { function walk(current: string) { for (const [short, pkg] of pkgs) { if (affectedSet.has(short)) continue; - if (pkg.deps.includes(current) || pkg.peers.includes(current)) { affectedSet.add(short); walk(short); @@ -76,12 +100,16 @@ function findAffected(pkgs: Map, target: PkgShort): PkgShort[] { } function main() { - const [targetShort, bumpType] = process.argv.slice(2) as [PkgShort, BumpType]; + const [targetShort, bumpType] = process.argv.slice(2).filter((arg) => !arg.startsWith("-")) as [ + PkgShort, + BumpType, + ]; + const validBumpTypes: BumpType[] = ["patch", "minor", "major"]; if (!targetShort || !validBumpTypes.includes(bumpType)) { - console.error("usage: bun run scripts/publish.ts "); - console.error(" e.g: bun run scripts/publish.ts rest patch"); + console.error("usage: bun run scripts/publish.ts [--dry-run]"); + console.error(" e.g: bun run scripts/publish.ts rest patch --dry-run"); process.exit(1); } @@ -91,14 +119,19 @@ function main() { process.exit(1); } + if (!isDryRun && git("status --porcelain pkgs")) { + console.error("work tree is dirty. commit or stash changes first."); + process.exit(1); + } + const pkgs = loadPackages(); const target = pkgs.get(targetShort)!; const affected = findAffected(pkgs, targetShort); console.log( - `bumping @purrkit/${targetShort} (${target.version} → ${bumpVersion(target.version, bumpType)})`, + `bumping @purrkit/${targetShort} (${target.version} -> ${bumpVersion(target.version, bumpType)})${isDryRun ? " [DRY RUN]" : ""}`, ); - console.log(`affected chain: ${affected.map((s) => `@purrkit/${s}`).join(" → ")}\n`); + console.log(`affected: ${affected.map((s) => `@purrkit/${s}`).join(" -> ")}`); for (const short of affected) { const pkg = pkgs.get(short)!; @@ -106,23 +139,34 @@ function main() { const newVersion = bumpVersion(oldVersion, bumpType); pkg.version = newVersion; - const raw = JSON.parse(readFileSync(pkg.path, "utf-8")); - raw.version = newVersion; - writeFileSync(pkg.path, JSON.stringify(raw, null, "\t") + "\n"); - console.log(`\t${pkg.name}: ${oldVersion} → ${newVersion}`); + if (!isDryRun) { + const raw = JSON.parse(readFileSync(pkg.path, "utf-8")); + raw.version = newVersion; + writeFileSync(pkg.path, JSON.stringify(raw, null, "\t") + "\n"); + } + console.log(`\t${pkg.name}: ${oldVersion} -> ${newVersion}`); } console.log("\nbuilding..."); for (const short of affected) { - console.log(`\tbuilding @purrkit/${short}...`); - execSync(`bun run build:${short}`, { cwd: join(import.meta.dir, ".."), stdio: "inherit" }); + run(`bun run build:${short}`); } console.log("\npublishing..."); for (const short of affected) { const pkg = pkgs.get(short)!; - console.log(`\tpublishing ${pkg.name}@${pkg.version}...`); - execSync("bun publish --access public", { cwd: join(PKGS_DIR, short), stdio: "inherit" }); + console.log(`\t${pkg.name}@${pkg.version}`); + run("bun publish --access public", join(PKGS_DIR, short), "\t "); + } + + console.log("\ncommitting & tagging..."); + const commitMsg = `release: ${affected.map((s) => `@purrkit/${s}@${pkgs.get(s)!.version}`).join(", ")}`; + run("git add pkgs/*/package.json"); + run(`git commit -m "${commitMsg}"`); + + for (const short of affected) { + const pkg = pkgs.get(short)!; + run(`git tag ${pkg.name}@${pkg.version}`); } console.log("\ndone.");