uniweb 0.37.1 → 0.39.0

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": "uniweb",
3
- "version": "0.37.1",
3
+ "version": "0.39.0",
4
4
  "description": "Create structured Vite + React sites with content/code separation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,15 +41,15 @@
41
41
  "js-yaml": "^4.1.0",
42
42
  "prompts": "^2.4.2",
43
43
  "tar": "^7.0.0",
44
- "@uniweb/core": "^0.16.0",
45
- "@uniweb/kit": "^0.15.3",
46
- "@uniweb/runtime": "^0.13.5",
47
- "@uniweb/semantic-parser": "^1.4.0"
44
+ "@uniweb/semantic-parser": "^1.4.0",
45
+ "@uniweb/runtime": "^0.13.7",
46
+ "@uniweb/core": "^0.18.0",
47
+ "@uniweb/kit": "^0.15.5"
48
48
  },
49
49
  "peerDependencies": {
50
- "@uniweb/build": "^0.33.0",
51
- "@uniweb/semantic-parser": "^1.4.0",
52
- "@uniweb/content-reader": "^1.2.4"
50
+ "@uniweb/build": "^0.35.0",
51
+ "@uniweb/content-reader": "^1.2.4",
52
+ "@uniweb/semantic-parser": "^1.4.0"
53
53
  },
