@data-fair/dev-server 1.13.0 → 2.0.0

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.
Files changed (43) hide show
  1. package/package.json +47 -62
  2. package/src/app.ts +278 -0
  3. package/src/config.ts +12 -0
  4. package/{server/index.js → src/index.ts} +6 -5
  5. package/src/ui-config.ts +6 -0
  6. package/ui/dist/assets/index-B_eKgwUO.css +5 -0
  7. package/ui/dist/assets/index-C7IbVpbV.js +167 -0
  8. package/ui/dist/fonts/XRXV3I6Li01BKofIMeaBXso-C3IBG1kp.woff2 +0 -0
  9. package/ui/dist/fonts/XRXV3I6Li01BKofINeaB-BaTF6Vo7.woff2 +0 -0
  10. package/ui/dist/fonts/XRXV3I6Li01BKofIO-aBXso-DcJfvmGA.woff2 +0 -0
  11. package/ui/dist/fonts/XRXV3I6Li01BKofIOOaBXso-BWI5zH9R.woff2 +0 -0
  12. package/ui/dist/fonts/XRXV3I6Li01BKofIOuaBXso-B55YuedR.woff2 +0 -0
  13. package/ui/dist/fonts/XRXX3I6Li01BKofIMNaDRs4-BbMn9XSX.woff2 +0 -0
  14. package/ui/dist/fonts/XRXX3I6Li01BKofIMNaHRs71cA-Cznx39fA.woff2 +0 -0
  15. package/ui/dist/fonts/XRXX3I6Li01BKofIMNaMRs71cA-CuWrHpFO.woff2 +0 -0
  16. package/ui/dist/fonts/XRXX3I6Li01BKofIMNaNRs71cA-D1eeM49Z.woff2 +0 -0
  17. package/ui/dist/fonts/XRXX3I6Li01BKofIMNaORs71cA-Bm_i0Dk1.woff2 +0 -0
  18. package/ui/dist/index.html +19 -0
  19. package/.eslintignore +0 -5
  20. package/.nvmrc +0 -1
  21. package/config/custom-environment-variables.js +0 -23
  22. package/config/default.js +0 -18
  23. package/config/development.js +0 -1
  24. package/config/production.js +0 -1
  25. package/dist/.nojekyll +0 -0
  26. package/dist/200.html +0 -9
  27. package/dist/_dev-server-nuxt/1c5f67f.js +0 -1
  28. package/dist/_dev-server-nuxt/2c7d7c0.js +0 -1
  29. package/dist/_dev-server-nuxt/3091234.js +0 -1
  30. package/dist/_dev-server-nuxt/5a68472.js +0 -1
  31. package/dist/_dev-server-nuxt/LICENSES +0 -52
  32. package/dist/_dev-server-nuxt/a62e828.js +0 -1
  33. package/dist/_dev-server-nuxt/b39b908.js +0 -1
  34. package/dist/_dev-server-nuxt/b64ddf5.js +0 -2
  35. package/dist/_dev-server-nuxt/c306f6e.js +0 -1
  36. package/dist/_dev-server-nuxt/c5e103d.js +0 -1
  37. package/dist/_dev-server-nuxt/dc90835.js +0 -2
  38. package/dist/_dev-server-nuxt/e5dea00.js +0 -1
  39. package/dist/_dev-server-nuxt/eb298ad.js +0 -8
  40. package/dist/index.html +0 -9
  41. package/nodemon.json +0 -5
  42. package/nuxt.config.js +0 -59
  43. package/server/app.js +0 -308
