Skip to content
This repository was archived by the owner on Apr 26, 2022. It is now read-only.

Commit a993e37

Browse files
committedAug 2, 2018
Initial commit
0 parents  commit a993e37

15 files changed

+4660
-0
lines changed
 

‎.circleci/config.yml

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
version: 2
2+
jobs:
3+
build:
4+
docker:
5+
- image: 'circleci/node:latest'
6+
steps:
7+
- checkout
8+
- run: yarn
9+
- run: yarn build
10+
- save_cache:
11+
paths:
12+
- node_modules
13+
key: moltin-request-{{ checksum "package.json" }}
14+
test:
15+
docker:
16+
- image: 'circleci/node:latest'
17+
steps:
18+
- checkout
19+
- restore_cache:
20+
keys:
21+
- moltin-request-{{ checksum "package.json" }}
22+
- run: yarn build
23+
- run: yarn test
24+
release:
25+
docker:
26+
- image: 'circleci/node:latest'
27+
steps:
28+
- checkout
29+
- restore_cache:
30+
keys:
31+
- moltin-request-{{ checksum "package.json" }}
32+
- run: yarn build
33+
- run: npx semantic-release
34+
workflows:
35+
version: 2
36+
build_test_release:
37+
jobs:
38+
- build
39+
- test:
40+
requires:
41+
- build
42+
- release:
43+
filters:
44+
branches:
45+
only: master
46+
requires:
47+
- test

‎.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# dependencies
2+
node_modules
3+
4+
# build
5+
dist
6+
7+
# misc
8+
*.log
9+
.DS_Store

‎.prettierignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist/
2+
package.json
3+
yarn.lock

‎.prettierrc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"singleQuote": true,
3+
"semi": false,
4+
"jsxBracketSameLine": true
5+
}

‎README.md

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# @moltin/request
2+
3+
[![npm version](https://img.shields.io/npm/v/@moltin/request.svg)](https://www.npmjs.com/package/@moltin/request) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
4+
5+
> 🎮 Minimal Moltin API request library for Node + browsers
6+
7+
## 🛠 Installation
8+
9+
```bash
10+
yarn add @moltin/request # npm install @moltin/request
11+
```
12+
13+
## 🚀 Quickstart (implicit)
14+
15+
```js
16+
import { createClient } from '@moltin/request'
17+
18+
const client = new createClient({
19+
client_id: '...'
20+
})
21+
22+
client
23+
.get('products')
24+
.then(console.log)
25+
.catch(console.error)
26+
```
27+
28+
## ⛽️ Quickstart (client credentials)
29+
30+
```js
31+
import { createClient } from '@moltin/request'
32+
33+
const client = new createClient({
34+
client_id: '...',
35+
client_secret: '...'
36+
})
37+
38+
client
39+
.post('brands', {
40+
name: 'My Special Brand',
41+
slug: 'my-special-brand',
42+
status: 'live'
43+
})
44+
.then(console.log)
45+
.catch(console.error)
46+
47+
client
48+
.put('brands/:id', {
49+
name: 'My Special Brand!'
50+
})
51+
.then(console.log)
52+
.catch(console.error)
53+
54+
client
55+
.delete('brands/:id')
56+
.then(console.log)
57+
.catch(console.error)
58+
```

‎jest.config.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module.exports = {
2+
roots: ['<rootDir>/src'],
3+
transform: {
4+
'^.+\\.tsx?$': 'ts-jest'
5+
},
6+
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
7+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
8+
verbose: true,
9+
testURL: 'http://localhost/'
10+
}

‎mock.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const { createClient } = require('./dist')
2+
3+
const client = new createClient({
4+
client_id: 'j6hSilXRQfxKohTndUuVrErLcSJWP15P347L6Im0M4'
5+
})
6+
7+
client.get('products').then(console.log)

‎package.json

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@moltin/request",
3+
"version": "0.0.0-development",
4+
"license": "MIT",
5+
"main": "dist/index.js",
6+
"typings": "dist/index.d.ts",
7+
"files": [
8+
"dist"
9+
],
10+
"scripts": {
11+
"build": "yarn clean && tsc -d",
12+
"clean": "rimraf dist",
13+
"prepublish": "yarn build",
14+
"test": "jest",
15+
"semantic-release": "semantic-release"
16+
},
17+
"dependencies": {
18+
"cross-fetch": "2.2.2"
19+
},
20+
"devDependencies": {
21+
"@types/fetch-mock": "6.0.3",
22+
"@types/jest": "23.3.1",
23+
"fetch-mock": "6.5.2",
24+
"jest": "23.4.2",
25+
"rimraf": "2.6.2",
26+
"semantic-release": "15.9.3",
27+
"ts-jest": "23.0.1",
28+
"typescript": "3.0.1"
29+
},
30+
"publishConfig": {
31+
"access": "public"
32+
},
33+
"repository": {
34+
"type": "git",
35+
"url": "https://github.com/moltin/moltin-request.git"
36+
}
37+
}

‎renovate.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": ["config:base", "docker:disable"],
3+
"automerge": true,
4+
"major": {
5+
"automerge": false
6+
},
7+
"reviewers": ["notrab", "ynnoj", "craigtweedy"]
8+
}

