@open-xchange/vite-plugin-ox-manifests 0.2.2 → 0.4.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.
package/README.md CHANGED
@@ -25,8 +25,6 @@ return {
25
25
  You can provide the following options to the plugin:
26
26
 
27
27
  * watch `<boolean>` If set to true, it will watch any changes to manifest.json files and will automatically reload the vite-dev-server. Default: `true`
28
- * appsuiteUrl `<string>` If this string is provided, the dev-server will try to fetch manifests from that location and will merge them together with local manifests. Duplicate entries will be removed. Useful for plugin development which require core manifests. Default: `undefined`
29
- * manifestApiPath `<string>` The path where this plugin looks for manifests is `appsuiteUrl + manifestApiPath`. If developing against a common Kubernetes based App Suite deployment, this most like does not have to be changed. Default: `'/api/manifest.json'`
30
28
  * entryPoints `<string> | <glob pattern>` Convenience method to specify additional entry points for the production build. The glob pattern will be resolved and injected into the `build.input` options of vite. Can be specified as a glob-pattern. Default: `undefined`
31
29
  * manifestsAsEntryPoints `<boolean>` If set to true, this will inject every entrypoint that is defined by a manifest.json file into the `build.input` options of vite. Default: `true`
32
30
  * transformAbsolutePaths `<boolean>` If set to true, every absolute path will be transformed into a relative path. This is especially useful, if the production path is not clear at build time. E.g. if you do not know, whether appsuite will be served under `/appsuite`. Default: `true`
package/index.js CHANGED
@@ -3,18 +3,14 @@ import manifestsPlugin from './src/plugins/manifests.js'
3
3
  import relativePathsPlugin from './src/plugins/relative-paths.js'
4
4
  import settingsPlugin from './src/plugins/settings.js'
5
5
  import servePlugin from './src/plugins/serve.js'
6
- import serverManifestPlugin from './src/plugins/server-manifests.js'
7
6
  import gettextPlugin from './src/plugins/gettext.js'
8
7
  import { deepMergeObject } from './src/util.js'
9
- import additionalManifestsPlugin from './src/plugins/additional-manifests.js'
10
8
 
11
9
  /**
12
10
  * Creates a vite-plugin to include manifests in dev and production mode
13
11
  *
14
12
  * @param {object} [options]
15
13
  * @param {boolean} [options.watch=false] - If set to true, this plugin will watch manifest changes and reload the ui
16
- * @param {string} [options.appsuiteUrl] - When used in dev-mode, the dev-server can merge the local manifests with the manifest-files from the appsuiteUrl server.
17
- * @param {Array} [options.additionalManifestUrls] - You can add additional urls which can point to manifest files during development. This parameter will be ignored in production
18
14
  * @param {string} [options.entryPoints] - Convenience method to specify additional entry points for the production build. Can be specified as a glob-pattern.
19
15
  * @param {boolean} [options.manifestsAsEntryPoints=true] - Specifies, that every path in a manifest is used as an entry-point for the production build.
20
16
  * @param {boolean} [options.transformAbsolutePaths=true] - If this is set to true, every path in the html-files is transformed to a relative path. Additionally, every preloaded file will also be loaded relative to the index.html
@@ -23,8 +19,6 @@ import additionalManifestsPlugin from './src/plugins/additional-manifests.js'
23
19
  */
24
20
  export default function ({
25
21
  watch = false,
26
- appsuiteUrl,
27
- additionalManifestUrls,
28
22
  entryPoints,
29
23
  manifestsAsEntryPoints = true,
30
24
  transformAbsolutePaths = true,
@@ -33,8 +27,6 @@ export default function ({
33
27
  } = {}) {
34
28
  const options = {
35
29
  watch,
36
- appsuiteUrl,
37
- additionalManifestUrls,
38
30
  entryPoints,
39
31
  manifestsAsEntryPoints,
40
32
  transformAbsolutePaths,
@@ -47,8 +39,6 @@ export default function ({
47
39
  settingsPlugin(options),
48
40
  relativePathsPlugin(options),
49
41
  servePlugin(options),
50
- serverManifestPlugin(options),
51
- additionalManifestsPlugin(options),
52
42
  gettextPlugin(options),
53
43
  // manifest plugin last
54
44
  manifestsPlugin(options)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-xchange/vite-plugin-ox-manifests",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "description": "A vite plugin to concat and serve ox manifests",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -43,6 +43,9 @@ export default function () {
43
43
  },
44
44
 
45
45
  getManifests () {
46
+ if (resolvedConfig.mode !== 'production') {
47
+ return manifests.map(({ namespace, path }) => ({ namespace, raw: `/@id/${path}.js`, path }))
48
+ }
46
49
  return manifests
47
50
  },
48
51
 
@@ -26,7 +26,7 @@ export default function ({ watch } = {}) {
26
26
  if (!moduleNode) return
27
27
  const hmrTS = moduleNode.lastHMRTimestamp
28
28
  if (!hmrTS) return
29
- manifest.timestamp = hmrTS
29
+ manifest.raw = `/${manifest.path}.js?t=${hmrTS}`
30
30
  })
31
31
  }
32
32
 
@@ -34,13 +34,13 @@ export default function ({ watch } = {}) {
34
34
  const { path } = parseurl(req)
35
35
  if (req.method !== 'GET') return next()
36
36
 
37
- if (path === '/api/manifest.json') {
37
+ if (path === '/api/manifest.json' || path === '/manifests') {
38
38
  const manifests = await this.getManifests()
39
39
  await addTimestamp(manifests)
40
40
  return sendJSON(res, manifests)
41
41
  }
42
42
 
43
- if (path === '/api/deps.json') {
43
+ if (path === '/api/deps.json' || path === '/dependencies') {
44
44
  return sendJSON(res, {})
45
45
  }
46
46
 
@@ -64,7 +64,7 @@ export async function isSettingsFile (entry, resolvedConfig) {
64
64
 
65
65
  export default function ({ autoloadSettings } = {}) {
66
66
  const settingsModules = {}
67
- let resolvedConfig
67
+ let resolvedConfig, moduleGraph
68
68
 
69
69
  return {
70
70
  configResolved (config) {
@@ -95,10 +95,22 @@ export default function ({ autoloadSettings } = {}) {
95
95
  return options
96
96
  },
97
97
 
98
+ configureServer ({ moduleGraph: mg }) {
99
+ moduleGraph = mg
100
+ },
101
+
98
102
  // specific call to collect all manifests
99
103
  getManifests () {
100
104
  return Object.entries(settingsModules).map(
101
- ([path, m]) => ({ ...m, path: basepath(path.substr(resolvedConfig.root.length + 1)) })
105
+ ([path, m]) => {
106
+ const newPath = basepath(path.substr(resolvedConfig.root.length + 1))
107
+ const manifest = { ...m, path: newPath }
108
+ const moduleNode = moduleGraph?.idToModuleMap.get(path)
109
+ if (moduleNode?.lastHMRTimestamp) {
110
+ manifest.raw = `/${manifest.path}.js?t=${moduleNode.lastHMRTimestamp}`
111
+ }
112
+ return manifest
113
+ }
102
114
  )
103
115
  },
104
116
 
@@ -1,18 +0,0 @@
1
- import axios from 'axios'
2
-
3
- export default function ({ additionalManifestUrls = [] } = {}) {
4
- return {
5
- async getManifests () {
6
- const manifestSets = await Promise.all(additionalManifestUrls.map(async url => {
7
- try {
8
- const res = await axios.get(url)
9
- return res.data
10
- } catch (e) {
11
- console.error(`Could not fetch manifest ${url}`, e)
12
- return []
13
- }
14
- }))
15
- return manifestSets.flat(1)
16
- }
17
- }
18
- }
@@ -1,21 +0,0 @@
1
- import axios from 'axios'
2
-
3
- export default function ({ appsuiteUrl } = {}) {
4
- let cache
5
- return {
6
- async getManifests () {
7
- if (!appsuiteUrl) return []
8
-
9
- if (cache) return cache
10
-
11
- try {
12
- const url = new URL('/api/manifest.json', appsuiteUrl)
13
- const res = await axios.get(url.href)
14
- return (cache = res.data)
15
- } catch (e) {
16
- console.error('Could not fetch server manifests', e)
17
- return []
18
- }
19
- }
20
- }
21
- }
@@ -1,104 +0,0 @@
1
- import { describe, it, expect, afterEach, jest } from '@jest/globals'
2
- import { createServer } from 'vite'
3
- import path from 'path'
4
- import vitePluginOxManifests from '../../index'
5
- import axios from 'axios'
6
- import express from 'express'
7
- import { getPort } from '../util'
8
-
9
- const PORT = getPort()
10
- const SERVER_PORT = getPort()
11
-
12
- describe('Server manifest scenario', function () {
13
- let server, expressServer
14
-
15
- afterEach(async function () {
16
- if (server) {
17
- await server.close()
18
- server = null
19
- }
20
- if (expressServer) {
21
- await expressServer.close()
22
- expressServer = null
23
- }
24
- })
25
-
26
- it('works in dev mode', async function () {
27
- server = await createServer({
28
- root: path.dirname(new URL(import.meta.url).pathname),
29
- logLevel: 'silent',
30
- plugins: [vitePluginOxManifests({
31
- appsuiteUrl: `http://localhost:${SERVER_PORT}`
32
- })]
33
- })
34
- await server.listen(PORT)
35
-
36
- const app = express()
37
- expressServer = app.listen(SERVER_PORT)
38
- app.get('/api/manifest.json', (req, res) => {
39
- res.json([{ namespace: 'server' }])
40
- })
41
-
42
- const res = await axios({ baseURL: `http://localhost:${PORT}/api/manifest.json` })
43
- const manifests = res.data
44
-
45
- expect(manifests).toHaveLength(2)
46
- expect(manifests[1].namespace).toEqual('test')
47
- expect(manifests[1].path).toContain('register')
48
- expect(manifests[0].namespace).toEqual('server')
49
- })
50
-
51
- it('only fetches manifests once from server', async function () {
52
- server = await createServer({
53
- root: path.dirname(new URL(import.meta.url).pathname),
54
- logLevel: 'silent',
55
- plugins: [vitePluginOxManifests({
56
- appsuiteUrl: `http://localhost:${SERVER_PORT}`
57
- })]
58
- })
59
- await server.listen(PORT)
60
-
61
- const app = express()
62
- expressServer = app.listen(SERVER_PORT)
63
- const respond = jest.fn((req, res) => {
64
- res.json([{ namespace: 'server' }])
65
- })
66
- app.get('/api/manifest.json', respond)
67
-
68
- expect(respond).not.toBeCalled()
69
-
70
- await axios({ baseURL: `http://localhost:${PORT}/api/manifest.json` })
71
-
72
- expect(respond).toBeCalledTimes(1)
73
-
74
- await axios({ baseURL: `http://localhost:${PORT}/api/manifest.json` })
75
-
76
- expect(respond).toBeCalledTimes(1)
77
- })
78
-
79
- it('overwrites existing manfests from server', async function () {
80
- server = await createServer({
81
- root: path.dirname(new URL(import.meta.url).pathname),
82
- logLevel: 'silent',
83
- plugins: [vitePluginOxManifests({
84
- appsuiteUrl: `http://localhost:${SERVER_PORT}`
85
- })]
86
- })
87
- await server.listen(PORT)
88
-
89
- const app = express()
90
- expressServer = app.listen(SERVER_PORT)
91
- app.get('/api/manifest.json', (req, res) => {
92
- // same as from client, but with additional property
93
- res.json([{ namespace: 'test', path: 'register', other: 'test' }])
94
- })
95
-
96
- const res = await axios({ baseURL: `http://localhost:${PORT}/api/manifest.json` })
97
- const manifests = res.data
98
-
99
- expect(manifests).toHaveLength(1)
100
- expect(manifests[0].namespace).toEqual('test')
101
- expect(manifests[0].path).toEqual('register')
102
- expect(manifests[0].other).toBeUndefined()
103
- })
104
- })
@@ -1,3 +0,0 @@
1
- {
2
- "namespace": "test"
3
- }
@@ -1 +0,0 @@
1
- console.log('Hello world')
@@ -1,64 +0,0 @@
1
- import { describe, it, expect, afterEach } from '@jest/globals'
2
- import { createServer } from 'vite'
3
- import path from 'path'
4
- import vitePluginOxManifests from '../../index'
5
- import { getPort } from '../util'
6
- import axios from 'axios'
7
- import express from 'express'
8
-
9
- const __dirname = path.dirname(new URL(import.meta.url).pathname)
10
- const PORT = getPort()
11
- const MANIFEST_PORT = getPort()
12
- const OTHER_PORT = getPort()
13
-
14
- describe('Additional upstream manifests', function () {
15
- let server, manifestServer, otherServer
16
-
17
- afterEach(async function () {
18
- if (server) {
19
- await server.close()
20
- server = null
21
- }
22
- if (manifestServer) {
23
- await manifestServer.close()
24
- manifestServer = null
25
- }
26
- if (otherServer) {
27
- await otherServer.close()
28
- otherServer = null
29
- }
30
- })
31
-
32
- it('works in dev mode', async function () {
33
- server = await createServer({
34
- root: __dirname,
35
- logLevel: 'silent',
36
- plugins: [vitePluginOxManifests({
37
- appsuiteUrl: `http://localhost:${MANIFEST_PORT}`,
38
- additionalManifestUrls: [`http://localhost:${OTHER_PORT}/path/to/file.json`]
39
- })]
40
- })
41
- await server.listen(PORT)
42
-
43
- // create a manifest server
44
- const app = express()
45
- manifestServer = app.listen(MANIFEST_PORT)
46
- app.get('/api/manifest.json', (req, res) => {
47
- res.json([{ namespace: 'server' }])
48
- })
49
-
50
- // create other server with random endpoint
51
- const app2 = express()
52
- otherServer = app2.listen(OTHER_PORT)
53
- app2.get('/path/to/file.json', (req, res) => {
54
- res.json([{ namespace: 'other' }])
55
- })
56
-
57
- const res = await axios({ baseURL: `http://localhost:${PORT}/api/manifest.json` })
58
- const manifests = res.data
59
- expect(Object.keys(manifests)).toHaveLength(3)
60
- expect(manifests.map(m => m.namespace)).toContain('test')
61
- expect(manifests.map(m => m.namespace)).toContain('server')
62
- expect(manifests.map(m => m.namespace)).toContain('other')
63
- })
64
- })
@@ -1,3 +0,0 @@
1
- {
2
- "namespace": "test"
3
- }
@@ -1 +0,0 @@
1
- console.log('Hello world')