npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@zen_flow/react-tinacms-github

v0.35.0-zenflow.2

Published

This package provides helpers for setting up TinaCMS to use the Github OAuth API.

Downloads

2

Readme

react-tinacms-github

This package provides helpers for setting up TinaCMS to use the Github OAuth API.

Installation

npm install --save react-tinacms-github

or

yarn add react-tinacms-github

GithubClient

The GithubClient class is used to interact with the GitHub API on the frontend, and is intended to be registered with the CMS as an External API. GithubClient takes an object of configuration data with the following structure:

interface GithubClientArgs {
  proxy: string             // URL to the API Proxy (see next-tinacms-github for an example)
  authCallbackRoute: string // OAuth Callback URL (see next-tinacms-github for an example)
  clientId: string          // Client ID for GitHub OAuth App
  baseRepoFullName: string  // Path to the GitHub repo where content is stored in the format {user}/{repo}, e.g. tinacms/tinacms.org
}

We can create and register an instance of GithubClient as follows:

import { TinaCMS } from 'tinacms'
import { GithubClient } from 'react-tinacms-github'

const githubClient = new GithubClient({
  proxy: '/api/proxy-github',
  authCallbackRoute: '/api/create-github-access-token'
  clientId: process.env.GITHUB_CLIENT_ID,
  baseRepoFullName: process.env.REPO_FULL_NAME
})

const cms = new TinaCMS({
  apis: {
    github: githubClient // equivalent to cms.registerApi('github', github)
  }
})

Available Properties

| property | descripton | | --- | --- | | isFork | Returns true if the repo being edited was forked from the base repo configured for the site. | | workingRepoFullName | The full name of the repo currently being edited (will refer to the fork if isFork is true) | | branchName | Name of the branch currently being edited

Available Methods

See also the GithubFile for easier-to-use wrappers around commit and fetchFile.

| method | description | | --- | --- | | async commit(filePath, sha, fileContents, commitMessage) | Creates a new commit | | async fetchFile(filepath, decoded) | Retrieves the contents of a file from the currently edited repo and branch | | async getDownloadUrl(path) | Returns a URL to download the specified file; used to display images in the CMS | | async upload(path, contents, commitMessage, encoded) | Uploads a file | | async delete(path, commitMessage) | Deletes a file | | async isAuthenticated() | Returns true if the user has been authenticated with GitHub, false otherwise | | async isAuthorized() | Returns true if the logged-in user has permission to push to the repository, false otherwise | | async getUser() | Retrieves data about the currently logged-in user | | async getRepository() | Retrieves data about the currently edited repository. | | async createFork() | Forks the base repo | | async createPR(title, body) | Creates a new pull request against the base repo | | setWorkingRepoFullName(name) | Changes the current repo being edited | | setWorkingBranch(branch) | changes the current branch being edited | | async fetchExistingPR() | Retrieves data about an open pull request for the current fork/branch if it exists | | async getBranchList() | Retrieves a list of all branches in the current repo | | async createBranch(name) | Creates a new branch |

useGithubClient

useGithubClient returns the GithubClient instance registered with the CMS.

function useGithubFile(): GithubClient
import { useGithubClient} from 'react-tinacms-github'

export function Page(props) => {
  const github = useGithubClient()

  React.useEffect(() => {
    console.log("Reading content from ", github.branchName)
  },[])

  //...
}

GithubMediaStore

GithubMediaStore is used to manage media over the Github API, and satisfies the MediaStore interface. GithubMediaStore should be passed an instance of GithubClient when it is created:

import { TinaCMS } from 'tinacms'
import { GithubClient, GithubMediaStore } from 'react-tinacms-github'

const githubClient = new GithubClient({
  proxy: '/api/proxy-github',
  authCallbackRoute: '/api/create-github-access-token'
  clientId: process.env.GITHUB_CLIENT_ID,
  baseRepoFullName: process.env.REPO_FULL_NAME
})

const mediaStore = new GithubMediaStore(githubClient)

const cms = new TinaCMS({
  apis: {
    github: githubClient // equivalent to cms.registerApi('github', githubClient)
  },
  media: mediaStore
})

Image formats for preview

Currently, the media manager and GitHub media store only supports previews for image files of the following formats: '.jpg', '.jpeg', '.png', '.webp', '.svg'. Other file types will show a file icon instead of an image preview in the media manager.

Authentication

For a detailed guide on setting up authentication with react-tinacms-github on a Next.js site, take a look at our Next.js + GitHub guide.

TinacmsGithubProvider

The TinacmsGithubProvider component controls edit access to your site and will send unauthenticated users through the authentication flow.

TinacmsGithubProvider can be configured with custom handlers that run after a user has logged in / logged out successfully. The below example uses custom onLogin / onLogout handlers to hit custom API routes that trigger Next.js Preview Mode:

import { TinacmsGithubProvider } from 'react-tinacms-github';

const enterEditMode = async () => {
  const token = localStorage.getItem('tinacms-github-token') || null
  const headers = new Headers()

  if (token) {
    headers.append('Authorization', 'Bearer ' + token)
  }

  const response = await fetch(`/api/preview`, { headers })
  const data = await response.json()

  if (response.status === 200) {
    window.location.reload()
  } else {
    throw new Error(data.message)
  }
}

