@ossy/app 1.11.0 → 1.11.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/build-terminal.js +170 -37
- package/cli/build.js +109 -43
- package/cli/dev.js +59 -15
- package/package.json +10 -10
package/cli/build-terminal.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import util from 'node:util'
|
|
2
|
+
|
|
1
3
|
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
2
4
|
|
|
3
5
|
const dim = (s) => `\x1b[2m${s}\x1b[0m`
|
|
@@ -15,6 +17,13 @@ function padVisible (s, width) {
|
|
|
15
17
|
return n >= width ? s : s + ' '.repeat(width - n)
|
|
16
18
|
}
|
|
17
19
|
|
|
20
|
+
function truncateVisible (s, maxW) {
|
|
21
|
+
const plain = stripAnsi(s)
|
|
22
|
+
if (plain.length <= maxW) return s
|
|
23
|
+
const cut = Math.max(0, maxW - 1)
|
|
24
|
+
return plain.slice(0, cut) + '…'
|
|
25
|
+
}
|
|
26
|
+
|
|
18
27
|
export function pageIdFromHydrateEntryName (entryName) {
|
|
19
28
|
const p = String(entryName)
|
|
20
29
|
return p.startsWith('hydrate__') ? p.slice('hydrate__'.length) : p
|
|
@@ -51,24 +60,35 @@ function rowLeadIcon (r, mode) {
|
|
|
51
60
|
return green('✔')
|
|
52
61
|
}
|
|
53
62
|
|
|
63
|
+
function useTty (stream) {
|
|
64
|
+
return (
|
|
65
|
+
stream.isTTY === true &&
|
|
66
|
+
process.env.TERM !== 'dumb' &&
|
|
67
|
+
process.env.CI !== 'true' &&
|
|
68
|
+
process.env.OSSY_PLAIN_OUTPUT !== '1'
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
54
72
|
/**
|
|
55
|
-
*
|
|
56
|
-
* TTY:
|
|
73
|
+
* Merged overview + per-page progress, split layout: left = status table, right = log tail.
|
|
74
|
+
* TTY: single redraw block + optional console capture into the right column.
|
|
57
75
|
*/
|
|
58
|
-
export function
|
|
76
|
+
export function createBuildDashboard ({
|
|
59
77
|
scope = '@ossy/app',
|
|
78
|
+
mode = 'full',
|
|
60
79
|
pageIds,
|
|
80
|
+
/** @type {Record<string, string>} route path per page id */
|
|
81
|
+
idToPath = {},
|
|
82
|
+
overview = { title: '@ossy/app', configRel: null, apiRoutes: [] },
|
|
61
83
|
stream = process.stdout,
|
|
62
|
-
/** `'full'`: hydrate + prerender columns. `'prerender-only'`: dev watch (client built separately). */
|
|
63
|
-
mode = 'full',
|
|
64
84
|
} = {}) {
|
|
65
85
|
const ids = [...pageIds].sort()
|
|
66
|
-
const maxId = Math.max(
|
|
67
|
-
const tty =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
86
|
+
const maxId = Math.max(6, ...ids.map((id) => String(id).length))
|
|
87
|
+
const tty = useTty(stream)
|
|
88
|
+
const termW = Math.max(60, stream.columns || 100)
|
|
89
|
+
const LEFT_W = Math.min(56, Math.max(38, Math.floor(termW * 0.42)))
|
|
90
|
+
const GAP = 2
|
|
91
|
+
const RIGHT_W = Math.max(16, termW - LEFT_W - GAP)
|
|
72
92
|
|
|
73
93
|
/** @type {Map<string, { bundle: object, prerender: object }>} */
|
|
74
94
|
const rows = new Map()
|
|
@@ -79,9 +99,13 @@ export function createParallelPagesReporter ({
|
|
|
79
99
|
})
|
|
80
100
|
}
|
|
81
101
|
|
|
102
|
+
const logBuffer = []
|
|
103
|
+
const MAX_LOG = 120
|
|
82
104
|
let frame = 0
|
|
83
105
|
let spinTimer = null
|
|
84
106
|
let blockLines = 0
|
|
107
|
+
let captureActive = false
|
|
108
|
+
let savedConsole = null
|
|
85
109
|
|
|
86
110
|
const anyRunning = () => {
|
|
87
111
|
for (const r of rows.values()) {
|
|
@@ -90,44 +114,107 @@ export function createParallelPagesReporter ({
|
|
|
90
114
|
return false
|
|
91
115
|
}
|
|
92
116
|
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
117
|
+
function pushLog (line) {
|
|
118
|
+
const s = String(line).trim() ? String(line) : ''
|
|
119
|
+
if (!s) return
|
|
120
|
+
if (!tty) {
|
|
121
|
+
stream.write(`${s}\n`)
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
logBuffer.push(dim(s))
|
|
125
|
+
if (logBuffer.length > MAX_LOG) logBuffer.splice(0, logBuffer.length - MAX_LOG)
|
|
126
|
+
redraw()
|
|
99
127
|
}
|
|
100
128
|
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
129
|
+
function leftHeaderLines () {
|
|
130
|
+
const out = []
|
|
131
|
+
out.push(bold(overview.title || `${scope} build`))
|
|
132
|
+
if (overview.configRel) {
|
|
133
|
+
out.push(`${dim('config')} ${truncateVisible(overview.configRel, LEFT_W - 10)}`)
|
|
105
134
|
}
|
|
135
|
+
const api = overview.apiRoutes || []
|
|
136
|
+
if (api.length === 0) {
|
|
137
|
+
/* noop */
|
|
138
|
+
} else if (api.length <= 2) {
|
|
139
|
+
for (const r of api) {
|
|
140
|
+
const line = `${dim('api')} ${truncateVisible(`${r.id} ${r.path}`, LEFT_W - 6)}`
|
|
141
|
+
out.push(line)
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
out.push(`${dim('api')} ${api.length} routes`)
|
|
145
|
+
}
|
|
146
|
+
out.push(dim('─'.repeat(Math.min(LEFT_W - 2, 44))))
|
|
147
|
+
return out
|
|
106
148
|
}
|
|
107
149
|
|
|
108
|
-
function
|
|
150
|
+
function lineForPageRow (id) {
|
|
109
151
|
const r = rows.get(id)
|
|
110
152
|
const lead = rowLeadIcon(r, mode)
|
|
153
|
+
const pathStr = idToPath[id] != null ? dim(String(idToPath[id])) : ''
|
|
111
154
|
const idCol = padVisible(dim(String(id)), maxId)
|
|
155
|
+
const pathPad = padVisible(pathStr, 14)
|
|
112
156
|
const p = fmtPart(r.prerender, 'html', frame)
|
|
113
157
|
if (mode === 'prerender-only') {
|
|
114
|
-
return ` ${lead} ${dim(scope)} ${idCol} ${p}`
|
|
158
|
+
return ` ${lead} ${dim(scope)} ${idCol} ${pathPad} ${p}`
|
|
115
159
|
}
|
|
116
160
|
const b = fmtPart(r.bundle, 'hydrate', frame)
|
|
117
|
-
return ` ${lead} ${dim(scope)} ${idCol} ${padVisible(b,
|
|
161
|
+
return ` ${lead} ${dim(scope)} ${idCol} ${pathPad} ${padVisible(b, 20)} ${p}`
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function buildLeftColumnLines () {
|
|
165
|
+
const head = leftHeaderLines()
|
|
166
|
+
const body = ids.map((id) => lineForPageRow(id))
|
|
167
|
+
return [...head, ...body]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function buildHeaderOnlyLines () {
|
|
171
|
+
return leftHeaderLines()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Right column row i: logs bottom-aligned to the block height */
|
|
175
|
+
function rightColumnLine (i, totalRows) {
|
|
176
|
+
const start = logBuffer.length - totalRows + i
|
|
177
|
+
if (start < 0 || start >= logBuffer.length) return dim('·')
|
|
178
|
+
return truncateVisible(logBuffer[start], RIGHT_W)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function paintRow (leftLine, rightLine) {
|
|
182
|
+
const L = padVisible(truncateVisible(leftLine, LEFT_W), LEFT_W)
|
|
183
|
+
const R = truncateVisible(rightLine, RIGHT_W)
|
|
184
|
+
return `${L}${' '.repeat(GAP)}${R}\n`
|
|
118
185
|
}
|
|
119
186
|
|
|
120
187
|
function redraw () {
|
|
121
188
|
if (!tty) return
|
|
122
|
-
const
|
|
189
|
+
const leftCol = buildLeftColumnLines()
|
|
190
|
+
const n = leftCol.length
|
|
191
|
+
const lines = []
|
|
192
|
+
for (let i = 0; i < n; i++) {
|
|
193
|
+
lines.push(paintRow(leftCol[i], rightColumnLine(i, n)))
|
|
194
|
+
}
|
|
123
195
|
if (blockLines === 0) {
|
|
124
|
-
for (const ln of lines) stream.write(
|
|
196
|
+
for (const ln of lines) stream.write(ln)
|
|
125
197
|
blockLines = lines.length
|
|
126
198
|
return
|
|
127
199
|
}
|
|
128
200
|
stream.write(`\x1b[${blockLines}A`)
|
|
129
201
|
for (const ln of lines) {
|
|
130
|
-
stream.write(`\x1b[2K\r${ln}
|
|
202
|
+
stream.write(`\x1b[2K\r${ln}`)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function ensureSpin () {
|
|
207
|
+
if (!tty || spinTimer) return
|
|
208
|
+
spinTimer = setInterval(() => {
|
|
209
|
+
frame += 1
|
|
210
|
+
redraw()
|
|
211
|
+
}, 80)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function stopSpin () {
|
|
215
|
+
if (spinTimer) {
|
|
216
|
+
clearInterval(spinTimer)
|
|
217
|
+
spinTimer = null
|
|
131
218
|
}
|
|
132
219
|
}
|
|
133
220
|
|
|
@@ -139,7 +226,58 @@ export function createParallelPagesReporter ({
|
|
|
139
226
|
if (err && !ok) stream.write(` ${red(String(err.message || err))}\n`)
|
|
140
227
|
}
|
|
141
228
|
|
|
229
|
+
function beginCapture () {
|
|
230
|
+
if (!tty || captureActive) return
|
|
231
|
+
captureActive = true
|
|
232
|
+
savedConsole = {
|
|
233
|
+
log: console.log,
|
|
234
|
+
warn: console.warn,
|
|
235
|
+
info: console.info,
|
|
236
|
+
error: console.error,
|
|
237
|
+
}
|
|
238
|
+
const fmt = (...a) => util.format(...a)
|
|
239
|
+
console.log = (...a) => {
|
|
240
|
+
pushLog(`[log] ${fmt(...a)}`)
|
|
241
|
+
}
|
|
242
|
+
console.warn = (...a) => {
|
|
243
|
+
pushLog(`[warn] ${fmt(...a)}`)
|
|
244
|
+
}
|
|
245
|
+
console.info = (...a) => {
|
|
246
|
+
pushLog(`[info] ${fmt(...a)}`)
|
|
247
|
+
}
|
|
248
|
+
console.error = (...a) => {
|
|
249
|
+
const msg = fmt(...a)
|
|
250
|
+
pushLog(`[error] ${msg}`)
|
|
251
|
+
savedConsole.error(`[@ossy/app] ${msg}`)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function endCapture () {
|
|
256
|
+
if (!captureActive || !savedConsole) return
|
|
257
|
+
console.log = savedConsole.log
|
|
258
|
+
console.warn = savedConsole.warn
|
|
259
|
+
console.info = savedConsole.info
|
|
260
|
+
console.error = savedConsole.error
|
|
261
|
+
savedConsole = null
|
|
262
|
+
captureActive = false
|
|
263
|
+
}
|
|
264
|
+
|
|
142
265
|
return {
|
|
266
|
+
pushLog,
|
|
267
|
+
|
|
268
|
+
/** Start optional console hijack + first paint (TTY). Plain header only when not a TTY. */
|
|
269
|
+
start () {
|
|
270
|
+
if (!tty) {
|
|
271
|
+
for (const ln of buildHeaderOnlyLines()) {
|
|
272
|
+
stream.write(`${ln}\n`)
|
|
273
|
+
}
|
|
274
|
+
stream.write('\n')
|
|
275
|
+
return
|
|
276
|
+
}
|
|
277
|
+
beginCapture()
|
|
278
|
+
redraw()
|
|
279
|
+
},
|
|
280
|
+
|
|
143
281
|
startBundle (pageId) {
|
|
144
282
|
if (mode === 'prerender-only') return
|
|
145
283
|
const r = rows.get(pageId)
|
|
@@ -188,23 +326,18 @@ export function createParallelPagesReporter ({
|
|
|
188
326
|
redraw()
|
|
189
327
|
},
|
|
190
328
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
stopSpin()
|
|
194
|
-
if (tty && blockLines > 0) {
|
|
195
|
-
redraw()
|
|
196
|
-
stream.write('\n')
|
|
197
|
-
blockLines = 0
|
|
198
|
-
}
|
|
329
|
+
printSectionTitle () {
|
|
330
|
+
/* merged into overview.title — no-op for API compat */
|
|
199
331
|
},
|
|
200
332
|
|
|
201
|
-
|
|
333
|
+
dispose () {
|
|
202
334
|
stopSpin()
|
|
335
|
+
endCapture()
|
|
203
336
|
if (tty && blockLines > 0) {
|
|
337
|
+
redraw()
|
|
204
338
|
stream.write('\n')
|
|
205
339
|
blockLines = 0
|
|
206
340
|
}
|
|
207
|
-
stream.write(`\n ${bold(scope)} ${dim(title)}\n`)
|
|
208
341
|
},
|
|
209
342
|
}
|
|
210
343
|
}
|
package/cli/build.js
CHANGED
|
@@ -12,7 +12,7 @@ import copy from 'rollup-plugin-copy';
|
|
|
12
12
|
import replace from '@rollup/plugin-replace';
|
|
13
13
|
import arg from 'arg'
|
|
14
14
|
import prerenderReactTask from './prerender-react.task.js'
|
|
15
|
-
import {
|
|
15
|
+
import { createBuildDashboard } from './build-terminal.js'
|
|
16
16
|
|
|
17
17
|
export const PAGE_FILE_PATTERN = /\.page\.(jsx?|tsx?)$/
|
|
18
18
|
export const API_FILE_PATTERN = /\.api\.(mjs|cjs|js)$/
|
|
@@ -210,10 +210,17 @@ export function createOssyClientRollupPlugins ({ nodeEnv, copyPublicFrom, buildP
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
/** Bundles a single Node ESM file (inline dynamic imports) for SSR / API / tasks. */
|
|
213
|
-
export async function bundleOssyNodeEntry ({ inputPath, outputFile, nodeEnv }) {
|
|
213
|
+
export async function bundleOssyNodeEntry ({ inputPath, outputFile, nodeEnv, onWarn }) {
|
|
214
214
|
const bundle = await rollup({
|
|
215
215
|
input: inputPath,
|
|
216
216
|
plugins: createOssyAppBundlePlugins({ nodeEnv }),
|
|
217
|
+
onwarn (warning, defaultHandler) {
|
|
218
|
+
if (onWarn) {
|
|
219
|
+
onWarn(warning)
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
defaultHandler(warning)
|
|
223
|
+
},
|
|
217
224
|
})
|
|
218
225
|
await bundle.write({
|
|
219
226
|
file: outputFile,
|
|
@@ -545,24 +552,46 @@ export function parsePagesFromSource(filePath) {
|
|
|
545
552
|
}
|
|
546
553
|
}
|
|
547
554
|
|
|
548
|
-
|
|
555
|
+
/**
|
|
556
|
+
* Same facts as the old build overview printout, for dashboards / plain logging.
|
|
557
|
+
*/
|
|
558
|
+
export function getBuildOverviewSnapshot ({
|
|
549
559
|
pagesSourcePath,
|
|
550
560
|
apiSourcePath,
|
|
551
561
|
apiOverviewFiles = [],
|
|
552
562
|
configPath,
|
|
553
563
|
pageFiles,
|
|
554
564
|
}) {
|
|
555
|
-
const rel = (p) => p ? path.relative(process.cwd(), p) : undefined
|
|
565
|
+
const rel = (p) => (p ? path.relative(process.cwd(), p) : undefined)
|
|
556
566
|
const srcDir = path.resolve(process.cwd(), 'src')
|
|
557
|
-
|
|
558
|
-
if (fs.existsSync(configPath)) {
|
|
559
|
-
console.log(` \x1b[36mConfig:\x1b[0m ${rel(configPath)}`)
|
|
560
|
-
}
|
|
561
|
-
console.log(' ' + '─'.repeat(50))
|
|
567
|
+
const configRel = fs.existsSync(configPath) ? rel(configPath) : null
|
|
562
568
|
|
|
563
569
|
const pages = pageFiles?.length
|
|
564
570
|
? pageFiles.map((f) => filePathToRoute(f, srcDir))
|
|
565
571
|
: parsePagesFromSource(pagesSourcePath)
|
|
572
|
+
|
|
573
|
+
const apiFilesToScan =
|
|
574
|
+
apiOverviewFiles?.length > 0
|
|
575
|
+
? apiOverviewFiles
|
|
576
|
+
: fs.existsSync(apiSourcePath)
|
|
577
|
+
? [apiSourcePath]
|
|
578
|
+
: []
|
|
579
|
+
const apiRoutes = []
|
|
580
|
+
for (const f of apiFilesToScan) {
|
|
581
|
+
if (fs.existsSync(f)) apiRoutes.push(...parsePagesFromSource(f))
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return { configRel, pages, apiRoutes }
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export function printBuildOverview (opts) {
|
|
588
|
+
const { configRel, pages, apiRoutes } = getBuildOverviewSnapshot(opts)
|
|
589
|
+
console.log('\n \x1b[1mBuild overview\x1b[0m')
|
|
590
|
+
if (configRel) {
|
|
591
|
+
console.log(` \x1b[36mConfig:\x1b[0m ${configRel}`)
|
|
592
|
+
}
|
|
593
|
+
console.log(' ' + '─'.repeat(50))
|
|
594
|
+
|
|
566
595
|
if (pages.length > 0) {
|
|
567
596
|
console.log(' \x1b[36mRoutes:\x1b[0m')
|
|
568
597
|
const maxId = Math.max(6, ...pages.map((p) => String(p.id).length))
|
|
@@ -576,16 +605,6 @@ export function printBuildOverview({
|
|
|
576
605
|
console.log(' \x1b[33mRoutes:\x1b[0m (could not parse or empty)')
|
|
577
606
|
}
|
|
578
607
|
|
|
579
|
-
const apiFilesToScan =
|
|
580
|
-
apiOverviewFiles?.length > 0
|
|
581
|
-
? apiOverviewFiles
|
|
582
|
-
: fs.existsSync(apiSourcePath)
|
|
583
|
-
? [apiSourcePath]
|
|
584
|
-
: []
|
|
585
|
-
const apiRoutes = []
|
|
586
|
-
for (const f of apiFilesToScan) {
|
|
587
|
-
if (fs.existsSync(f)) apiRoutes.push(...parsePagesFromSource(f))
|
|
588
|
-
}
|
|
589
608
|
if (apiRoutes.length > 0) {
|
|
590
609
|
console.log(' \x1b[36mAPI routes:\x1b[0m')
|
|
591
610
|
apiRoutes.forEach((r) => {
|
|
@@ -601,10 +620,6 @@ export const build = async (cliArgs) => {
|
|
|
601
620
|
'-c': '--config',
|
|
602
621
|
}, { argv: cliArgs })
|
|
603
622
|
|
|
604
|
-
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mbuild\x1b[0m')
|
|
605
|
-
console.log(' \x1b[2m────────────────────────────────────────\x1b[0m')
|
|
606
|
-
|
|
607
|
-
|
|
608
623
|
const scriptDir = path.dirname(url.fileURLToPath(import.meta.url))
|
|
609
624
|
const buildPath = path.resolve('build')
|
|
610
625
|
const srcDir = path.resolve('src')
|
|
@@ -613,7 +628,10 @@ export const build = async (cliArgs) => {
|
|
|
613
628
|
|
|
614
629
|
resetOssyBuildDir(buildPath)
|
|
615
630
|
|
|
616
|
-
writeResourceTemplatesBarrelIfPresent({
|
|
631
|
+
const resourceTemplatesResult = writeResourceTemplatesBarrelIfPresent({
|
|
632
|
+
cwd: process.cwd(),
|
|
633
|
+
log: false,
|
|
634
|
+
})
|
|
617
635
|
|
|
618
636
|
const pagesGeneratedPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
|
|
619
637
|
|
|
@@ -636,14 +654,6 @@ export const build = async (cliArgs) => {
|
|
|
636
654
|
let middlewareSourcePath = path.resolve('src/middleware.js');
|
|
637
655
|
const publicDir = path.resolve('public')
|
|
638
656
|
|
|
639
|
-
printBuildOverview({
|
|
640
|
-
pagesSourcePath: pagesGeneratedPath,
|
|
641
|
-
apiSourcePath,
|
|
642
|
-
apiOverviewFiles,
|
|
643
|
-
configPath,
|
|
644
|
-
pageFiles,
|
|
645
|
-
});
|
|
646
|
-
|
|
647
657
|
if (!fs.existsSync(middlewareSourcePath)) {
|
|
648
658
|
middlewareSourcePath = path.resolve(scriptDir, 'middleware.js')
|
|
649
659
|
}
|
|
@@ -656,21 +666,82 @@ export const build = async (cliArgs) => {
|
|
|
656
666
|
const apiBundlePath = path.join(ossyDir, OSSY_API_SERVER_BUNDLE)
|
|
657
667
|
const tasksBundlePath = path.join(ossyDir, OSSY_TASKS_SERVER_BUNDLE)
|
|
658
668
|
|
|
669
|
+
const useDashboard = Object.keys(clientHydrateInput).length > 0
|
|
670
|
+
const overviewSnap = getBuildOverviewSnapshot({
|
|
671
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
672
|
+
apiSourcePath,
|
|
673
|
+
apiOverviewFiles,
|
|
674
|
+
configPath,
|
|
675
|
+
pageFiles,
|
|
676
|
+
})
|
|
677
|
+
const idToPath = Object.fromEntries(
|
|
678
|
+
pageFiles.map((f) => [
|
|
679
|
+
clientHydrateIdForPage(f, srcDir),
|
|
680
|
+
filePathToRoute(f, srcDir).path,
|
|
681
|
+
])
|
|
682
|
+
)
|
|
683
|
+
const pageIds = useDashboard
|
|
684
|
+
? [...new Set(pageFiles.map((f) => clientHydrateIdForPage(f, srcDir)))].sort()
|
|
685
|
+
: []
|
|
686
|
+
|
|
687
|
+
let dashboard = null
|
|
688
|
+
if (useDashboard && pageIds.length > 0) {
|
|
689
|
+
dashboard = createBuildDashboard({
|
|
690
|
+
mode: 'full',
|
|
691
|
+
pageIds,
|
|
692
|
+
idToPath,
|
|
693
|
+
overview: {
|
|
694
|
+
title: '@ossy/app build',
|
|
695
|
+
configRel: overviewSnap.configRel,
|
|
696
|
+
apiRoutes: overviewSnap.apiRoutes,
|
|
697
|
+
},
|
|
698
|
+
})
|
|
699
|
+
dashboard.start()
|
|
700
|
+
if (resourceTemplatesResult.wrote && resourceTemplatesResult.path) {
|
|
701
|
+
dashboard.pushLog(
|
|
702
|
+
`[resource-templates] merged ${resourceTemplatesResult.count} → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
703
|
+
)
|
|
704
|
+
}
|
|
705
|
+
} else {
|
|
706
|
+
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mbuild\x1b[0m')
|
|
707
|
+
printBuildOverview({
|
|
708
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
709
|
+
apiSourcePath,
|
|
710
|
+
apiOverviewFiles,
|
|
711
|
+
configPath,
|
|
712
|
+
pageFiles,
|
|
713
|
+
})
|
|
714
|
+
if (resourceTemplatesResult.wrote && resourceTemplatesResult.path) {
|
|
715
|
+
console.log(
|
|
716
|
+
`[@ossy/app][resource-templates] merged ${resourceTemplatesResult.count} template(s) → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
717
|
+
)
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
const warnSink = dashboard
|
|
722
|
+
? (w) => {
|
|
723
|
+
dashboard.pushLog(`rollup: ${w.message}`)
|
|
724
|
+
}
|
|
725
|
+
: undefined
|
|
726
|
+
|
|
659
727
|
await bundleOssyNodeEntry({
|
|
660
728
|
inputPath: pagesGeneratedPath,
|
|
661
729
|
outputFile: pagesBundlePath,
|
|
662
730
|
nodeEnv: 'production',
|
|
731
|
+
onWarn: warnSink,
|
|
663
732
|
})
|
|
664
733
|
await bundleOssyNodeEntry({
|
|
665
734
|
inputPath: apiSourcePath,
|
|
666
735
|
outputFile: apiBundlePath,
|
|
667
736
|
nodeEnv: 'production',
|
|
737
|
+
onWarn: warnSink,
|
|
668
738
|
})
|
|
669
739
|
const { taskSourcePath } = resolveTaskSource({ srcDir, buildPath })
|
|
670
740
|
await bundleOssyNodeEntry({
|
|
671
741
|
inputPath: taskSourcePath,
|
|
672
742
|
outputFile: tasksBundlePath,
|
|
673
743
|
nodeEnv: 'production',
|
|
744
|
+
onWarn: warnSink,
|
|
674
745
|
})
|
|
675
746
|
|
|
676
747
|
writeAppRuntimeShims({
|
|
@@ -679,14 +750,7 @@ export const build = async (cliArgs) => {
|
|
|
679
750
|
})
|
|
680
751
|
copyOssyAppRuntime({ scriptDir, buildPath })
|
|
681
752
|
|
|
682
|
-
if (
|
|
683
|
-
const pageIds = [
|
|
684
|
-
...new Set(pageFiles.map((f) => clientHydrateIdForPage(f, srcDir))),
|
|
685
|
-
].sort()
|
|
686
|
-
const reporter = pageIds.length
|
|
687
|
-
? createParallelPagesReporter({ pageIds })
|
|
688
|
-
: null
|
|
689
|
-
reporter?.printSectionTitle('client hydrate + prerender (parallel)')
|
|
753
|
+
if (useDashboard && dashboard) {
|
|
690
754
|
try {
|
|
691
755
|
await prerenderReactTask.handler({
|
|
692
756
|
op: 'runProduction',
|
|
@@ -699,13 +763,15 @@ export const build = async (cliArgs) => {
|
|
|
699
763
|
configSourcePath,
|
|
700
764
|
createClientRollupPlugins: createOssyClientRollupPlugins,
|
|
701
765
|
minifyBrowserStaticChunks,
|
|
702
|
-
reporter,
|
|
766
|
+
reporter: dashboard,
|
|
703
767
|
})
|
|
704
768
|
} finally {
|
|
705
|
-
|
|
769
|
+
dashboard.dispose()
|
|
706
770
|
}
|
|
707
771
|
}
|
|
708
772
|
|
|
709
|
-
|
|
773
|
+
if (useDashboard && dashboard) {
|
|
774
|
+
console.log(' \x1b[2m────────────────────────────────────────\x1b[0m')
|
|
775
|
+
}
|
|
710
776
|
console.log(' \x1b[32m✔\x1b[0m \x1b[1m@ossy/app\x1b[0m \x1b[2mbuild finished\x1b[0m\n')
|
|
711
777
|
};
|
package/cli/dev.js
CHANGED
|
@@ -3,6 +3,8 @@ import url from 'url';
|
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import {
|
|
5
5
|
printBuildOverview,
|
|
6
|
+
getBuildOverviewSnapshot,
|
|
7
|
+
filePathToRoute,
|
|
6
8
|
discoverFilesByPattern,
|
|
7
9
|
PAGE_FILE_PATTERN,
|
|
8
10
|
generatePagesModule,
|
|
@@ -29,16 +31,13 @@ import {
|
|
|
29
31
|
OSSY_RESOURCE_TEMPLATES_OUT,
|
|
30
32
|
} from './build.js';
|
|
31
33
|
import prerenderReactTask from './prerender-react.task.js'
|
|
32
|
-
import {
|
|
34
|
+
import { createBuildDashboard } from './build-terminal.js'
|
|
33
35
|
import { watch } from 'rollup';
|
|
34
36
|
import arg from 'arg'
|
|
35
37
|
import { spawn } from 'node:child_process'
|
|
36
38
|
// import inject from '@rollup/plugin-inject'
|
|
37
39
|
|
|
38
40
|
export const dev = async (cliArgs) => {
|
|
39
|
-
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mdev\x1b[0m')
|
|
40
|
-
console.log(' \x1b[2m────────────────────────────────────────\x1b[0m')
|
|
41
|
-
|
|
42
41
|
const options = arg({
|
|
43
42
|
'--config': String,
|
|
44
43
|
'-c': '--config',
|
|
@@ -53,7 +52,11 @@ export const dev = async (cliArgs) => {
|
|
|
53
52
|
|
|
54
53
|
resetOssyBuildDir(buildPath)
|
|
55
54
|
|
|
56
|
-
writeResourceTemplatesBarrelIfPresent({
|
|
55
|
+
const resourceTemplatesResult = writeResourceTemplatesBarrelIfPresent({
|
|
56
|
+
cwd: process.cwd(),
|
|
57
|
+
log: false,
|
|
58
|
+
})
|
|
59
|
+
let resourceTemplatesDevLogged = false
|
|
57
60
|
|
|
58
61
|
const pagesGeneratedPath = path.join(ossyGeneratedDir(buildPath), OSSY_GEN_PAGES_BASENAME)
|
|
59
62
|
fs.writeFileSync(
|
|
@@ -76,13 +79,21 @@ export const dev = async (cliArgs) => {
|
|
|
76
79
|
let middlewareSourcePath = path.resolve(options['--middleware-source'] || 'src/middleware.js');
|
|
77
80
|
const publicDir = path.resolve('public')
|
|
78
81
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
if (pageFiles.length === 0) {
|
|
83
|
+
console.log('\n \x1b[1m@ossy/app\x1b[0m \x1b[2mdev\x1b[0m')
|
|
84
|
+
printBuildOverview({
|
|
85
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
86
|
+
apiSourcePath,
|
|
87
|
+
apiOverviewFiles,
|
|
88
|
+
configPath,
|
|
89
|
+
pageFiles,
|
|
90
|
+
})
|
|
91
|
+
if (resourceTemplatesResult.wrote && resourceTemplatesResult.path) {
|
|
92
|
+
console.log(
|
|
93
|
+
`[@ossy/app][resource-templates] merged ${resourceTemplatesResult.count} template(s) → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
86
97
|
|
|
87
98
|
if (!fs.existsSync(middlewareSourcePath)) {
|
|
88
99
|
middlewareSourcePath = path.resolve(scriptDir, 'middleware.js')
|
|
@@ -247,10 +258,43 @@ export const dev = async (cliArgs) => {
|
|
|
247
258
|
const pageIds = [
|
|
248
259
|
...new Set(pageFiles.map((f) => clientHydrateIdForPage(f, srcDir))),
|
|
249
260
|
].sort()
|
|
261
|
+
const overviewSnap = getBuildOverviewSnapshot({
|
|
262
|
+
pagesSourcePath: pagesGeneratedPath,
|
|
263
|
+
apiSourcePath,
|
|
264
|
+
apiOverviewFiles,
|
|
265
|
+
configPath,
|
|
266
|
+
pageFiles,
|
|
267
|
+
})
|
|
268
|
+
const idToPath = Object.fromEntries(
|
|
269
|
+
pageFiles.map((f) => [
|
|
270
|
+
clientHydrateIdForPage(f, srcDir),
|
|
271
|
+
filePathToRoute(f, srcDir).path,
|
|
272
|
+
])
|
|
273
|
+
)
|
|
250
274
|
const reporter = pageIds.length
|
|
251
|
-
?
|
|
275
|
+
? createBuildDashboard({
|
|
276
|
+
mode: 'prerender-only',
|
|
277
|
+
pageIds,
|
|
278
|
+
idToPath,
|
|
279
|
+
overview: {
|
|
280
|
+
title: '@ossy/app dev',
|
|
281
|
+
configRel: overviewSnap.configRel,
|
|
282
|
+
apiRoutes: overviewSnap.apiRoutes,
|
|
283
|
+
},
|
|
284
|
+
})
|
|
252
285
|
: null
|
|
253
|
-
reporter?.
|
|
286
|
+
reporter?.start()
|
|
287
|
+
if (
|
|
288
|
+
!resourceTemplatesDevLogged &&
|
|
289
|
+
resourceTemplatesResult.wrote &&
|
|
290
|
+
resourceTemplatesResult.path &&
|
|
291
|
+
reporter
|
|
292
|
+
) {
|
|
293
|
+
reporter.pushLog(
|
|
294
|
+
`[resource-templates] merged ${resourceTemplatesResult.count} → ${path.relative(process.cwd(), resourceTemplatesResult.path)}`
|
|
295
|
+
)
|
|
296
|
+
resourceTemplatesDevLogged = true
|
|
297
|
+
}
|
|
254
298
|
try {
|
|
255
299
|
await prerenderReactTask.handler({
|
|
256
300
|
op: 'prerenderPagesParallel',
|
|
@@ -311,7 +355,7 @@ export const dev = async (cliArgs) => {
|
|
|
311
355
|
}
|
|
312
356
|
const norm = filename.replace(/\\/g, '/')
|
|
313
357
|
if (/\.resource\.js$/.test(norm) && norm.includes('resource-templates/')) {
|
|
314
|
-
writeResourceTemplatesBarrelIfPresent({ cwd: process.cwd(), log:
|
|
358
|
+
writeResourceTemplatesBarrelIfPresent({ cwd: process.cwd(), log: false })
|
|
315
359
|
const rtOut = path.join(resourceTemplatesDir(process.cwd()), OSSY_RESOURCE_TEMPLATES_OUT)
|
|
316
360
|
if (fs.existsSync(rtOut) && typeof watcher?.invalidate === 'function') {
|
|
317
361
|
watcher.invalidate(rtOut)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.1",
|
|
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.11.
|
|
31
|
-
"@ossy/design-system": "^1.11.
|
|
32
|
-
"@ossy/pages": "^1.11.
|
|
33
|
-
"@ossy/router": "^1.11.
|
|
34
|
-
"@ossy/router-react": "^1.11.
|
|
35
|
-
"@ossy/sdk": "^1.11.
|
|
36
|
-
"@ossy/sdk-react": "^1.11.
|
|
37
|
-
"@ossy/themes": "^1.11.
|
|
30
|
+
"@ossy/connected-components": "^1.11.1",
|
|
31
|
+
"@ossy/design-system": "^1.11.1",
|
|
32
|
+
"@ossy/pages": "^1.11.1",
|
|
33
|
+
"@ossy/router": "^1.11.1",
|
|
34
|
+
"@ossy/router-react": "^1.11.1",
|
|
35
|
+
"@ossy/sdk": "^1.11.1",
|
|
36
|
+
"@ossy/sdk-react": "^1.11.1",
|
|
37
|
+
"@ossy/themes": "^1.11.1",
|
|
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": "dfa200a3ea12c726db2054a0ab902844507716a0"
|
|
71
71
|
}
|