@ossy/app 0.15.13 → 1.0.1

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/dev.js CHANGED
@@ -7,20 +7,20 @@ import {
7
7
  generatePagesModule,
8
8
  discoverModulePageFiles,
9
9
  resolveApiSource,
10
- ossyCleanBuildDirPlugin,
11
- ensureOssyGeneratedDir,
10
+ resetOssyBuildDir,
11
+ createOssyRollupPlugins,
12
+ writePageHydrateStubs,
13
+ buildClientHydrateInput,
14
+ clientHydrateIdForPage,
12
15
  ossyGeneratedDir,
13
16
  OSSY_GEN_PAGES_BASENAME,
14
17
  OSSY_GEN_API_BASENAME,
15
- resolvePageShellSource,
18
+ writeResourceTemplatesBarrelIfPresent,
19
+ resourceTemplatesDir,
20
+ OSSY_RESOURCE_TEMPLATES_OUT,
21
+ ossyServerExternal,
16
22
  } from './build.js';
17
23
  import { watch } from 'rollup';
18
- import babel from '@rollup/plugin-babel';
19
- import { nodeResolve as resolveDependencies } from '@rollup/plugin-node-resolve'
20
- import resolveCommonJsDependencies from '@rollup/plugin-commonjs'
21
- import json from "@rollup/plugin-json"
22
- import copy from 'rollup-plugin-copy';
23
- import replace from '@rollup/plugin-replace';
24
24
  import arg from 'arg'
25
25
  import { spawn } from 'node:child_process'
26
26
  // import inject from '@rollup/plugin-inject'
