@publish.os/nextjs 0.0.1-alpha.81 → 0.0.1-alpha.91

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.
Files changed (265) hide show
  1. package/compiler-assets/nextjs/defaults/app/globals.css +1 -0
  2. package/compiler-assets/nextjs/defaults/group/index.tsx +50 -0
  3. package/compiler-assets/nextjs/defaults/group/layout.tsx +8 -8
  4. package/compiler-assets/nextjs/defaults/group/page.tsx +44 -43
  5. package/compiler-assets/nextjs/defaults/project/next.config.mjs +33 -13
  6. package/compiler-assets/nextjs/defaults/project/tsconfig.json.template +10 -3
  7. package/compiler-assets/nextjs/defaults/root/css/animation.css +131 -0
  8. package/compiler-assets/nextjs/defaults/root/css/components/code-block.css +18 -0
  9. package/compiler-assets/nextjs/defaults/root/css/components/dialog.css +4 -1
  10. package/compiler-assets/nextjs/defaults/root/css/components/menu.css +1 -1
  11. package/compiler-assets/nextjs/defaults/root/css/components/navigation-menu.css +1 -1
  12. package/compiler-assets/nextjs/defaults/root/css/components/popover.css +1 -1
  13. package/compiler-assets/nextjs/defaults/root/css/components/select.css +1 -1
  14. package/compiler-assets/nextjs/defaults/root/css/components/tooltip.css +1 -1
  15. package/compiler-assets/nextjs/defaults/root/css/shadow.css +6 -25
  16. package/compiler-assets/nextjs/defaults/root/css/typography.css +51 -68
  17. package/compiler-assets/nextjs/defaults/root/globals.css +25 -0
  18. package/compiler-assets/nextjs/defaults/root/{page.tsx → index.tsx} +6 -2
  19. package/compiler-assets/nextjs/defaults/root/layout.tsx +7 -1
  20. package/compiler-assets/nextjs/defaults/root/theme.css +22 -22
  21. package/compiler-assets/nextjs/shims/document.tsx +38 -0
  22. package/compiler-assets/nextjs/shims/generated-group-page.tsx +19 -2
  23. package/compiler-assets/nextjs/shims/generated-leaf-page.tsx +18 -2
  24. package/compiler-assets/nextjs/shims/global-layout.tsx +19 -85
  25. package/compiler-assets/nextjs/shims/global-not-found.tsx +69 -0
  26. package/compiler-assets/nextjs/shims/markdown-route.ts +2 -0
  27. package/compiler-assets/nextjs/shims/metadata-icons.tsx +39 -0
  28. package/compiler-assets/nextjs/shims/not-found-content.tsx +53 -0
  29. package/compiler-assets/nextjs/shims/not-found-navigation.tsx +60 -0
  30. package/compiler-assets/nextjs/shims/proxy.ts +143 -65
  31. package/compiler-assets/nextjs/shims/publish-os-theme-provider.tsx +76 -15
  32. package/compiler-assets/nextjs/shims/root-page.tsx +7 -1
  33. package/compiler-assets/nextjs/shims/site-fenced-code-block.tsx +30 -0
  34. package/compiler-assets/nextjs/shims/site-heading-level.tsx +14 -0
  35. package/compiler-assets/nextjs/shims/site-mdx-components.tsx +112 -0
  36. package/compiler-assets/nextjs/shims/site-mdx.tsx +17 -0
  37. package/compiler-assets/nextjs/shims/theme-defaults.css +41 -25
  38. package/dist/build-operation-5QMLXF7N.js +89 -0
  39. package/dist/{button-CFdx-ohV.d.ts → button-BdCScEKi.d.ts} +6 -6
  40. package/dist/capture-local-source-WGGDIUU2.js +258 -0
  41. package/dist/chunk-22RSSUNV.js +13 -0
  42. package/dist/chunk-4BC2L2KA.js +620 -0
  43. package/dist/chunk-5J3YUNRY.js +121 -0
  44. package/dist/chunk-5KAD7W53.js +248 -0
  45. package/dist/chunk-6C65KV7O.js +142 -0
  46. package/dist/chunk-6D2E6UMD.js +695 -0
  47. package/dist/chunk-7NY22B5U.js +161 -0
  48. package/dist/chunk-AI2UULNX.js +9 -0
  49. package/dist/chunk-EFO6AWXN.js +19 -0
  50. package/dist/chunk-F3AGNDF4.js +2377 -0
  51. package/dist/chunk-GBPLER5H.js +426 -0
  52. package/dist/chunk-IL4RJOKI.js +186 -0
  53. package/dist/chunk-NNBJZPFM.js +193 -0
  54. package/dist/chunk-ORIUWJBQ.js +58 -0
  55. package/dist/chunk-OXOFRXEI.js +7129 -0
  56. package/dist/chunk-UYGCOWRF.js +1709 -0
  57. package/dist/chunk-WL75GQ5M.js +80 -0
  58. package/dist/compiler.d.ts +54 -7
  59. package/dist/compiler.js +121 -13147
  60. package/dist/components/blocks/agent-actions.d.ts +81 -0
  61. package/dist/components/blocks/agent-actions.js +594 -0
  62. package/dist/components/blocks/toc.d.ts +43 -0
  63. package/dist/components/blocks/toc.js +136 -0
  64. package/dist/components/ui/button.d.ts +5 -0
  65. package/dist/components/ui/button.js +94 -0
  66. package/dist/compose-CVBJRAF6.js +16 -0
  67. package/dist/config/createNextConfig.js +27 -0
  68. package/dist/dev-operation-OSHHWRWK.js +1095 -0
  69. package/dist/framework-selection-ZVO323PK.js +11 -0
  70. package/dist/ide-support-CU6Z5PVR.js +16 -0
  71. package/dist/index.d.ts +55 -4
  72. package/dist/jsx-dev-runtime.d.ts +6 -0
  73. package/dist/jsx-dev-runtime.js +100 -0
  74. package/dist/jsx-runtime.d.ts +7 -0
  75. package/dist/jsx-runtime.js +97 -0
  76. package/dist/kernel/components/blocks/AgentActions.d.ts +35 -6
  77. package/dist/kernel/components/blocks/AgentActions.js +401 -150
  78. package/dist/kernel/components/blocks/agent-actions.d.ts +5 -0
  79. package/dist/kernel/components/blocks/agent-actions.js +594 -0
  80. package/dist/kernel/components/blocks/animated-icon-swap.js +1 -1
  81. package/dist/kernel/components/blocks/color-palette.js +4 -4
  82. package/dist/kernel/components/blocks/logo-block.js +3 -3
  83. package/dist/kernel/components/blocks/nav-breadcrumb.d.ts +10 -2
  84. package/dist/kernel/components/blocks/nav-breadcrumb.js +22 -7
  85. package/dist/kernel/components/blocks/navbar.d.ts +2 -2
  86. package/dist/kernel/components/blocks/navbar.js +406 -65
  87. package/dist/kernel/components/blocks/navigation-progress.js +6 -3
  88. package/dist/kernel/components/blocks/next-prev.d.ts +1 -1
  89. package/dist/kernel/components/blocks/next-prev.js +12 -24
  90. package/dist/kernel/components/blocks/page-list.d.ts +1 -1
  91. package/dist/kernel/components/blocks/page-list.js +7 -6
  92. package/dist/kernel/components/blocks/search.d.ts +83 -58
  93. package/dist/kernel/components/blocks/search.js +554 -428
  94. package/dist/kernel/components/blocks/sidebar-node.d.ts +2 -2
  95. package/dist/kernel/components/blocks/sidebar-node.js +12 -10
  96. package/dist/kernel/components/blocks/sidebar.d.ts +3 -3
  97. package/dist/kernel/components/blocks/sidebar.js +24 -14
  98. package/dist/kernel/components/blocks/theme-toggle.d.ts +2 -2
  99. package/dist/kernel/components/blocks/theme-toggle.js +47 -1
  100. package/dist/kernel/components/blocks/toc-client.d.ts +40 -0
  101. package/dist/kernel/components/blocks/toc-client.js +495 -0
  102. package/dist/kernel/components/blocks/toc.d.ts +19 -1
  103. package/dist/kernel/components/blocks/toc.js +122 -180
  104. package/dist/kernel/components/mdx/components/blockquote.js +2 -2
  105. package/dist/kernel/components/mdx/components/callout.d.ts +5 -7
  106. package/dist/kernel/components/mdx/components/callout.js +67 -36
  107. package/dist/kernel/components/mdx/components/code-block.d.ts +5 -2
  108. package/dist/kernel/components/mdx/components/code-block.js +106 -5
  109. package/dist/kernel/components/mdx/components/copy-code-button.d.ts +8 -0
  110. package/dist/kernel/components/mdx/components/copy-code-button.js +61 -0
  111. package/dist/kernel/components/mdx/components/figure-caption.d.ts +1 -1
  112. package/dist/kernel/components/mdx/components/figure-caption.js +4 -3
  113. package/dist/kernel/components/mdx/components/figure.d.ts +6 -2
  114. package/dist/kernel/components/mdx/components/figure.js +24 -14
  115. package/dist/kernel/components/mdx/components/footnotes.js +1 -1
  116. package/dist/kernel/components/mdx/components/heading-copy-link.js +4 -4
  117. package/dist/kernel/components/mdx/components/heading.js +6 -3
  118. package/dist/kernel/components/mdx/components/hr.js +2 -2
  119. package/dist/kernel/components/mdx/components/image-zoom.js +2 -2
  120. package/dist/kernel/components/mdx/components/image.d.ts +1 -1
  121. package/dist/kernel/components/mdx/components/image.js +94 -68
  122. package/dist/kernel/components/mdx/components/inline-code.js +2 -2
  123. package/dist/kernel/components/mdx/components/kbd.d.ts +2 -2
  124. package/dist/kernel/components/mdx/components/kbd.js +5 -4
  125. package/dist/kernel/components/mdx/components/link.d.ts +35 -4
  126. package/dist/kernel/components/mdx/components/link.js +3 -3
  127. package/dist/kernel/components/mdx/components/paragraph.js +2 -5
  128. package/dist/kernel/components/mdx/components/strikethrough.js +1 -1
  129. package/dist/kernel/components/mdx/components/table.js +2 -2
  130. package/dist/kernel/components/mdx/components/task-list.js +2 -2
  131. package/dist/kernel/components/mdx/components/video-player.d.ts +6 -2
  132. package/dist/kernel/components/mdx/components/video-player.js +8 -4
  133. package/dist/kernel/components/mdx/components/video.d.ts +5 -3
  134. package/dist/kernel/components/mdx/components/video.js +8 -6
  135. package/dist/kernel/components/mdx/error-boundary.js +2 -2
  136. package/dist/kernel/components/mdx/error-fallback.js +1 -1
  137. package/dist/kernel/components/mdx/mdx.d.ts +28 -14
  138. package/dist/kernel/components/mdx/mdx.js +336 -63
  139. package/dist/kernel/components/mdx/rehype-heading-ids.d.ts +1 -0
  140. package/dist/kernel/components/mdx/rehype-heading-ids.js +6 -4
  141. package/dist/kernel/components/next-image.d.ts +12 -0
  142. package/dist/kernel/components/next-image.js +61 -0
  143. package/dist/kernel/components/ui/accordion.js +1 -1
  144. package/dist/kernel/components/ui/breadcrumb-trail.d.ts +6 -23
  145. package/dist/kernel/components/ui/breadcrumb-trail.js +2 -2
  146. package/dist/kernel/components/ui/breadcrumb.d.ts +11 -3
  147. package/dist/kernel/components/ui/breadcrumb.js +10 -8
  148. package/dist/kernel/components/ui/button-group.js +8 -7
  149. package/dist/kernel/components/ui/button.d.ts +58 -6
  150. package/dist/kernel/components/ui/button.js +43 -39
  151. package/dist/kernel/components/ui/card.d.ts +2 -2
  152. package/dist/kernel/components/ui/card.js +1 -1
  153. package/dist/kernel/components/ui/dialog.js +1 -1
  154. package/dist/kernel/components/ui/drawer.d.ts +3 -1
  155. package/dist/kernel/components/ui/drawer.js +6 -2
  156. package/dist/kernel/components/ui/input.d.ts +2 -2
  157. package/dist/kernel/components/ui/input.js +1 -1
  158. package/dist/kernel/components/ui/kbd.js +10 -17
  159. package/dist/kernel/components/ui/link.d.ts +11 -3
  160. package/dist/kernel/components/ui/link.js +12 -11
  161. package/dist/kernel/components/ui/menu.js +6 -6
  162. package/dist/kernel/components/ui/mod-key.d.ts +10 -0
  163. package/dist/kernel/components/ui/mod-key.js +36 -0
  164. package/dist/kernel/components/ui/navigation-menu.js +3 -3
  165. package/dist/kernel/components/ui/popover.js +1 -1
  166. package/dist/kernel/components/ui/progress.js +2 -2
  167. package/dist/kernel/components/ui/scroll-area.js +5 -5
  168. package/dist/kernel/components/ui/select.js +8 -11
  169. package/dist/kernel/components/ui/separator.js +1 -1
  170. package/dist/kernel/components/ui/table.js +1 -1
  171. package/dist/kernel/components/ui/tabs.js +1 -1
  172. package/dist/kernel/components/ui/tag.js +1 -1
  173. package/dist/kernel/components/ui/text.d.ts +2 -2
  174. package/dist/kernel/components/ui/text.js +1 -1
  175. package/dist/kernel/components/ui/toast.js +1 -1
  176. package/dist/kernel/components/ui/tooltip.js +1 -1
  177. package/dist/kernel/defaults.registry.d.ts +11 -24
  178. package/dist/kernel/defaults.registry.js +11 -26
  179. package/dist/kernel/routes/agent/markdown.d.ts +3 -1
  180. package/dist/kernel/routes/agent/markdown.js +219 -48
  181. package/dist/kernel/routes/layouts/group.d.ts +1 -1
  182. package/dist/kernel/routes/layouts/group.js +5 -7
  183. package/dist/kernel/routes/metadata/feed.d.ts +1 -1
  184. package/dist/kernel/routes/metadata/feed.js +111 -81
  185. package/dist/kernel/routes/metadata/llms.d.ts +12 -3
  186. package/dist/kernel/routes/metadata/llms.js +156 -59
  187. package/dist/kernel/routes/metadata/og-image.js +1 -1
  188. package/dist/kernel/routes/metadata/robots.d.ts +1 -1
  189. package/dist/kernel/routes/metadata/robots.js +2 -2
  190. package/dist/kernel/routes/metadata/sitemap.d.ts +26 -4
  191. package/dist/kernel/routes/metadata/sitemap.js +206 -38
  192. package/dist/kernel/routes/not-found.d.ts +34 -0
  193. package/dist/kernel/routes/not-found.js +213 -0
  194. package/dist/kernel/routes/pages/group.d.ts +2 -2
  195. package/dist/kernel/routes/pages/group.js +21 -13
  196. package/dist/kernel/routes/pages/leaf.d.ts +28 -1
  197. package/dist/kernel/routes/pages/leaf.js +25 -16
  198. package/dist/kernel/routes/pages/root.js +19 -13
  199. package/dist/keyboard-shortcuts.js +1 -1
  200. package/dist/resolvers/manifest-resolver.js +29 -6
  201. package/dist/search.d.ts +6 -7
  202. package/dist/search.js +52 -29
  203. package/dist/{sidebar-types-Bgchdfd6.d.ts → sidebar-types-DKpR27II.d.ts} +1 -1
  204. package/dist/theme-scope.js +1 -1
  205. package/dist/{types-DHBm7-j6.d.ts → types-CJWRG05y.d.ts} +20 -1
  206. package/dist/{types-B_b3C0U6.d.ts → types-CUtrppxt.d.ts} +8 -2
  207. package/dist/{types-CIwwieNw.d.ts → types-J2w_puPF.d.ts} +11 -10
  208. package/dist/types.d.ts +15 -6
  209. package/dist/utils/heading-ids.js +30 -11
  210. package/dist/utils/toc-selection.d.ts +7 -0
  211. package/dist/utils/toc-selection.js +14 -0
  212. package/dist/validate-local-source-SV44DBQT.js +16 -0
  213. package/dist/validate-publish-os-source-NZJF3TB2.js +14 -0
  214. package/init/seed/minimal/.gitignore +1 -0
  215. package/init/seed/minimal/publish.os/assets/blog/hello-world.svg +13 -0
  216. package/init/seed/minimal/publish.os/assets/favicon.dark.svg +13 -0
  217. package/init/seed/minimal/publish.os/assets/favicon.svg +13 -0
  218. package/init/seed/minimal/publish.os/blog/content/hello-world.mdx +48 -0
  219. package/init/seed/minimal/publish.os/blog/content/series-a.mdx +11 -0
  220. package/init/seed/minimal/publish.os/blog/index.tsx +82 -0
  221. package/init/seed/minimal/publish.os/blog/layout.tsx +13 -0
  222. package/init/seed/minimal/publish.os/blog/page.tsx +76 -0
  223. package/init/seed/minimal/publish.os/components/blog/copy-link.tsx +64 -0
  224. package/init/seed/minimal/publish.os/docs/content/get-started.mdx +6 -11
  225. package/init/seed/minimal/publish.os/docs/content/groups.mdx +6 -7
  226. package/init/seed/minimal/publish.os/docs/content/{theme.mdx → themes.mdx} +14 -12
  227. package/init/seed/minimal/publish.os/publish.os.config.json +7 -7
  228. package/init/seed/minimal/publish.os/theme.css +52 -24
  229. package/init/seed/minimal/publish.os/tsconfig.json +3 -0
  230. package/init/seed/minimal/seed.json +12 -2
  231. package/init/seed/scratch/publish.os/docs/content/get-started.mdx +6 -0
  232. package/init/seed/scratch/publish.os/publish.os.config.json +4 -0
  233. package/init/seed/scratch/seed.json +5 -0
  234. package/package.json +55 -44
  235. package/release/app/phosphor/package.json +5 -5
  236. package/release/app/phosphor/pnpm-lock.yaml.template +553 -377
  237. package/release/app/phosphor/pnpm-workspace.yaml +3 -0
  238. package/release/compiler/package.json +5 -3
  239. package/release/compiler/pnpm-lock.yaml.template +500 -303
  240. package/release/compiler/pnpm-workspace.yaml +3 -0
  241. package/release/release.json +8 -37
  242. package/compiler-assets/nextjs/defaults/group/leaf.tsx +0 -48
  243. package/dist/icons.d.ts +0 -1
  244. package/dist/icons.js +0 -2
  245. package/dist/kernel/components/blocks/design-system-preview.d.ts +0 -61
  246. package/dist/kernel/components/blocks/design-system-preview.js +0 -648
  247. package/dist/kernel/components/blocks/link-playground.d.ts +0 -5
  248. package/dist/kernel/components/blocks/link-playground.js +0 -744
  249. package/dist/kernel/components/blocks/navigation-progress-playground.d.ts +0 -5
  250. package/dist/kernel/components/blocks/navigation-progress-playground.js +0 -629
  251. package/dist/kernel/components/mdx/components/pre.d.ts +0 -6
  252. package/dist/kernel/components/mdx/components/pre.js +0 -18
  253. package/dist/kernel/components/ui/meta-key.d.ts +0 -17
  254. package/dist/kernel/components/ui/meta-key.js +0 -9
  255. package/dist/kernel/components/ui/theme-toggle.d.ts +0 -24
  256. package/dist/kernel/components/ui/theme-toggle.js +0 -58
  257. package/dist/kernel/framework-icons.d.ts +0 -1
  258. package/dist/kernel/framework-icons.js +0 -39
  259. package/dist/link-CYaCRDb6.d.ts +0 -35
  260. package/release/app/lucide/package.json +0 -30
  261. package/release/app/lucide/pnpm-lock.yaml.template +0 -2905
  262. package/release/app/lucide/pnpm-workspace.yaml +0 -11
  263. package/release/app/tabler/package.json +0 -30
  264. package/release/app/tabler/pnpm-lock.yaml.template +0 -2911
  265. package/release/app/tabler/pnpm-workspace.yaml +0 -11
