theauthapi 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +15 -0
- package/.prettierrc.json +1 -0
- package/jest.config.js +5 -0
- package/jest.setup.ts +0 -0
- package/package.json +34 -29
- package/src/endpoints/ApiKeys/ApiKeys.ts +68 -0
- package/src/endpoints/ApiKeys/ApiKeysInterface.ts +11 -0
- package/src/endpoints/Projects/Projects.ts +62 -0
- package/src/endpoints/Projects/ProjectsInterface.ts +9 -0
- package/src/index.ts +103 -0
- package/src/libraryMeta.ts +1 -0
- package/src/services/ApiRequest/ApiCall.ts +7 -0
- package/src/services/ApiRequest/ApiRequest.ts +132 -0
- package/src/services/ApiRequest/ApiRequestError.ts +7 -0
- package/src/services/ApiRequest/HttpMethod.ts +7 -0
- package/src/tests/endpoints/apiKeys.spec.ts +102 -0
- package/src/tests/endpoints/projects.spec.ts +105 -0
- package/src/tests/index.spec.ts +35 -0
- package/src/tests/testServer/middleware/middleware.ts +17 -0
- package/src/tests/testServer/routes/apiKeys.ts +89 -0
- package/src/tests/testServer/routes/auth.ts +24 -0
- package/src/tests/testServer/routes/projects.ts +87 -0
- package/src/tests/testServer/server.ts +16 -0
- package/src/types/index.ts +59 -0
- package/src/util/index.ts +7 -0
- package/tsconfig.json +102 -0
- package/index.js +0 -182
- package/test.js +0 -113
package/index.js
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const assert = require('assert')
|
|
4
|
-
const removeSlash = require('remove-trailing-slash')
|
|
5
|
-
const axios = require('axios')
|
|
6
|
-
const axiosRetry = require('axios-retry')
|
|
7
|
-
const ms = require('ms')
|
|
8
|
-
const version = require('./package.json').version
|
|
9
|
-
const isString = require('lodash.isstring')
|
|
10
|
-
const NodeCache = require('node-cache')
|
|
11
|
-
|
|
12
|
-
const noop = () => {}
|
|
13
|
-
|
|
14
|
-
// const axios = require('axios').default;
|
|
15
|
-
|
|
16
|
-
class TheAuthAPI {
|
|
17
|
-
/**
|
|
18
|
-
* Initialize a new `Analytics` with your Segment project's `writeKey` and an
|
|
19
|
-
* optional dictionary of `options`.
|
|
20
|
-
*
|
|
21
|
-
* @param {String} writeKey
|
|
22
|
-
* @param {Object} [options] (optional)
|
|
23
|
-
* @property {Number} flushAt (default: 20)
|
|
24
|
-
* @property {Number} flushInterval (default: 10000)
|
|
25
|
-
* @property {String} host (default: 'https://api.segment.io')
|
|
26
|
-
* @property {Boolean} enable (default: true)
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
constructor (writeKey, options) {
|
|
30
|
-
options = options || {}
|
|
31
|
-
|
|
32
|
-
assert(writeKey, 'You must pass your project\'s write key.')
|
|
33
|
-
this.queue = []
|
|
34
|
-
this.writeKey = writeKey
|
|
35
|
-
this.host = removeSlash(options.host || 'https://api.theauthapi.com')
|
|
36
|
-
this.timeout = options.timeout || false
|
|
37
|
-
this.cacheTTL = options.cacheTTL || 60
|
|
38
|
-
|
|
39
|
-
Object.defineProperty(this, 'enable', {
|
|
40
|
-
configurable: false,
|
|
41
|
-
writable: false,
|
|
42
|
-
enumerable: true,
|
|
43
|
-
value: typeof options.enable === 'boolean' ? options.enable : true
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
axiosRetry(axios, {
|
|
47
|
-
retries: options.retryCount || 3,
|
|
48
|
-
retryCondition: this._isErrorRetryable,
|
|
49
|
-
retryDelay: axiosRetry.exponentialDelay
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
this.cache = new NodeCache({
|
|
53
|
-
stdTTL: this.cacheTTL,
|
|
54
|
-
checkperiod: this.cacheTTL * 0.2,
|
|
55
|
-
useClones: false
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
_validate (key, type) {
|
|
60
|
-
try {
|
|
61
|
-
if (!key || !isString(key)) throw new Error('must pass a string')
|
|
62
|
-
} catch (e) {
|
|
63
|
-
throw e
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Send a track `message`.
|
|
69
|
-
*
|
|
70
|
-
* @param {Object} message
|
|
71
|
-
* @param {Function} [callback] (optional)
|
|
72
|
-
* @return {TheAnalyticsAPI}
|
|
73
|
-
*/
|
|
74
|
-
|
|
75
|
-
async authenticateAPIKey (key, callback) {
|
|
76
|
-
this._validate(key, 'api_key')
|
|
77
|
-
|
|
78
|
-
callback = callback || noop
|
|
79
|
-
|
|
80
|
-
const data = {
|
|
81
|
-
credentials: { api_key: key },
|
|
82
|
-
timestamp: new Date().getTime(),
|
|
83
|
-
sentAt: new Date().getTime()
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const done = err => {
|
|
87
|
-
// callbacks.forEach(callback => callback(err))
|
|
88
|
-
callback(err, data)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const headers = {}
|
|
92
|
-
|
|
93
|
-
headers['user-agent'] = `theauthapi-client-node/${version}`
|
|
94
|
-
headers['x-api-key'] = headers['api_key'] = this.writeKey
|
|
95
|
-
|
|
96
|
-
const req = {
|
|
97
|
-
method: 'POST',
|
|
98
|
-
url: `${this.host}/auth/authenticate`,
|
|
99
|
-
/* auth: {
|
|
100
|
-
username: this.writeKey
|
|
101
|
-
}, */
|
|
102
|
-
data,
|
|
103
|
-
headers
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (this.timeout) {
|
|
107
|
-
req.timeout = typeof this.timeout === 'string' ? ms(this.timeout) : this.timeout
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
const data = await axios(req).data
|
|
112
|
-
done(data)
|
|
113
|
-
return data
|
|
114
|
-
} catch (err) {
|
|
115
|
-
if (err.response) {
|
|
116
|
-
const error = new Error(err.response.statusText)
|
|
117
|
-
return done(error)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
done(err)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
_isErrorRetryable (error) {
|
|
125
|
-
// Retry Network Errors.
|
|
126
|
-
if (axiosRetry.isNetworkError(error)) {
|
|
127
|
-
return true
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (!error.response) {
|
|
131
|
-
// Cannot determine if the request can be retried
|
|
132
|
-
return false
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Retry Server Errors (5xx).
|
|
136
|
-
if (error.response.status >= 500 && error.response.status <= 599) {
|
|
137
|
-
return true
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Retry if rate limited.
|
|
141
|
-
if (error.response.status === 429) {
|
|
142
|
-
return true
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return false
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
getCache (key) {
|
|
149
|
-
const value = this.cache.get(key)
|
|
150
|
-
if (value) {
|
|
151
|
-
return Promise.resolve(value)
|
|
152
|
-
} else {
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
setCache (key, value, ttl = null) {
|
|
158
|
-
if (ttl) this.cache.set(key, value, ttl)
|
|
159
|
-
else this.cache.set(key, value)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
delCache (keys) {
|
|
163
|
-
this.cache.del(keys)
|
|
164
|
-
}
|
|
165
|
-
delCacheStartWith (startStr = '') {
|
|
166
|
-
if (!startStr) {
|
|
167
|
-
return
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const keys = this.cache.keys()
|
|
171
|
-
for (const key of keys) {
|
|
172
|
-
if (key.indexOf(startStr) === 0) {
|
|
173
|
-
this.del(key)
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
flushCache () {
|
|
178
|
-
this.cache.flushAll()
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
module.exports = TheAuthAPI
|
package/test.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
const express = require('express')
|
|
2
|
-
// const delay = require('delay')
|
|
3
|
-
// const pify = require('pify')
|
|
4
|
-
const auth = require('basic-auth').auth
|
|
5
|
-
|
|
6
|
-
const test = require('ava')
|
|
7
|
-
const version = require('./package.json').version
|
|
8
|
-
const TheAuthAPI = require('.')
|
|
9
|
-
/* var sinon = require('sinon')
|
|
10
|
-
var spy = sinon.spy
|
|
11
|
-
var stub = sinon.stub
|
|
12
|
-
|
|
13
|
-
const noop = () => {}
|
|
14
|
-
|
|
15
|
-
const context = {
|
|
16
|
-
library: {
|
|
17
|
-
name: 'theanalyticsapi',
|
|
18
|
-
version
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const metadata = { nodeVersion: process.versions.node }
|
|
23
|
-
*/
|
|
24
|
-
const port = 4063
|
|
25
|
-
|
|
26
|
-
const createClient = options => {
|
|
27
|
-
options = Object.assign({
|
|
28
|
-
host: `http://localhost:${port}`
|
|
29
|
-
}, options)
|
|
30
|
-
|
|
31
|
-
const client = new TheAuthAPI('key', options)
|
|
32
|
-
return client
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
test.before.cb(t => {
|
|
36
|
-
express()
|
|
37
|
-
.post('/auth/authenticate', (req, res) => {
|
|
38
|
-
const batch = req.body
|
|
39
|
-
|
|
40
|
-
const { name: writeKey } = auth(req)
|
|
41
|
-
if (!writeKey) {
|
|
42
|
-
return res.status(400).json({
|
|
43
|
-
error: { message: 'missing write key' }
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const ua = req.headers['user-agent']
|
|
48
|
-
if (ua !== `theauthapi-client-node/${version}`) {
|
|
49
|
-
return res.status(400).json({
|
|
50
|
-
error: { message: 'invalid user-agent' }
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (batch[0] === 'error') {
|
|
55
|
-
return res.status(400).json({
|
|
56
|
-
error: { message: 'error' }
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (batch[0] === 'timeout') {
|
|
61
|
-
return setTimeout(() => res.end(), 5000)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
res.json({})
|
|
65
|
-
})
|
|
66
|
-
.listen(port, t.end)
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
test('expose a constructor', t => {
|
|
70
|
-
t.is(typeof TheAuthAPI, 'function')
|
|
71
|
-
})
|
|
72
|
-
/*
|
|
73
|
-
test('require a write key', t => {
|
|
74
|
-
t.throws(() => new TheAuthAPI(), 'You must pass your project\'s write key.')
|
|
75
|
-
})
|
|
76
|
-
*/
|
|
77
|
-
test('default options', t => {
|
|
78
|
-
const client = new TheAuthAPI('key')
|
|
79
|
-
|
|
80
|
-
t.is(client.writeKey, 'key')
|
|
81
|
-
t.is(client.host, 'https://api.theauthapi.com')
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
test('remove trailing slashes from `host`', t => {
|
|
85
|
-
const client = new TheAuthAPI('key', { host: 'http://google.com///' })
|
|
86
|
-
|
|
87
|
-
t.is(client.host, 'http://google.com')
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
test('overwrite defaults with options', t => {
|
|
91
|
-
const client = new TheAuthAPI('key', {
|
|
92
|
-
host: 'a'
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
t.is(client.host, 'a')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
test('isErrorRetryable', t => {
|
|
99
|
-
const client = createClient()
|
|
100
|
-
|
|
101
|
-
t.false(client._isErrorRetryable({}))
|
|
102
|
-
|
|
103
|
-
// ETIMEDOUT is retryable as per `is-retry-allowed` (used by axios-retry in `isNetworkError`).
|
|
104
|
-
t.true(client._isErrorRetryable({ code: 'ETIMEDOUT' }))
|
|
105
|
-
|
|
106
|
-
// ECONNABORTED is not retryable as per `is-retry-allowed` (used by axios-retry in `isNetworkError`).
|
|
107
|
-
t.false(client._isErrorRetryable({ code: 'ECONNABORTED' }))
|
|
108
|
-
|
|
109
|
-
t.true(client._isErrorRetryable({ response: { status: 500 } }))
|
|
110
|
-
t.true(client._isErrorRetryable({ response: { status: 429 } }))
|
|
111
|
-
|
|
112
|
-
t.false(client._isErrorRetryable({ response: { status: 200 } }))
|
|
113
|
-
})
|