@ossy/app 1.14.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ossy/app",
3
- "version": "1.14.0",
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.14.0",
31
- "@ossy/design-system": "^1.14.0",
32
- "@ossy/pages": "^1.14.0",
33
- "@ossy/platform": "^1.13.0",
34
- "@ossy/router": "^1.14.0",
35
- "@ossy/router-react": "^1.14.0",
36
- "@ossy/sdk": "^1.14.0",
37
- "@ossy/sdk-react": "^1.14.0",
38
- "@ossy/themes": "^1.14.0",
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": "c496b1f449dba609d65efac16aa100a02a5f0595"
71
+ "gitHead": "6476ba57e0bdf65f55dfd6671a59c7a7ad773327"
72
72
  }
package/cli/Middleware.js DELETED
@@ -1,3 +0,0 @@
1
- // dummy file so it can be imported
2
-
3
- export default undefined
@@ -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
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * Default config when src/config.js does not exist.
3
- * Provides empty defaults so the server can always merge config.
4
- */
5
- export default {}
@@ -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' }
@@ -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
- }