@@ -28,80 +28,55 @@ import { spawn } from 'node:child_process'
28
28
  export const dev = async (cliArgs) => {
29
29
  console.log('[@ossy/app][dev] Starting...')
30
30
 
31
- const options = arg({
32
- '--pages': String,
33
- '--p': '--pages',
34
-
35
- '--destination': String,
36
- '--d': '--destination',
37
-
31
+ const options = arg({
38
32
  '--config': String,
39
33
  '-c': '--config',
40
-
41
- '--api-source': String,
42
34
  }, { argv: cliArgs, permissive: true })
43
35
 
44
36
 
45
37
  const scriptDir = path.dirname(url.fileURLToPath(import.meta.url))
46
- const cwd = process.cwd()
47
- const pagesOpt = options['--pages'] || 'src'
48
- const buildPath = path.resolve(options['--destination'] || 'build')
49
- ensureOssyGeneratedDir(buildPath)
50
- const srcDir = path.resolve(pagesOpt)
38
+ const buildPath = path.resolve('build')
39
+ const srcDir = path.resolve('src')
51
40
  const configPath = path.resolve(options['--config'] || 'src/config.js');
52
41
  const pageFiles = discoverPageFiles(srcDir)
53
- const modulePageFiles = await discoverModulePageFiles({ cwd, configPath })
54
- const pagesJsxPath = path.resolve('src/pages.jsx')
55
- const hasPagesJsx = fs.existsSync(pagesJsxPath)
42
+ const modulePageFiles = await discoverModulePageFiles({ configPath })
56
43
 
57
- let effectivePagesSource
58
- let isPageFiles = false
59
- if (pageFiles.length > 0 || modulePageFiles.length > 0) {
60
- const pagesGeneratedPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
61
- fs.writeFileSync(
62
- pagesGeneratedPath,
63
- generatePagesModule([...pageFiles, ...modulePageFiles], cwd, pagesOpt, pagesGeneratedPath)
64
- )
65
- effectivePagesSource = pagesGeneratedPath
66
- isPageFiles = true
67
- } else if (hasPagesJsx) {
68
- effectivePagesSource = pagesJsxPath
69
- } else {
70
- throw new Error(`[@ossy/app][dev] No pages found. Create *.page.jsx files in src/, or src/pages.jsx`);
71
- }
44
+ resetOssyBuildDir(buildPath)
45
+
46
+ writeResourceTemplatesBarrelIfPresent({ cwd: process.cwd(), log: true })
47
+
48
+ const allPageFiles = [...pageFiles, ...modulePageFiles]
49
+ const pagesGeneratedPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
50
+ fs.writeFileSync(
51
+ pagesGeneratedPath,
52
+ generatePagesModule(allPageFiles, srcDir, pagesGeneratedPath)
53
+ )
54
+ const effectivePagesSource = pagesGeneratedPath
55
+ const ossyDir = ossyGeneratedDir(buildPath)
56
+ writePageHydrateStubs(allPageFiles, srcDir, ossyDir)
57
+ const clientHydrateInput = buildClientHydrateInput(allPageFiles, srcDir, ossyDir)
72
58
 
73
59
  const {
74
60
  apiSourcePath: resolvedApi,
75
61
  apiOverviewFiles,
76
62
  } = resolveApiSource({
77
- cwd,
78
- pagesOpt,
79
- scriptDir,
80
- explicitApiSource: options['--api-source'],
63
+ srcDir,
81
64
  buildPath,
82
65
  })
83
66
  let apiSourcePath = resolvedApi
84
67
  let middlewareSourcePath = path.resolve(options['--middleware-source'] || 'src/middleware.js');
85
68
  const publicDir = path.resolve('public')
86
69
 
87
- const inputClient = path.resolve(scriptDir, 'client.js')
88
70
  const inputServer = path.resolve(scriptDir, 'server.js')
89
71
 
90
- const inputFiles = [inputClient, inputServer]
91
-
92
72
  printBuildOverview({
93
73
  pagesSourcePath: effectivePagesSource,
94
74
  apiSourcePath,
95
75
  apiOverviewFiles,
96
76
  configPath,
97
- isPageFiles,
98
- pageFiles: isPageFiles ? [...pageFiles, ...modulePageFiles] : [],
77
+ pageFiles,
99
78
  });
100
79
 
101
- if (!fs.existsSync(apiSourcePath)) {
102
- apiSourcePath = path.resolve(scriptDir, 'api.js')
103
- }
104
-
105
80
  if (!fs.existsSync(middlewareSourcePath)) {
106
81
  middlewareSourcePath = path.resolve(scriptDir, 'middleware.js')
107
82
  }
@@ -110,80 +85,59 @@ export const dev = async (cliArgs) => {
110
85
  ? configPath
111
86
  : path.resolve(scriptDir, 'default-config.js')
112
87
 
113
- const pageShellSourcePath = resolvePageShellSource(cwd, scriptDir)
88
+ const sharedPluginOpts = {
89
+ pagesGeneratedPath: effectivePagesSource,
90
+ apiSourcePath,
91
+ middlewareSourcePath,
92
+ configSourcePath,
93
+ nodeEnv: 'development',
94
+ buildPath,
95
+ }
96
+
97
+ const serverPlugins = createOssyRollupPlugins({
98
+ ...sharedPluginOpts,
99
+ nodeExternals: true,
100
+ preferBuiltins: true,
101
+ copyPublicFrom: publicDir,
102
+ })
114
103
 
115
- const inputOptions = {
116
- input: inputFiles,
117
- plugins: [
118
- ossyCleanBuildDirPlugin(buildPath),
119
- // inject({ 'React': 'react' }),
120
- replace({
121
- preventAssignment: true,
122
- delimiters: ['%%', '%%'],
123
- '@ossy/app/source-file': path.resolve(scriptDir, 'default-app.jsx'),
124
- }),
125
- replace({
126
- preventAssignment: true,
127
- delimiters: ['%%', '%%'],
128
- '@ossy/pages/source-file': effectivePagesSource,
129
- }),
130
- replace({
131
- preventAssignment: true,
132
- delimiters: ['%%', '%%'],
133
- '@ossy/api/source-file': apiSourcePath,
134
- }),
135
- replace({
136
- preventAssignment: true,
137
- delimiters: ['%%', '%%'],
138
- '@ossy/middleware/source-file': middlewareSourcePath,
139
- }),
140
- replace({
141
- preventAssignment: true,
142
- delimiters: ['%%', '%%'],
143
- '@ossy/config/source-file': configSourcePath,
144
- }),
145
- replace({
146
- preventAssignment: true,
147
- delimiters: ['%%', '%%'],
148
- '@ossy/page-shell/source-file': pageShellSourcePath,
149
- }),
150
- replace({
151
- preventAssignment: true,
152
- 'process.env.NODE_ENV': JSON.stringify('development')
153
- }),
154
- json(),
155
- // removeOwnPeerDependencies(),
156
- resolveCommonJsDependencies(),
157
- resolveDependencies({ preferBuiltins: true }),
158
- babel({
159
- babelHelpers: 'bundled',
160
- // exclude: ['**/node_modules/**/*'],
161
- presets: ['@babel/preset-env', '@babel/preset-react']
162
- }),
163
- // preserveDirectives(),
164
- // minifyJS(),
165
- copy({
166
- targets: [
167
- fs.existsSync(publicDir)
168
- ? { src: `${publicDir}/**/*`, dest: 'build/public' }
169
- : undefined,
170
- ].filter(x => !!x)
171
- })
172
- ],
173
- };
104
+ const clientPlugins = createOssyRollupPlugins({
105
+ ...sharedPluginOpts,
106
+ nodeExternals: false,
107
+ preferBuiltins: false,
108
+ })
174
109
 
175
- const outputOptions = {
176
- dir: 'build',
177
- // preserveModules: true,
178
- entryFileNames: ({ name }) => {
179
- const serverFileNames = ['server', 'api', 'middleware']
180
- if (serverFileNames.includes(name)) return '[name].js'
181
- if (name === 'client') return 'public/static/main.js'
182
- if (name === 'config') return 'public/static/[name].js'
110
+ const serverOutput = {
111
+ dir: buildPath,
112
+ format: 'esm',
113
+ preserveModules: true,
114
+ preserveModulesRoot: path.dirname(inputServer),
115
+ entryFileNames ({ name }) {
116
+ return name === 'server' ? 'server.js' : '[name].js'
117
+ },
118
+ assetFileNames: '[name][extname]',
119
+ }
120
+
121
+ const clientOutput = {
122
+ dir: buildPath,
123
+ format: 'esm',
124
+ entryFileNames ({ name }) {
125
+ if (name.startsWith('hydrate__')) {
126
+ const pageId = name.slice('hydrate__'.length)
127
+ return `public/static/hydrate-${pageId}.js`
128
+ }
183
129
  return 'public/static/[name].js'
184
130
  },
185
131
  chunkFileNames: 'public/static/[name]-[hash].js',
186
- format: 'esm',
132
+ }
133
+
134
+ let restartTimer = null
135
+ const scheduleRestart = () => {
136
+ clearTimeout(restartTimer)
137
+ restartTimer = setTimeout(async () => {
138
+ await triggerReload()
139
+ restartServer()
140
+ }, 100)
187
141
  }
188
142
 
189
143
  let serverProcess = null
@@ -218,11 +172,24 @@ export const dev = async (cliArgs) => {
218
172
  }
219
173
  }
220
174
 
221
- const watcher = watch({
222
- ...inputOptions,
223
- output: outputOptions,
224
- watch: { clearScreen: false },
225
- })
175
+ const watchConfigs = [
176
+ {
177
+ input: { server: inputServer },
178
+ output: serverOutput,
179
+ plugins: serverPlugins,
180
+ external: ossyServerExternal,
181
+ watch: { clearScreen: false },
182
+ },
183
+ ]
184
+ if (Object.keys(clientHydrateInput).length > 0) {
185
+ watchConfigs.push({
186
+ input: clientHydrateInput,
187
+ output: clientOutput,
188
+ plugins: clientPlugins,
189
+ watch: { clearScreen: false },
190
+ })
191
+ }
192
+ const watcher = watch(watchConfigs)
226
193
 
227
194
  watcher.on('event', async (event) => {
228
195
  if (event.code === 'BUNDLE_START') {
@@ -235,18 +202,14 @@ export const dev = async (cliArgs) => {
235
202
  console.log(`[@ossy/app][dev] Built in ${event.duration}ms`)
236
203
  }
237
204
  if (event.code === 'END') {
238
- await triggerReload()
239
- restartServer()
205
+ scheduleRestart()
240
206
  }
241
207
  })
242
208
 
243
209
  const regenApiBundle = () => {
244
210
  if (options['--api-source']) return
245
211
  resolveApiSource({
246
- cwd,
247
- pagesOpt,
248
- scriptDir,
249
- explicitApiSource: undefined,
212
+ srcDir,
250
213
  buildPath,
251
214
  })
252
215
  const gen = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_API_BASENAME)
@@ -258,18 +221,28 @@ export const dev = async (cliArgs) => {
258
221
  fs.watch(srcDir, { recursive: true }, (eventType, filename) => {
259
222
  if (!filename) return
260
223
  if (/\.page\.(jsx?|tsx?)$/.test(filename)) {
261
- if (!isPageFiles) return
262
- const files = discoverPageFiles(srcDir)
263
- if (files.length > 0) {
264
- const pagesGeneratedPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
265
- fs.writeFileSync(
266
- pagesGeneratedPath,
267
- generatePagesModule(files, cwd, pagesOpt, pagesGeneratedPath)
268
- )
224
+ const combined = [...discoverPageFiles(srcDir), ...modulePageFiles]
225
+ const regenPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
226
+ fs.writeFileSync(regenPath, generatePagesModule(combined, srcDir, regenPath))
227
+ writePageHydrateStubs(combined, srcDir, ossyDir)
228
+ if (typeof watcher?.invalidate === 'function') {
229
+ watcher.invalidate(regenPath)
230
+ for (const f of combined) {
231
+ const hid = clientHydrateIdForPage(f, srcDir)
232
+ watcher.invalidate(path.join(ossyDir, `hydrate-${hid}.jsx`))
233
+ }
269
234
  }
270
235
  }
271
- if (/\.api\.(mjs|cjs|js)$/.test(filename) || /(^|\/)api\.js$/.test(filename.replace(/\\/g, '/'))) {
236
+ if (/\.api\.(mjs|cjs|js)$/.test(filename)) {
272
237
  regenApiBundle()
273
238
  }
239
+ const norm = filename.replace(/\\/g, '/')
240
+ if (/\.resource\.js$/.test(norm) && norm.includes('resource-templates/')) {
241
+ writeResourceTemplatesBarrelIfPresent({ cwd: process.cwd(), log: true })
242
+ const rtOut = path.join(resourceTemplatesDir(process.cwd()), OSSY_RESOURCE_TEMPLATES_OUT)
243
+ if (fs.existsSync(rtOut) && typeof watcher?.invalidate === 'function') {
244
+ watcher.invalidate(rtOut)
245
+ }
246
+ }
274
247
  })
275
248
  };
package/cli/server.js CHANGED
@@ -1,20 +1,24 @@
1
1
  import path from 'path';
2
2
  import url from 'url'
3
- import React, { createElement } from 'react';
3
+ import React, { cloneElement } from 'react';
4
4
  import express from 'express'
5
5
  import morgan from 'morgan'
6
- import { Router } from '@ossy/router'
6
+ import { Router as OssyRouter } from '@ossy/router'
7
7
  import { prerenderToNodeStream } from 'react-dom/static'
8
8
  import { ProxyInternal } from './proxy-internal.js'
9
9
  import cookieParser from 'cookie-parser'
10
10
 
11
- import App from '%%@ossy/app/source-file%%'
11
+ import pages from '%%@ossy/pages/source-file%%'
12
12
  import ApiRoutes from '%%@ossy/api/source-file%%'
13
13
  import Middleware from '%%@ossy/middleware/source-file%%'
14
14
  import configModule from '%%@ossy/config/source-file%%'
15
15
 
16
16
  const buildTimeConfig = configModule?.default ?? configModule ?? {}
17
17
 
18
+ /** `api.generated.js` is always present; default may still be empty. */
19
+ const apiRouteList = ApiRoutes ?? []
20
+ const pageList = pages ?? []
21
+
18
22
  const app = express();
19
23
 
20
24
  const currentDir = path.dirname(url.fileURLToPath(import.meta.url))
@@ -104,16 +108,18 @@ const middleware = [
104
108
 
105
109
  app.use(middleware)
106
110
 
107
- const ApiRouter = Router.of({ pages: ApiRoutes || [] })
111
+ const Router = OssyRouter.of({
112
+ pages: [...apiRouteList, ...pageList]
113
+ })
108
114
 
109
115
  app.all('*all', (req, res) => {
110
116
  const pathname = req.originalUrl
111
117
 
112
- const apiRoute = ApiRouter.getPageByUrl(pathname)
118
+ const route = Router.getPageByUrl(pathname)
113
119
 
114
- if (apiRoute) {
120
+ if (route && typeof route.handle === 'function') {
115
121
  console.log(`[@ossy/app][server] Handling API route: ${pathname}`)
116
- apiRoute.handle(req, res)
122
+ route.handle(req, res)
117
123
  return
118
124
  }
119
125
 
@@ -130,25 +136,32 @@ app.all('*all', (req, res) => {
130
136
  sidebarPrimaryCollapsed: userAppSettings.sidebarPrimaryCollapsed === true,
131
137
  }
132
138
 
133
- renderToString(App, appConfig)
139
+ if (!route?.element) {
140
+ res.status(404).send('Not found')
141
+ return
142
+ }
143
+
144
+ prerenderHtmlDocument(cloneElement(route.element, appConfig), appConfig, route.id)
134
145
  .then(html => { res.send(html) })
135
146
  .catch(err => { res.send(err) })
136
147
 
137
- });
148
+ })
138
149
 
139
150
  app.listen(port, () => {
140
151
  console.log(`[@ossy/app][server] Running on http://localhost:${port}`);
141
152
  });
142
153
 
143
- async function renderToString(App, config) {
154
+ async function prerenderHtmlDocument (rootElement, config, pageId) {
144
155
 
145
156
  const devReloadScript = isDevReloadEnabled
146
157
  ? `(function(){try{var es=new EventSource('/__ossy_reload');es.addEventListener('reload',function(){location.reload();});}catch(e){}})();`
147
158
  : ``
148
159
 
149
- const { prelude } = await prerenderToNodeStream(createElement(App, config), {
160
+ const hydrateUrl = `/static/hydrate-${pageId}.js`
161
+
162
+ const { prelude } = await prerenderToNodeStream(rootElement, {
150
163
  bootstrapScriptContent: `window.__INITIAL_APP_CONFIG__ = ${JSON.stringify(config)};${devReloadScript}`,
151
- bootstrapModules: ['/static/main.js']
164
+ bootstrapModules: [hydrateUrl]
152
165
  });
153
166
 
154
167
  return new Promise((resolve, reject) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ossy/app",
3
- "version": "0.15.13",
3
+ "version": "1.0.1",
4
4
  "description": "",
5
5
  "source": "./src/index.js",
6
6
  "main": "./src/index.js",
@@ -22,18 +22,17 @@
22
22
  "@babel/cli": "^7.26.4",
23
23
  "@babel/core": "^7.26.0",
24
24
  "@babel/eslint-parser": "^7.15.8",
25
- "@babel/preset-env": "^7.26.0",
26
25
  "@babel/preset-react": "^7.26.3",
27
26
  "@babel/register": "^7.25.9",
28
- "@ossy/connected-components": ">=0.5.0 <1.0.0",
29
- "@ossy/design-system": ">=0.5.0 <1.0.0",
30
- "@ossy/pages": ">=0.5.0 <1.0.0",
31
- "@ossy/resource-templates": ">=0.5.0 <1.0.0",
32
- "@ossy/router": ">=0.5.0 <1.0.0",
33
- "@ossy/router-react": ">=0.5.0 <1.0.0",
34
- "@ossy/sdk": ">=0.5.0 <1.0.0",
35
- "@ossy/sdk-react": ">=0.5.0 <1.0.0",
36
- "@ossy/themes": ">=0.5.0 <1.0.0",
27
+ "@ossy/connected-components": ">=1.0.0 <2.0.0",
28
+ "@ossy/design-system": ">=1.0.0 <2.0.0",
29
+ "@ossy/pages": ">=1.0.0 <2.0.0",
30
+ "@ossy/resource-templates": ">=1.0.0 <2.0.0",
31
+ "@ossy/router": ">=1.0.0 <2.0.0",
32
+ "@ossy/router-react": ">=1.0.0 <2.0.0",
33
+ "@ossy/sdk": ">=1.0.0 <2.0.0",
34
+ "@ossy/sdk-react": ">=1.0.0 <2.0.0",
35
+ "@ossy/themes": ">=1.0.0 <2.0.0",
37
36
  "@rollup/plugin-alias": "^6.0.0",
38
37
  "@rollup/plugin-babel": "6.1.0",
39
38
  "@rollup/plugin-commonjs": "^29.0.0",
@@ -41,7 +40,6 @@
41
40
  "@rollup/plugin-json": "^6.1.0",
42
41
  "@rollup/plugin-node-resolve": "^16.0.3",
43
42
  "@rollup/plugin-replace": "^6.0.2",
44
- "@rollup/plugin-terser": "0.4.4",
45
43
  "@rollup/plugin-typescript": "^12.3.0",
46
44
  "arg": "^5.0.2",
47
45
  "babel-loader": "^10.0.0",
@@ -57,7 +55,8 @@
57
55
  "rollup-plugin-node-externals": "^8.1.2",
58
56
  "rollup-plugin-peer-deps-external": "^2.2.4",
59
57
  "rollup-plugin-postcss-modules": "^2.1.1",
60
- "rollup-plugin-preserve-directives": "^0.4.0"
58
+ "rollup-plugin-preserve-directives": "^0.4.0",
59
+ "terser": "^5.17.4"
61
60
  },
62
61
  "files": [
63
62
  "/cli",
@@ -66,5 +65,5 @@
66
65
  "README.md",
67
66
  "tsconfig.json"
68
67
  ],
69
- "gitHead": "280ce1f62d7daf721909ac5eabe4181991e00456"
68
+ "gitHead": "e5276fdb5dedf68b966d851077461b188c613241"
70
69
  }
@@ -3,11 +3,10 @@ import path from 'path'
3
3
  import { fileURLToPath } from 'url'
4
4
 
5
5
  const STUBS = [
6
- ['api.js', 'export default []\n'],
7
6
  ['middleware.js', 'export default []\n'],
8
7
  ]
9
8
 
10
- /** Ensures build/api.js and build/middleware.js exist when Rollup omits empty chunks. */
9
+ /** Ensures build/middleware.js exists when Rollup omits an empty middleware chunk. */
11
10
  export function ensureBuildStubs(buildDir) {
12
11
  if (!fs.existsSync(buildDir)) {
13
12
  console.warn(`[ensure-build-stubs] skip: ${buildDir} missing`)
package/src/index.js CHANGED
@@ -1,2 +1,7 @@
1
- export { build, buildWorker } from '../cli/build.js'
1
+ export {
2
+ build,
3
+ writeResourceTemplatesBarrelIfPresent,
4
+ resourceTemplatesDir,
5
+ OSSY_RESOURCE_TEMPLATES_OUT,
6
+ } from '../cli/build.js'
2
7
  export { dev } from '../cli/dev.js'
package/cli/Api.js DELETED
@@ -1,3 +0,0 @@
1
- // dummy file so it can be imported
2
-
3
- export default undefined
package/cli/client.js DELETED
@@ -1,8 +0,0 @@
1
- import React, { createElement } from 'react'
2
- import 'react-dom'
3
- import { hydrateRoot } from 'react-dom/client';
4
- import App from '%%@ossy/app/source-file%%'
5
-
6
- const initialConfig = window.__INITIAL_APP_CONFIG__ || {}
7
-
8
- hydrateRoot(document, createElement(App, initialConfig))
@@ -1,11 +0,0 @@
1
- import React from 'react'
2
- import { App } from '@ossy/connected-components'
3
- import pages from '%%@ossy/pages/source-file%%'
4
- import pageShell from '%%@ossy/page-shell/source-file%%'
5
-
6
- /**
7
- * App entry. Uses App from @ossy/connected-components with pages from src/pages.jsx.
8
- */
9
- export default function DefaultApp (config) {
10
- return React.createElement(App, { ...config, pages, pageShell })
11
- }
@@ -1,9 +0,0 @@
1
- import React from 'react'
2
-
3
- /**
4
- * Used when the site has no `src/page-shell.jsx`.
5
- * Module pages still call {@link usePageShell} but get a passthrough.
6
- */
7
- export default function PageShellDefault ({ children }) {
8
- return children
9
- }