Skip to content
This repository has been archived by the owner on Jan 22, 2021. It is now read-only.

Commit

Permalink
Add list method (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
rogaldh committed Jan 16, 2020
1 parent 60a024c commit 358a4a4
Show file tree
Hide file tree
Showing 10 changed files with 569 additions and 30 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 Netology Group
Copyright (c) 2019 OLC Netology group LLC

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
47 changes: 29 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,42 +1,53 @@
{
"name": "@ulms/events",
"version": "0.2.0",
"version": "0.2.1",
"description": "JavaScript API-client for uLMS Events service",
"homepage": "https://github.com/netology-group/ulms-events-js",
"bugs": {
"url": "https://github.com/netology-group/ulms-events-js/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/netology-group/ulms-events-js"
},
"license": "MIT",
"author": "OLC Netology group LLC",
"files": [
"es",
"lib"
],
"main": "lib/index.js",
"module": "es/index.js",
"scripts": {
"prebuild": "rm -rf es lib",
"build": "npm run build:es && npm run build:lib",
"build:es": "BABEL_ENV=es babel src -d es",
"build:lib": "BABEL_ENV=lib babel src -d lib",
"build:es": "BABEL_ENV=es babel src --config-file ./.babelrc.json -d es",
"build:lib": "BABEL_ENV=lib babel src --config-file ./.babelrc.json -d lib",
"lint": "eslint .",
"prebuild": "rm -rf es lib",
"prepublishOnly": "npm run test && npm run build",
"test": "eslint ."
"tap": "tap --node-arg=--require=./test/babel-register.js",
"tapas": "npm run tap \"test/**/*.test.js\"",
"test": "eslint . && npm run tapas"
},
"repository": {
"type": "git",
"url": "git+https://github.com/netology-group/ulms-events-js.git"
},
"author": "netology-group",
"license": "MIT",
"bugs": {
"url": "https://github.com/netology-group/ulms-events-js/issues"
},
"homepage": "https://github.com/netology-group/ulms-events-js#readme",
"dependencies": {},
"devDependencies": {
"@babel/cli": "~7.2.3",
"@babel/core": "~7.2.2",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-transform-block-scoping": "^7.7.4",
"@babel/preset-env": "~7.3.1",
"@babel/register": "^7.7.7",
"@netology-group/account": "^2.5.1",
"babel-plugin-annotate-pure-calls": "^0.4.0",
"debug": "^4.1.1",
"eslint": "~5.12.1",
"eslint-config-standard": "~12.0.0",
"eslint-plugin-import": "~2.15.0",
"eslint-plugin-node": "~8.0.1",
"eslint-plugin-promise": "~4.0.1",
"eslint-plugin-standard": "~4.0.0"
},
"dependencies": {}
"eslint-plugin-standard": "~4.0.0",
"fetch-mock": "^8.3.1",
"isomorphic-fetch": "^2.2.1",
"tap": "^12.4.0"
}
}
111 changes: 108 additions & 3 deletions src/events.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,50 @@
const fFetchPageUntil = (fn, options, acc) => function fetchEach () {
const maybePage = fn(options, acc)
if (!(maybePage instanceof Promise)) throw new Error('awaits promise')

return maybePage
.then(([opts, result]) => {
return opts
? fFetchPageUntil(fn, { ...options, ...opts }, result)
: result
})
}

const trampoline = function (fn) {
return function (...argv) {
let result = fn(...argv)

const isCallable = a => a instanceof Function
const repeat = (nextFn) => {
const nextIsCallable = isCallable(nextFn)

return !nextIsCallable
? Promise.resolve(nextFn)
: nextFn().then(repeat)
}

return repeat(result)
}
}

