@ossy/platform 1.38.5 → 1.38.7
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/package.json +9 -9
- package/src/PlatformShell.jsx +11 -11
- package/src/runtime.js +9 -3
- package/src/server.js +21 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/platform",
|
|
3
|
-
"version": "1.38.
|
|
3
|
+
"version": "1.38.7",
|
|
4
4
|
"description": "Ossy application server runtime",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
"@aws-sdk/s3-request-presigner": "^3.1057.0",
|
|
39
39
|
"@aws-sdk/util-create-request": "^3.972.26",
|
|
40
40
|
"@aws-sdk/util-format-url": "^3.972.17",
|
|
41
|
-
"@ossy/event-store": "^1.7.
|
|
42
|
-
"@ossy/observability": "^1.7.
|
|
43
|
-
"@ossy/policies": "^1.12.
|
|
44
|
-
"@ossy/router": "^1.39.
|
|
45
|
-
"@ossy/sdk": "^1.39.
|
|
46
|
-
"@ossy/tokens": "^1.12.
|
|
47
|
-
"@ossy/users": "^1.12.
|
|
41
|
+
"@ossy/event-store": "^1.7.7",
|
|
42
|
+
"@ossy/observability": "^1.7.7",
|
|
43
|
+
"@ossy/policies": "^1.12.7",
|
|
44
|
+
"@ossy/router": "^1.39.7",
|
|
45
|
+
"@ossy/sdk": "^1.39.7",
|
|
46
|
+
"@ossy/tokens": "^1.12.7",
|
|
47
|
+
"@ossy/users": "^1.12.7",
|
|
48
48
|
"cookie-parser": "^1.4.7",
|
|
49
49
|
"dotenv": ">=16.0.0 <18.0.0",
|
|
50
50
|
"express": ">=5.0.0 <6.0.0",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"src",
|
|
63
63
|
"Dockerfile"
|
|
64
64
|
],
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "f65df0cd6da864c314c4f424112e05e8e2dec0ff"
|
|
66
66
|
}
|
package/src/PlatformShell.jsx
CHANGED
|
@@ -13,24 +13,24 @@ import { ComponentSlotsProvider, Slot } from '@ossy/design-system'
|
|
|
13
13
|
* to override or fill these slots with layout-specific components — the inner
|
|
14
14
|
* provider shallow-merges on top.
|
|
15
15
|
*
|
|
16
|
-
* Slot regions rendered here:
|
|
17
|
-
* header
|
|
18
|
-
* sidebar
|
|
19
|
-
* toolbar
|
|
20
|
-
* notifications
|
|
21
|
-
* system-messages
|
|
16
|
+
* Slot regions rendered here (namespaced keys from app `export const slots`):
|
|
17
|
+
* shell:header — top bar across full width
|
|
18
|
+
* shell:sidebar — left column, full height
|
|
19
|
+
* shell:toolbar — below header, above content (contextual actions)
|
|
20
|
+
* shell:notifications — floating / bottom corner (toasts, badges)
|
|
21
|
+
* shell:system-messages — banner above content (maintenance, errors)
|
|
22
22
|
*
|
|
23
23
|
* @param {{ slots?: Record<string, import('react').ComponentType | null>, children: import('react').ReactNode }} props
|
|
24
24
|
*/
|
|
25
25
|
export function PlatformShell({ slots = {}, children }) {
|
|
26
26
|
return (
|
|
27
27
|
<ComponentSlotsProvider slots={slots}>
|
|
28
|
-
<Slot name="system-messages" />
|
|
29
|
-
<Slot name="header" />
|
|
30
|
-
<Slot name="sidebar" />
|
|
31
|
-
<Slot name="toolbar" />
|
|
28
|
+
<Slot name="shell:system-messages" />
|
|
29
|
+
<Slot name="shell:header" />
|
|
30
|
+
<Slot name="shell:sidebar" />
|
|
31
|
+
<Slot name="shell:toolbar" />
|
|
32
32
|
{children}
|
|
33
|
-
<Slot name="notifications" />
|
|
33
|
+
<Slot name="shell:notifications" />
|
|
34
34
|
</ComponentSlotsProvider>
|
|
35
35
|
)
|
|
36
36
|
}
|
package/src/runtime.js
CHANGED
|
@@ -5,6 +5,7 @@ import cookieParser from 'cookie-parser'
|
|
|
5
5
|
import morgan from 'morgan'
|
|
6
6
|
import { Router as OssyRouter } from '@ossy/router'
|
|
7
7
|
import { loadManifest, resolveEntryUrl } from './server.js'
|
|
8
|
+
import { buildManifestSummary } from '@ossy/app/manifest/build-manifest-summary'
|
|
8
9
|
import { ProxyInternal } from './proxy-internal.js'
|
|
9
10
|
import { loadSite, invalidateSite } from './site-loader.js'
|
|
10
11
|
import { createLogger } from '@ossy/observability'
|
|
@@ -48,7 +49,7 @@ function buildSiteContext (manifest, buildDir) {
|
|
|
48
49
|
return promise
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
return { pageRouter, apiRouter, manifest, loadEntry }
|
|
52
|
+
return { pageRouter, apiRouter, manifest, manifestSummary: buildManifestSummary(manifest), loadEntry }
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
async function getSiteContext (domain) {
|
|
@@ -127,7 +128,7 @@ export async function startRuntime ({ port } = {}) {
|
|
|
127
128
|
return
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
const { pageRouter, apiRouter, manifest, loadEntry } = context
|
|
131
|
+
const { pageRouter, apiRouter, manifest, manifestSummary, loadEntry } = context
|
|
131
132
|
|
|
132
133
|
try {
|
|
133
134
|
const apiRoute = apiRouter.getPageByUrl(requestUrl)
|
|
@@ -172,9 +173,14 @@ export async function startRuntime ({ port } = {}) {
|
|
|
172
173
|
theme: req.userAppSettings?.theme || cloneSerializable(config?.theme),
|
|
173
174
|
themes: cloneSerializable(config?.themes),
|
|
174
175
|
resourceTemplates: cloneSerializable(manifest.resourceTemplates),
|
|
176
|
+
manifestSummary: cloneSerializable(manifestSummary),
|
|
175
177
|
url: requestUrl,
|
|
176
178
|
isAuthenticated: !!req.isAuthenticated,
|
|
177
|
-
pages: manifest.pages.map((page) => ({
|
|
179
|
+
pages: manifest.pages.map((page) => ({
|
|
180
|
+
id: page.id,
|
|
181
|
+
path: page.path,
|
|
182
|
+
...(page.package ? { package: page.package } : {}),
|
|
183
|
+
})),
|
|
178
184
|
pageId: pageRoute.id,
|
|
179
185
|
}
|
|
180
186
|
const html = await mod.render(props)
|
package/src/server.js
CHANGED
|
@@ -10,6 +10,8 @@ import { SDK } from '@ossy/sdk'
|
|
|
10
10
|
import { AggregateRebuild } from '@ossy/event-store'
|
|
11
11
|
import { TaskService } from './tasks/task-service.js'
|
|
12
12
|
import { ChangeStream } from './tasks/change-stream.js'
|
|
13
|
+
import { CONTENT_SLOT_NAME } from '@ossy/app/runtime/resolve-shell-slots'
|
|
14
|
+
import { buildManifestSummary } from '@ossy/app/manifest/build-manifest-summary'
|
|
13
15
|
import { registerResourceTemplate } from './resources/resource-template.registry.js'
|
|
14
16
|
import { IntegrationService } from './integration.service.js'
|
|
15
17
|
import { ActionService } from './actions/action.service.js'
|
|
@@ -55,12 +57,12 @@ export function loadManifest (buildDir) {
|
|
|
55
57
|
const apis = entries.filter((e) => e.type === 'api' && validRoutable(e))
|
|
56
58
|
const tasks = entries.filter((e) => e.type === 'task')
|
|
57
59
|
const components = Array.isArray(manifest.components) ? manifest.components : []
|
|
58
|
-
const slots = Array.isArray(manifest.slots) ? manifest.slots : []
|
|
59
60
|
const resourceTemplates = Array.isArray(manifest.resourceTemplates) ? manifest.resourceTemplates : []
|
|
60
61
|
const aggregates = Array.isArray(manifest.aggregates) ? manifest.aggregates : []
|
|
61
62
|
const integrations = Array.isArray(manifest.integrations) ? manifest.integrations : []
|
|
62
63
|
const startups = Array.isArray(manifest.startups) ? manifest.startups : []
|
|
63
64
|
const actions = Array.isArray(manifest.actions) ? manifest.actions : []
|
|
65
|
+
const emails = Array.isArray(manifest.emails) ? manifest.emails : []
|
|
64
66
|
const layouts = Array.isArray(manifest.layouts) ? manifest.layouts : []
|
|
65
67
|
for (const e of entries) { if ((e.type === 'page' || e.type === 'api') && !validRoutable(e)) {
|
|
66
68
|
log.warn(`Skipping ${e.type} "${e.id}" — manifest entry has no path.`)
|
|
@@ -72,12 +74,12 @@ export function loadManifest (buildDir) {
|
|
|
72
74
|
apis,
|
|
73
75
|
tasks,
|
|
74
76
|
components,
|
|
75
|
-
slots,
|
|
76
77
|
resourceTemplates,
|
|
77
78
|
aggregates,
|
|
78
79
|
integrations,
|
|
79
80
|
startups,
|
|
80
81
|
actions,
|
|
82
|
+
emails,
|
|
81
83
|
layouts,
|
|
82
84
|
config: manifest.config || {},
|
|
83
85
|
}
|
|
@@ -108,6 +110,7 @@ export async function startServer (options = {}) {
|
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
const manifest = loadManifest(buildDir)
|
|
113
|
+
const manifestSummary = buildManifestSummary(manifest)
|
|
111
114
|
const config = manifest.config
|
|
112
115
|
const supportedLanguages = Array.isArray(config.supportedLanguages) ? config.supportedLanguages : []
|
|
113
116
|
const defaultLanguage = config.defaultLanguage
|
|
@@ -201,25 +204,12 @@ export async function startServer (options = {}) {
|
|
|
201
204
|
}
|
|
202
205
|
}
|
|
203
206
|
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
// Layout-level ComponentSlotsProviders can merge on top to override slots
|
|
211
|
-
// for their subtree (e.g. layout fills `header` with brand-specific chrome).
|
|
212
|
-
/** @type {Array<{ id: string, entry: string }>} */
|
|
213
|
-
const slotComponentEntries = []
|
|
214
|
-
for (const slotEntry of manifest.slots ?? []) {
|
|
215
|
-
try {
|
|
216
|
-
// Verify the chunk is importable at startup so we fail fast on bad builds.
|
|
217
|
-
await import(resolveEntryUrl(slotEntry.entry, buildDir))
|
|
218
|
-
slotComponentEntries.push({ id: slotEntry.slot, entry: slotEntry.entry })
|
|
219
|
-
} catch (err) {
|
|
220
|
-
log.warn(`Failed to load slot component "${slotEntry.slot}"`, undefined, err)
|
|
221
|
-
}
|
|
222
|
-
}
|
|
207
|
+
// App-controlled shell slots: `export const slots` in `*.layout.jsx` is recorded
|
|
208
|
+
// on `manifest.layouts[0].slots` at build time and resolved at render in page-runtime.
|
|
209
|
+
const layoutSlots =
|
|
210
|
+
layoutEntry && typeof layoutEntry.slots === 'object' && !Array.isArray(layoutEntry.slots)
|
|
211
|
+
? layoutEntry.slots
|
|
212
|
+
: {}
|
|
223
213
|
|
|
224
214
|
// Register the SDK so all tasks receive it as `sdk`.
|
|
225
215
|
// Priority: explicit options.sdk → SDK.of() from env vars → null (direct-DB fallback in tasks).
|
|
@@ -332,19 +322,25 @@ export async function startServer (options = {}) {
|
|
|
332
322
|
}
|
|
333
323
|
const Layout = appLayout?.component ?? null
|
|
334
324
|
const layoutEntry = appLayout?.entry ?? null
|
|
325
|
+
// Page component → `shell:content` is resolved in page-runtime (SSR + hydrate).
|
|
335
326
|
const props = {
|
|
336
327
|
...config,
|
|
337
328
|
...(req.userAppSettings || {}),
|
|
338
329
|
theme: req.userAppSettings?.theme || cloneSerializable(config?.theme),
|
|
339
330
|
themes: cloneSerializable(config?.themes),
|
|
340
331
|
resourceTemplates: cloneSerializable(manifest.resourceTemplates),
|
|
332
|
+
manifestSummary: cloneSerializable(manifestSummary),
|
|
341
333
|
url: requestUrl,
|
|
342
334
|
isAuthenticated: !!req.isAuthenticated,
|
|
343
|
-
pages: manifest.pages.map((page) => ({
|
|
335
|
+
pages: manifest.pages.map((page) => ({
|
|
336
|
+
id: page.id,
|
|
337
|
+
path: page.path,
|
|
338
|
+
...(page.package ? { package: page.package } : {}),
|
|
339
|
+
})),
|
|
344
340
|
pageId: pageRoute.id,
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
341
|
+
componentEntries: manifest.components,
|
|
342
|
+
layoutSlots,
|
|
343
|
+
contentSlotName: CONTENT_SLOT_NAME,
|
|
348
344
|
Layout,
|
|
349
345
|
layoutEntry,
|
|
350
346
|
}
|