package/dist/index.html DELETED
@@ -1,9 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="application" name="application-name" content="DataFair - Dev server"><meta data-n-head="1" data-hid="description" name="description" content="A development server for optimal development experience of data-fair applications."><meta data-n-head="1" data-hid="robots" name="robots" content="noindex"><title>DataFair - Dev server</title><link rel="preload" href="/_dev-server-nuxt/e5dea00.js" as="script"><link rel="preload" href="/_dev-server-nuxt/dc90835.js" as="script"><link rel="preload" href="/_dev-server-nuxt/b64ddf5.js" as="script"><link rel="preload" href="/_dev-server-nuxt/2c7d7c0.js" as="script">
5
- </head>
6
- <body>
7
- <div id="__nuxt"><style>#nuxt-loading{background:#fff;visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #000;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style> <script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script> <div id="nuxt-loading" aria-live="polite" role="status"><div>Loading...</div></div> </div><script>window.__NUXT__={config:{_app:{basePath:"/",assetsPath:"/_dev-server-nuxt/",cdnURL:null}}}</script>
8
- <script src="/_dev-server-nuxt/e5dea00.js"></script><script src="/_dev-server-nuxt/dc90835.js"></script><script src="/_dev-server-nuxt/b64ddf5.js"></script><script src="/_dev-server-nuxt/2c7d7c0.js"></script></body>
9
- </html>
package/nodemon.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "verbose": false,
3
- "ext": "js json html",
4
- "watch": ["server/", "config/", "package.json", "nuxt.config.js"]
5
- }
package/nuxt.config.js DELETED
@@ -1,59 +0,0 @@
1
- let config = require('config')
2
-
3
- if (process.argv.slice(-1)[0] === 'generate') {
4
- const nuxtConfigInject = require('@koumoul/nuxt-config-inject')
5
- config = nuxtConfigInject.prepare(config)
6
- }
7
-
8
- const locales = ['en', 'fr']
9
-
10
- module.exports = {
11
- ssr: false,
12
- target: 'static',
13
- components: true,
14
- srcDir: 'public/',
15
- telemetry: false,
16
- build: {
17
- publicPath: '/_dev-server-nuxt'
18
- },
19
- modules: ['@nuxtjs/axios', ['@nuxtjs/i18n', {
20
- seo: false,
21
- locales,
22
- defaultLocale: 'en',
23
- vueI18nLoader: true,
24
- strategy: 'no_prefix',
25
- detectBrowserLanguage: {
26
- useCookie: true,
27
- cookieKey: 'i18n_lang'
28
- },
29
- vueI18n: {
30
- fallbackLocale: 'en'
31
- }
32
- }]],
33
- axios: {
34
- browserBaseURL: 'http://localhost:5888/data-fair'
35
- },
36
- buildModules: ['@nuxtjs/vuetify'],
37
- vuetify: {
38
- theme: {
39
- themes: {
40
- light: {
41
- primary: '#1E88E5', // colors.blue.darken1
42
- accent: '#F57C00', // colors.orange.darken2
43
- warning: '#F57C00' // colors.orange.darken2
44
- }
45
- }
46
- }
47
- },
48
- env: { app: config.app, dataFair: config.dataFair, iframeLog: config.iframeLog, locales },
49
- head: {
50
- title: 'DataFair - Dev server',
51
- meta: [
52
- { charset: 'utf-8' },
53
- { name: 'viewport', content: 'width=device-width, initial-scale=1' },
54
- { hid: 'application', name: 'application-name', content: 'DataFair - Dev server' },
55
- { hid: 'description', name: 'description', content: 'A development server for optimal development experience of data-fair applications.' },
56
- { hid: 'robots', name: 'robots', content: 'noindex' }
57
- ]
58
- }
59
- }
package/server/app.js DELETED
@@ -1,308 +0,0 @@
1
- // Express app for TaxMan own API and UI
2
- const util = require('util')
3
- const path = require('path')
4
- const { spawn } = require('child_process')
5
- const express = require('express')
6
- const bodyParser = require('body-parser')
7
- const config = require('config')
8
- const eventToPromise = require('event-to-promise')
9
- const http = require('http')
10
- const fs = require('fs-extra')
11
- const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware')
12
- const cors = require('cors')
13
- const kill = require('tree-kill')
14
- const escapeStringRegexp = require('escape-string-regexp')
15
- const parse5 = require('parse5')
16
- const { WebSocket, WebSocketServer } = require('ws')
17
- const debug = require('debug')('df-dev-server')
18
- const chalk = require('chalk')
19
- const Extractor = require('html-extractor')
20
- const htmlExtractor = new Extractor()
21
- htmlExtractor.extract = util.promisify(htmlExtractor.extract)
22
- const vIframeVersion = require('@koumoul/v-iframe/package.json').version
23
- const iframeResizerVersion = require('iframe-resizer/package.json').version
24
-
25
- const app = express()
26
- const server = http.createServer(app)
27
-
28
- // web socket server, used both by dev-server UI (opened on / path)
29
- // and by application (opened on /data-fair), in this case we transmit all messages to and from data-fair
30
- const wss = new WebSocketServer({ noServer: true })
31
- let devServerWS, dataFairWS
32
- server.on('upgrade', function upgrade (req, socket, head) {
33
- wss.handleUpgrade(req, socket, head, (ws) => {
34
- if (req.url === '/data-fair') {
35
- if (dataFairWS) dataFairWS.terminate()
36
- dataFairWS = ws
37
- ws.on('message', (data) => {
38
- if (dataFairOutputWS) {
39
- const message = JSON.parse(data)
40
- if (message.type === 'subscribe') message.apiKey = config.dataFair.apiKey
41
- dataFairOutputWS.send(JSON.stringify(message))
42
- }
43
- })
44
- } else {
45
- if (devServerWS) devServerWS.terminate()
46
- devServerWS = ws
47
- }
48
- wss.emit('connection', ws, req)
49
- })
50
- })
51
-
52
- const dfWsUrl = config.dataFair.url.replace('http://', 'ws://').replace('https://', 'wss://') + '/'
53
- const dataFairOutputWS = new WebSocket(dfWsUrl)
54
- dataFairOutputWS.on('open', () => dataFairOutputWS.send('connect to external websocket server', dfWsUrl))
55
- dataFairOutputWS.on('message', (data) => { if (dataFairWS) dataFairWS.send(data.toString()) })
56
- dataFairOutputWS.on('error', (err) => console.error('failed to connect to external websocket server', dfWsUrl, err))
57
-
58
- app.use(cors())
59
- app.use(bodyParser.json())
60
-
61
- // very basic CRUD of config
62
- app.get('/config', (req, res, next) => {
63
- const devConfig = fs.existsSync('.dev-config.json') ? fs.readJsonSync('.dev-config.json') : {}
64
- debug('read dev config', devConfig)
65
- res.send(devConfig)
66
- })
67
- app.put('/config', (req, res, next) => {
68
- debug('save dev config', req.body)
69
- fs.writeJsonSync('.dev-config.json', req.body, { spaces: 2 })
70
- res.send(req.body)
71
- })
72
- app.post('/config/error', (req, res) => {
73
- console.log('Application sent an error', req.body)
74
- if (devServerWS) devServerWS.send(JSON.stringify({ type: 'app-error', data: req.body }))
75
- else console.error('no dev-server websocket open to send error to')
76
- res.send()
77
- })
78
-
79
- // re-expose the application performing similar modifications to the body as data-fair
80
- const appUrl = new URL(config.app.url)
81
- app.use('/app', createProxyMiddleware({
82
- target: appUrl.origin,
83
- pathRewrite: { '^/app': appUrl.pathname === '/' ? '' : appUrl.pathname },
84
- secure: false,
85
- changeOrigin: true,
86
- selfHandleResponse: true, // so that the onProxyRes takes care of sending the response
87
- onProxyReq (proxyReq, req, res) {
88
- proxyReq.setHeader('Accept-Encoding', 'identity') // disable compression
89
- },
90
- onProxyRes (proxyRes, req, res) {
91
- const configuration = fs.existsSync('.dev-config.json') ? fs.readJsonSync('.dev-config.json') : {}
92
- // console.log('inject config', configuration)
93
- const dataBuffers = []
94
- proxyRes.on('data', (data) => { dataBuffers.push(data) })
95
- proxyRes.on('end', async () => {
96
- try {
97
- let output = Buffer.concat(dataBuffers)
98
- const body = output.toString()
99
- if (body.includes('%APPLICATION%')) {
100
- const filledBody = body.replace(/%APPLICATION%/g, JSON.stringify({
101
- id: 'dev-application',
102
- title: 'Dev application',
103
- configuration,
104
- exposedUrl: 'http://localhost:5888/app',
105
- href: 'http://localhost:5888/config',
106
- apiUrl: 'http://localhost:5888/data-fair/api/v1',
107
- wsUrl: 'ws://localhost:5888/data-fair',
108
- owner: config.dataFair && config.dataFair.owner
109
- }))
110
- const document = parse5.parse(filledBody)
111
- const html = document.childNodes.find(c => c.tagName === 'html')
112
- if (!html) throw new Error('HTML structure is broken, expect html, head and body elements')
113
- const headNode = html.childNodes.find(c => c.tagName === 'head')
114
- const bodyNode = html.childNodes.find(c => c.tagName === 'body')
115
- if (!headNode || !bodyNode) throw new Error('HTML structure is broken, expect html, head and body elements')
116
-
117
- // add a script to simulate instrumentation by capture service
118
- if (req.query.thumbnail === 'true') {
119
- headNode.childNodes.push({
120
- nodeName: 'script',
121
- tagName: 'script',
122
- attrs: [{ name: 'type', value: 'text/javascript' }],
123
- childNodes: [{
124
- nodeName: '#text',
125
- value: `
126
- console.log('[capture] Simulate a screenshot capture context')
127
- var triggerCalled = false
128
- window.triggerCapture = function (animationSupported) {
129
- triggerCalled = true
130
- console.log('[capture] triggerCapture called')
131
- if (animationSupported) {
132
- console.log('[capture] this application supports animated screenshots')
133
- var i = 0
134
- const interval = setInterval(function () {
135
- i++
136
- if (i === 1800) {
137
- console.error('[capture] stop after the maximum number of frames was attained')
138
- clearInterval(interval)
139
- }
140
- var stopped = window.animateCaptureFrame()
141
- if (stopped) {
142
- console.log('[capture] animation was stopped after ' + i + ' frames')
143
- clearInterval(interval)
144
- }
145
- }, 67)
146
- return true
147
- } else {
148
- console.log('[capture] this application does not support animated screenshots')
149
- }
150
- }
151
- setTimeout(function() {
152
- if (!triggerCalled) {
153
- console.error('[capture] triggerCapture was not called after a 5s wait')
154
- }
155
- }, 5000)
156
- `
157
- }]
158
- })
159
- }
160
-
161
- const { meta } = await htmlExtractor.extract(filledBody)
162
- // add @koumoul/v-iframe/content-window.min.js to support state sync with portals, etc.
163
- if (meta['df:sync-state'] === 'true') {
164
- bodyNode.childNodes.push({
165
- nodeName: 'script',
166
- tagName: 'script',
167
- attrs: [
168
- { name: 'type', value: 'text/javascript' },
169
- { name: 'src', value: `https://cdn.jsdelivr.net/npm/@koumoul/v-iframe@${vIframeVersion}/content-window.js` }
170
- ]
171
- })
172
- }
173
- // add iframe-resizer/js/iframeResizer.contentWindow.min.js to support dynamic resizing of the iframe in portals, etc
174
- if (meta['df:overflow'] === 'true') {
175
- bodyNode.childNodes.push({
176
- nodeName: 'script',
177
- tagName: 'script',
178
- attrs: [
179
- { name: 'type', value: 'text/javascript' },
180
- { name: 'src', value: `https://cdn.jsdelivr.net/npm/iframe-resizer@${iframeResizerVersion}/js/iframeResizer.contentWindow.min.js` }
181
- ]
182
- })
183
- }
184
-
185
- output = parse5.serialize(document)
186
-
187
- // proxyRes.headers['content-length'] = output.length
188
- delete proxyRes.headers['content-length']
189
- delete proxyRes.headers['last-modified']
190
- delete proxyRes.headers['max-age']
191
- delete proxyRes.headers.etag
192
- proxyRes.headers['cache-control'] = 'no-cache'
193
- }
194
- res.writeHead(proxyRes.statusCode, proxyRes.headers)
195
- res.end(output)
196
- } catch (err) {
197
- console.error(err)
198
- res.writeHead(500)
199
- res.end(err.message)
200
- }
201
- })
202
- }
203
- }))
204
-
205
- for (const proxyPath of config.app.proxyPaths) {
206
- app.use(proxyPath, createProxyMiddleware({
207
- target: appUrl.origin,
208
- secure: false,
209
- changeOrigin: true,
210
- ws: true
211
- }))
212
- }
213
-
214
- // re-expose a data-fair instance to access datasets, etc.
215
- const dfUrl = new URL(config.dataFair.url)
216
- app.use('/data-fair', createProxyMiddleware({
217
- target: dfUrl.origin,
218
- pathRewrite: { '^/data-fair': dfUrl.pathname },
219
- secure: false,
220
- changeOrigin: true,
221
- selfHandleResponse: true, // so that the onProxyRes takes care of sending the response
222
- onProxyReq (proxyReq, req, res) {
223
- // no gzip so that we can process the content
224
- proxyReq.setHeader('accept-encoding', 'identity')
225
-
226
- // authentication through api key only
227
- proxyReq.setHeader('cookie', '')
228
- if (config.dataFair.apiKey) proxyReq.setHeader('x-apiKey', config.dataFair.apiKey)
229
-
230
- // body was already parsed by body-parser and no longer available as a stream
231
- fixRequestBody(proxyReq, req, res)
232
- },
233
- onProxyRes (proxyRes, req, res) {
234
- if (proxyRes.headers['content-type'] && proxyRes.headers['content-type'].startsWith('application/json')) {
235
- let body = ''
236
- proxyRes.on('data', (data) => { body += data.toString() })
237
- proxyRes.on('end', () => {
238
- const output = body.replace(new RegExp(escapeStringRegexp(config.dataFair.url), 'g'), 'http://localhost:5888/data-fair')
239
- // proxyRes.headers['content-length'] = output.length
240
- delete proxyRes.headers['content-length']
241
- res.writeHead(proxyRes.statusCode, proxyRes.headers)
242
- // make all references to data-fair url point to local proxy
243
- res.end(output)
244
- })
245
- } else {
246
- res.writeHead(proxyRes.statusCode, proxyRes.headers)
247
- proxyRes.pipe(res)
248
- }
249
- }
250
- }))
251
-
252
- // also re-expose the simple-directory instance matching data-fair
253
- if (dfUrl.pathname === '/data-fair') {
254
- app.use('/simple-directory', createProxyMiddleware({
255
- target: dfUrl.origin,
256
- secure: false,
257
- changeOrigin: true
258
- }))
259
- }
260
-
261
- // run the dev-src command from current project
262
- let spawnedDevSrc
263
-
264
- // Run app and return it in a promise
265
- exports.run = async () => {
266
- if (process.env.NODE_ENV === 'development') {
267
- const { Nuxt, Builder } = require('nuxt')
268
- const nuxtConfig = require('../nuxt.config.js')
269
- nuxtConfig.dev = true
270
- const nuxt = new Nuxt(nuxtConfig)
271
- app.use(nuxt.render)
272
- await new Builder(nuxt).build()
273
- } else {
274
- const nuxtConfigInject = require('@koumoul/nuxt-config-inject')
275
- const distOrigin = path.join(__dirname, '..', 'dist')
276
- const distConfig = path.join(__dirname, '..', 'dist-config')
277
- await fs.remove(distConfig)
278
- await fs.copy(distOrigin, distConfig)
279
- nuxtConfigInject.replace(config, [distConfig + '/**/*'])
280
- app.use(express.static(distConfig))
281
- }
282
- server.listen(config.port)
283
- await eventToPromise(server, 'listening')
284
- console.log(chalk.bold.blue('\nDataFair dev server available on ') + chalk.underline.bold.blue(`http://localhost:${config.port}`))
285
-
286
- if (fs.existsSync('package.json')) {
287
- const pJson = fs.readJsonSync('package.json')
288
- if (pJson.scripts && pJson.scripts[config.app.script]) {
289
- console.log(chalk.blue(`running application with "npm run ${config.app.script}"`))
290
- spawnedDevSrc = spawn('npm', ['run', config.app.script], { stdio: 'inherit', shell: true }).on('error', (err) => {
291
- console.error(`failure in spawned "${config.app.script}" command`, err)
292
- })
293
- } else {
294
- console.error(chalk.red(`No script "${config.app.script}" in package.json`))
295
- }
296
- }
297
- // if (process.env.NODE_ENV !== 'development') open('http://localhost:5888')
298
- return server
299
- }
300
-
301
- exports.stop = async () => {
302
- if (spawnedDevSrc) kill(spawnedDevSrc.pid)
303
- if (devServerWS) devServerWS.terminate()
304
- if (dataFairWS) dataFairWS.terminate()
305
- server.close()
306
- await eventToPromise(server, 'close')
307
- await app.get('client').close()
308
- }