Public
Edited
Nov 3, 2023
Paused
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function gh(
link // chosen link in github repo
, {
endpoint = "repos", // endpoint string
ghToken = credentials[0].ghToken, // GitHub Personal Access Token, see https://docs.github.com/en/rest
debug = false // if true, return API url
} = {}) {

// main url endpoint for API, see https://docs.github.com/en/rest/repos/contents#custom-media-types-for-repository-contents
const URL_PREFIX = 'https://api.github.com'

// create header for accepting responses, see https://docs.github.com/en/rest/overview/media-types?apiVersion=2022-11-28
const headers = {
Accept: `application/vnd.github.raw`
}
if (ghToken !== null) {
headers["Authorization"] = `token ${ghToken}`
}

// parse data link: url → path
if (link == undefined) { return "Include GitHub Link (Docs: https://observablehq.com/@periscopic/github-api-in-observable)"}

// parsing the github link
let urlLink = ""
if (link !== "") {
const rawLink = String(link)
let inputLink = rawLink

// get url components to ping api
let unpack = inputLink.split("/").slice(3)
let owner = unpack.slice(0, 1)
let repo = unpack.slice(1, 2)
let flowType = unpack.slice(2, 3) // the kind of link, tree or blob
let branch = unpack.slice(3, 4)
let path = unpack.slice(4)

// get the default branch via the api
let fetchMeta = `${URL_PREFIX}/repos/${[owner, repo].join("/")}`
let resMeta = await fetch(fetchMeta, {
headers: headers
}).then((response) => response.json())
let defaultBranch = resMeta.default_branch

// define branch parameter
let branchRef = branch.slice(0, 1).length === 0 | branch.slice(0, 1)[0] === defaultBranch ? "" : "?ref=" + branch.slice(0, 1)[0]

// define the owner/repo/path
let linkArray = [owner, repo, "contents", path, branchRef]
let linkCollapsed = linkArray.flat()

// finish creating url link
urlLink = linkCollapsed.slice(0, -1).join("/") + linkCollapsed.slice(-1)
if (!urlLink.startsWith("/") & urlLink !== "") { urlLink = '/' + urlLink }
}

// parse the endpoint
const rawEndpoint = String(endpoint)
let urlEndpoint = rawEndpoint
if (!urlEndpoint.startsWith("/")) { urlEndpoint = '/' + urlEndpoint }

// make full link to ping api
let fetchQuery = `${URL_PREFIX}${urlEndpoint}${urlLink}`
if (debug) { return fetchQuery }

// get response, use username/password if provided
const response = await fetch(fetchQuery, {
headers: headers
})

// return response
return response

}
Insert cell
Insert cell
// pack up Observable Secrets, or return empty
credentials = {
try {
let ghToken = Secret("GH_API_PAT")
return [{ghToken}]
} catch (error) {
return [{ghToken: null}]
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more