export class HttpEventsResource {
constructor (
host,
endpoint,
httpClient,
tokenProvider
) {
this.baseUrl = `${host}/${endpoint}`
this.httpClient = httpClient
this.tokenProvider = tokenProvider
if (typeof endpoint === 'string') {
// TODO: deprecate complex url later
this.baseUrl = `${host}/${endpoint}`
this.httpClient = httpClient
this.tokenProvider = tokenProvider
} else {
// bypass solid url on instantiation
this.baseUrl = `${host}`
this.httpClient = endpoint
this.tokenProvider = httpClient
}
}
static _headers (token, params = {}) {
const { randomId } = params
Expand All @@ -23,6 +60,9 @@ export class HttpEventsResource {
...additionalHeaders
}
}
_token () {
return this.tokenProvider.getToken()
}
getState (audience, roomId, params = {}) {
const { offset, direction } = params
const qsParts = []
Expand All @@ -47,6 +87,71 @@ export class HttpEventsResource {
)
)
}
_list (opts = {}) {
const {
qs,
after,
audience,
before,
direction,
lastId,
page,
roomId,
type
} = opts

if (!audience) return Promise.reject(new TypeError('`audience` is absent'))
if (!direction) return Promise.reject(new TypeError('`direction` is absent'))
if (!roomId) return Promise.reject(new TypeError('`roomId` is absent'))

const qsParts = qs && qs.length ? qs.split('&') : []

if (!qs) {
!isNaN(after) && qsParts.push(`after=${after}`)
!isNaN(before) && qsParts.push(`before=${before}`)
direction && qsParts.push(`direction=${direction}`)
lastId && qsParts.push(`last_id=${lastId}`)
type && qsParts.push(`type=${type}`)
page && qsParts.push(`page=${page}`)

qsParts.push(`audience=${audience}`)
qsParts.push(`room_id=${roomId}`)
}

return this._token()
.then((token) => {
const qs = qsParts.length ? `?${qsParts.join('&')}` : ''

const url = new URL(`${this.baseUrl}/${audience}/rooms/${roomId}/events${qs}`)

return this.httpClient.get(
url.href,
{
headers: HttpEventsResource._headers(token)
}
)
})
}
list (opts) {
const { direction = 'forward' } = opts
const options = { ...opts, direction }

const mergeResult = (o, acc = []) => {
return this._list(o)
.then((res) => {
const accNext = o.direction === 'forward'
? acc.concat(res.events)
: res.events.concat(acc)

return res.has_next_page
? [ { ...options, qs: res.next_page }, accNext ]
: [ undefined, { events: accNext } ]
})
}
const shouldFetch = trampoline(fFetchPageUntil)

return shouldFetch(mergeResult, options, [])
}
getEvents (audience, roomId, direction, params = {}) {
const { after, before, lastId, type } = params
const qsParts = []
Expand Down
31 changes: 24 additions & 7 deletions src/http-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,54 @@

export class FetchHttpClient {
static _processResponse (response) {
if (response.status === 204) {
return null
if (response.status === 200) return response.json()
if (response.status === 204) return Promise.resolve()

if (/^4\d{2}/.test(response.status)) {
return response.json().then((a) => {
return Promise.reject(a)
})
}

return response.json()
return response.text().then((text) => {
throw new Error(text)
})
}
constructor () {
this.__fetch = fetch
return this
}
__provider (provider) {
if (!provider) throw new TypeError('provider is absent')
this.__fetch = provider

return this
}
get (url, config) {
return fetch(url, {
return this.__fetch.call(null, url, {
method: 'GET',
headers: config.headers
})
.then(FetchHttpClient._processResponse)
}
post (url, data, config) {
return fetch(url, {
return this.__fetch.call(null, url, {
method: 'POST',
headers: config.headers,
body: JSON.stringify(data)
})
.then(FetchHttpClient._processResponse)
}
patch (url, data, config) {
return fetch(url, {
return this.__fetch.call(null, url, {
method: 'PATCH',
headers: config.headers,
body: JSON.stringify(data)
})
.then(FetchHttpClient._processResponse)
}
delete (url, data, config) {
return fetch(url, {
return this.__fetch.call(null, url, {
method: 'DELETE',
headers: config.headers,
body: JSON.stringify(data)
Expand Down
6 changes: 5 additions & 1 deletion src/token-provider.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
export class SimpleTokenProvider {
constructor (token) {
this.token = token
if (!token) throw new TypeError('Can not initialize TokenProvider. `token` is absent')
this.token = typeof token !== 'string' ? String(token) : token
}
getToken () {
return Promise.resolve(this.token)
}
token () {
return this.getToken()
}
}
6 changes: 6 additions & 0 deletions test/babel-register.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const babelrc = require('../.babelrc.json')

// eslint-disable-next-line node/no-unpublished-require
require('@babel/register')({
...babelrc.env.cjs
})
Loading

0 comments on commit 358a4a4

Please sign in to comment.