uniweb 0.12.13 → 0.12.14

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.12.13",
3
+ "version": "0.12.14",
4
4
  "description": "Create structured Vite + React sites with content/code separation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,9 +41,9 @@
41
41
  "js-yaml": "^4.1.0",
42
42
  "prompts": "^2.4.2",
43
43
  "tar": "^7.0.0",
44
- "@uniweb/core": "0.7.11",
44
+ "@uniweb/runtime": "0.8.13",
45
45
  "@uniweb/kit": "0.9.11",
46
- "@uniweb/runtime": "0.8.13"
46
+ "@uniweb/core": "0.7.11"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@uniweb/build": "0.14.2",
package/src/index.js CHANGED
@@ -449,14 +449,26 @@ async function main() {
449
449
  // Output convention: the version goes to stdout (parseable, scriptable —
450
450
  // `version=$(uniweb --version)` should keep working). Any staleness
451
451
  // notice goes to stderr, so it shows in interactive terminals but
452
- // doesn't pollute captured output. Cache-only — never makes a network
453
- // call from this path.
452
+ // doesn't pollute captured output.
453
+ //
454
+ // Two staleness paths split by stdout TTY-ness:
455
+ // - TTY (interactive user typed it): fetch the registry with a tight
456
+ // timeout. Accuracy matters — a fresh install would otherwise see
457
+ // no notice on its first invocation (the cache is empty). Network
458
+ // latency is acceptable here, capped at ~1.5s by the abort timeout.
459
+ // - Non-TTY (script captured stdout, piped through, etc.): cache-only.
460
+ // Scripts must stay fast and offline-safe. The `gh --version` /
461
+ // `claude --version` convention.
454
462
  if (command === '--version' || command === '-v') {
455
463
  console.log(`uniweb ${getCliVersion()}`)
456
464
  if (isGlobalInstall()) {
457
465
  try {
458
- const { maybeNotifyFromCache } = await import('./utils/update-check.js')
459
- maybeNotifyFromCache(getCliVersion(), 'soft')
466
+ const { fetchAndNotifyIfNewer, maybeNotifyFromCache } = await import('./utils/update-check.js')
467
+ if (process.stdout.isTTY) {
468
+ await fetchAndNotifyIfNewer(getCliVersion(), { tone: 'soft' })
469
+ } else {
470
+ maybeNotifyFromCache(getCliVersion(), 'soft')
471
+ }
460
472
  } catch { /* ignore */ }
461
473
  }
462
474
  return
@@ -101,6 +101,47 @@ export function maybeNotifyFromCache(currentVersion, tone = 'eager') {
101
101
  // and gets the eager default. Keeps that call site unchanged.
102
102
  export const maybeEagerNotification = maybeNotifyFromCache
103
103
 
104
+ /**
105
+ * Fetch the latest version (with a tight timeout) and print a notice if
106
+ * a newer version is found. Updates the on-disk cache as a side effect
107
+ * so future cache-only callers benefit too.
108
+ *
109
+ * Use this for TTY invocations of `--version` / `-v` where the user is
110
+ * interactively asking about the version and a brief network wait is
111
+ * acceptable. Don't use it for non-TTY callers — scripts capturing
112
+ * stdout (`version=$(uniweb -v)`) need a fast, offline-safe path.
113
+ *
114
+ * @param {string} currentVersion
115
+ * @param {object} [opts]
116
+ * @param {number} [opts.timeoutMs=1500] Network timeout. Slow / offline
117
+ * calls return silently — never block the verb for long.
118
+ * @param {'eager'|'soft'} [opts.tone='soft'] Notification copy.
119
+ * @returns {Promise<boolean>} true if a notice was printed.
120
+ */
121
+ export async function fetchAndNotifyIfNewer(currentVersion, { timeoutMs = 1500, tone = 'soft' } = {}) {
122
+ const controller = new AbortController()
123
+ const timer = setTimeout(() => controller.abort(), timeoutMs)
124
+ let latest = null
125
+ try {
126
+ const res = await fetch('https://registry.npmjs.org/uniweb/latest', { signal: controller.signal })
127
+ if (res.ok) {
128
+ const data = await res.json()
129
+ latest = data?.version || null
130
+ }
131
+ } catch {
132
+ // Aborted, network error, parse error — all silent. The verb
133
+ // shouldn't block on update-check failures.
134
+ } finally {
135
+ clearTimeout(timer)
136
+ }
137
+ if (!latest) return false
138
+ // Refresh the cache so other code paths see this fresh result.
139
+ writeState({ lastCheck: Date.now(), latestVersion: latest })
140
+ if (compareSemver(latest, currentVersion) <= 0) return false
141
+ printNotification(currentVersion, latest, tone)
142
+ return true
143
+ }
144
+
104
145
  /**
105
146
  * Start a non-blocking update check.
106
147
  *