‎src/index.ts

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import 'cross-fetch/polyfill'
2+
3+
import { InitOptions, Options, Headers, AuthBody } from './types'
4+
import { removeLeadingSlash } from './utils'
5+
6+
export class createClient {
7+
private client_id: string
8+
private client_secret?: string
9+
private options?: Options
10+
11+
constructor(options: InitOptions) {
12+
const { client_id, client_secret, ...others } = options
13+
14+
this.client_id = client_id
15+
this.client_secret = client_secret ? client_secret : undefined
16+
this.options = others || {}
17+
}
18+
19+
async request(method: string, path: string, data: object = undefined) {
20+
try {
21+
const { application, currency, customer_token } = this.options
22+
const uri: string = `https://api.moltin.com/v2/${removeLeadingSlash(
23+
path
24+
)}`
25+
const headers: Headers = {
26+
'Content-Type': 'application/json',
27+
Authorization: `Bearer ${await this.authenticate()}`,
28+
...(application && { 'X-MOLTIN-APPLICATION': application }),
29+
...(currency && { 'X-MOLTIN-CURRENCY': currency }),
30+
...(customer_token && { 'X-MOLTIN-CUSTOMER-TOKEN': customer_token })
31+
}
32+
33+
const response = await fetch(uri, {
34+
method,
35+
headers,
36+
...(data && { body: JSON.stringify({ data }) })
37+
})
38+
const json = await response.json()
39+
40+
if (response.ok) {
41+
return json
42+
}
43+
44+
return {
45+
errors: json.errors
46+
}
47+
} catch (errors) {
48+
return {
49+
errors
50+
}
51+
}
52+
}
53+
54+
async authenticate() {
55+
const { client_id, client_secret } = this
56+
57+
if (!client_id) {
58+
throw new Error('You must provide a client_id')
59+
}
60+
61+
const uri: string = 'https://api.moltin.com/oauth/access_token'
62+
const body: AuthBody = {
63+
grant_type: client_secret ? 'client_credentials' : 'implicit',
64+
client_id,
65+
...(client_secret && { client_secret })
66+
}
67+
68+
const response = await fetch(uri, {
69+
method: 'POST',
70+
headers: {
71+
'Content-Type': 'application/x-www-form-urlencoded'
72+
},
73+
body: Object.keys(body)
74+
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(body[k])}`)
75+
.join('&')
76+
})
77+
78+
const { access_token }: { access_token: string } = await response.json()
79+
80+
if (!access_token) {
81+
throw new Error('Unable to obtain an access token')
82+
}
83+
84+
return access_token
85+
}
86+
87+
post(path: string, data: object) {
88+
return this.request('POST', path, data)
89+
}
90+
91+
get(path: string) {
92+
return this.request('GET', path)
93+
}
94+
95+
put(path: string, data: object) {
96+
return this.request('PUT', path, data)
97+
}
98+
99+
delete(path: string) {
100+
return this.request('DELETE', path)
101+
}
102+
}

‎src/types.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export interface InitOptions {
2+
client_id: string
3+
client_secret?: string
4+
application?: string
5+
currency?: string
6+
customer_token?: string
7+
}
8+
9+
export interface Options {
10+
application?: string
11+
currency?: string
12+
customer_token?: string
13+
}
14+
15+
export interface Headers {
16+
[key: string]: string
17+
}
18+
19+
export interface AuthBody {
20+
grant_type: 'client_credentials' | 'implicit'
21+
client_id: string
22+
client_secret?: string
23+
}

‎src/utils.test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { removeLeadingSlash } from './utils'
2+
3+
it('leading slash is removed', () => {
4+
const string = '/test'
5+
6+
expect(removeLeadingSlash(string)).toEqual('test')
7+
})

‎src/utils.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function removeLeadingSlash(string: string) {
2+
return string.replace(/^\/+/, '')
3+
}

‎tsconfig.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"module": "commonjs",
5+
"moduleResolution": "node",
6+
"rootDir": "src",
7+
"outDir": "dist",
8+
"sourceMap": true,
9+
"noUnusedLocals": true,
10+
"lib": ["es2015", "dom", "esnext"]
11+
},
12+
"exclude": ["node_modules", "dist", "examples"]
13+
}

‎yarn.lock

+4,328
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
This repository has been archived.