import { checkForSDKUpdates, gatherDependencyFiles, Release,} from "./check_update.ts";import { getJSON } from "./utilities.ts";import { projectScripts } from "./mod.ts";import { getProtocolInterface, JSONValue } from "./deps.ts";
export const SDK_NAME = "the Slack SDK";
interface InstallUpdateResponse { name: string; updates: Update[]; error?: { message: string; } | null;}
export interface Update { name: string; previous: string; installed: string; error?: { message: string; } | null;}
export const updateDependencies = async () => { const { releases } = await checkForSDKUpdates(); const updatableReleases = releases.filter((r) => r.update && r.current && r.latest ); const updateResp = await createUpdateResp(updatableReleases);
if (!updateResp.error) { try { runBuildHook(); } catch (err) { updateResp.error = { message: err.message }; } }
return updateResp;};
export async function createUpdateResp( releases: Release[],): Promise<InstallUpdateResponse> { const updateResp: InstallUpdateResponse = { name: SDK_NAME, updates: [] };
if (!releases.length) return updateResp;
try { const cwd = Deno.cwd(); const { dependencyFiles } = await gatherDependencyFiles(cwd);
for (const [file, _] of dependencyFiles) { try { const fileUpdateResp = await updateDependencyFile( `${cwd}/${file}`, releases, ); updateResp.updates = [...updateResp.updates, ...fileUpdateResp]; } catch (err) { updateResp.error = updateResp.error ? { message: updateResp.error.message += `\n ${err.message}` } : { message: err.message }; } } } catch (err) { updateResp.error = { message: err.message }; }
updateResp.updates = [...new Set(updateResp.updates)];
return updateResp;}
export async function updateDependencyFile( path: string, releases: Release[],): Promise<Update[]> { try { const dependencyJSON = await getJSON(path); const isParsable = dependencyJSON && typeof dependencyJSON === "object" && !Array.isArray(dependencyJSON) && (dependencyJSON.imports || dependencyJSON.hooks);
if (!isParsable) return [];
const dependencyKey = dependencyJSON.imports ? "imports" : "hooks";
const { updatedDependencies, updateSummary } = updateDependencyMap( dependencyJSON[dependencyKey], releases, );
dependencyJSON[dependencyKey] = updatedDependencies; await Deno.writeTextFile( path, JSON.stringify(dependencyJSON, null, 2).concat("\n"), );
return updateSummary; } catch (err) { if (!(err.cause instanceof Deno.errors.NotFound)) throw err; }
return [];}
export function updateDependencyMap( dependencyMap: JSONValue, releases: Release[],) { const mapIsObject = dependencyMap && typeof dependencyMap === "object" && !Array.isArray(dependencyMap);
const updatedDependencies = mapIsObject ? { ...dependencyMap } : {}; const updateSummary: Update[] = [];
for (const [key, val] of Object.entries(updatedDependencies)) { for (const { name, current, latest } of releases) { if (current && latest && typeof val === "string" && val.includes(name)) { updatedDependencies[key] = val.replace(current, latest); updateSummary.push({ name, previous: current, installed: latest, }); } } }
return { updatedDependencies, updateSummary };}
function runBuildHook(): void { try { const { hooks: { build } } = projectScripts([]); const buildArgs = build.split(" "); Deno.run({ cmd: buildArgs }); } catch (err) { throw new Error(err); }}
if (import.meta.main) { const protocol = getProtocolInterface(Deno.args); protocol.respond(JSON.stringify(await updateDependencies()));}