251148c3ff
## Summary - add repository-wide quality tooling and verification scaffolding, including CI workflows, pnpm workspace setup, ESLint/Prettier/markdown checks, and generated-output verification helpers - reorganize skill sources and generation flow by introducing canonical `_source` variants, generator/manifests, reusable helper abstractions, and shared web-automation/browser utilities - clean up and expand documentation so the root README flows into docs and skill docs, with clearer development, reviewer, installer, and workflow guidance ## Notable changes - docs flow and consistency cleanup across `README.md`, `docs/README.md`, and related docs - new scripts for `check`, docs verification, generated-file verification, shell portability, and safe directory replacement - refactors in Atlassian and web-automation skill runtimes to reduce duplication and centralize reusable code - changelog, development documentation, and CI surface updates ## Test Plan - [ ] `pnpm run check` - [ ] review generated/manifests and skill sync outputs - [ ] smoke-check docs flow from `README.md` to `docs/README.md` to skill docs ## Notes - this branch currently includes tracked `skills/web-automation/shared/node_modules` content that should be reviewed carefully as potentially noisy/accidental committed artifacts Co-authored-by: Stefano Fiorini <stefano.fiorini@firsthorizon.com> Reviewed-on: #1
88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
// ⚠️ GENERATED FILE – do not edit directly. Edit the canonical source in skills/atlassian/shared/scripts/ and run `pnpm run sync:pi`.
|
||
import { createBasicAuthHeader } from "./config.js";
|
||
import type { AtlassianConfig, FetchLike } from "./types.js";
|
||
|
||
export type HttpMethod = "GET" | "POST" | "PUT";
|
||
|
||
export function createJsonHeaders(config: AtlassianConfig, includeJsonBody: boolean) {
|
||
const headers: Array<[string, string]> = [
|
||
["Accept", "application/json"],
|
||
["Authorization", createBasicAuthHeader(config)],
|
||
];
|
||
|
||
if (includeJsonBody) {
|
||
headers.push(["Content-Type", "application/json"]);
|
||
}
|
||
|
||
return headers;
|
||
}
|
||
|
||
export async function parseResponse(response: Response) {
|
||
if (response.status === 204) {
|
||
return null;
|
||
}
|
||
|
||
const contentType = response.headers.get("content-type") ?? "";
|
||
|
||
if (contentType.includes("application/json")) {
|
||
try {
|
||
return await response.json();
|
||
} catch {
|
||
throw new Error("Malformed JSON response from Atlassian API");
|
||
}
|
||
}
|
||
|
||
return response.text();
|
||
}
|
||
|
||
export function createStatusError(errorPrefix: string, response: Response) {
|
||
const base = `${errorPrefix}: ${response.status} ${response.statusText}`;
|
||
|
||
switch (response.status) {
|
||
case 401:
|
||
return new Error(`${base} - check ATLASSIAN_EMAIL and ATLASSIAN_API_TOKEN`);
|
||
case 403:
|
||
return new Error(`${base} - verify product permissions for this account`);
|
||
case 404:
|
||
return new Error(`${base} - verify the resource identifier or API path`);
|
||
case 429:
|
||
return new Error(`${base} - retry later or reduce request rate`);
|
||
default:
|
||
return new Error(base);
|
||
}
|
||
}
|
||
|
||
export async function sendJsonRequest(options: {
|
||
config: AtlassianConfig;
|
||
fetchImpl?: FetchLike;
|
||
url: string;
|
||
method: HttpMethod;
|
||
body?: unknown;
|
||
errorPrefix: string;
|
||
handleResponseError?: (response: Response) => Error | undefined;
|
||
}) {
|
||
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
||
|
||
if (!fetchImpl) {
|
||
throw new Error("Fetch API is not available in this runtime");
|
||
}
|
||
|
||
const response = await fetchImpl(options.url, {
|
||
method: options.method,
|
||
headers: createJsonHeaders(options.config, options.body !== undefined),
|
||
...(options.body === undefined ? {} : { body: JSON.stringify(options.body) }),
|
||
});
|
||
|
||
if (!response.ok) {
|
||
const customError = options.handleResponseError?.(response);
|
||
|
||
if (customError) {
|
||
throw customError;
|
||
}
|
||
|
||
throw createStatusError(options.errorPrefix, response);
|
||
}
|
||
|
||
return parseResponse(response);
|
||
}
|