@ossy/app 1.4.1 → 1.6.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/cli/render-page.task.js +35 -0
- package/cli/server.js +34 -41
- package/package.json +10 -10
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { cloneElement } from 'react'
|
|
2
|
+
import { prerenderToNodeStream } from 'react-dom/static'
|
|
3
|
+
|
|
4
|
+
/** Strips non-JSON content (e.g. React elements on `pages`) for the bootstrap script. */
|
|
5
|
+
export function appConfigForBootstrap (appConfig) {
|
|
6
|
+
if (!appConfig || typeof appConfig !== 'object') return appConfig
|
|
7
|
+
const pages = Array.isArray(appConfig.pages)
|
|
8
|
+
? appConfig.pages.map(({ id, path }) => ({ id, path }))
|
|
9
|
+
: appConfig.pages
|
|
10
|
+
return { ...appConfig, pages }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const BuildPage = {
|
|
14
|
+
async handle ({ route, appConfig, isDevReloadEnabled }) {
|
|
15
|
+
const rootElement = cloneElement(route.element, appConfig)
|
|
16
|
+
const devReloadScript = isDevReloadEnabled
|
|
17
|
+
? `(function(){try{var es=new EventSource('/__ossy_reload');es.addEventListener('reload',function(){location.reload();});}catch(e){}})();`
|
|
18
|
+
: ``
|
|
19
|
+
|
|
20
|
+
const hydrateUrl = `/static/hydrate-${route.id}.js`
|
|
21
|
+
const { prelude } = await prerenderToNodeStream(rootElement, {
|
|
22
|
+
bootstrapScriptContent: `window.__INITIAL_APP_CONFIG__ = ${JSON.stringify(appConfigForBootstrap(appConfig))};${devReloadScript}`,
|
|
23
|
+
bootstrapModules: [hydrateUrl],
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
let data = ''
|
|
28
|
+
prelude.on('data', (chunk) => {
|
|
29
|
+
data += chunk
|
|
30
|
+
})
|
|
31
|
+
prelude.on('end', () => resolve(data))
|
|
32
|
+
prelude.on('error', reject)
|
|
33
|
+
})
|
|
34
|
+
},
|
|
35
|
+
}
|
package/cli/server.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import url from 'url'
|
|
3
|
-
import React, { cloneElement } from 'react';
|
|
4
3
|
import express from 'express'
|
|
5
4
|
import morgan from 'morgan'
|
|
6
5
|
import { Router as OssyRouter } from '@ossy/router'
|
|
7
|
-
import { prerenderToNodeStream } from 'react-dom/static'
|
|
8
6
|
import { ProxyInternal } from './proxy-internal.js'
|
|
9
7
|
import cookieParser from 'cookie-parser'
|
|
8
|
+
import { BuildPage } from './render-page.task.js'
|
|
10
9
|
|
|
11
10
|
import pages from './.ossy/pages.bundle.js'
|
|
12
11
|
import ApiRoutes from './.ossy/api.bundle.js'
|
|
@@ -112,36 +111,54 @@ const Router = OssyRouter.of({
|
|
|
112
111
|
pages: [...apiRouteList, ...pageList]
|
|
113
112
|
})
|
|
114
113
|
|
|
115
|
-
|
|
116
|
-
const pathname = req.originalUrl
|
|
117
|
-
|
|
118
|
-
const route = Router.getPageByUrl(pathname)
|
|
119
|
-
|
|
120
|
-
if (route && typeof route.handle === 'function') {
|
|
121
|
-
console.log(`[@ossy/app][server] Handling API route: ${pathname}`)
|
|
122
|
-
route.handle(req, res)
|
|
123
|
-
return
|
|
124
|
-
}
|
|
125
|
-
|
|
114
|
+
function resolveAppConfig ({ req, buildTimeConfig, activeRouteId }) {
|
|
126
115
|
const userAppSettings = req.userAppSettings || {}
|
|
127
|
-
|
|
128
|
-
|
|
116
|
+
const pages = pageList.map((page) => {
|
|
117
|
+
const entry = {
|
|
118
|
+
id: page?.id,
|
|
119
|
+
path: page?.path,
|
|
120
|
+
}
|
|
121
|
+
if (activeRouteId != null && page?.id === activeRouteId) {
|
|
122
|
+
entry.element = page?.element
|
|
123
|
+
}
|
|
124
|
+
return entry
|
|
125
|
+
})
|
|
126
|
+
return {
|
|
129
127
|
...buildTimeConfig,
|
|
130
128
|
url: req.originalUrl,
|
|
131
129
|
theme: userAppSettings.theme || buildTimeConfig.theme || 'light',
|
|
132
130
|
isAuthenticated: req.isAuthenticated || false,
|
|
133
131
|
workspaceId: userAppSettings.workspaceId || buildTimeConfig.workspaceId,
|
|
134
132
|
apiUrl: buildTimeConfig.apiUrl,
|
|
133
|
+
pages,
|
|
135
134
|
/** Primary app shell sidebar: icon rail when true (persisted in `x-ossy-user-settings`). */
|
|
136
135
|
sidebarPrimaryCollapsed: userAppSettings.sidebarPrimaryCollapsed === true,
|
|
137
136
|
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
app.all('*all', (req, res) => {
|
|
140
|
+
const pathname = req.originalUrl
|
|
141
|
+
|
|
142
|
+
const route = Router.getPageByUrl(pathname)
|
|
143
|
+
|
|
144
|
+
if (route && typeof route.handle === 'function') {
|
|
145
|
+
console.log(`[@ossy/app][server] Handling API route: ${pathname}`)
|
|
146
|
+
route.handle(req, res)
|
|
147
|
+
return
|
|
148
|
+
}
|
|
138
149
|
|
|
139
150
|
if (!route?.element) {
|
|
140
151
|
res.status(404).send('Not found')
|
|
141
152
|
return
|
|
142
153
|
}
|
|
143
154
|
|
|
144
|
-
|
|
155
|
+
const appConfig = resolveAppConfig({
|
|
156
|
+
req,
|
|
157
|
+
buildTimeConfig,
|
|
158
|
+
activeRouteId: route.id,
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
BuildPage.handle({ route, appConfig, isDevReloadEnabled })
|
|
145
162
|
.then(html => { res.send(html) })
|
|
146
163
|
.catch(err => { res.send(err) })
|
|
147
164
|
|
|
@@ -149,28 +166,4 @@ app.all('*all', (req, res) => {
|
|
|
149
166
|
|
|
150
167
|
app.listen(port, () => {
|
|
151
168
|
console.log(`[@ossy/app][server] Running on http://localhost:${port}`);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
async function prerenderHtmlDocument (rootElement, config, pageId) {
|
|
155
|
-
|
|
156
|
-
const devReloadScript = isDevReloadEnabled
|
|
157
|
-
? `(function(){try{var es=new EventSource('/__ossy_reload');es.addEventListener('reload',function(){location.reload();});}catch(e){}})();`
|
|
158
|
-
: ``
|
|
159
|
-
|
|
160
|
-
const hydrateUrl = `/static/hydrate-${pageId}.js`
|
|
161
|
-
|
|
162
|
-
const { prelude } = await prerenderToNodeStream(rootElement, {
|
|
163
|
-
bootstrapScriptContent: `window.__INITIAL_APP_CONFIG__ = ${JSON.stringify(config)};${devReloadScript}`,
|
|
164
|
-
bootstrapModules: [hydrateUrl]
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
return new Promise((resolve, reject) => {
|
|
168
|
-
let data = '';
|
|
169
|
-
prelude.on('data', chunk => {
|
|
170
|
-
data += chunk;
|
|
171
|
-
});
|
|
172
|
-
prelude.on('end', () => resolve(data));
|
|
173
|
-
prelude.on('error', reject);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
}
|
|
169
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"@babel/eslint-parser": "^7.15.8",
|
|
28
28
|
"@babel/preset-react": "^7.26.3",
|
|
29
29
|
"@babel/register": "^7.25.9",
|
|
30
|
-
"@ossy/connected-components": "^1.
|
|
31
|
-
"@ossy/design-system": "^1.
|
|
32
|
-
"@ossy/pages": "^1.
|
|
33
|
-
"@ossy/router": "^1.
|
|
34
|
-
"@ossy/router-react": "^1.
|
|
35
|
-
"@ossy/sdk": "^1.
|
|
36
|
-
"@ossy/sdk-react": "^1.
|
|
37
|
-
"@ossy/themes": "^1.
|
|
30
|
+
"@ossy/connected-components": "^1.6.0",
|
|
31
|
+
"@ossy/design-system": "^1.6.0",
|
|
32
|
+
"@ossy/pages": "^1.6.0",
|
|
33
|
+
"@ossy/router": "^1.6.0",
|
|
34
|
+
"@ossy/router-react": "^1.6.0",
|
|
35
|
+
"@ossy/sdk": "^1.6.0",
|
|
36
|
+
"@ossy/sdk-react": "^1.6.0",
|
|
37
|
+
"@ossy/themes": "^1.6.0",
|
|
38
38
|
"@rollup/plugin-alias": "^6.0.0",
|
|
39
39
|
"@rollup/plugin-babel": "6.1.0",
|
|
40
40
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"README.md",
|
|
68
68
|
"tsconfig.json"
|
|
69
69
|
],
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "a1c29650f72ec23bd397d3c9e1c42387461acf8e"
|
|
71
71
|
}
|