@@ -0,0 +1,695 @@
1
+ import {
2
+ PUBLIC_SEARCH_DIRECTORY
3
+ } from "./chunk-EFO6AWXN.js";
4
+ import {
5
+ AppError
6
+ } from "./chunk-22RSSUNV.js";
7
+
8
+ // src/lib/compiler/lifecycle/output-ownership.ts
9
+ import { createHash, randomUUID } from "crypto";
10
+ import { constants } from "fs";
11
+ import {
12
+ link,
13
+ lstat,
14
+ mkdir,
15
+ mkdtemp,
16
+ open,
17
+ readdir,
18
+ realpath,
19
+ rename,
20
+ rmdir,
21
+ unlink,
22
+ writeFile
23
+ } from "fs/promises";
24
+ import { basename, dirname, join } from "path";
25
+ var MUTABLE_PREVIEW_ENTRIES = /* @__PURE__ */ new Set([
26
+ "node_modules",
27
+ ".next",
28
+ "next-env.d.ts",
29
+ "tsconfig.tsbuildinfo",
30
+ ".operation-owner.json",
31
+ ".preview-cache.json",
32
+ PUBLIC_SEARCH_DIRECTORY
33
+ ]);
34
+ async function generatedInventory(outputDir, stagingDir) {
35
+ if (stagingDir && (dirname(stagingDir) !== outputDir || !/^\.refresh-[a-zA-Z0-9]{6}$/u.test(basename(stagingDir))))
36
+ throw modifiedOutput(stagingDir);
37
+ let inventory = /* @__PURE__ */ Object.create(null);
38
+ async function assertMutable(path) {
39
+ try {
40
+ let entry = await lstat(path);
41
+ if (entry.isDirectory()) {
42
+ if (await assertLocalDirectory(path), path === join(outputDir, ".next/dev/node_modules")) return;
43
+ for (let name of await readdir(path))
44
+ await assertMutable(join(path, name));
45
+ } else if (!entry.isFile()) throw redirectedOutput(path);
46
+ } catch (error) {
47
+ if (error.code !== "ENOENT") throw error;
48
+ }
49
+ }
50
+ async function visit(path) {
51
+ let absolute = join(outputDir, path), entry = await lstat(absolute);
52
+ if (stagingDir && absolute === stagingDir) {
53
+ await assertLocalDirectory(absolute);
54
+ return;
55
+ }
56
+ if (MUTABLE_PREVIEW_ENTRIES.has(path)) {
57
+ if (["node_modules", ".next", PUBLIC_SEARCH_DIRECTORY].includes(path))
58
+ await assertLocalDirectory(absolute), path !== "node_modules" && await assertMutable(absolute);
59
+ else if (!entry.isFile()) throw redirectedOutput(absolute);
60
+ return;
61
+ }
62
+ if (entry.isDirectory()) {
63
+ await assertLocalDirectory(absolute), inventory[path] = "directory";
64
+ for (let name of (await readdir(absolute)).sort())
65
+ await visit(path ? `${path}/${name}` : name);
66
+ } else if (entry.isFile()) {
67
+ let file = await open(
68
+ absolute,
69
+ constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK
70
+ );
71
+ try {
72
+ if (!(await file.stat()).isFile()) throw modifiedOutput(path);
73
+ inventory[path] = createHash("sha256").update(await file.readFile()).digest("hex");
74
+ } finally {
75
+ await file.close();
76
+ }
77
+ } else throw modifiedOutput(path);
78
+ }
79
+ return await visit(""), inventory;
80
+ }
81
+ function modifiedOutput(path) {
82
+ return new AppError({
83
+ code: "FRAMEWORK_LOCAL_OUTPUT_MODIFIED",
84
+ message: `Generated preview contains unverified or modified files: ${path || ".operation-owner.json"}. The files were preserved.`,
85
+ fix: "Move custom work into the authored source, or restore the generated file before restarting this preview."
86
+ });
87
+ }
88
+ async function assertGeneratedOutput(options) {
89
+ if (options.scope === void 0 || !await lstat(options.outputDir).then(() => !0).catch((error) => {
90
+ if (error.code !== "ENOENT") throw error;
91
+ return !1;
92
+ })) return;
93
+ let owner = await readGeneratedOwner(options.outputDir, options.scope), actual = await generatedInventory(
94
+ options.outputDir,
95
+ options.stagingDir
96
+ );
97
+ assertInventory(actual, [owner.generated]);
98
+ }
99
+ async function readGeneratedOwner(outputDir, scope) {
100
+ let owner = await readOwnership(
101
+ join(outputDir, ".operation-owner.json"),
102
+ 16777216
103
+ );
104
+ if (!owner || owner.scope !== scope || owner.operation !== "dev" || !owner.generated || typeof owner.generated != "object" || Array.isArray(owner.generated))
105
+ throw modifiedOutput("");
106
+ return { ...owner, generated: owner.generated };
107
+ }
108
+ function assertInventory(actual, expected) {
109
+ for (let [path, digest] of Object.entries(actual))
110
+ if (!expected.some((inventory) => inventory[path] === digest))
111
+ throw modifiedOutput(path);
112
+ }
113
+ async function prepareGeneratedOutputUpdate(options) {
114
+ let scope = options.scope;
115
+ if (scope === void 0) return;
116
+ let output = { ...options, operation: "dev" };
117
+ await assertOperationOutput(output);
118
+ let identity = await assertLocalDirectory(options.outputDir), stagingIdentity = await assertLocalDirectory(options.stagingDir), owner = await readGeneratedOwner(options.outputDir, scope), current = await generatedInventory(
119
+ options.outputDir,
120
+ options.stagingDir
121
+ );
122
+ assertInventory(current, [owner.generated]);
123
+ let incoming = await generatedInventory(options.incoming), assertCurrent = async () => {
124
+ await assertLocalDirectory(options.outputDir, identity), await assertLocalDirectory(options.stagingDir, stagingIdentity), await assertOperationOutput(output);
125
+ let latest = await readGeneratedOwner(options.outputDir, scope);
126
+ if (JSON.stringify(latest) !== JSON.stringify(owner))
127
+ throw ownershipError();
128
+ };
129
+ return async () => {
130
+ await assertCurrent();
131
+ let actual = await generatedInventory(
132
+ options.outputDir,
133
+ options.stagingDir
134
+ );
135
+ assertInventory(actual, [owner.generated, incoming]);
136
+ let temporary = join(
137
+ options.stagingDir,
138
+ `.operation-owner-${randomUUID()}.tmp`
139
+ );
140
+ await writeFile(
141
+ temporary,
142
+ `${JSON.stringify({ ...owner, generated: actual })}
143
+ `,
144
+ { flag: "wx" }
145
+ ), await assertCurrent(), await rename(temporary, join(options.outputDir, ".operation-owner.json"));
146
+ };
147
+ }
148
+ function localOperationName({
149
+ operation,
150
+ scope
151
+ }) {
152
+ if (scope !== void 0 && (operation !== "dev" || typeof scope != "string" || !/^[a-f0-9]{64}$/u.test(scope)))
153
+ throw new AppError({
154
+ code: "FRAMEWORK_LOCAL_OPERATION_INVALID",
155
+ message: "A scoped development operation requires a lowercase SHA-256 identity. Retry with the selected preview's internal identity."
156
+ });
157
+ return scope === void 0 ? operation : `dev-${scope}`;
158
+ }
159
+ async function assertOperationOutput(options) {
160
+ if (localOperationName(options), !!await lstat(options.outputDir).then(() => !0).catch((error) => {
161
+ if (error.code !== "ENOENT") throw error;
162
+ return !1;
163
+ })) {
164
+ await assertLocalDirectory(options.outputDir);
165
+ try {
166
+ let owner = await readOwnership(
167
+ join(options.outputDir, ".operation-owner.json"),
168
+ options.scope === void 0 ? 16384 : 16777216
169
+ );
170
+ if (!owner || owner.schemaVersion !== 1 || owner.sourceRoot !== options.sourceRoot || owner.operation !== options.operation || owner.scope !== options.scope)
171
+ throw ownershipError();
172
+ } catch {
173
+ throw ownershipError();
174
+ }
175
+ }
176
+ }
177
+ async function markOperationOutput(options) {
178
+ localOperationName(options);
179
+ let identity = await assertLocalDirectory(options.outputDir), owner = {
180
+ schemaVersion: 1,
181
+ sourceRoot: options.sourceRoot,
182
+ operation: options.operation,
183
+ scope: options.scope,
184
+ ...options.scope === void 0 ? {} : { generated: await generatedInventory(options.outputDir) }
185
+ }, marker = join(options.outputDir, ".operation-owner.json"), temporary = join(
186
+ options.outputDir,
187
+ `.operation-owner-init-${randomUUID()}.tmp`
188
+ );
189
+ await writeFile(temporary, `${JSON.stringify(owner)}
190
+ `, {
191
+ flag: "wx",
192
+ mode: 384
193
+ });
194
+ let failure;
195
+ try {
196
+ await assertLocalDirectory(options.outputDir, identity), await link(temporary, marker);
197
+ } catch (error) {
198
+ failure = { error };
199
+ }
200
+ try {
201
+ await assertLocalDirectory(options.outputDir, identity), await unlink(temporary);
202
+ } catch (error) {
203
+ if (!failure) throw error;
204
+ failure.error instanceof Error && (failure.error.cause = {
205
+ previous: failure.error.cause,
206
+ cleanup: error,
207
+ retained: temporary
208
+ });
209
+ }
210
+ if (failure) throw failure.error;
211
+ }
212
+ function ownershipError() {
213
+ return new AppError({
214
+ code: "FRAMEWORK_LOCAL_OUTPUT_OWNERSHIP",
215
+ message: "The generated output could not be verified. Its files were preserved.",
216
+ fix: "Stop commands using this source, then run the command again to rebuild its generated output."
217
+ });
218
+ }
219
+ function redirectedOutput(path) {
220
+ return new AppError({
221
+ code: "FRAMEWORK_LOCAL_OUTPUT_REDIRECTED",
222
+ message: `The source-owned preview state was redirected at ${path}. Restore it before continuing. Linked targets were preserved.`
223
+ });
224
+ }
225
+ async function assertLocalDirectory(path, expected) {
226
+ let entry = await lstat(path);
227
+ if (!entry.isDirectory() || entry.isSymbolicLink() || await realpath(path) !== path || expected && (entry.dev !== expected.dev || entry.ino !== expected.ino))
228
+ throw new AppError({
229
+ code: "FRAMEWORK_LOCAL_OUTPUT_REDIRECTED",
230
+ message: "The source-owned output directory was redirected or replaced. Restore it before continuing.",
231
+ details: { path }
232
+ });
233
+ return entry;
234
+ }
235
+ async function readOwnership(path, maximumSize = 16384) {
236
+ let file = await open(
237
+ path,
238
+ constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK
239
+ );
240
+ try {
241
+ let entry = await file.stat();
242
+ if (!entry.isFile() || entry.size > maximumSize) throw ownershipError();
243
+ return JSON.parse(await file.readFile("utf8"));
244
+ } finally {
245
+ await file.close();
246
+ }
247
+ }
248
+ async function ensureLocalOutputRoot({
249
+ sourceRoot
250
+ }) {
251
+ let sourceIdentity = await assertLocalDirectory(sourceRoot), outputRoot = join(sourceRoot, ".publish.os");
252
+ await mkdir(outputRoot).catch((error) => {
253
+ if (error.code !== "EEXIST") throw error;
254
+ });
255
+ let outputIdentity = await assertLocalDirectory(outputRoot), assertCurrent = async () => {
256
+ await assertLocalDirectory(sourceRoot, sourceIdentity), await assertLocalDirectory(outputRoot, outputIdentity);
257
+ };
258
+ return await assertCurrent(), { outputRoot, assertCurrent };
259
+ }
260
+ async function recoverOperationOutput(options) {
261
+ try {
262
+ await assertOperationOutput(options), await assertGeneratedOutput(options);
263
+ return;
264
+ } catch (error) {
265
+ if (!(error instanceof AppError) || ![
266
+ "FRAMEWORK_LOCAL_OUTPUT_OWNERSHIP",
267
+ "FRAMEWORK_LOCAL_OUTPUT_MODIFIED",
268
+ "FRAMEWORK_LOCAL_OUTPUT_REDIRECTED"
269
+ ].includes(error.code))
270
+ throw error;
271
+ }
272
+ await options.assertCurrent();
273
+ let recoveryRoot = join(dirname(options.outputDir), "recovery");
274
+ await mkdir(recoveryRoot, { recursive: !0 }), await assertLocalDirectory(recoveryRoot);
275
+ let recovery = await mkdtemp(
276
+ join(recoveryRoot, `${localOperationName(options)}-`)
277
+ );
278
+ try {
279
+ await options.assertCurrent(), await rename(options.outputDir, join(recovery, "output"));
280
+ } catch (error) {
281
+ throw await rmdir(recovery), error;
282
+ }
283
+ }
284
+
285
+ // src/lib/compiler/lifecycle/operation-lock.ts
286
+ import { randomUUID as randomUUID2 } from "crypto";
287
+ import { constants as constants2 } from "fs";
288
+ import {
289
+ lstat as lstat2,
290
+ mkdir as mkdir2,
291
+ open as open2,
292
+ readdir as readdir2,
293
+ realpath as realpath2,
294
+ rmdir as rmdir2,
295
+ unlink as unlink2,
296
+ writeFile as writeFile2
297
+ } from "fs/promises";
298
+ import { hostname } from "os";
299
+ import { isAbsolute, join as join2, resolve } from "path";
300
+ function lockError({
301
+ code,
302
+ message,
303
+ sourceRoot
304
+ }) {
305
+ return new AppError({
306
+ code,
307
+ message,
308
+ details: { sourceRoot },
309
+ fix: code === "FRAMEWORK_LOCAL_OPERATION_ACTIVE" ? "Stop the running command for this source, then run the command again." : `Stop commands using this source, move only ${join2(sourceRoot, ".publish.os")} aside to preserve it, then run the command again.`
310
+ });
311
+ }
312
+ async function directoryIdentity({
313
+ path,
314
+ sourceRoot
315
+ }) {
316
+ let identity = await lstat2(path);
317
+ if (!identity.isDirectory() || identity.isSymbolicLink() || await realpath2(path) !== path)
318
+ throw lockError({
319
+ code: "FRAMEWORK_LOCAL_LOCK_REDIRECTED",
320
+ message: "The operation lock directory is redirected. Restore the source-owned output directory before retrying.",
321
+ sourceRoot
322
+ });
323
+ return identity;
324
+ }
325
+ async function verifyDirectory({
326
+ directory,
327
+ sourceRoot
328
+ }) {
329
+ let current = await directoryIdentity({ path: directory.path, sourceRoot });
330
+ if (current.dev !== directory.identity.dev || current.ino !== directory.identity.ino)
331
+ throw lockError({
332
+ code: "FRAMEWORK_LOCAL_LOCK_REDIRECTED",
333
+ message: "The operation lock directory changed. Restore the source-owned output directory before retrying.",
334
+ sourceRoot
335
+ });
336
+ }
337
+ async function createLock({
338
+ path,
339
+ owner
340
+ }) {
341
+ await mkdir2(path);
342
+ let identity = await directoryIdentity({
343
+ path,
344
+ sourceRoot: owner.sourceRoot
345
+ });
346
+ return await writeFile2(join2(path, "owner.json"), `${JSON.stringify(owner)}
347
+ `, {
348
+ flag: "wx"
349
+ }), { path, identity };
350
+ }
351
+ async function readOwner({
352
+ directory,
353
+ sourceRoot
354
+ }) {
355
+ await verifyDirectory({ directory, sourceRoot });
356
+ try {
357
+ let file = await open2(
358
+ join2(directory.path, "owner.json"),
359
+ constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK
360
+ );
361
+ try {
362
+ let identity = await file.stat();
363
+ if (!identity.isFile() || identity.size > 16384)
364
+ throw new Error("Invalid lock metadata file.");
365
+ let owner = JSON.parse(await file.readFile("utf8"));
366
+ if (!owner || typeof owner != "object")
367
+ throw new Error("Invalid lock metadata.");
368
+ let value = owner;
369
+ if (typeof value.sourceRoot != "string" || !isAbsolute(value.sourceRoot) || !["build", "dev", "ide", "dependencies"].includes(
370
+ value.operation ?? ""
371
+ ) || value.scope !== void 0 && (value.operation !== "dev" || typeof value.scope != "string" || !/^[a-f0-9]{64}$/u.test(value.scope)) || !Number.isSafeInteger(value.pid) || (value.pid ?? 0) <= 0 || typeof value.hostname != "string" || !value.hostname || typeof value.token != "string" || !/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/u.test(
372
+ value.token
373
+ ))
374
+ throw new Error("Invalid lock metadata.");
375
+ return await verifyDirectory({ directory, sourceRoot }), value;
376
+ } finally {
377
+ await file.close();
378
+ }
379
+ } catch {
380
+ throw lockError({
381
+ code: "FRAMEWORK_LOCAL_LOCK_UNVERIFIED",
382
+ message: "The operation lock owner cannot be verified. Inspect the source-owned lock before retrying.",
383
+ sourceRoot
384
+ });
385
+ }
386
+ }
387
+ async function assertOwnedLock({
388
+ directory,
389
+ parent,
390
+ owner,
391
+ activePreparation = !1
392
+ }) {
393
+ await verifyDirectory({ directory: parent, sourceRoot: owner.sourceRoot });
394
+ let current = await readOwner({ directory, sourceRoot: owner.sourceRoot });
395
+ if (current.sourceRoot !== owner.sourceRoot || current.token !== owner.token || current.operation !== owner.operation || current.scope !== owner.scope)
396
+ throw lockError({
397
+ code: "FRAMEWORK_LOCAL_LOCK_UNVERIFIED",
398
+ message: "The operation lock now belongs to another owner. Leave it in place and inspect the active operation.",
399
+ sourceRoot: owner.sourceRoot
400
+ });
401
+ let files = await readdir2(directory.path);
402
+ if (activePreparation && owner.operation === "dependencies" && files.length === 2 && files.includes("owner.json") && files.includes("active-preparation.json"))
403
+ await assertPreparationMarker({ directory, owner });
404
+ else if (files.length !== 1 || files[0] !== "owner.json")
405
+ throw lockError({
406
+ code: "FRAMEWORK_LOCAL_LOCK_UNVERIFIED",
407
+ message: "The operation lock contains unknown files. Leave it in place and inspect the lock before retrying.",
408
+ sourceRoot: owner.sourceRoot
409
+ });
410
+ await verifyDirectory({ directory: parent, sourceRoot: owner.sourceRoot }), await verifyDirectory({ directory, sourceRoot: owner.sourceRoot });
411
+ }
412
+ async function assertPreparationMarker({
413
+ directory,
414
+ owner
415
+ }) {
416
+ try {
417
+ let file = await open2(
418
+ join2(directory.path, "active-preparation.json"),
419
+ constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK
420
+ );
421
+ try {
422
+ let identity = await file.stat();
423
+ if (!identity.isFile() || identity.size > 16384 || await file.readFile("utf8") !== `${JSON.stringify(owner)}
424
+ `)
425
+ throw new Error("Invalid active preparation marker.");
426
+ } finally {
427
+ await file.close();
428
+ }
429
+ await verifyDirectory({ directory, sourceRoot: owner.sourceRoot });
430
+ } catch {
431
+ throw lockError({
432
+ code: "FRAMEWORK_LOCAL_LOCK_UNVERIFIED",
433
+ message: "Dependency preparation shutdown cannot be verified. Preserve the checkout lock and verify its recorded processes before recovery.",
434
+ sourceRoot: owner.sourceRoot
435
+ });
436
+ }
437
+ }
438
+ async function removeOwnedLock({
439
+ directory,
440
+ parent,
441
+ owner,
442
+ beforeRemoval
443
+ }) {
444
+ await assertOwnedLock({ directory, parent, owner }), beforeRemoval?.(), await unlink2(join2(directory.path, "owner.json")), await rmdir2(directory.path);
445
+ }
446
+ function assertDeadOwner({
447
+ owner,
448
+ operation,
449
+ scope
450
+ }) {
451
+ if (owner.operation !== operation || owner.scope !== scope || owner.hostname !== hostname())
452
+ throw lockError({
453
+ code: "FRAMEWORK_LOCAL_LOCK_UNVERIFIED",
454
+ message: "The operation lock owner cannot be verified on this host. Inspect the recorded owner before retrying.",
455
+ sourceRoot: owner.sourceRoot
456
+ });
457
+ try {
458
+ process.kill(owner.pid, 0);
459
+ } catch (error) {
460
+ if (error.code === "ESRCH") return;
461
+ throw lockError({
462
+ code: "FRAMEWORK_LOCAL_LOCK_UNVERIFIED",
463
+ message: "The operation lock owner may still be running. Verify that process has stopped before retrying.",
464
+ sourceRoot: owner.sourceRoot
465
+ });
466
+ }
467
+ throw lockError({
468
+ code: "FRAMEWORK_LOCAL_OPERATION_ACTIVE",
469
+ message: `A ${operation} operation already owns ${owner.sourceRoot}. Stop that operation before starting another writer.`,
470
+ sourceRoot: owner.sourceRoot
471
+ });
472
+ }
473
+ async function acquireOperationLock({
474
+ sourceRoot,
475
+ outputRoot,
476
+ operation,
477
+ scope,
478
+ signal
479
+ }) {
480
+ signal?.throwIfAborted();
481
+ let operationName = localOperationName({ operation, scope }), canonicalSource = await realpath2(sourceRoot), root = resolve(outputRoot);
482
+ await directoryIdentity({ path: root, sourceRoot: canonicalSource });
483
+ let locksPath = join2(root, ".locks");
484
+ await mkdir2(locksPath).catch((error) => {
485
+ if (error.code !== "EEXIST") throw error;
486
+ });
487
+ let locks = {
488
+ path: locksPath,
489
+ identity: await directoryIdentity({
490
+ path: locksPath,
491
+ sourceRoot: canonicalSource
492
+ })
493
+ }, owner = {
494
+ sourceRoot: canonicalSource,
495
+ operation,
496
+ scope,
497
+ pid: process.pid,
498
+ hostname: hostname(),
499
+ token: randomUUID2()
500
+ }, transitionPath = join2(locksPath, `${operationName}.transition`), transition = async ({
501
+ waitForActive = !1
502
+ } = {}) => {
503
+ for (let attempt = 0; ; attempt += 1) {
504
+ await verifyDirectory({ directory: locks, sourceRoot: canonicalSource });
505
+ try {
506
+ return await createLock({ path: transitionPath, owner });
507
+ } catch (error) {
508
+ if (error.code !== "EEXIST") throw error;
509
+ if (waitForActive && attempt < 50) {
510
+ await new Promise((resolve2) => setTimeout(resolve2, 10));
511
+ continue;
512
+ }
513
+ throw lockError({
514
+ code: "FRAMEWORK_LOCAL_LOCK_UNVERIFIED",
515
+ message: "Another operation is changing or recovering this lock. Wait for it to finish; inspect an abandoned transition before retrying.",
516
+ sourceRoot: canonicalSource
517
+ });
518
+ }
519
+ }
520
+ }, guard = await transition({
521
+ waitForActive: operation === "ide" || operation === "dependencies"
522
+ }), lock, interruptedRecovery = !1;
523
+ try {
524
+ signal?.throwIfAborted();
525
+ try {
526
+ lock = await createLock({ path: join2(locksPath, operationName), owner });
527
+ } catch (error) {
528
+ if (error.code !== "EEXIST") throw error;
529
+ let existing = {
530
+ path: join2(locksPath, operationName),
531
+ identity: await directoryIdentity({
532
+ path: join2(locksPath, operationName),
533
+ sourceRoot: canonicalSource
534
+ })
535
+ }, previous = await readOwner({
536
+ directory: existing,
537
+ sourceRoot: canonicalSource
538
+ });
539
+ operation === "dependencies" && await assertOwnedLock({
540
+ directory: existing,
541
+ parent: locks,
542
+ owner: previous,
543
+ activePreparation: !0
544
+ }), assertDeadOwner({ owner: previous, operation, scope }), signal?.throwIfAborted(), await removeOwnedLock({
545
+ directory: existing,
546
+ parent: locks,
547
+ owner: previous,
548
+ beforeRemoval: () => {
549
+ interruptedRecovery = !0;
550
+ }
551
+ }), signal?.throwIfAborted(), lock = await createLock({ path: join2(locksPath, operationName), owner }), interruptedRecovery = !1;
552
+ }
553
+ signal?.aborted && (await removeOwnedLock({ directory: lock, parent: locks, owner }), signal.throwIfAborted()), operation === "dependencies" && (interruptedRecovery = !0, await writeFile2(
554
+ join2(lock.path, "active-preparation.json"),
555
+ `${JSON.stringify(owner)}
556
+ `,
557
+ { flag: "wx", mode: 384 }
558
+ ), interruptedRecovery = !1);
559
+ } finally {
560
+ interruptedRecovery || await removeOwnedLock({
561
+ directory: guard,
562
+ parent: locks,
563
+ owner
564
+ });
565
+ }
566
+ let released = !1;
567
+ return async ({ shutdownUnverified = !1 } = {}) => {
568
+ if (released) return;
569
+ let guard2 = await transition({ waitForActive: !0 }), preserveGuard = shutdownUnverified;
570
+ try {
571
+ shutdownUnverified ? (await assertOwnedLock({
572
+ directory: lock,
573
+ parent: locks,
574
+ owner,
575
+ activePreparation: operation === "dependencies"
576
+ }), await writeFile2(
577
+ join2(lock.path, "shutdown-unverified.json"),
578
+ `${JSON.stringify(owner)}
579
+ `,
580
+ { flag: "wx", mode: 384 }
581
+ ), preserveGuard = !1) : (operation === "dependencies" && (await assertOwnedLock({
582
+ directory: lock,
583
+ parent: locks,
584
+ owner,
585
+ activePreparation: !0
586
+ }), await unlink2(join2(lock.path, "active-preparation.json"))), await removeOwnedLock({ directory: lock, parent: locks, owner })), released = !0;
587
+ } finally {
588
+ preserveGuard || await removeOwnedLock({ directory: guard2, parent: locks, owner });
589
+ }
590
+ };
591
+ }
592
+
593
+ // src/lib/compiler/lifecycle/owned-directory-publication.ts
594
+ import { lstat as lstat3, mkdir as mkdir3, mkdtemp as mkdtemp2, rename as rename2, rm } from "fs/promises";
595
+ import { basename as basename2, join as join3 } from "path";
596
+ async function assertMissing(path) {
597
+ try {
598
+ await lstat3(path);
599
+ } catch (error) {
600
+ if (error.code === "ENOENT") return;
601
+ throw error;
602
+ }
603
+ throw new AppError({
604
+ code: "FRAMEWORK_LOCAL_OUTPUT_REDIRECTED",
605
+ message: `Owned output appeared during publication: ${path}. The previous bytes were preserved.`
606
+ });
607
+ }
608
+ async function publishOwnedDirectory(options) {
609
+ options.signal?.throwIfAborted(), await options.assertOwner(), await mkdir3(options.stagingRoot, { recursive: !0 });
610
+ let stagingRootIdentity = await assertLocalDirectory(options.stagingRoot), stage = await mkdtemp2(
611
+ join3(options.stagingRoot, `${options.stagingPrefix}-`)
612
+ ), stageIdentity = await assertLocalDirectory(stage), incoming = join3(stage, "incoming"), retainStage = !1, assertStage = async () => {
613
+ try {
614
+ await options.assertOwner(), await assertLocalDirectory(options.stagingRoot, stagingRootIdentity), await assertLocalDirectory(stage, stageIdentity);
615
+ } catch (error) {
616
+ throw options.onRecoveryRequired?.(), error;
617
+ }
618
+ }, previous, previousIdentity, recoveryEntry, recoveryRootIdentity, recoveryEntryIdentity, movedPrevious = !1, published = !1, failure;
619
+ try {
620
+ await mkdir3(incoming), await assertLocalDirectory(incoming), await options.prepareIncoming(incoming), options.signal?.throwIfAborted(), await assertStage();
621
+ let preparedIncomingIdentity = await assertLocalDirectory(incoming);
622
+ await options.validateIncoming?.(incoming), await assertStage(), await assertLocalDirectory(incoming, preparedIncomingIdentity);
623
+ try {
624
+ previousIdentity = await lstat3(options.targetDirectory), await assertLocalDirectory(options.targetDirectory, previousIdentity);
625
+ } catch (error) {
626
+ if (error.code !== "ENOENT") throw error;
627
+ previousIdentity = void 0;
628
+ }
629
+ if (previousIdentity) {
630
+ options.recoveryRoot ? (await mkdir3(options.recoveryRoot, { recursive: !0 }), recoveryRootIdentity = await assertLocalDirectory(options.recoveryRoot), recoveryEntry = await mkdtemp2(
631
+ join3(options.recoveryRoot, `${basename2(options.targetDirectory)}-`)
632
+ ), recoveryEntryIdentity = await assertLocalDirectory(recoveryEntry), previous = join3(recoveryEntry, basename2(options.targetDirectory))) : previous = join3(stage, "previous"), await assertStage(), recoveryRootIdentity && options.recoveryRoot && await assertLocalDirectory(options.recoveryRoot, recoveryRootIdentity), recoveryEntryIdentity && recoveryEntry && await assertLocalDirectory(recoveryEntry, recoveryEntryIdentity), await assertLocalDirectory(options.targetDirectory, previousIdentity), await rename2(options.targetDirectory, previous), movedPrevious = !0;
633
+ try {
634
+ await assertLocalDirectory(previous, previousIdentity);
635
+ } catch (error) {
636
+ throw retainStage = !0, options.onRecoveryRequired?.(), new AggregateError(
637
+ [error],
638
+ `Owned output changed while being retained; preserve the previous output at ${previous}.`
639
+ );
640
+ }
641
+ }
642
+ try {
643
+ options.signal?.throwIfAborted(), await assertStage(), await assertLocalDirectory(incoming, preparedIncomingIdentity), await assertMissing(options.targetDirectory), await options.beforePublish?.(), await rename2(incoming, options.targetDirectory), published = !0;
644
+ } catch (publishError) {
645
+ if (movedPrevious && previous && previousIdentity)
646
+ try {
647
+ await assertStage(), recoveryRootIdentity && options.recoveryRoot && await assertLocalDirectory(
648
+ options.recoveryRoot,
649
+ recoveryRootIdentity
650
+ ), recoveryEntryIdentity && recoveryEntry && await assertLocalDirectory(recoveryEntry, recoveryEntryIdentity), await assertMissing(options.targetDirectory), await rename2(previous, options.targetDirectory), await assertLocalDirectory(options.targetDirectory, previousIdentity), movedPrevious = !1;
651
+ } catch (rollbackError) {
652
+ throw retainStage = !0, options.onRecoveryRequired?.(), new AggregateError(
653
+ [publishError, rollbackError],
654
+ `Owned output publication failed; the previous output remains at ${previous}.`
655
+ );
656
+ }
657
+ throw publishError;
658
+ }
659
+ } catch (error) {
660
+ failure = error;
661
+ }
662
+ if (!retainStage && (!failure || options.cleanupFailedStaging !== !1))
663
+ try {
664
+ await assertStage(), await rm(stage, { recursive: !0, force: !0 });
665
+ } catch (cleanupError) {
666
+ failure = failure ? new AggregateError(
667
+ [failure, cleanupError],
668
+ `Owned output publication failed; staging cleanup also failed at ${stage}.`
669
+ ) : cleanupError;
670
+ }
671
+ if (recoveryEntry && !movedPrevious)
672
+ try {
673
+ options.recoveryRoot && recoveryRootIdentity && await assertLocalDirectory(options.recoveryRoot, recoveryRootIdentity), recoveryEntryIdentity && await assertLocalDirectory(recoveryEntry, recoveryEntryIdentity), await rm(recoveryEntry, { recursive: !0, force: !0 });
674
+ } catch (cleanupError) {
675
+ failure = failure ? new AggregateError(
676
+ [failure, cleanupError],
677
+ `Owned output publication failed; recovery cleanup also failed at ${recoveryEntry}.`
678
+ ) : cleanupError;
679
+ }
680
+ if (failure) throw failure;
681
+ if (!published) throw new Error("Owned output was not published.");
682
+ }
683
+
684
+ export {
685
+ assertGeneratedOutput,
686
+ prepareGeneratedOutputUpdate,
687
+ localOperationName,
688
+ assertOperationOutput,
689
+ markOperationOutput,
690
+ assertLocalDirectory,
691
+ ensureLocalOutputRoot,
692
+ recoverOperationOutput,
693
+ acquireOperationLock,
694
+ publishOwnedDirectory
695
+ };