Skip to content

Commit 9bc4fbd

Browse files
committed
Initial commit
0 parents  commit 9bc4fbd

35 files changed

+6271
-0
lines changed

sematext-experience/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.vercel
2+
.env
3+
node_modules

sematext-experience/api/callback.js

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const { parse } = require('url')
2+
const { HOST } = require('../lib/env')
3+
const redirectUri = `${HOST}/api/callback`
4+
const getAccessToken = require('../lib/get-access-token')
5+
const setMetadata = require('../lib/set-metadata')
6+
7+
module.exports = async (req, res) => {
8+
const {
9+
query: { code, configurationId, next, teamId }
10+
} = parse(req.url, true)
11+
if (!code) {
12+
res.statusCode = 400
13+
res.end('missing query parameter: code')
14+
return
15+
}
16+
17+
console.log('Getting accessToken')
18+
console.log('redirectUri: ', redirectUri)
19+
const token = await getAccessToken({
20+
code,
21+
redirectUri
22+
})
23+
24+
console.log('Storing accessToken to metadata')
25+
await setMetadata({ configurationId, token, teamId }, { token })
26+
27+
res.statusCode = 302
28+
res.setHeader('Location', next)
29+
res.end()
30+
}

sematext-experience/api/ui.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const { withUiHook } = require('@zeit/integration-utils')
2+
const route = require('../lib/route')
3+
4+
module.exports = withUiHook(async arg => {
5+
let {
6+
payload: { action }
7+
} = arg
8+
if (action === 'view') {
9+
action = 'index'
10+
}
11+
if (action === 'region') {
12+
action = 'index'
13+
}
14+
15+
return route(arg, action)
16+
})

sematext-experience/lib/env.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const REQUIRED = ['CLIENT_ID', 'CLIENT_SECRET', 'HOST']
2+
3+
for (const name of REQUIRED) {
4+
if (!process.env[name]) {
5+
throw new Error(`Missing environment variables: ${name}`)
6+
}
7+
}
8+
9+
module.exports = process.env
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const fetch = require('node-fetch')
2+
const { stringify } = require('querystring')
3+
const { CLIENT_ID, CLIENT_SECRET } = require('./env')
4+
const responseError = require('./response-error')
5+
6+
module.exports = async ({ code, redirectUri }) => {
7+
const res = await fetch('https://api.zeit.co/v2/oauth/access_token', {
8+
headers: {
9+
'Content-Type': 'application/x-www-form-urlencoded'
10+
},
11+
method: 'POST',
12+
body: stringify({
13+
client_id: CLIENT_ID,
14+
client_secret: CLIENT_SECRET,
15+
code,
16+
redirect_uri: redirectUri
17+
})
18+
})
19+
20+
if (!res.ok) {
21+
throw await responseError(res)
22+
}
23+
24+
const body = await res.json()
25+
return body.access_token
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = async res => {
2+
const body = await res.json()
3+
const err = new Error(
4+
body.error ? body.error.message : 'Internal server error'
5+
)
6+
err.res = res
7+
err.body = body
8+
return err
9+
}

sematext-experience/lib/route.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { parse } = require('url')
2+
let routes
3+
4+
module.exports = (arg, action, state = {}) => {
5+
if (!routes) {
6+
routes = {
7+
'index': require('../ui')
8+
}
9+
}
10+
11+
if (!action) {
12+
action = arg.payload.action
13+
}
14+
15+
const { pathname, query } = parse(action, true)
16+
for (const [p, fn] of Object.entries(routes)) {
17+
if (p === pathname) {
18+
return fn(arg, { params: query, state })
19+
}
20+
}
21+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const fetch = require('node-fetch')
2+
const { stringify } = require('querystring')
3+
const responseError = require('./response-error')
4+
5+
module.exports = async ({ configurationId, teamId, token }, data) => {
6+
const query = stringify({ teamId })
7+
const res = await fetch(
8+
`https://api.zeit.co/v1/integrations/configuration/${encodeURIComponent(
9+
configurationId
10+
)}/metadata?${query}`,
11+
{
12+
method: 'POST',
13+
headers: {
14+
Authorization: `Bearer ${token}`
15+
},
16+
body: JSON.stringify(data)
17+
}
18+
)
19+
20+
const body = await res.json()
21+
if (!res.ok) {
22+
throw await responseError(res)
23+
}
24+
25+
return body
26+
}

sematext-experience/package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "sematext-experience",
3+
"version": "0.0.0",
4+
"license": "MIT",
5+
"scripts": {
6+
"format": "prettier-standard --format",
7+
"lint": "prettier-standard --format --lint '**/*.js'"
8+
},
9+
"dependencies": {
10+
"@zeit/integration-utils": "0.6.4",
11+
"ms": "2.1.2",
12+
"node-fetch": "2.6.0",
13+
"raw-body": "2.4.1"
14+
},
15+
"devDependencies": {
16+
"prettier-standard": "^16.3.0"
17+
}
18+
}

sematext-experience/ui/index.js

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
const { htm } = require('@zeit/integration-utils')
2+
3+
module.exports = async (arg, { state }) => {
4+
const { payload } = arg
5+
const { clientState, teamId, token } = payload
6+
const {
7+
region = 'us'
8+
} = clientState
9+
const { errorMessage } = state
10+
11+
return htm`
12+
<Page>
13+
14+
<Fieldset>
15+
<FsContent>
16+
<H2>Create Your Sematext Account</H2>
17+
<P>Visit <Link href="https://apps.sematext.com/ui/registration" target="_blank">Sematext</Link> and create an account.</P>
18+
</FsContent>
19+
<FsFooter>
20+
If you already have an account, you can use that account instead.
21+
</FsFooter>
22+
</Fieldset>
23+
24+
<Fieldset>
25+
<FsContent>
26+
<H2>Select Region</H2>
27+
<P>The region you chose when creating your account.</P>
28+
<Select name="region" value=${region} action="region">
29+
<Option value="us" caption="US" />
30+
<Option value="eu" caption="EU" />
31+
</Select>
32+
</FsContent>
33+
</Fieldset>
34+
35+
<Fieldset>
36+
<FsContent>
37+
<H2>Create an Experience App</H2>
38+
<P>Go to <Link href=${`https://apps.${
39+
region === 'us' ? '' : 'eu.'
40+
}sematext.com/ui/rum`} target="_blank">Sematext Experience</Link> and click on the <B>"+ New Experience App"</B> button to create an App.</P>
41+
<P>Once the App is created, follow the <B>"Experience Script Installation"</B> to activate real user monitoring.</P>
42+
</FsContent>
43+
</Fieldset>
44+
45+
${errorMessage ? htm`<Notice type="error">${errorMessage}</Notice>` : ''}
46+
</Page>
47+
`
48+
}

sematext-experience/vercel.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": 2,
3+
"functions": {
4+
"api/ui.js": {
5+
"memory": 1024,
6+
"maxDuration": 10
7+
},
8+
"api/callback.js": {
9+
"memory": 1024,
10+
"maxDuration": 10
11+
}
12+
},
13+
"env": {
14+
"CLIENT_ID": "@sematext-experience-client-id",
15+
"CLIENT_SECRET": "@sematext-experience-client-secret",
16+
"HOST": "@sematext-experience-host"
17+
}
18+
}

0 commit comments

Comments
 (0)