@uniweb/build 1.10.2 → 1.10.4

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/build",
3
- "version": "1.10.2",
3
+ "version": "1.10.4",
4
4
  "description": "Build tooling for the Uniweb Component Web Platform",
5
5
  "type": "module",
6
6
  "exports": {
@@ -56,12 +56,12 @@
56
56
  "js-yaml": "^4.3.2",
57
57
  "sharp": "^0.35.5",
58
58
  "yaml": "^2.5.0",
59
- "@uniweb/content-reader": "~1.5.7",
60
- "@uniweb/projections": "~1.2.1",
61
59
  "@uniweb/semantic-parser": "~1.13.0",
60
+ "@uniweb/content-reader": "~1.5.7",
61
+ "@uniweb/content-writer": "~1.3.1",
62
62
  "@uniweb/schemas": "~1.6.5",
63
- "@uniweb/theming": "~1.2.1",
64
- "@uniweb/content-writer": "~1.3.1"
63
+ "@uniweb/projections": "~1.2.1",
64
+ "@uniweb/theming": "~1.2.1"
65
65
  },
66
66
  "optionalDependencies": {
67
67
  "@uniweb/runtime": "~1.2.3"
@@ -601,9 +601,10 @@ function mountHasContent(dirPath) {
601
601
  *
602
602
  * Split out from resolveMounts so the dev server can learn which directories a
603
603
  * site mounts without re-running resolveMounts' validation — that would repeat
604
- * its warnings on every startup, and the watcher only needs paths. Both callers
605
- * share this one definition of what a mount key looks like, so the prefix can
606
- * never mean one thing to the collector and another to the watcher.
604
+ * its warnings on every startup, and the watcher only needs paths. Every reader —
605
+ * the collector, the watcher, a pull (`uwx/git-authored.js`) and `uniweb status` among
606
+ * them — shares this one definition of what a mount key looks like, so the prefix can never mean
607
+ * one thing to one of them and another to the next.
607
608
  *
608
609
  * @param {Object} pathsConfig - The paths: object from site.yml
609
610
  * @returns {Array<[string, string]>} [routeSegment, relativePath] pairs
@@ -297,3 +297,54 @@ export async function forgetDeployYml(siteDir) {
297
297
  await unlink(path)
298
298
  return names
299
299
  }
300
+
301
+ /**
302
+ * Move a deploy.yml off the keys retired on 2026-09-20 — `lastDeploy:` to `deploys:`, and
303
+ * `autoSave:` to `saveDeploys:` — keeping its comments.
304
+ *
305
+ * ⛔ NOTHING READS THE OLD KEYS, and a renamed key returns empty rather than failing: a
306
+ * target's record under `lastDeploy:` is a deploy nothing can see, and `autoSave: off` is
307
+ * ignored, so deploys are recorded after all. `uniweb doctor` names both, and this is its fix.
308
+ *
309
+ * A target's record moves to `deploys:` when that target has none there; when it has, the
310
+ * one in `deploys:` is newer, and the old is dropped. `autoSave: off` becomes
311
+ * `saveDeploys: false`; any other value is the default, and goes.
312
+ *
313
+ * @param {string} siteDir
314
+ * @returns {Promise<{ moved: string[], dropped: string[], saveDeploys: boolean|null } | null>}
315
+ * null when the file has neither key, or there is no file
316
+ */
317
+ export async function retireDeployYmlKeys(siteDir) {
318
+ const path = join(siteDir, 'deploy.yml')
319
+ if (!existsSync(path)) return null
320
+ const doc = parseDocument(await readFile(path, 'utf8'))
321
+ if (doc.errors.length) throw new Error(`${path}: ${doc.errors[0].message}`)
322
+ const old = doc.get('lastDeploy')
323
+ const autoSave = doc.get('autoSave')
324
+ if (old === undefined && autoSave === undefined) return null
325
+ const moved = []
326
+ const dropped = []
327
+ if (isMap(old)) {
328
+ if (!isMap(doc.get('deploys'))) doc.set('deploys', doc.createNode({}))
329
+ const deploys = doc.get('deploys')
330
+ for (const pair of old.items) {
331
+ const name = String(pair.key?.value ?? pair.key)
332
+ if (deploys.has(name)) dropped.push(name)
333
+ else {
334
+ deploys.set(name, pair.value)
335
+ moved.push(name)
336
+ }
337
+ }
338
+ }
339
+ doc.delete('lastDeploy')
340
+ let saveDeploys = null
341
+ if (autoSave !== undefined) {
342
+ if (String(autoSave) === 'off' && !doc.has('saveDeploys')) {
343
+ doc.set('saveDeploys', false)
344
+ saveDeploys = false
345
+ }
346
+ doc.delete('autoSave')
347
+ }
348
+ await writeFile(path, String(doc))
349
+ return { moved, dropped, saveDeploys }
350
+ }
package/src/site/index.js CHANGED
@@ -14,7 +14,7 @@ export { PREVIEW_ENV, encodePreview, readPreview } from './preview.js'
14
14
  export { DEV_PORT_ENV, DEV_RECORD_ENV, runningDevServer, stopDevServer } from './dev-server.js'
15
15
  // Where a statically built site lives, as its deploy target or author states it (`./site-address.js`).
16
16
  export { ORIGIN_ENV, refuseUnreadableAddress } from './site-address.js'
17
- export { collectSiteContent } from './content-collector.js'
17
+ export { collectSiteContent, mountEntriesOf } from './content-collector.js'
18
18
  // The `agents:` vocabulary lives in @uniweb/projections (which owns the block);
19
19
  // re-exported so the CLI can validate an author's spelling, and read an
20
20
  // `expectedOrigins` entry by its rule, without taking a direct dependency on it.
@@ -57,4 +57,4 @@ export {
57
57
  mergeDataIntoContent
58
58
  } from './data-fetcher.js'
59
59
  export { loadDeployYml, resolveTarget, resolvePublishTarget } from './deploy-config.js'
60
- export { recordLastDeploy, recordTarget, forgetDeploys, forgetDeployYml } from './deploy-config-writer.js'
60
+ export { recordLastDeploy, recordTarget, forgetDeploys, forgetDeployYml, retireDeployYmlKeys } from './deploy-config-writer.js'