Skip to content

Commit

Permalink
first setup: Medium library
Browse files Browse the repository at this point in the history
  • Loading branch information
cecepqwords committed Jul 23, 2018
0 parents commit 7d81c8f
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"presets": ["babel-preset-expo"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
}
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/**/*
.expo/*
npm-debug.*
1 change: 1 addition & 0 deletions .watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
37 changes: 37 additions & 0 deletions App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';

import { Medium } from "./src";

export default class App extends React.Component {

handlePress = async () => {
const result = await Medium.logInAsync({
'client_id': '70eaa8fd5369',
'scope': Medium.getScopes(),
'state': 'my arbitary state'
})

console.log(result);
}

render() {
return (
<View style={styles.container}>
<Button
title="Login with Medium"
onPress={this.handlePress}
/>
</View>
);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
27 changes: 27 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"expo": {
"name": "react-native-expo-medium-login",
"description": "This project is really great.",
"slug": "react-native-expo-medium-login",
"privacy": "public",
"sdkVersion": "28.0.0",
"platforms": ["ios", "android"],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
}
}
}
Binary file added assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"main": "node_modules/expo/AppEntry.js",
"private": true,
"dependencies": {
"expo": "^28.0.0",
"lodash": "^4.17.10",
"react": "16.3.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-28.0.0.tar.gz"
}
}
95 changes: 95 additions & 0 deletions src/Medium.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Import Dependencies
*
* We're use AuthSession
* @see https://docs.expo.io/versions/v28.0.0/sdk/auth-session
*
*/
import { AuthSession } from "expo";
import isPlainObject from 'lodash/isPlainObject';

/**
* BASE Constant
* This is used for base setting
*
*/
export const AUTH_URL = 'https://medium.com/m/oauth/authorize';

/**
* SCOPE Constant
* This is for default constant scope used by medium
* @see https://github.com/Medium/medium-api-docs#21-browser-based-authentication
*
*/
export const SCOPES = [
"basicProfile", "listPublications", "publishPost"
];

/**
* Get the redirect url, and copy given url to your medium application project `Callback URLs`
* @see https://docs.expo.io/versions/v28.0.0/sdk/auth-session#authsessiongetredirecturl
*
*/
export function getRedirectUrl() {
return AuthSession.getRedirectUrl();
}

/**
* Get all scopes
*/
export function getScopes() {
return SCOPES.join();
}

/**
* Converts an object to a query string.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
*
* @param {Object} params An object to convert
* @returns {String} A query string with key value pair
*/
function objectToQueryString(params) {
return '?' + Object.entries(params)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
}

/**
* Get code information from login with medium
* @see https://github.com/Medium/medium-api-docs#2-authentication
*
* @param {Object} credentials Object of credentials you need to access information
*/
export async function logInAsync(credentials) {
if (!isPlainObject(credentials)) {
throw new Error('Credentials must be plain objects.');
}

if (typeof credentials.client_id === 'undefined'
|| typeof credentials.scope === 'undefined'
|| typeof credentials.state === 'undefined'
) {
throw new Error(
'Credentials may not have an undefined "type" property. ' +
'Have you missing a value?'
);
}

// get the redirect uri
let redirectUrl = getRedirectUrl();

// append new object
credentials.response_type = 'code'; // always be `code`
credentials.redirect_uri = redirectUrl;

// get the auth url
let authUrl = `${AUTH_URL}` + objectToQueryString(credentials);

// start async
const result = await AuthSession.startAsync({
authUrl: authUrl
})

// give the result of start async
return result;
}
11 changes: 11 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* We're use expo SDK 28.0.0
*/

import * as Medium from "./Medium";
import { getScopes } from "./Medium";

export {
Medium,
getScopes
}

0 comments on commit 7d81c8f

Please sign in to comment.