@ossy/app 1.15.0 → 1.15.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.js +225 -748
- package/package.json +11 -11
- package/cli/Middleware.js +0 -3
- package/cli/build-terminal.js +0 -242
- package/cli/default-config.js +0 -5
- package/cli/prerender-react.task.js +0 -8
- package/cli/render-page.task.js +0 -51
- package/scripts/ensure-build-stubs.mjs +0 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -27,15 +27,15 @@
|
|
|
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.15.
|
|
31
|
-
"@ossy/design-system": "^1.15.
|
|
32
|
-
"@ossy/pages": "^1.15.
|
|
33
|
-
"@ossy/platform": "^1.14.
|
|
34
|
-
"@ossy/router": "^1.15.
|
|
35
|
-
"@ossy/router-react": "^1.15.
|
|
36
|
-
"@ossy/sdk": "^1.15.
|
|
37
|
-
"@ossy/sdk-react": "^1.15.
|
|
38
|
-
"@ossy/themes": "^1.15.
|
|
30
|
+
"@ossy/connected-components": "^1.15.1",
|
|
31
|
+
"@ossy/design-system": "^1.15.1",
|
|
32
|
+
"@ossy/pages": "^1.15.1",
|
|
33
|
+
"@ossy/platform": "^1.14.1",
|
|
34
|
+
"@ossy/router": "^1.15.1",
|
|
35
|
+
"@ossy/router-react": "^1.15.1",
|
|
36
|
+
"@ossy/sdk": "^1.15.1",
|
|
37
|
+
"@ossy/sdk-react": "^1.15.1",
|
|
38
|
+
"@ossy/themes": "^1.15.1",
|
|
39
39
|
"@rollup/plugin-alias": "^6.0.0",
|
|
40
40
|
"@rollup/plugin-babel": "6.1.0",
|
|
41
41
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"README.md",
|
|
69
69
|
"tsconfig.json"
|
|
70
70
|
],
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "6476ba57e0bdf65f55dfd6671a59c7a7ad773327"
|
|
72
72
|
}
|
package/cli/Middleware.js
DELETED
package/cli/build-terminal.js
DELETED
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
2
|
-
|
|
3
|
-
const dim = (s) => `\x1b[2m${s}\x1b[0m`
|
|
4
|
-
const bold = (s) => `\x1b[1m${s}\x1b[0m`
|
|
5
|
-
const green = (s) => `\x1b[32m${s}\x1b[0m`
|
|
6
|
-
const red = (s) => `\x1b[31m${s}\x1b[0m`
|
|
7
|
-
const yellow = (s) => `\x1b[33m${s}\x1b[0m`
|
|
8
|
-
|
|
9
|
-
function stripAnsi (s) {
|
|
10
|
-
return String(s).replace(/\x1b\[[0-9;]*m/g, '')
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function padVisible (s, width) {
|
|
14
|
-
const n = stripAnsi(s).length
|
|
15
|
-
return n >= width ? s : s + ' '.repeat(width - n)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function truncateVisible (s, maxW) {
|
|
19
|
-
const plain = stripAnsi(s)
|
|
20
|
-
if (plain.length <= maxW) return s
|
|
21
|
-
const cut = Math.max(0, maxW - 1)
|
|
22
|
-
return plain.slice(0, cut) + '…'
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function pageIdFromHydrateEntryName (entryName) {
|
|
26
|
-
const p = String(entryName)
|
|
27
|
-
return p.startsWith('hydrate__') ? p.slice('hydrate__'.length) : p
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function fmtPart (part, shortLabel, frame) {
|
|
31
|
-
if (part.s === 'idle') return dim('—')
|
|
32
|
-
if (part.s === 'running') {
|
|
33
|
-
const sp = SPINNER[frame % SPINNER.length]
|
|
34
|
-
return `${yellow(sp)} ${dim(shortLabel + '…')}`
|
|
35
|
-
}
|
|
36
|
-
if (part.s === 'ok') return `${green('✔')} ${dim(`${part.ms}ms`)}`
|
|
37
|
-
if (part.s === 'fail') return `${red('✖')} ${dim(shortLabel)}`
|
|
38
|
-
if (part.s === 'skip') return dim(part.note ? `— ${part.note}` : '—')
|
|
39
|
-
return dim('—')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function rowLeadIcon (r, mode) {
|
|
43
|
-
if (mode === 'prerender-only') {
|
|
44
|
-
const p = r.prerender.s
|
|
45
|
-
if (p === 'fail') return red('✖')
|
|
46
|
-
if (p === 'running') return yellow('◐')
|
|
47
|
-
if (p === 'ok' || p === 'skip') return green('✔')
|
|
48
|
-
if (p === 'idle') return dim('·')
|
|
49
|
-
return green('✔')
|
|
50
|
-
}
|
|
51
|
-
const b = r.bundle.s
|
|
52
|
-
const p = r.prerender.s
|
|
53
|
-
if (b === 'fail' || p === 'fail') return red('✖')
|
|
54
|
-
if (b === 'running' || p === 'running') return yellow('◐')
|
|
55
|
-
if (b === 'ok' && p === 'idle') return yellow('◐')
|
|
56
|
-
if (b === 'ok' && (p === 'ok' || p === 'skip')) return green('✔')
|
|
57
|
-
if (b === 'idle' && p === 'idle') return dim('·')
|
|
58
|
-
return green('✔')
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function useTty (stream) {
|
|
62
|
-
return (
|
|
63
|
-
stream.isTTY === true &&
|
|
64
|
-
process.env.TERM !== 'dumb' &&
|
|
65
|
-
process.env.CI !== 'true' &&
|
|
66
|
-
process.env.OSSY_PLAIN_OUTPUT !== '1'
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function createBuildDashboard ({
|
|
71
|
-
scope = '@ossy/app',
|
|
72
|
-
mode = 'full',
|
|
73
|
-
pageIds,
|
|
74
|
-
idToPath = {},
|
|
75
|
-
overview = { title: '@ossy/app', configRel: null, apiRoutes: [] },
|
|
76
|
-
stream = process.stdout,
|
|
77
|
-
} = {}) {
|
|
78
|
-
const ids = [...pageIds].sort()
|
|
79
|
-
const maxId = Math.max(6, ...ids.map((id) => String(id).length))
|
|
80
|
-
const tty = useTty(stream)
|
|
81
|
-
const termW = Math.max(60, stream.columns || 100)
|
|
82
|
-
|
|
83
|
-
const rows = new Map()
|
|
84
|
-
for (const id of ids) {
|
|
85
|
-
rows.set(id, {
|
|
86
|
-
bundle: { s: 'idle' },
|
|
87
|
-
prerender: { s: 'idle' },
|
|
88
|
-
})
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
let frame = 0
|
|
92
|
-
let spinTimer = null
|
|
93
|
-
let blockLines = 0
|
|
94
|
-
|
|
95
|
-
const anyRunning = () => {
|
|
96
|
-
for (const r of rows.values()) {
|
|
97
|
-
if (r.bundle.s === 'running' || r.prerender.s === 'running') return true
|
|
98
|
-
}
|
|
99
|
-
return false
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function headerLines () {
|
|
103
|
-
const out = []
|
|
104
|
-
out.push(bold(overview.title || `${scope} build`))
|
|
105
|
-
if (overview.configRel) {
|
|
106
|
-
out.push(`${dim('config')} ${truncateVisible(overview.configRel, termW - 10)}`)
|
|
107
|
-
}
|
|
108
|
-
const api = overview.apiRoutes || []
|
|
109
|
-
if (api.length > 0) {
|
|
110
|
-
if (api.length <= 2) {
|
|
111
|
-
for (const r of api) {
|
|
112
|
-
out.push(`${dim('api')} ${truncateVisible(`${r.id} ${r.path}`, termW - 6)}`)
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
out.push(`${dim('api')} ${api.length} routes`)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
out.push(dim('─'.repeat(Math.min(termW - 2, 44))))
|
|
119
|
-
return out
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function lineForPageRow (id) {
|
|
123
|
-
const r = rows.get(id)
|
|
124
|
-
const lead = rowLeadIcon(r, mode)
|
|
125
|
-
const pathStr = idToPath[id] != null ? dim(String(idToPath[id])) : ''
|
|
126
|
-
const idCol = padVisible(dim(String(id)), maxId)
|
|
127
|
-
const pathPad = padVisible(pathStr, 14)
|
|
128
|
-
const p = fmtPart(r.prerender, 'html', frame)
|
|
129
|
-
if (mode === 'prerender-only') {
|
|
130
|
-
return ` ${lead} ${dim(scope)} ${idCol} ${pathPad} ${p}`
|
|
131
|
-
}
|
|
132
|
-
const b = fmtPart(r.bundle, 'hydrate', frame)
|
|
133
|
-
return ` ${lead} ${dim(scope)} ${idCol} ${pathPad} ${padVisible(b, 20)} ${p}`
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function buildLines () {
|
|
137
|
-
return [...headerLines(), ...ids.map((id) => lineForPageRow(id))]
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function redraw () {
|
|
141
|
-
if (!tty) return
|
|
142
|
-
const lines = buildLines()
|
|
143
|
-
if (blockLines === 0) {
|
|
144
|
-
for (const ln of lines) stream.write(ln + '\n')
|
|
145
|
-
blockLines = lines.length
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
stream.write(`\x1b[${blockLines}A`)
|
|
149
|
-
for (const ln of lines) stream.write(`\x1b[2K\r${ln}\n`)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function ensureSpin () {
|
|
153
|
-
if (!tty || spinTimer) return
|
|
154
|
-
spinTimer = setInterval(() => {
|
|
155
|
-
frame += 1
|
|
156
|
-
redraw()
|
|
157
|
-
}, 80)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function stopSpin () {
|
|
161
|
-
if (spinTimer) {
|
|
162
|
-
clearInterval(spinTimer)
|
|
163
|
-
spinTimer = null
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function nonTtyLine (id, phase, ok, ms, err) {
|
|
168
|
-
const label = phase === 'bundle' ? 'hydrate' : 'prerender'
|
|
169
|
-
const icon = ok ? green('✔') : red('✖')
|
|
170
|
-
const time = ms != null ? dim(` (${ms}ms)`) : ''
|
|
171
|
-
stream.write(`${icon} ${dim(`${scope}:${label}:`)}${id}${time}\n`)
|
|
172
|
-
if (err && !ok) stream.write(` ${red(String(err.message || err))}\n`)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
start () {
|
|
177
|
-
if (!tty) {
|
|
178
|
-
for (const ln of headerLines()) stream.write(`${ln}\n`)
|
|
179
|
-
stream.write('\n')
|
|
180
|
-
return
|
|
181
|
-
}
|
|
182
|
-
redraw()
|
|
183
|
-
},
|
|
184
|
-
|
|
185
|
-
startBundle (pageId) {
|
|
186
|
-
if (mode === 'prerender-only') return
|
|
187
|
-
const r = rows.get(pageId)
|
|
188
|
-
if (!r) return
|
|
189
|
-
r.bundle = { s: 'running' }
|
|
190
|
-
ensureSpin()
|
|
191
|
-
redraw()
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
completeBundle (pageId, { ok, ms, error }) {
|
|
195
|
-
if (mode === 'prerender-only') return
|
|
196
|
-
const r = rows.get(pageId)
|
|
197
|
-
if (!r) return
|
|
198
|
-
r.bundle = ok ? { s: 'ok', ms } : { s: 'fail', ms, error }
|
|
199
|
-
if (!ok) {
|
|
200
|
-
r.prerender = { s: 'skip', note: 'bundle failed' }
|
|
201
|
-
if (!tty) nonTtyLine(pageId, 'bundle', false, ms, error)
|
|
202
|
-
}
|
|
203
|
-
if (!anyRunning()) stopSpin()
|
|
204
|
-
redraw()
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
startPrerender (pageId) {
|
|
208
|
-
const r = rows.get(pageId)
|
|
209
|
-
if (!r || r.prerender.s === 'skip') return
|
|
210
|
-
r.prerender = { s: 'running' }
|
|
211
|
-
ensureSpin()
|
|
212
|
-
redraw()
|
|
213
|
-
},
|
|
214
|
-
|
|
215
|
-
completePrerender (pageId, { ok, ms, error }) {
|
|
216
|
-
const r = rows.get(pageId)
|
|
217
|
-
if (!r || r.prerender.s === 'skip') return
|
|
218
|
-
r.prerender = ok ? { s: 'ok', ms } : { s: 'fail', ms, error }
|
|
219
|
-
if (!tty) nonTtyLine(pageId, 'prerender', ok, ms, error)
|
|
220
|
-
if (!anyRunning()) stopSpin()
|
|
221
|
-
redraw()
|
|
222
|
-
},
|
|
223
|
-
|
|
224
|
-
skipPrerender (pageId, note) {
|
|
225
|
-
const r = rows.get(pageId)
|
|
226
|
-
if (!r) return
|
|
227
|
-
if (r.bundle.s === 'fail') return
|
|
228
|
-
r.prerender = { s: 'skip', note: note || 'skipped' }
|
|
229
|
-
if (!tty) stream.write(`${dim('—')} ${scope}:prerender:${pageId} (${note})\n`)
|
|
230
|
-
redraw()
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
dispose () {
|
|
234
|
-
stopSpin()
|
|
235
|
-
if (tty && blockLines > 0) {
|
|
236
|
-
redraw()
|
|
237
|
-
stream.write('\n')
|
|
238
|
-
blockLines = 0
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
|
-
}
|
|
242
|
-
}
|
package/cli/default-config.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
|
|
3
|
-
export function staticHtmlPathForRoute (routePath, publicDir) {
|
|
4
|
-
const segments = routePath === '/' ? [] : routePath.replace(/^\//, '').split('/')
|
|
5
|
-
return path.join(publicDir, ...segments, 'index.html')
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export default { type: '@ossy/app/prerender-react' }
|
package/cli/render-page.task.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { renderPage as ssrRender } from '../ssr/app.mjs'
|
|
2
|
-
|
|
3
|
-
export function buildPrerenderAppConfig ({
|
|
4
|
-
buildTimeConfig,
|
|
5
|
-
pageList,
|
|
6
|
-
activeRouteId,
|
|
7
|
-
urlPath,
|
|
8
|
-
isAuthenticated = false,
|
|
9
|
-
}) {
|
|
10
|
-
const pages = pageList.map((page) => ({
|
|
11
|
-
id: page?.id,
|
|
12
|
-
path: page?.path,
|
|
13
|
-
}))
|
|
14
|
-
return {
|
|
15
|
-
...buildTimeConfig,
|
|
16
|
-
url: urlPath,
|
|
17
|
-
theme: buildTimeConfig.theme || 'light',
|
|
18
|
-
isAuthenticated,
|
|
19
|
-
workspaceId: buildTimeConfig.workspaceId,
|
|
20
|
-
apiUrl: buildTimeConfig.apiUrl,
|
|
21
|
-
pages,
|
|
22
|
-
pageId: activeRouteId,
|
|
23
|
-
sidebarPrimaryCollapsed: false,
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function jsonSafeClone (value) {
|
|
28
|
-
if (value == null || typeof value !== 'object') return value
|
|
29
|
-
try {
|
|
30
|
-
return JSON.parse(JSON.stringify(value))
|
|
31
|
-
} catch {
|
|
32
|
-
return value
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function buildHydrationAppConfig (appConfig) {
|
|
37
|
-
if (!appConfig || typeof appConfig !== 'object') return appConfig
|
|
38
|
-
return {
|
|
39
|
-
...appConfig,
|
|
40
|
-
theme: jsonSafeClone(appConfig.theme),
|
|
41
|
-
themes: jsonSafeClone(appConfig.themes),
|
|
42
|
-
resourceTemplates: jsonSafeClone(appConfig.resourceTemplates),
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export const BuildPage = {
|
|
47
|
-
async handle ({ route, appConfig }) {
|
|
48
|
-
const config = buildHydrationAppConfig(appConfig)
|
|
49
|
-
return ssrRender(route.id, config, {})
|
|
50
|
-
},
|
|
51
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import { fileURLToPath } from 'url'
|
|
4
|
-
|
|
5
|
-
const STUBS = [
|
|
6
|
-
['middleware.js', 'export default []\n'],
|
|
7
|
-
]
|
|
8
|
-
|
|
9
|
-
/** Ensures build/middleware.js exists when Rollup omits an empty middleware chunk. */
|
|
10
|
-
export function ensureBuildStubs(buildDir) {
|
|
11
|
-
if (!fs.existsSync(buildDir)) {
|
|
12
|
-
console.warn(`[ensure-build-stubs] skip: ${buildDir} missing`)
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
for (const [name, content] of STUBS) {
|
|
16
|
-
const filePath = path.join(buildDir, name)
|
|
17
|
-
if (!fs.existsSync(filePath)) {
|
|
18
|
-
fs.writeFileSync(filePath, content)
|
|
19
|
-
console.log(`[ensure-build-stubs] wrote ${name} (rollup omitted empty chunk)`)
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const isMain =
|
|
25
|
-
process.argv[1] &&
|
|
26
|
-
path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)
|
|
27
|
-
|
|
28
|
-
if (isMain) {
|
|
29
|
-
const buildDir = path.join(process.cwd(), 'build')
|
|
30
|
-
if (!fs.existsSync(buildDir)) {
|
|
31
|
-
console.error('[ensure-build-stubs] build/ missing; run build first')
|
|
32
|
-
process.exit(1)
|
|
33
|
-
}
|
|
34
|
-
ensureBuildStubs(buildDir)
|
|
35
|
-
}
|