54
54
  "peerDependenciesMeta": {
55
55
  "@uniweb/build": {
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-09-02T17:42:38.924Z",
3
+ "generatedAt": "2026-09-02T19:47:04.699Z",
4
4
  "packages": {
5
5
  "@uniweb/api": {
6
- "version": "0.2.2",
6
+ "version": "0.2.4",
7
7
  "path": "framework/api",
8
8
  "deps": [
9
9
  "@uniweb/core"
10
10
  ]
11
11
  },
12
12
  "@uniweb/build": {
13
- "version": "0.33.0",
13
+ "version": "0.35.0",
14
14
  "path": "framework/build",
15
15
  "deps": [
16
16
  "@uniweb/content-reader",
@@ -34,7 +34,7 @@
34
34
  "deps": []
35
35
  },
36
36
  "@uniweb/core": {
37
- "version": "0.16.0",
37
+ "version": "0.18.0",
38
38
  "path": "framework/core",
39
39
  "deps": [
40
40
  "@uniweb/semantic-parser",
@@ -47,14 +47,14 @@
47
47
  "deps": []
48
48
  },
49
49
  "@uniweb/icons": {
50
- "version": "0.4.7",
50
+ "version": "0.4.9",
51
51
  "path": "framework/icons",
52
52
  "deps": [
53
53
  "@uniweb/core"
54
54
  ]
55
55
  },
56
56
  "@uniweb/kit": {
57
- "version": "0.15.3",
57
+ "version": "0.15.5",
58
58
  "path": "framework/kit",
59
59
  "deps": [
60
60
  "@uniweb/core",
@@ -73,7 +73,7 @@
73
73
  "deps": []
74
74
  },
75
75
  "@uniweb/projections": {
76
- "version": "0.5.4",
76
+ "version": "0.5.6",
77
77
  "path": "framework/projections",
78
78
  "deps": [
79
79
  "@uniweb/content-writer",
@@ -81,7 +81,7 @@
81
81
  ]
82
82
  },
83
83
  "@uniweb/runtime": {
84
- "version": "0.13.5",
84
+ "version": "0.13.7",
85
85
  "path": "framework/runtime",
86
86
  "deps": [
87
87
  "@uniweb/core",
@@ -119,7 +119,7 @@
119
119
  "deps": []
120
120
  },
121
121
  "@uniweb/unipress": {
122
- "version": "0.8.20",
122
+ "version": "0.9.1",
123
123
  "path": "framework/unipress",
124
124
  "deps": [
125
125
  "@uniweb/build",
@@ -1,3 +1,23 @@
1
+ /**
2
+ * ⛔ **HUMAN OUTPUT IN THIS FILE GOES TO STDERR, NEVER STDOUT.**
3
+ *
4
+ * `stdout` is the CLI's DATA channel. `uniweb register --json` promises a single
5
+ * parseable JSON line there, and `register` diverts its own output accordingly —
6
+ * but it calls into this module, which wrote prose to stdout directly, so the
7
+ * promise broke for any caller that piped it.
8
+ *
9
+ * ⭐ Measured by the `flows` lane at `uniweb@0.37.1`: two stray lines ahead of
10
+ * the JSON on the cold path — down from ~35 before the delegated builder's
11
+ * stdout was redirected to fd 2, which is why the two defects share one symptom
12
+ * and only one of them was fixed. Every line here is prose, a prompt, or a
13
+ * cancellation notice; none of it is anything a machine reads. On stderr it is
14
+ * equally visible to a human and invisible to a pipe.
15
+ *
16
+ * ⚖️ This is not a `--json` special case. A utility that cannot see the flag
17
+ * should not be choosing the stream at all — which is exactly how it got the
18
+ * choice wrong. `cli/test/porcelain-stdout.test.js` walks `register`'s import
19
+ * graph and fails on a new `console.log`.
20
+ */
1
21
  /**
2
22
  * Registry (new-backend) credential storage + login.
3
23
  *
@@ -212,11 +232,11 @@ export async function ensureRegistryAuth({
212
232
  }
213
233
 
214
234
  if (stored && isExpired(stored)) {
215
- console.log(
235
+ console.error(
216
236
  `\x1b[33mSession expired.\x1b[0m ${command} requires a Uniweb account.\n`
217
237
  )
218
238
  } else {
219
- console.log(`${command} requires a Uniweb account.\n`)
239
+ console.error(`${command} requires a Uniweb account.\n`)
220
240
  }
221
241
 
222
242
  // Interactive: hand off to the multi-method login picker, reuse its session.
@@ -273,7 +293,7 @@ async function loginViaPassword({ apiBase, nonInteractive }) {
273
293
  ],
274
294
  {
275
295
  onCancel: () => {
276
- console.log('\nLogin cancelled.')
296
+ console.error('\nLogin cancelled.')
277
297
  process.exit(0)
278
298
  }
279
299
  }
@@ -300,7 +320,7 @@ async function loginViaTokenPaste({ apiBase, nonInteractive }) {
300
320
  },
301
321
  {
302
322
  onCancel: () => {
303
- console.log('\nLogin cancelled.')
323
+ console.error('\nLogin cancelled.')
304
324
  process.exit(0)
305
325
  }
306
326
  }
@@ -398,14 +418,14 @@ export async function awaitBrowserCallback({
398
418
  const { port } = server.address()
399
419
  const redirectUri = `http://127.0.0.1:${port}/callback`
400
420
  const url = buildUrl(redirectUri)
401
- console.log(`\x1b[36m→\x1b[0m ${openingLabel}`)
402
- console.log(` \x1b[2m${url}\x1b[0m`)
421
+ console.error(`\x1b[36m→\x1b[0m ${openingLabel}`)
422
+ console.error(` \x1b[2m${url}\x1b[0m`)
403
423
  const opened = await openBrowser(url)
404
424
  if (!opened)
405
- console.log(
425
+ console.error(
406
426
  '\x1b[33m⚠\x1b[0m Could not open a browser automatically — open the URL above.'
407
427
  )
408
- console.log(
428
+ console.error(
409
429
  `\x1b[2m${waitingLabel || `Waiting (${Math.round(timeoutMs / 1000)}s)…`}\x1b[0m`
410
430
  )
411
431
  })
@@ -528,10 +548,10 @@ export async function runRegistryLogin({ apiBase, args = [] } = {}) {
528
548
  existing.username ||
529
549
  existing.handle ||
530
550
  (existing.uuid ? `account ${existing.uuid}` : '')
531
- console.log(
551
+ console.error(
532
552
  `Already logged in${who ? ` as \x1b[1m${who}\x1b[0m` : ''}${apiBase ? ` (${apiBase})` : ''}.`
533
553
  )
534
- console.log('\x1b[2mContinuing will replace the existing session.\x1b[0m\n')
554
+ console.error('\x1b[2mContinuing will replace the existing session.\x1b[0m\n')
535
555
  }
536
556
 
537
557
  const { isNonInteractive } = await import('./interactive.js')
@@ -558,7 +578,7 @@ export async function runRegistryLogin({ apiBase, args = [] } = {}) {
558
578
  if (account?.username) record.username = account.username
559
579
  if (account?.handle) record.handle = account.handle
560
580
  await writeRegistryAuth(record)
561
- console.log(
581
+ console.error(
562
582
  `\x1b[32m✓\x1b[0m Logged in${account?.username ? ` as \x1b[1m${account.username}\x1b[0m` : ''}${apiBase ? ` (${apiBase})` : ''}`
563
583
  )
564
584
  return record
@@ -604,7 +624,7 @@ export async function runRegistryLogin({ apiBase, args = [] } = {}) {
604
624
  },
605
625
  {
606
626
  onCancel: () => {
607
- console.log('\nLogin cancelled.')
627
+ console.error('\nLogin cancelled.')
608
628
  process.exit(0)
609
629
  }
610
630
  }
@@ -626,7 +646,7 @@ export async function runRegistryLogin({ apiBase, args = [] } = {}) {
626
646
  }
627
647
 
628
648
  if (record?.token) {
629
- console.log(
649
+ console.error(
630
650
  `\x1b[32m✓\x1b[0m Logged in${record.username ? ` as \x1b[1m${record.username}\x1b[0m` : ''}${apiBase ? ` (${apiBase})` : ''}`
631
651
  )
632
652
  }
@@ -1,3 +1,23 @@
1
+ /**
2
+ * ⛔ **HUMAN OUTPUT IN THIS FILE GOES TO STDERR, NEVER STDOUT.**
3
+ *
4
+ * `stdout` is the CLI's DATA channel. `uniweb register --json` promises a single
5
+ * parseable JSON line there, and `register` diverts its own output accordingly —
6
+ * but it calls into this module, which wrote prose to stdout directly, so the
7
+ * promise broke for any caller that piped it.
8
+ *
9
+ * ⭐ Measured by the `flows` lane at `uniweb@0.37.1`: two stray lines ahead of
10
+ * the JSON on the cold path — down from ~35 before the delegated builder's
11
+ * stdout was redirected to fd 2, which is why the two defects share one symptom
12
+ * and only one of them was fixed. Every line here is prose, a prompt, or a
13
+ * cancellation notice; none of it is anything a machine reads. On stderr it is
14
+ * equally visible to a human and invisible to a pipe.
15
+ *
16
+ * ⚖️ This is not a `--json` special case. A utility that cannot see the flag
17
+ * should not be choosing the stream at all — which is exactly how it got the
18
+ * choice wrong. `cli/test/porcelain-stdout.test.js` walks `register`'s import
19
+ * graph and fails on a new `console.log`.
20
+ */
1
21
  /**
2
22
  * New-backend org operations for the publish-scope bootstrap — used by
3
23
  * `uniweb register`'s scope resolution and the `uniweb org` command.
@@ -150,7 +170,7 @@ export async function deriveScope({
150
170
  const h = orgs[0].handle
151
171
  const label = isPersonal(h) ? `your personal org @${h}` : `your org @${h}`
152
172
  if (nonInteractive) {
153
- console.log(
173
+ console.error(
154
174
  `Publishing under ${label.replace(`@${h}`, `\x1b[1m@${h}\x1b[0m`)}.`
155
175
  )
156
176
  return h
@@ -165,13 +185,13 @@ export async function deriveScope({
165
185
  },
166
186
  {
167
187
  onCancel: () => {
168
- console.log('\nCancelled.')
188
+ console.error('\nCancelled.')
169
189
  process.exit(0)
170
190
  }
171
191
  }
172
192
  )
173
193
  if (!ok) {
174
- console.log(
194
+ console.error(
175
195
  'Pass --scope @org, or create another with `uniweb org create <handle>`.'
176
196
  )
177
197
  return null
@@ -189,7 +209,7 @@ export async function deriveScope({
189
209
  ordered.find((u) => isPersonal(u.handle)) ||
190
210
  orgs.find((u) => u.is_primary) ||
191
211
  orgs[0]
192
- console.log(
212
+ console.error(
193
213
  `Multiple orgs; using \x1b[1m@${pick.handle}\x1b[0m (non-interactive).`
194
214
  )
195
215
  return pick.handle
@@ -208,7 +228,7 @@ export async function deriveScope({
208
228
  },
209
229
  {
210
230
  onCancel: () => {
211
- console.log('\nCancelled.')
231
+ console.error('\nCancelled.')
212
232
  process.exit(0)
213
233
  }
214
234
  }
@@ -281,7 +301,7 @@ export async function offerCreateOrg({
281
301
  { title: 'A new organization…', value: ':new' }
282
302
  ]
283
303
  if (!canClaimPersonal) {
284
- console.log(
304
+ console.error(
285
305
  `\x1b[2m@${personal} exists but you're not a member of it — ask its admin, or create another org.\x1b[0m`
286
306
  )
287
307
  }
@@ -296,7 +316,7 @@ export async function offerCreateOrg({
296
316
  },
297
317
  {
298
318
  onCancel: () => {
299
- console.log('\nCancelled.')
319
+ console.error('\nCancelled.')
300
320
  process.exit(0)
301
321
  }
302
322
  }
@@ -314,7 +334,7 @@ export async function offerCreateOrg({
314
334
  },
315
335
  {
316
336
  onCancel: () => {
317
- console.log('\nCancelled.')
337
+ console.error('\nCancelled.')
318
338
  process.exit(0)
319
339
  }
320
340
  }
@@ -325,7 +345,7 @@ export async function offerCreateOrg({
325
345
 
326
346
  try {
327
347
  const org = await createOrg({ apiBase, token, handle })
328
- console.log(
348
+ console.error(
329
349
  `\x1b[32m✓\x1b[0m Created \x1b[1m@${org.handle}\x1b[0m — you're a member${org.is_primary ? ' (primary)' : ''}.`
330
350
  )
331
351
  return org.handle