@ossy/app 0.15.12 → 0.15.13
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 +6 -0
- package/cli/build.js +94 -33
- package/cli/default-app.jsx +3 -2
- package/cli/dev.js +9 -1
- package/cli/page-shell-default.jsx +9 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -25,6 +25,12 @@ For a single-file setup, use `src/pages.jsx` (legacy).
|
|
|
25
25
|
|
|
26
26
|
Split pages are merged into **`build/.ossy/pages.generated.jsx`** (next to other build output) during `dev` / `build`.
|
|
27
27
|
|
|
28
|
+
List **`modules: ['@your/npm-package', ...]`** in `src/config.js` to pull in every **`*.page.js`**, **`*.page.jsx`**, **`*.page.ts`**, and **`*.page.tsx`** file under each package’s **`src/`** tree (any subfolder). Deprecated: **`pagesModules`** / **`pagesModule`** — still read for now, with a deprecation warning.
|
|
29
|
+
|
|
30
|
+
Optional **`src/page-shell.jsx`** (or `.js`): default export your site layout component. **`usePageShell()`** from `@ossy/connected-components` wraps module pages in that shell so packages do not import site paths.
|
|
31
|
+
|
|
32
|
+
**Note:** **`@ossy/connected-components`** is slated for retirement; its responsibilities (app shell, routing wrapper, **`usePageShell`**, etc.) should move into **`@ossy/app`** or smaller focused packages over time. See that package’s README.
|
|
33
|
+
|
|
28
34
|
Add `src/config.js` for workspace and theme:
|
|
29
35
|
|
|
30
36
|
```js
|
package/cli/build.js
CHANGED
|
@@ -37,6 +37,17 @@ export function ensureOssyGeneratedDir (buildPath) {
|
|
|
37
37
|
return dir
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export function resolvePageShellSource (cwd, scriptDir) {
|
|
41
|
+
const candidates = [
|
|
42
|
+
path.resolve(cwd, 'src/page-shell.jsx'),
|
|
43
|
+
path.resolve(cwd, 'src/page-shell.js'),
|
|
44
|
+
]
|
|
45
|
+
for (const p of candidates) {
|
|
46
|
+
if (fs.existsSync(p)) return p
|
|
47
|
+
}
|
|
48
|
+
return path.resolve(scriptDir, 'page-shell-default.jsx')
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
function relToGeneratedImport (generatedAbs, targetAbs) {
|
|
41
52
|
return path.relative(path.dirname(generatedAbs), targetAbs).replace(/\\/g, '/')
|
|
42
53
|
}
|
|
@@ -280,6 +291,27 @@ export function filePathToRoute(filePath, srcDir) {
|
|
|
280
291
|
return { id, path: routePath }
|
|
281
292
|
}
|
|
282
293
|
|
|
294
|
+
/** Route base for `filePathToRoute`: site `--pages` dir, or a package’s `src` dir (first `src` segment in the path). */
|
|
295
|
+
export function pageFilesRouteBaseDir (filePath, sitePagesDir) {
|
|
296
|
+
const fp = path.resolve(filePath)
|
|
297
|
+
const siteRoot = path.resolve(sitePagesDir)
|
|
298
|
+
const sitePrefix = siteRoot + path.sep
|
|
299
|
+
if (fp === siteRoot || fp.startsWith(sitePrefix)) {
|
|
300
|
+
return siteRoot
|
|
301
|
+
}
|
|
302
|
+
const parts = fp.split(path.sep)
|
|
303
|
+
const srcIdx = parts.indexOf('src')
|
|
304
|
+
if (srcIdx !== -1) {
|
|
305
|
+
return parts.slice(0, srcIdx + 1).join(path.sep)
|
|
306
|
+
}
|
|
307
|
+
return siteRoot
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Derive `{ id, path }` for build overview when mixing site pages and installable `modules` package paths. */
|
|
311
|
+
export function routeForPageFileOverview (filePath, sitePagesDir) {
|
|
312
|
+
return filePathToRoute(filePath, pageFilesRouteBaseDir(filePath, sitePagesDir))
|
|
313
|
+
}
|
|
314
|
+
|
|
283
315
|
export function generatePagesModule (pageFiles, cwd, srcDir, generatedPath) {
|
|
284
316
|
const resolvedSrc = path.resolve(cwd, srcDir)
|
|
285
317
|
const lines = [
|
|
@@ -300,7 +332,8 @@ export function generatePagesModule (pageFiles, cwd, srcDir, generatedPath) {
|
|
|
300
332
|
'',
|
|
301
333
|
'export default [',
|
|
302
334
|
...pageFiles.map((f, i) => {
|
|
303
|
-
const
|
|
335
|
+
const base = pageFilesRouteBaseDir(f, resolvedSrc)
|
|
336
|
+
const { id, path: defaultPath } = filePathToRoute(f, base)
|
|
304
337
|
const pathStr = JSON.stringify(defaultPath)
|
|
305
338
|
return ` toPage(_page${i}, { id: '${id}', path: ${pathStr} }),`
|
|
306
339
|
}),
|
|
@@ -309,6 +342,21 @@ export function generatePagesModule (pageFiles, cwd, srcDir, generatedPath) {
|
|
|
309
342
|
return lines.join('\n')
|
|
310
343
|
}
|
|
311
344
|
|
|
345
|
+
function installableModulePackagesFromCfgObject (cfg, warn) {
|
|
346
|
+
if (Array.isArray(cfg.modules) && cfg.modules.length) {
|
|
347
|
+
return cfg.modules
|
|
348
|
+
}
|
|
349
|
+
if (Array.isArray(cfg.pagesModules) && cfg.pagesModules.length) {
|
|
350
|
+
warn?.('[@ossy/app][build] `pagesModules` is deprecated; use `modules` in src/config.js')
|
|
351
|
+
return cfg.pagesModules
|
|
352
|
+
}
|
|
353
|
+
if (typeof cfg.pagesModule === 'string') {
|
|
354
|
+
warn?.('[@ossy/app][build] `pagesModule` is deprecated; use `modules: [ ... ]` in src/config.js')
|
|
355
|
+
return [cfg.pagesModule]
|
|
356
|
+
}
|
|
357
|
+
return []
|
|
358
|
+
}
|
|
359
|
+
|
|
312
360
|
export async function discoverModulePageFiles({ cwd, configPath }) {
|
|
313
361
|
if (!configPath || !fs.existsSync(configPath)) return []
|
|
314
362
|
try {
|
|
@@ -316,54 +364,59 @@ export async function discoverModulePageFiles({ cwd, configPath }) {
|
|
|
316
364
|
// importable (configs often import theme/template modules that may not be
|
|
317
365
|
// resolvable in the build-time node context).
|
|
318
366
|
const cfgSource = fs.readFileSync(configPath, 'utf8')
|
|
319
|
-
const
|
|
367
|
+
const moduleNames = []
|
|
368
|
+
let warnedLegacy = false
|
|
369
|
+
const warnOnce = (msg) => {
|
|
370
|
+
if (!warnedLegacy) {
|
|
371
|
+
console.warn(msg)
|
|
372
|
+
warnedLegacy = true
|
|
373
|
+
}
|
|
374
|
+
}
|
|
320
375
|
|
|
321
|
-
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
376
|
+
const modulesArr = cfgSource.match(/\bmodules\s*:\s*\[([^\]]*)\]/m)
|
|
377
|
+
const pagesModulesArr = cfgSource.match(/\bpagesModules\s*:\s*\[([^\]]*)\]/m)
|
|
378
|
+
const listBody = modulesArr?.[1] ?? pagesModulesArr?.[1]
|
|
379
|
+
if (listBody !== undefined && listBody !== null) {
|
|
380
|
+
if (pagesModulesArr && !modulesArr) {
|
|
381
|
+
warnOnce('[@ossy/app][build] `pagesModules` is deprecated; use `modules` in src/config.js')
|
|
382
|
+
}
|
|
325
383
|
const re = /['"]([^'"]+)['"]/g
|
|
326
384
|
let m
|
|
327
|
-
while ((m = re.exec(
|
|
385
|
+
while ((m = re.exec(listBody)) !== null) moduleNames.push(m[1])
|
|
328
386
|
}
|
|
329
387
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
388
|
+
if (moduleNames.length === 0) {
|
|
389
|
+
const singlePagesModule = cfgSource.match(/\bpagesModule\s*:\s*['"]([^'"]+)['"]/m)
|
|
390
|
+
if (singlePagesModule?.[1]) {
|
|
391
|
+
warnOnce('[@ossy/app][build] `pagesModule` is deprecated; use `modules: [ ... ]` in src/config.js')
|
|
392
|
+
moduleNames.push(singlePagesModule[1])
|
|
393
|
+
}
|
|
334
394
|
}
|
|
335
395
|
|
|
336
|
-
|
|
396
|
+
const loadFromNames = (names) => {
|
|
337
397
|
const req = createRequire(path.resolve(cwd, 'package.json'))
|
|
338
398
|
const files = []
|
|
339
|
-
for (const name of
|
|
399
|
+
for (const name of names) {
|
|
340
400
|
const pkgJsonPath = req.resolve(`${name}/package.json`)
|
|
341
401
|
const pkgDir = path.dirname(pkgJsonPath)
|
|
342
|
-
const
|
|
343
|
-
files.push(...discoverPageFiles(
|
|
402
|
+
const moduleSrcDir = path.join(pkgDir, 'src')
|
|
403
|
+
files.push(...discoverPageFiles(moduleSrcDir))
|
|
344
404
|
}
|
|
345
405
|
return files
|
|
346
406
|
}
|
|
347
407
|
|
|
408
|
+
if (moduleNames.length) {
|
|
409
|
+
return loadFromNames(moduleNames)
|
|
410
|
+
}
|
|
411
|
+
|
|
348
412
|
const mod = await import(url.pathToFileURL(configPath))
|
|
349
413
|
const cfg = mod?.default ?? mod ?? {}
|
|
350
|
-
const modules2 =
|
|
351
|
-
? cfg.pagesModules
|
|
352
|
-
: (typeof cfg.pagesModule === 'string' ? [cfg.pagesModule] : [])
|
|
414
|
+
const modules2 = installableModulePackagesFromCfgObject(cfg, (msg) => console.warn(msg))
|
|
353
415
|
|
|
354
416
|
if (!modules2.length) return []
|
|
355
|
-
|
|
356
|
-
const req = createRequire(path.resolve(cwd, 'package.json'))
|
|
357
|
-
const files = []
|
|
358
|
-
for (const name of modules2) {
|
|
359
|
-
const pkgJsonPath = req.resolve(`${name}/package.json`)
|
|
360
|
-
const pkgDir = path.dirname(pkgJsonPath)
|
|
361
|
-
const modulePagesDir = path.join(pkgDir, 'src', 'pages')
|
|
362
|
-
files.push(...discoverPageFiles(modulePagesDir))
|
|
363
|
-
}
|
|
364
|
-
return files
|
|
417
|
+
return loadFromNames(modules2)
|
|
365
418
|
} catch (e) {
|
|
366
|
-
console.warn('[@ossy/app][build]
|
|
419
|
+
console.warn('[@ossy/app][build] `modules` config could not be loaded; continuing without installable module pages')
|
|
367
420
|
return []
|
|
368
421
|
}
|
|
369
422
|
}
|
|
@@ -421,9 +474,10 @@ export function printBuildOverview({
|
|
|
421
474
|
console.log(` \x1b[36mAPI:\x1b[0m ${rel(apiSourcePath)}`)
|
|
422
475
|
console.log(' ' + '─'.repeat(50))
|
|
423
476
|
|
|
424
|
-
const pages =
|
|
425
|
-
|
|
426
|
-
|
|
477
|
+
const pages =
|
|
478
|
+
isPageFiles && pageFiles?.length
|
|
479
|
+
? pageFiles.map((f) => routeForPageFileOverview(f, srcDir))
|
|
480
|
+
: parsePagesFromSource(pagesSourcePath)
|
|
427
481
|
if (pages.length > 0) {
|
|
428
482
|
console.log(' \x1b[36mRoutes:\x1b[0m')
|
|
429
483
|
const maxId = Math.max(6, ...pages.map((p) => String(p.id).length))
|
|
@@ -635,7 +689,7 @@ export const build = async (cliArgs) => {
|
|
|
635
689
|
apiOverviewFiles,
|
|
636
690
|
configPath,
|
|
637
691
|
isPageFiles,
|
|
638
|
-
pageFiles: isPageFiles ? pageFiles : [],
|
|
692
|
+
pageFiles: isPageFiles ? [...pageFiles, ...modulePageFiles] : [],
|
|
639
693
|
});
|
|
640
694
|
|
|
641
695
|
if (!fs.existsSync(apiSourcePath)) {
|
|
@@ -650,6 +704,8 @@ export const build = async (cliArgs) => {
|
|
|
650
704
|
? configPath
|
|
651
705
|
: path.resolve(scriptDir, 'default-config.js')
|
|
652
706
|
|
|
707
|
+
const pageShellSourcePath = resolvePageShellSource(cwd, scriptDir)
|
|
708
|
+
|
|
653
709
|
const inputOptions = {
|
|
654
710
|
input: inputFiles,
|
|
655
711
|
plugins: [
|
|
@@ -680,6 +736,11 @@ export const build = async (cliArgs) => {
|
|
|
680
736
|
delimiters: ['%%', '%%'],
|
|
681
737
|
'@ossy/config/source-file': configSourcePath,
|
|
682
738
|
}),
|
|
739
|
+
replace({
|
|
740
|
+
preventAssignment: true,
|
|
741
|
+
delimiters: ['%%', '%%'],
|
|
742
|
+
'@ossy/page-shell/source-file': pageShellSourcePath,
|
|
743
|
+
}),
|
|
683
744
|
replace({
|
|
684
745
|
preventAssignment: true,
|
|
685
746
|
'process.env.NODE_ENV': JSON.stringify('production')
|
package/cli/default-app.jsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { App } from '@ossy/connected-components'
|
|
3
3
|
import pages from '%%@ossy/pages/source-file%%'
|
|
4
|
+
import pageShell from '%%@ossy/page-shell/source-file%%'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* App entry. Uses App from @ossy/connected-components with pages from src/pages.jsx.
|
|
7
8
|
*/
|
|
8
|
-
export default function DefaultApp(config) {
|
|
9
|
-
return React.createElement(App, { ...config, pages })
|
|
9
|
+
export default function DefaultApp (config) {
|
|
10
|
+
return React.createElement(App, { ...config, pages, pageShell })
|
|
10
11
|
}
|
package/cli/dev.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
ossyGeneratedDir,
|
|
13
13
|
OSSY_GEN_PAGES_BASENAME,
|
|
14
14
|
OSSY_GEN_API_BASENAME,
|
|
15
|
+
resolvePageShellSource,
|
|
15
16
|
} from './build.js';
|
|
16
17
|
import { watch } from 'rollup';
|
|
17
18
|
import babel from '@rollup/plugin-babel';
|
|
@@ -94,7 +95,7 @@ export const dev = async (cliArgs) => {
|
|
|
94
95
|
apiOverviewFiles,
|
|
95
96
|
configPath,
|
|
96
97
|
isPageFiles,
|
|
97
|
-
pageFiles: isPageFiles ? pageFiles : [],
|
|
98
|
+
pageFiles: isPageFiles ? [...pageFiles, ...modulePageFiles] : [],
|
|
98
99
|
});
|
|
99
100
|
|
|
100
101
|
if (!fs.existsSync(apiSourcePath)) {
|
|
@@ -109,6 +110,8 @@ export const dev = async (cliArgs) => {
|
|
|
109
110
|
? configPath
|
|
110
111
|
: path.resolve(scriptDir, 'default-config.js')
|
|
111
112
|
|
|
113
|
+
const pageShellSourcePath = resolvePageShellSource(cwd, scriptDir)
|
|
114
|
+
|
|
112
115
|
const inputOptions = {
|
|
113
116
|
input: inputFiles,
|
|
114
117
|
plugins: [
|
|
@@ -139,6 +142,11 @@ export const dev = async (cliArgs) => {
|
|
|
139
142
|
delimiters: ['%%', '%%'],
|
|
140
143
|
'@ossy/config/source-file': configSourcePath,
|
|
141
144
|
}),
|
|
145
|
+
replace({
|
|
146
|
+
preventAssignment: true,
|
|
147
|
+
delimiters: ['%%', '%%'],
|
|
148
|
+
'@ossy/page-shell/source-file': pageShellSourcePath,
|
|
149
|
+
}),
|
|
142
150
|
replace({
|
|
143
151
|
preventAssignment: true,
|
|
144
152
|
'process.env.NODE_ENV': JSON.stringify('development')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.13",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"README.md",
|
|
67
67
|
"tsconfig.json"
|
|
68
68
|
],
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "280ce1f62d7daf721909ac5eabe4181991e00456"
|
|
70
70
|
}
|