const exitEditMode = () => {
  return fetch(`/api/reset-preview`).then(() => {
    window.location.reload()
  })
}

const YourLayout = ({ error, children }) => {
  return (
    <TinacmsGithubProvider
      onLogin={enterEditMode}
      onLogout={exitEditMode}
      error={error}>
      {children}
    </TinacmsGithubProvider>
  )
}

useGithubAuthRedirect

GitHub's OAuth flow involves redirecting a user to a page on your website that will receive their authentication token payload. The useGithubAuthRedirect hook can be used to automatically receive this payload and make it available to the GitHub Client.

// pages/github/authorizing.tsx
// Our Github app redirects back to this page with auth code

import { useGithubAuthRedirect } from 'react-tinacms-github'

export default function Authorizing() {
  // Let the main app know, that we receieved an auth code from the Github redirect
  useGithubAuthRedirect()
  return (
      <h2>Authorizing with Github, Please wait...</h2>
  )
}

Using GitHub Forms

Any forms that we have on our site can be created with the useGithubJsonForm or useGithubMarkdownForm helpers.

function BlogTemplate({ jsonFile }) {
  const formOptions = {
    label: 'Blog Post',
    fields: [],
  }

  // Registers a JSON Tina Form
  const [data, form] = useGithubJsonForm(jsonFile, formOptions)

  // ...
}

useGithubJsonForm requires the GithubClient api to be registered with the CMS on the github namespace.

GitHub Delete Action

This is a delete action for the GitHub client.

It will delete the entire form file. So the primary use case would be dynamic pages like blog pages or docs pages. (Commonly used with markdown files but could be any file format)

Form Actions panel with Delete button

Options

interface options {
  getTitle?: (form: Form) => string
  getFilePath?: (form: Form) => string
}

| Option | Description | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | getTitle | This function takes in the form as its parameter and returns the title that will displayed in the delete action (Optional) | | getFilePath | This function takes in the form as its parameter and returns the github file path that will be used when deleting the file in github (Optional) |

Example

import { CreateGithubDeleteAction } from 'tinacms-react-github'
//...

const deleteAction = CreateGithubDeleteAction()
const formOptions = {
  label: 'Edit blog post',
  actions: [deleteAction],
  //...
}

Or if you want to change the title displayed in the modal

import { CreateGithubDeleteAction } from 'tinacms-react-github'
//...

const deleteAction = CreateGithubDeleteAction({
    getTitle: (form)=>{
        return form.values.frontmatter.title
    },
})
const formOptions = {
   label: "Edit blog post",
   actions: [deleteAction],
   fields: [
     {
       name: "frontmatter.title",
       label: "Title",
       component: "text",
     },
     //...
}

GithubFile and useGithubFile

The GithubFile class is a helper class to provide methods for manipulating a single file in your GitHub repo.

Signature

The GithubFile constructor takes four parameters: cms, path, parse, and serialize.

| argument | description | | --- | --- | | cms | An instance of TinaCMS | | path | Filepath, relative to repository root | | parse | Function to deserialize file contents into an object | | serialize | Function to serialize data object into a string |

Methods

The GithubFile class has two public methods:

| method | description | | --- | --- | | fetchFile | Wraps GithubClient#fetchFile; async function to retrieve file contents from GitHub API | | commit | Wraps GithubClient#commit; async function to commit changes to a file |

Usage Example

import { GithubFile } from 'react-tinacms-github'

async function example() {
  const navigationFile = new GithubFile(
    cms,
    'content/navigation.json',
    JSON.parse,
    JSON.stringify
  )

  // get file contents from GitHub
  const navigation = await navigationFile.fetchFile()

  // modify the file data
  navigation.push({ url: 'https://tinacms.org', title: 'TinaCMS' })

  // commit the updated file data
  await navigationFile.commit(navigation, 'Update navigation')
}

useGithubFile

useGithubFile wraps the GithubFile class and is designed to be used from inside a Function Component.

interface UseGithubFileArgs {
  path: string
  parse?: parseFn
  serialize?: serializeFn
}

function useGithubFile(args: UseGithubFileArgs): GithubFile

useGithubFile is intended to provide a more flexible abstraction than the form helpers, giving you file manipulation methods that you can use in conjunction with useForm.

import { useGithubFile } from 'react-tinacms-github'
import { useForm, usePlugin } from 'tinacms'

export function Page(props) => {

  const { fetchFile, commit } = useGithubFile({
    path: 'content/home-page.json',
    parse: JSON.parse,
    stringify: JSON.stringify
  })

  const [homepageData, homepageForm] = useForm({
    loadInitialValues: fetchFile,
    onSubmit: commit,

    id: 'home-page',
    label: 'Home Page',
    fields: [
      //...
    ],
  })
  usePlugin(homepageForm)

  //...
}

Events and Alerts

The GithubClient defines several events:

| Event Name | Description | | --- | --- | | github:commit | A commit has been made to a file. | | github:error | An error was encountered when interacting with the GitHub API. | | github:branch:checkout | The client switched to a new branch. | | github:branch:create | A new branch was created in GitHub. |

Alerts

| Event | Level | Default Message | | --- | --- | --- | | github:commit | Success | Saved Successfully: Changes committed to {repo} | | github:branch:checkout | Info | Switched to branch {name}|