@publish.os/nextjs 0.0.1-alpha.8 → 0.0.1-alpha.90

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 (201) 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 +7 -3
  4. package/compiler-assets/nextjs/defaults/group/page.tsx +35 -43
  5. package/compiler-assets/nextjs/defaults/project/next.config.mjs +22 -11
  6. package/compiler-assets/nextjs/defaults/project/tsconfig.json.template +1 -4
  7. package/compiler-assets/nextjs/defaults/root/css/animation.css +131 -0
  8. package/compiler-assets/nextjs/defaults/root/css/components/dialog.css +4 -1
  9. package/compiler-assets/nextjs/defaults/root/css/components/menu.css +1 -1
  10. package/compiler-assets/nextjs/defaults/root/css/components/navigation-menu.css +1 -1
  11. package/compiler-assets/nextjs/defaults/root/css/components/popover.css +1 -1
  12. package/compiler-assets/nextjs/defaults/root/css/components/select.css +1 -1
  13. package/compiler-assets/nextjs/defaults/root/css/components/tooltip.css +1 -1
  14. package/compiler-assets/nextjs/defaults/root/css/shadow.css +6 -25
  15. package/compiler-assets/nextjs/defaults/root/css/typography.css +51 -68
  16. package/compiler-assets/nextjs/defaults/root/globals.css +25 -0
  17. package/compiler-assets/nextjs/defaults/root/{page.tsx → index.tsx} +6 -2
  18. package/compiler-assets/nextjs/defaults/root/layout.tsx +7 -1
  19. package/compiler-assets/nextjs/defaults/root/theme.css +22 -22
  20. package/compiler-assets/nextjs/shims/generated-group-page.tsx +19 -2
  21. package/compiler-assets/nextjs/shims/generated-leaf-page.tsx +16 -2
  22. package/compiler-assets/nextjs/shims/global-layout.tsx +11 -43
  23. package/compiler-assets/nextjs/shims/proxy.ts +21 -9
  24. package/compiler-assets/nextjs/shims/publish-os-theme-provider.tsx +76 -15
  25. package/compiler-assets/nextjs/shims/root-page.tsx +7 -1
  26. package/compiler-assets/nextjs/shims/site-fenced-code-block.tsx +34 -0
  27. package/compiler-assets/nextjs/shims/site-heading-level.tsx +14 -0
  28. package/compiler-assets/nextjs/shims/site-mdx-components.tsx +100 -0
  29. package/compiler-assets/nextjs/shims/site-mdx.tsx +12 -0
  30. package/compiler-assets/nextjs/shims/theme-defaults.css +41 -25
  31. package/dist/build-operation-2JAYBSKF.js +83 -0
  32. package/dist/button-CtzUJB8u.d.ts +11 -0
  33. package/dist/{button-CFdx-ohV.d.ts → button-c3WGnxIj.d.ts} +3 -3
  34. package/dist/chunk-535TM4A5.js +1455 -0
  35. package/dist/chunk-726GV2NF.js +2344 -0
  36. package/dist/chunk-7OGTPSKI.js +156 -0
  37. package/dist/chunk-AI2UULNX.js +9 -0
  38. package/dist/chunk-B2V22WRT.js +297 -0
  39. package/dist/chunk-DLDFHU7Y.js +191 -0
  40. package/dist/chunk-DWA3ZRGW.js +142 -0
  41. package/dist/chunk-GGKFQ3MA.js +621 -0
  42. package/dist/chunk-H6XILMZX.js +6154 -0
  43. package/dist/chunk-NECL5IBJ.js +318 -0
  44. package/dist/chunk-SVYGXXYR.js +36 -0
  45. package/dist/chunk-UF6ATARM.js +1100 -0
  46. package/dist/chunk-VO2I7MTM.js +56 -0
  47. package/dist/chunk-WDY4IK6Z.js +128 -0
  48. package/dist/chunk-WKTEO6RS.js +586 -0
  49. package/dist/chunk-YLTOLYWM.js +92 -0
  50. package/dist/compiler.d.ts +41 -7
  51. package/dist/compiler.js +48 -13143
  52. package/dist/compose-NN23UJGC.js +13 -0
  53. package/dist/config/createNextConfig.js +13 -0
  54. package/dist/dev-operation-TZDVJCN7.js +1055 -0
  55. package/dist/framework-selection-X4U6Y6QC.js +10 -0
  56. package/dist/ide-support-ZNW7ODFY.js +15 -0
  57. package/dist/index.d.ts +15 -3
  58. package/dist/kernel/components/blocks/AgentActions.js +71 -61
  59. package/dist/kernel/components/blocks/design-system-preview.d.ts +1 -1
  60. package/dist/kernel/components/blocks/design-system-preview.js +32 -13
  61. package/dist/kernel/components/blocks/link-playground.js +2 -2
  62. package/dist/kernel/components/blocks/logo-block.js +2 -2
  63. package/dist/kernel/components/blocks/nav-breadcrumb.d.ts +10 -2
  64. package/dist/kernel/components/blocks/nav-breadcrumb.js +20 -5
  65. package/dist/kernel/components/blocks/navbar.d.ts +2 -2
  66. package/dist/kernel/components/blocks/navbar.js +401 -60
  67. package/dist/kernel/components/blocks/navigation-progress-playground.js +4 -4
  68. package/dist/kernel/components/blocks/navigation-progress.js +4 -1
  69. package/dist/kernel/components/blocks/next-prev.d.ts +1 -1
  70. package/dist/kernel/components/blocks/next-prev.js +11 -23
  71. package/dist/kernel/components/blocks/page-list.d.ts +1 -1
  72. package/dist/kernel/components/blocks/page-list.js +5 -4
  73. package/dist/kernel/components/blocks/search.d.ts +83 -58
  74. package/dist/kernel/components/blocks/search.js +553 -426
  75. package/dist/kernel/components/blocks/sidebar-node.d.ts +2 -2
  76. package/dist/kernel/components/blocks/sidebar-node.js +11 -9
  77. package/dist/kernel/components/blocks/sidebar.d.ts +3 -3
  78. package/dist/kernel/components/blocks/sidebar.js +18 -11
  79. package/dist/kernel/components/blocks/theme-toggle.d.ts +2 -2
  80. package/dist/kernel/components/blocks/theme-toggle.js +48 -2
  81. package/dist/kernel/components/blocks/toc.js +3 -3
  82. package/dist/kernel/components/mdx/components/blockquote.js +1 -1
  83. package/dist/kernel/components/mdx/components/callout.d.ts +5 -7
  84. package/dist/kernel/components/mdx/components/callout.js +66 -35
  85. package/dist/kernel/components/mdx/components/code-block.d.ts +5 -2
  86. package/dist/kernel/components/mdx/components/code-block.js +106 -5
  87. package/dist/kernel/components/mdx/components/copy-code-button.d.ts +8 -0
  88. package/dist/kernel/components/mdx/components/copy-code-button.js +60 -0
  89. package/dist/kernel/components/mdx/components/figure-caption.js +1 -1
  90. package/dist/kernel/components/mdx/components/figure.js +1 -1
  91. package/dist/kernel/components/mdx/components/heading-copy-link.js +3 -3
  92. package/dist/kernel/components/mdx/components/image-zoom.d.ts +2 -2
  93. package/dist/kernel/components/mdx/components/image-zoom.js +1 -1
  94. package/dist/kernel/components/mdx/components/image.js +77 -56
  95. package/dist/kernel/components/mdx/components/inline-code.js +1 -1
  96. package/dist/kernel/components/mdx/components/kbd.d.ts +2 -2
  97. package/dist/kernel/components/mdx/components/kbd.js +3 -2
  98. package/dist/kernel/components/mdx/components/link.d.ts +35 -4
  99. package/dist/kernel/components/mdx/components/link.js +1 -1
  100. package/dist/kernel/components/mdx/components/paragraph.js +1 -4
  101. package/dist/kernel/components/mdx/components/task-list.js +1 -1
  102. package/dist/kernel/components/mdx/components/video-player.js +2 -2
  103. package/dist/kernel/components/mdx/components/video.js +1 -1
  104. package/dist/kernel/components/mdx/error-boundary.d.ts +1 -1
  105. package/dist/kernel/components/mdx/mdx.d.ts +12 -8
  106. package/dist/kernel/components/mdx/mdx.js +115 -39
  107. package/dist/kernel/components/mdx/rehype-heading-ids.js +1 -1
  108. package/dist/kernel/components/mdx/types.d.ts +1 -1
  109. package/dist/kernel/components/ui/breadcrumb-trail.d.ts +6 -23
  110. package/dist/kernel/components/ui/breadcrumb.d.ts +11 -3
  111. package/dist/kernel/components/ui/breadcrumb.js +6 -4
  112. package/dist/kernel/components/ui/button-group.d.ts +1 -1
  113. package/dist/kernel/components/ui/button-group.js +5 -4
  114. package/dist/kernel/components/ui/button.d.ts +2 -2
  115. package/dist/kernel/components/ui/button.js +6 -6
  116. package/dist/kernel/components/ui/card.d.ts +2 -2
  117. package/dist/kernel/components/ui/drawer.d.ts +3 -1
  118. package/dist/kernel/components/ui/drawer.js +5 -1
  119. package/dist/kernel/components/ui/input.d.ts +4 -4
  120. package/dist/kernel/components/ui/kbd.d.ts +1 -1
  121. package/dist/kernel/components/ui/kbd.js +9 -16
  122. package/dist/kernel/components/ui/link.d.ts +5 -3
  123. package/dist/kernel/components/ui/link.js +10 -9
  124. package/dist/kernel/components/ui/menu.js +5 -5
  125. package/dist/kernel/components/ui/mod-key.d.ts +10 -0
  126. package/dist/kernel/components/ui/mod-key.js +36 -0
  127. package/dist/kernel/components/ui/navigation-menu.js +2 -2
  128. package/dist/kernel/components/ui/progress.js +1 -1
  129. package/dist/kernel/components/ui/scroll-area.d.ts +8 -8
  130. package/dist/kernel/components/ui/scroll-area.js +4 -4
  131. package/dist/kernel/components/ui/select.js +7 -10
  132. package/dist/kernel/components/ui/text.d.ts +2 -2
  133. package/dist/kernel/components/ui/theme-toggle.d.ts +3 -3
  134. package/dist/kernel/components/ui/theme-toggle.js +4 -9
  135. package/dist/kernel/defaults.registry.d.ts +9 -9
  136. package/dist/kernel/defaults.registry.js +9 -9
  137. package/dist/kernel/routes/agent/markdown.d.ts +0 -1
  138. package/dist/kernel/routes/layouts/group.d.ts +1 -1
  139. package/dist/kernel/routes/metadata/feed.d.ts +1 -1
  140. package/dist/kernel/routes/metadata/feed.js +13 -9
  141. package/dist/kernel/routes/metadata/llms.d.ts +2 -1
  142. package/dist/kernel/routes/metadata/llms.js +4 -4
  143. package/dist/kernel/routes/metadata/robots.d.ts +1 -1
  144. package/dist/kernel/routes/metadata/robots.js +2 -2
  145. package/dist/kernel/routes/metadata/sitemap.d.ts +6 -3
  146. package/dist/kernel/routes/metadata/sitemap.js +48 -20
  147. package/dist/kernel/routes/pages/group.d.ts +1 -1
  148. package/dist/kernel/routes/pages/group.js +20 -12
  149. package/dist/kernel/routes/pages/leaf.d.ts +2 -2
  150. package/dist/kernel/routes/pages/leaf.js +20 -12
  151. package/dist/kernel/routes/pages/root.d.ts +2 -2
  152. package/dist/kernel/routes/pages/root.js +18 -12
  153. package/dist/resolvers/manifest-resolver.js +29 -6
  154. package/dist/search.d.ts +6 -7
  155. package/dist/search.js +47 -22
  156. package/dist/{sidebar-types-Bgchdfd6.d.ts → sidebar-types-DKpR27II.d.ts} +1 -1
  157. package/dist/{types-CIwwieNw.d.ts → types-BzkZty3r.d.ts} +23 -3
  158. package/dist/{types-DHBm7-j6.d.ts → types-CJWRG05y.d.ts} +20 -1
  159. package/dist/{types-B_b3C0U6.d.ts → types-CUtrppxt.d.ts} +8 -2
  160. package/dist/types.d.ts +14 -6
  161. package/dist/validate-local-source-XRL2Y7XE.js +14 -0
  162. package/dist/validate-publish-os-source-DAPZ4QGE.js +12 -0
  163. package/init/seed/minimal/.gitignore +1 -0
  164. package/init/seed/minimal/publish.os/assets/favicon/favicon.dark.png +0 -0
  165. package/init/seed/minimal/publish.os/assets/favicon/favicon.png +0 -0
  166. package/init/seed/minimal/publish.os/docs/content/get-started.mdx +6 -10
  167. package/init/seed/minimal/publish.os/docs/content/groups.mdx +1 -1
  168. package/init/seed/minimal/publish.os/docs/content/{theme.mdx → themes.mdx} +14 -12
  169. package/init/seed/minimal/publish.os/publish.os.config.json +3 -7
  170. package/init/seed/minimal/publish.os/theme.css +52 -24
  171. package/init/seed/minimal/publish.os/tsconfig.json +3 -0
  172. package/init/seed/minimal/seed.json +4 -1
  173. package/init/seed/scratch/publish.os/docs/content/get-started.mdx +6 -0
  174. package/init/seed/scratch/publish.os/publish.os.config.json +4 -0
  175. package/init/seed/scratch/seed.json +5 -0
  176. package/package.json +12 -26
  177. package/release/app/phosphor/package.json +3 -3
  178. package/release/app/phosphor/pnpm-lock.yaml.template +523 -360
  179. package/release/app/phosphor/pnpm-workspace.yaml +3 -0
  180. package/release/compiler/package.json +1 -1
  181. package/release/compiler/pnpm-lock.yaml.template +439 -286
  182. package/release/compiler/pnpm-workspace.yaml +3 -0
  183. package/release/release.json +7 -36
  184. package/compiler-assets/nextjs/defaults/group/leaf.tsx +0 -48
  185. package/dist/icons.d.ts +0 -1
  186. package/dist/icons.js +0 -2
  187. package/dist/kernel/components/mdx/components/pre.d.ts +0 -6
  188. package/dist/kernel/components/mdx/components/pre.js +0 -18
  189. package/dist/kernel/components/ui/meta-key.d.ts +0 -17
  190. package/dist/kernel/components/ui/meta-key.js +0 -9
  191. package/dist/kernel/framework-icons.d.ts +0 -1
  192. package/dist/kernel/framework-icons.js +0 -39
  193. package/dist/link-CYaCRDb6.d.ts +0 -35
  194. package/dist/route-metadata-og-image-BeKKFHg7.d.ts +0 -58
  195. package/dist/types-sM2g9nW0.d.ts +0 -12
  196. package/release/app/lucide/package.json +0 -30
  197. package/release/app/lucide/pnpm-lock.yaml.template +0 -2905
  198. package/release/app/lucide/pnpm-workspace.yaml +0 -11
  199. package/release/app/tabler/package.json +0 -30
  200. package/release/app/tabler/pnpm-lock.yaml.template +0 -2911
  201. package/release/app/tabler/pnpm-workspace.yaml +0 -11
@@ -0,0 +1,1055 @@
1
+ import {
2
+ withCheckoutPreparation
3
+ } from "./chunk-DWA3ZRGW.js";
4
+ import {
5
+ approveLocalComposition
6
+ } from "./chunk-SVYGXXYR.js";
7
+ import {
8
+ withLocalOperation
9
+ } from "./chunk-B2V22WRT.js";
10
+ import {
11
+ LocalProcessError,
12
+ installLocalApp,
13
+ localProcessEnvironment,
14
+ startLocalProcess
15
+ } from "./chunk-WKTEO6RS.js";
16
+ import {
17
+ assertGeneratedOutput,
18
+ assertLocalDirectory,
19
+ assertOperationOutput,
20
+ prepareGeneratedOutputUpdate
21
+ } from "./chunk-GGKFQ3MA.js";
22
+ import {
23
+ assertFrameworkSelection
24
+ } from "./chunk-DLDFHU7Y.js";
25
+ import "./chunk-7OGTPSKI.js";
26
+ import {
27
+ PUBLIC_PAGEFIND_DIRECTORY,
28
+ isExcludedSourcePath
29
+ } from "./chunk-YLTOLYWM.js";
30
+ import "./chunk-AI2UULNX.js";
31
+ import {
32
+ AppError,
33
+ readInstalledFramework
34
+ } from "./chunk-WDY4IK6Z.js";
35
+
36
+ // src/lib/compiler/lifecycle/dev-operation.ts
37
+ import { createHash as createHash4 } from "crypto";
38
+ import { mkdtemp as mkdtemp2, readFile as readFile5, realpath as realpath2, rm as rm3 } from "fs/promises";
39
+ import { createServer } from "net";
40
+ import { join as join5 } from "path";
41
+ import { setTimeout as delay } from "timers/promises";
42
+ import { stripVTControlCharacters } from "util";
43
+
44
+ // src/lib/compiler/lifecycle/checkout-development.ts
45
+ import { createHash as createHash2 } from "crypto";
46
+ import { mkdtemp, readFile as readFile2, rm, stat, writeFile } from "fs/promises";
47
+ import { createRequire } from "module";
48
+ import { dirname, isAbsolute, join as join2 } from "path";
49
+
50
+ // src/lib/compiler/lifecycle/source-watch.ts
51
+ import { createHash } from "crypto";
52
+ import { watch } from "fs";
53
+ import { lstat, readdir, readFile } from "fs/promises";
54
+ import { join, relative } from "path";
55
+ function ignored(sourceRoot, path, include) {
56
+ let name = relative(sourceRoot, path).replace(/\\/g, "/");
57
+ return (include ? !include(name) : isExcludedSourcePath(name)) || name.split("/").length === 1 && name.startsWith(".env") || name.split("/").some(
58
+ (segment) => ["node_modules", ".next", ".cache", ".turbo", ".git"].includes(segment)
59
+ );
60
+ }
61
+ function changesBetween(before, after) {
62
+ return [.../* @__PURE__ */ new Set([...before.keys(), ...after.keys()])].sort().flatMap((path) => {
63
+ let previous = before.get(path), current = after.get(path);
64
+ return previous === current ? [] : [
65
+ {
66
+ path,
67
+ action: previous === void 0 ? "added" : current === void 0 ? "deleted" : "edited"
68
+ }
69
+ ];
70
+ });
71
+ }
72
+ async function watchSource(options) {
73
+ let watchers = /* @__PURE__ */ new Map(), closed = !1, scan = Promise.resolve(), baseline = /* @__PURE__ */ new Map(), scanNow = async () => {
74
+ let visited = /* @__PURE__ */ new Set(), identity = /* @__PURE__ */ new Map();
75
+ await visit(options.sourceRoot, visited, identity);
76
+ for (let [path, entry] of watchers)
77
+ visited.has(path) || (entry.watcher.close(), watchers.delete(path));
78
+ return identity;
79
+ }, rescan = () => (scan = scan.then(async () => {
80
+ if (closed) return;
81
+ let identity = await scanNow();
82
+ changesBetween(baseline, identity).length > 0 && options.onChange();
83
+ }).catch(options.onError), scan), visit = async (directory, visited, identity) => {
84
+ if (closed || ignored(options.sourceRoot, directory, options.include))
85
+ return;
86
+ let entry = await lstat(directory, { bigint: !0 }).catch(
87
+ (error) => {
88
+ if (error.code !== "ENOENT") throw error;
89
+ }
90
+ );
91
+ if (closed) return;
92
+ if (entry && entry.isFile() && identity.set(
93
+ relative(options.sourceRoot, directory).replace(/\\/g, "/"),
94
+ [
95
+ entry.mode,
96
+ entry.dev,
97
+ entry.ino,
98
+ entry.size,
99
+ entry.mtimeNs,
100
+ entry.ctimeNs
101
+ ].map(String).join(":")
102
+ ), !entry?.isDirectory() || entry.isSymbolicLink()) {
103
+ watchers.get(directory)?.watcher.close(), watchers.delete(directory);
104
+ return;
105
+ }
106
+ visited.add(directory);
107
+ let previous = watchers.get(directory);
108
+ if (previous && (previous.dev !== entry.dev || previous.ino !== entry.ino) && (previous.watcher.close(), watchers.delete(directory)), !watchers.has(directory)) {
109
+ let watcher = watch(directory, (_event, filename) => {
110
+ closed || filename && ignored(
111
+ options.sourceRoot,
112
+ join(directory, filename),
113
+ options.include
114
+ ) || rescan();
115
+ });
116
+ watcher.on("error", (error) => {
117
+ closed || options.onError(error);
118
+ }), watchers.set(directory, { watcher, dev: entry.dev, ino: entry.ino });
119
+ }
120
+ let entries = await readdir(directory, { withFileTypes: !0 }).catch(
121
+ (error) => {
122
+ if (error.code !== "ENOENT" && error.code !== "ENOTDIR") throw error;
123
+ return [];
124
+ }
125
+ );
126
+ for (let child of entries)
127
+ await visit(join(directory, child.name), visited, identity);
128
+ };
129
+ try {
130
+ scan = scanNow().then((identity) => {
131
+ baseline = identity;
132
+ }), await scan;
133
+ } catch (error) {
134
+ closed = !0;
135
+ for (let { watcher } of watchers.values()) watcher.close();
136
+ throw error;
137
+ }
138
+ return {
139
+ reconcileStartup: rescan,
140
+ revision: async () => {
141
+ if (await scan, closed) return;
142
+ let before = await scanNow(), hash = createHash("sha256");
143
+ for (let path of [...before.keys()].sort()) {
144
+ let contents = await readFile(join(options.sourceRoot, path)).catch(
145
+ (error) => {
146
+ if (!(error.code === "ENOENT" || error.code === "ENOTDIR"))
147
+ throw error;
148
+ }
149
+ );
150
+ if (!contents) return;
151
+ hash.update(JSON.stringify([path, contents.byteLength])), hash.update("\0"), hash.update(contents);
152
+ }
153
+ let after = await scanNow();
154
+ return changesBetween(before, after).length === 0 ? `sha256:${hash.digest("hex")}` : void 0;
155
+ },
156
+ takeChanges: async () => {
157
+ if (await scan, closed) return [];
158
+ let current = await scanNow(), changes = changesBetween(baseline, current);
159
+ return baseline = current, changes;
160
+ },
161
+ stop: async () => {
162
+ closed = !0;
163
+ for (let { watcher } of watchers.values()) watcher.close();
164
+ watchers.clear(), await scan;
165
+ }
166
+ };
167
+ }
168
+
169
+ // src/lib/compiler/lifecycle/checkout-development.ts
170
+ var compilerPaths = [
171
+ "src/compiler.ts",
172
+ "src/lib/compiler",
173
+ "compiler-assets/nextjs",
174
+ "release",
175
+ "package.json",
176
+ "tsconfig.json"
177
+ ], workspacePaths = [
178
+ "package.json",
179
+ "pnpm-lock.yaml",
180
+ "pnpm-workspace.yaml",
181
+ ".pnpmfile.mjs"
182
+ ], includesPath = (paths, path) => path === "" || paths.some(
183
+ (input) => input === path || input.startsWith(`${path}/`) || path.startsWith(`${input}/`)
184
+ );
185
+ async function watchCheckout(options) {
186
+ let workspaceRoot;
187
+ for (let directory = options.packageRoot; ; directory = dirname(directory)) {
188
+ if (await stat(join2(directory, "pnpm-workspace.yaml")).then((entry) => entry.isFile()).catch((error) => {
189
+ if (error.code !== "ENOENT") throw error;
190
+ return !1;
191
+ })) {
192
+ workspaceRoot = directory;
193
+ break;
194
+ }
195
+ if (directory === dirname(directory)) break;
196
+ }
197
+ let compiler = await watchSource({
198
+ ...options,
199
+ sourceRoot: options.packageRoot,
200
+ include: (path) => includesPath(
201
+ workspaceRoot === options.packageRoot ? [...compilerPaths, ...workspacePaths] : compilerPaths,
202
+ path
203
+ ) && path !== "compiler-assets/nextjs/defaults/root" && !path.startsWith("compiler-assets/nextjs/defaults/root/")
204
+ }), workspace;
205
+ try {
206
+ workspaceRoot && workspaceRoot !== options.packageRoot && (workspace = await watchSource({
207
+ ...options,
208
+ sourceRoot: workspaceRoot,
209
+ include: (path) => includesPath(workspacePaths, path)
210
+ }));
211
+ } catch (error) {
212
+ throw await compiler.stop(), error;
213
+ }
214
+ return {
215
+ workspaceRoot,
216
+ reconcileStartup: async () => {
217
+ await compiler.reconcileStartup(), await workspace?.reconcileStartup();
218
+ },
219
+ takeChanges: async () => [
220
+ ...(await compiler.takeChanges()).map((change) => ({
221
+ ...change,
222
+ path: `framework/${change.path}`,
223
+ dependency: workspacePaths.includes(change.path)
224
+ })),
225
+ ...(await workspace?.takeChanges() ?? []).map((change) => ({
226
+ ...change,
227
+ path: `workspace/${change.path}`,
228
+ dependency: !0
229
+ }))
230
+ ],
231
+ revision: async () => {
232
+ let revisions = [
233
+ await compiler.revision(),
234
+ await workspace?.revision()
235
+ ];
236
+ if (!(!revisions[0] || workspace && !revisions[1]))
237
+ return createHash2("sha256").update(JSON.stringify(revisions)).digest("hex");
238
+ },
239
+ dependencyRevision: async () => {
240
+ let hash = createHash2("sha256"), paths = /* @__PURE__ */ new Set([
241
+ join2(options.packageRoot, "package.json"),
242
+ ...workspacePaths.map(
243
+ (path) => join2(workspaceRoot ?? options.packageRoot, path)
244
+ )
245
+ ]);
246
+ for (let path of paths)
247
+ hash.update(path), hash.update(
248
+ await readFile2(path).catch((error) => {
249
+ if (error.code !== "ENOENT") throw error;
250
+ return "missing";
251
+ })
252
+ ), hash.update("\0");
253
+ return hash.digest("hex");
254
+ },
255
+ stop: async () => {
256
+ await Promise.all([compiler.stop(), workspace?.stop()]);
257
+ }
258
+ };
259
+ }
260
+ async function prepareCheckoutDependencies(options) {
261
+ if (!options.pnpmExecutable || !isAbsolute(options.pnpmExecutable))
262
+ throw new AppError({
263
+ code: "FRAMEWORK_PNPM_MISSING",
264
+ message: "Checkout development requires the caller's pnpm executable."
265
+ });
266
+ for (let root of /* @__PURE__ */ new Set([options.packageRoot, options.workspaceRoot])) {
267
+ if (!root) continue;
268
+ let manifest = JSON.parse(
269
+ await readFile2(join2(root, "package.json"), "utf8")
270
+ );
271
+ for (let kind of [
272
+ "dependencies",
273
+ "devDependencies",
274
+ "optionalDependencies"
275
+ ])
276
+ for (let [name, version] of Object.entries(manifest[kind] ?? {}))
277
+ if (["@publish.os/nextjs", "@publish.os/cli"].includes(name) && (typeof version != "string" || !/^(?:workspace:|link:|file:)/.test(version)))
278
+ throw new AppError({
279
+ code: "FRAMEWORK_SELECTION_INVALID",
280
+ message: "Checkout dependencies cannot acquire PublishOS packages from npm.",
281
+ fix: "Use the local workspace or artifact dependency, then save again."
282
+ });
283
+ }
284
+ try {
285
+ await withCheckoutPreparation({
286
+ packageRoot: options.packageRoot,
287
+ workspaceRoot: options.workspaceRoot,
288
+ signal: options.lifetime.signal,
289
+ prepare: async (confirmStopped) => {
290
+ try {
291
+ await startLocalProcess({
292
+ command: options.pnpmExecutable,
293
+ args: [
294
+ "--filter",
295
+ "@publish.os/nextjs...",
296
+ "install",
297
+ "--frozen-lockfile",
298
+ "--prefer-offline",
299
+ "--fetch-timeout=10000"
300
+ ],
301
+ cwd: options.workspaceRoot ?? options.packageRoot,
302
+ environment: {
303
+ ...localProcessEnvironment({ mode: "development" }),
304
+ CI: "true"
305
+ },
306
+ signal: AbortSignal.any([
307
+ options.lifetime.signal,
308
+ AbortSignal.timeout(12e4)
309
+ ]),
310
+ onShutdown: options.lifetime.onShutdown,
311
+ quiet: !0
312
+ }).completion, confirmStopped();
313
+ } catch (error) {
314
+ throw (!(error instanceof AppError) || error.code !== "FRAMEWORK_PROCESS_SHUTDOWN_FAILED") && confirmStopped(), error;
315
+ }
316
+ }
317
+ });
318
+ } catch (error) {
319
+ throw error instanceof LocalProcessError && error.output.trim() && process.stderr.write(error.output), error;
320
+ }
321
+ }
322
+ async function runCheckoutCompiler(options) {
323
+ let selection = options.request.context?.framework;
324
+ if (selection?.kind !== "checkout" || !options.request.paths.output)
325
+ throw new AppError({
326
+ code: "FRAMEWORK_SELECTION_INVALID",
327
+ message: "Compiler updates require the selected checkout and owned output."
328
+ });
329
+ let temporary = await mkdtemp(
330
+ join2(dirname(options.request.paths.output), "compiler-")
331
+ ), identity = await assertLocalDirectory(temporary), requestPath = join2(temporary, "request.json"), resultPath = join2(temporary, "result.json"), importIndex = process.execArgv.indexOf("--import"), retain = !1;
332
+ try {
333
+ await writeFile(requestPath, JSON.stringify(options.request), {
334
+ flag: "wx",
335
+ mode: 384
336
+ }), await startLocalProcess({
337
+ command: process.execPath,
338
+ args: [
339
+ "--import",
340
+ importIndex === -1 ? createRequire(join2(selection.packageRoot, "package.json")).resolve(
341
+ "tsx/esm"
342
+ ) : process.execArgv[importIndex + 1] ?? "",
343
+ join2(
344
+ selection.packageRoot,
345
+ "src/lib/compiler/lifecycle/checkout-compiler-worker.ts"
346
+ ),
347
+ requestPath,
348
+ resultPath
349
+ ],
350
+ cwd: selection.packageRoot,
351
+ environment: {
352
+ ...localProcessEnvironment({ mode: "development" }),
353
+ TSX_TSCONFIG_PATH: join2(selection.packageRoot, "tsconfig.json")
354
+ },
355
+ signal: AbortSignal.any([
356
+ options.lifetime.signal,
357
+ AbortSignal.timeout(18e4)
358
+ ]),
359
+ onShutdown: options.lifetime.onShutdown
360
+ }).completion;
361
+ let response = JSON.parse(await readFile2(resultPath, "utf8"));
362
+ if (response?.result?.type !== "result" || !["success", "failure", "cancelled"].includes(response.result.status) || !Array.isArray(response.events))
363
+ throw new Error("Invalid compiler result");
364
+ return response;
365
+ } catch (error) {
366
+ throw options.lifetime.signal.throwIfAborted(), error instanceof AppError && error.code === "FRAMEWORK_PROCESS_SHUTDOWN_FAILED" ? (retain = !0, error) : new AppError({
367
+ code: "FRAMEWORK_CHECKOUT_COMPILE_FAILED",
368
+ message: "The checkout compiler could not apply this edit.",
369
+ fix: "Correct the compiler error and save again. The previous preview remains available.",
370
+ details: { cause: error }
371
+ });
372
+ } finally {
373
+ retain || (await assertLocalDirectory(temporary, identity), await rm(temporary, { recursive: !0, force: !0 }));
374
+ }
375
+ }
376
+
377
+ // src/lib/compiler/lifecycle/preview-cache.ts
378
+ import { createHash as createHash3 } from "crypto";
379
+ import {
380
+ lstat as lstat2,
381
+ readdir as readdir2,
382
+ readFile as readFile3,
383
+ realpath,
384
+ writeFile as writeFile2
385
+ } from "fs/promises";
386
+ import { join as join3 } from "path";
387
+ var CACHE_FILE = ".preview-cache.json", GENERATED_FILES = [
388
+ "package.json",
389
+ "pnpm-lock.yaml",
390
+ "manifest.generated.ts",
391
+ "next.config.mjs",
392
+ "postcss.config.mjs",
393
+ "proxy.ts",
394
+ "tsconfig.json"
395
+ ], GENERATED_DIRECTORIES = [".meta", "app", "source", "public", "scripts"], INSTALLATION_FILES = [
396
+ "node_modules/.modules.yaml",
397
+ "node_modules/.package-map.json",
398
+ "node_modules/.pnpm/lock.yaml",
399
+ "node_modules/next/package.json",
400
+ "node_modules/next/dist/bin/next",
401
+ "node_modules/@publish.os/nextjs/package.json"
402
+ ];
403
+ async function hashEntry({
404
+ hash,
405
+ outputDir,
406
+ path
407
+ }) {
408
+ let absolute = join3(outputDir, path), entry = await lstat2(absolute);
409
+ if (entry.isFile()) {
410
+ hash.update(`file:${JSON.stringify(path)}\0`), hash.update(await readFile3(absolute)), hash.update("\0");
411
+ return;
412
+ }
413
+ if (!entry.isDirectory())
414
+ throw new Error(`Unexpected generated preview entry: ${path}`);
415
+ hash.update(`directory:${JSON.stringify(path)}\0`);
416
+ for (let name of (await readdir2(absolute)).sort())
417
+ await hashEntry({ hash, outputDir, path: join3(path, name) });
418
+ }
419
+ async function outputIntegrity({
420
+ outputDir,
421
+ inputKind
422
+ }) {
423
+ let hash = createHash3("sha256");
424
+ for (let path of [
425
+ ...GENERATED_FILES,
426
+ ...inputKind === "checkout" ? ["next.config.base.mjs"] : [],
427
+ ...GENERATED_DIRECTORIES,
428
+ ...INSTALLATION_FILES.filter(
429
+ (path2) => inputKind !== "checkout" || path2 !== "node_modules/@publish.os/nextjs/package.json"
430
+ )
431
+ ])
432
+ await hashEntry({ hash, outputDir, path });
433
+ return `sha256:${hash.digest("hex")}`;
434
+ }
435
+ async function reusablePreview(options) {
436
+ if (options.revision)
437
+ try {
438
+ let cache = JSON.parse(
439
+ await readFile3(join3(options.outputDir, CACHE_FILE), "utf8")
440
+ );
441
+ if (cache.version !== 5 || cache.inputKind !== (options.inputKind ?? "customer") || cache.runtimeGraph !== (options.inputKind === "checkout" ? "checkout-source" : void 0) || cache.runtime !== options.runtime || cache.sourcePath !== options.sourcePath || typeof cache.integrity != "string")
442
+ return;
443
+ let current = cache.revision === options.revision && cache.frameworkIdentity === options.frameworkIdentity && cache.compilerRevision === options.compilerRevision && cache.checkoutDependencyRevision === options.checkoutDependencyRevision && cache.url === options.url;
444
+ return !current && options.inputKind !== "checkout" || options.inputKind === "checkout" && (!options.checkoutRoot || await realpath(
445
+ join3(options.outputDir, "node_modules/@publish.os/nextjs")
446
+ ) !== await realpath(options.checkoutRoot)) || (options.ide && await readFile3(join3(options.sourceRoot, ".publish.os/ide/metadata.json")), cache.integrity !== await outputIntegrity(options)) ? void 0 : {
447
+ current,
448
+ dependenciesChanged: cache.checkoutDependencyRevision !== options.checkoutDependencyRevision
449
+ };
450
+ } catch {
451
+ return;
452
+ }
453
+ }
454
+ async function recordPreviewCache(options) {
455
+ if (!options.revision) return;
456
+ let cache = {
457
+ version: 5,
458
+ inputKind: options.inputKind ?? "customer",
459
+ ...options.inputKind === "checkout" ? { runtimeGraph: "checkout-source" } : {},
460
+ revision: options.revision,
461
+ runtime: options.runtime,
462
+ frameworkIdentity: options.frameworkIdentity,
463
+ ...options.compilerRevision ? { compilerRevision: options.compilerRevision } : {},
464
+ ...options.checkoutDependencyRevision ? { checkoutDependencyRevision: options.checkoutDependencyRevision } : {},
465
+ url: options.url,
466
+ sourcePath: options.sourcePath,
467
+ integrity: await outputIntegrity(options)
468
+ };
469
+ await writeFile2(
470
+ join3(options.outputDir, CACHE_FILE),
471
+ `${JSON.stringify(cache)}
472
+ `
473
+ );
474
+ }
475
+
476
+ // src/lib/compiler/lifecycle/refresh-preview.ts
477
+ import {
478
+ cp,
479
+ lstat as lstat3,
480
+ mkdir,
481
+ readdir as readdir3,
482
+ readFile as readFile4,
483
+ rename,
484
+ rm as rm2,
485
+ writeFile as writeFile3
486
+ } from "fs/promises";
487
+ import { dirname as dirname2, join as join4, relative as relative2 } from "path";
488
+ var PRESERVED_PREVIEW_ENTRIES = /* @__PURE__ */ new Set([
489
+ "node_modules",
490
+ ".next",
491
+ ".operation-owner.json",
492
+ ".preview-cache.json",
493
+ PUBLIC_PAGEFIND_DIRECTORY
494
+ ]);
495
+ async function refreshPreview(options) {
496
+ let sync = async (source, target) => {
497
+ options.signal.throwIfAborted(), await assertLocalDirectory(source), await assertLocalDirectory(target);
498
+ let incoming = new Map(
499
+ (await readdir3(source, { withFileTypes: !0 })).map((entry) => [
500
+ entry.name,
501
+ entry
502
+ ])
503
+ ), previous = await readdir3(target, { withFileTypes: !0 }), preserved = (name) => {
504
+ let path = relative2(options.outputDir, join4(target, name)).replace(
505
+ /\\/g,
506
+ "/"
507
+ );
508
+ return PRESERVED_PREVIEW_ENTRIES.has(path) || path.startsWith(".refresh-");
509
+ };
510
+ for (let old of previous)
511
+ preserved(old.name) || incoming.has(old.name) || await rm2(join4(target, old.name), { recursive: !0, force: !0 });
512
+ for (let [name, entry] of incoming) {
513
+ if (preserved(name)) continue;
514
+ let from = join4(source, name), to = join4(target, name), old = await lstat3(to).catch((error) => {
515
+ if (error.code !== "ENOENT") throw error;
516
+ });
517
+ if (old?.isSymbolicLink() || entry.isSymbolicLink())
518
+ throw new AppError({
519
+ code: "FRAMEWORK_LOCAL_OUTPUT_REDIRECTED",
520
+ message: "Preview output was redirected. Restore the source-owned output before restarting preview."
521
+ });
522
+ if (entry.isDirectory() && old?.isDirectory())
523
+ await sync(from, to);
524
+ else if (entry.isFile() && old?.isFile()) {
525
+ if ((await readFile4(from)).equals(await readFile4(to))) continue;
526
+ await rename(from, to);
527
+ } else
528
+ old && await rm2(to, { recursive: !0, force: !0 }), await rename(from, to);
529
+ }
530
+ };
531
+ await assertLocalDirectory(options.incoming), await mkdir(join4(options.incoming, "public"), { recursive: !0 });
532
+ for (let path of PRESERVED_PREVIEW_ENTRIES) {
533
+ if (dirname2(path) === ".") continue;
534
+ (await lstat3(join4(options.outputDir, path)).catch(
535
+ (error) => {
536
+ if (error.code !== "ENOENT") throw error;
537
+ }
538
+ ))?.isDirectory() && await mkdir(join4(options.incoming, dirname2(path)), { recursive: !0 });
539
+ }
540
+ await sync(options.incoming, options.outputDir);
541
+ }
542
+ async function restartPreview(options) {
543
+ let previous = join4(options.incoming, "..", "previous"), previousIdentity = await assertLocalDirectory(options.outputDir);
544
+ await mkdir(previous);
545
+ let preserved = ["node_modules", ".next", ".operation-owner.json"];
546
+ for (let entry of await readdir3(options.outputDir))
547
+ preserved.includes(entry) || entry.startsWith(".refresh-") || await cp(join4(options.outputDir, entry), join4(previous, entry), {
548
+ recursive: !0
549
+ });
550
+ options.signal.throwIfAborted(), await assertLocalDirectory(options.outputDir, previousIdentity), await options.stop();
551
+ let movedDependencies = !1;
552
+ try {
553
+ options.dependencies && (await rename(
554
+ join4(options.outputDir, "node_modules"),
555
+ join4(previous, "node_modules")
556
+ ), movedDependencies = !0, await rename(
557
+ join4(options.incoming, "node_modules"),
558
+ join4(options.outputDir, "node_modules")
559
+ )), await refreshPreview(options), await options.start();
560
+ } catch (error) {
561
+ try {
562
+ await options.stop(), await assertLocalDirectory(options.outputDir, previousIdentity), movedDependencies && (await rename(
563
+ join4(options.outputDir, "node_modules"),
564
+ join4(options.incoming, "..", "failed-node_modules")
565
+ ).catch((cause) => {
566
+ if (cause.code !== "ENOENT") throw cause;
567
+ }), await rename(
568
+ join4(previous, "node_modules"),
569
+ join4(options.outputDir, "node_modules")
570
+ )), await refreshPreview({
571
+ incoming: previous,
572
+ outputDir: options.outputDir,
573
+ signal: AbortSignal.timeout(3e3)
574
+ });
575
+ let cache = await readFile4(join4(previous, ".preview-cache.json")).catch(
576
+ (cause) => {
577
+ if (cause.code !== "ENOENT") throw cause;
578
+ }
579
+ );
580
+ cache && await writeFile3(join4(options.outputDir, ".preview-cache.json"), cache), options.signal.aborted || await options.start();
581
+ } catch (cause) {
582
+ throw new AppError({
583
+ code: "FRAMEWORK_PREVIEW_RECOVERY_FAILED",
584
+ message: "The previous preview could not be restored. Generated recovery state was retained.",
585
+ fix: "Stop checkout dev and inspect the retained generated output before retrying.",
586
+ details: { cause: new AggregateError([error, cause]) }
587
+ });
588
+ }
589
+ throw error;
590
+ }
591
+ }
592
+
593
+ // src/lib/compiler/lifecycle/dev-operation.ts
594
+ async function readSourceSelection(sourceRoot) {
595
+ let raw = await readFile5(
596
+ join5(sourceRoot, "publish.os.config.json"),
597
+ "utf8"
598
+ ).catch(() => "");
599
+ try {
600
+ return JSON.parse(raw);
601
+ } catch {
602
+ return;
603
+ }
604
+ }
605
+ async function availablePort({
606
+ port,
607
+ host
608
+ }) {
609
+ return await new Promise((resolve) => {
610
+ let server = createServer();
611
+ server.unref(), server.once(
612
+ "error",
613
+ (error) => resolve(
614
+ host === "::1" && (error.code === "EAFNOSUPPORT" || error.code === "EADDRNOTAVAIL")
615
+ )
616
+ ), server.listen({ host, port }, () => server.close(() => resolve(!0)));
617
+ });
618
+ }
619
+ async function previewPort(requested, explicit) {
620
+ if (!Number.isInteger(requested) || requested < 1 || requested > 65535)
621
+ throw new AppError({
622
+ code: "FRAMEWORK_PREVIEW_PORT_INVALID",
623
+ message: "The preview port must be an integer from 1 through 65535. Set a valid --port value."
624
+ });
625
+ for (let port = requested; port <= 65535; port += 1) {
626
+ if (await availablePort({ port, host: "127.0.0.1" }) && await availablePort({ port, host: "::1" }) && await availablePort({ port }))
627
+ return port;
628
+ if (explicit) {
629
+ let alternative = await previewPort(
630
+ requested < 65535 ? requested + 1 : 8080,
631
+ !1
632
+ ).catch(() => {
633
+ });
634
+ throw new AppError({
635
+ code: "FRAMEWORK_PREVIEW_PORT_UNAVAILABLE",
636
+ message: `Port ${requested} is in use. Stop the server on that port${alternative ? ` or run publish.os dev --port ${alternative}` : " and choose another port"}.`
637
+ });
638
+ }
639
+ }
640
+ throw new AppError({
641
+ code: "FRAMEWORK_PREVIEW_PORT_UNAVAILABLE",
642
+ message: `No free preview port is available from ${requested} through 65535. Stop another local server or select a lower --port.`
643
+ });
644
+ }
645
+ async function runDevelopment(options) {
646
+ let requestedPort = options.request.port ?? 8080, port = await previewPort(
647
+ requestedPort,
648
+ options.request.portExplicit === !0
649
+ ), url = `http://localhost:${port}`, frameworkIdentity = options.request.context?.archive?.integrity ?? "", inputKind = options.request.context?.framework?.kind ?? "customer", framework = await readInstalledFramework();
650
+ options.request.context?.framework !== void 0 && (frameworkIdentity = await assertFrameworkSelection({
651
+ context: options.request.context,
652
+ framework,
653
+ runtime: void 0
654
+ }));
655
+ let sessionCancellation = new AbortController();
656
+ port !== requestedPort && options.onEvent?.({
657
+ type: "progress",
658
+ message: `Port ${requestedPort} is in use. Using ${port}.`
659
+ });
660
+ let scope = options.request.context?.framework?.kind === "checkout" ? createHash4("sha256").update(
661
+ JSON.stringify([
662
+ await realpath2(options.request.context.framework.packageRoot),
663
+ port
664
+ ])
665
+ ).digest("hex") : void 0;
666
+ return await withLocalOperation({
667
+ sourceRoot: options.request.paths.source,
668
+ outputDir: options.request.paths.output,
669
+ operation: "dev",
670
+ scope,
671
+ signal: options.signal ? AbortSignal.any([options.signal, sessionCancellation.signal]) : sessionCancellation.signal,
672
+ run: async (lifetime) => {
673
+ let localOptions = { ...options, signal: lifetime.signal }, stopped = !1, dirty = !1, refreshing, startupReconciliation, timer, ready = !1, checkoutWatch, checkoutDependenciesDirty = !1, rejectSession = () => {
674
+ }, failed = new Promise((_resolve, reject) => {
675
+ rejectSession = reject;
676
+ });
677
+ failed.catch(() => {
678
+ });
679
+ let abortSession = () => rejectSession(lifetime.signal.reason);
680
+ lifetime.signal.addEventListener("abort", abortSession, { once: !0 });
681
+ let watchOptions = {
682
+ onChange: () => {
683
+ dirty = !0, timer && clearTimeout(timer), timer = setTimeout(() => {
684
+ ready && drain();
685
+ }, 100);
686
+ },
687
+ onError: (cause) => {
688
+ let error = new AppError({
689
+ code: "FRAMEWORK_PREVIEW_WATCH_FAILED",
690
+ message: `The source watcher stopped: ${cause instanceof Error ? cause.message : String(cause)}. Restart preview after correcting the file-system error.`
691
+ });
692
+ sessionCancellation.abort(error), rejectSession(error);
693
+ }
694
+ }, sourceWatch = await watchSource({
695
+ ...watchOptions,
696
+ sourceRoot: lifetime.sourceRoot
697
+ });
698
+ lifetime.onShutdown(async () => {
699
+ stopped = !0, timer && clearTimeout(timer), await sourceWatch.stop(), await checkoutWatch?.stop(), await startupReconciliation, await refreshing;
700
+ }), options.request.context?.framework?.kind === "checkout" && (checkoutWatch = await watchCheckout({
701
+ ...watchOptions,
702
+ packageRoot: options.request.context.framework.packageRoot
703
+ }));
704
+ let initialRevision = await sourceWatch.revision(), initialCompilerRevision = await checkoutWatch?.revision(), initialDependencyRevision = await checkoutWatch?.dependencyRevision(), initialConfig = await readSourceSelection(lifetime.sourceRoot) ?? {}, reuse = await reusablePreview({
705
+ outputDir: lifetime.outputDir,
706
+ sourceRoot: lifetime.sourceRoot,
707
+ revision: initialRevision,
708
+ runtime: options.request.context?.framework ? `${framework.packageName}@${framework.version}` : initialConfig.runtime ?? "",
709
+ frameworkIdentity,
710
+ compilerRevision: initialCompilerRevision,
711
+ checkoutDependencyRevision: initialDependencyRevision,
712
+ inputKind,
713
+ url,
714
+ sourcePath: options.request.context?.sourcePath ?? "publish.os",
715
+ ide: !!options.request.context?.ide,
716
+ checkoutRoot: options.request.context?.framework?.kind === "checkout" ? options.request.context.framework.packageRoot : void 0
717
+ });
718
+ checkoutDependenciesDirty = reuse?.dependenciesChanged ?? !1;
719
+ let validateSource = async () => (await import("./validate-local-source-XRL2Y7XE.js")).validateLocalSource({
720
+ options: localOptions,
721
+ sourceDir: lifetime.sourceDir,
722
+ sourceRoot: lifetime.sourceRoot
723
+ }), prepared = reuse ? void 0 : await validateSource(), selection = {
724
+ runtime: options.request.context?.framework ? `${framework.packageName}@${framework.version}` : prepared?.source.config.runtime ?? initialConfig.runtime
725
+ }, assertSelection = async () => {
726
+ if (options.request.context?.framework) return;
727
+ let config = await readSourceSelection(lifetime.sourceRoot);
728
+ if (config && config.runtime !== selection.runtime)
729
+ throw new AppError({
730
+ code: "FRAMEWORK_PREVIEW_RESTART_REQUIRED",
731
+ message: "The framework pin changed. Restart publish.os dev to use the new selection."
732
+ });
733
+ };
734
+ if (options.request.context?.ide) {
735
+ let { prepareIdeSupport } = await import("./ide-support-ZNW7ODFY.js");
736
+ await prepareIdeSupport({
737
+ publishOsDir: lifetime.sourceRoot,
738
+ // Only a verified unchanged source can defer validation until IDE repair.
739
+ source: prepared?.source ?? (reuse?.current ? async () => (await validateSource()).source : (await validateSource()).source),
740
+ framework: prepared?.framework ?? framework,
741
+ frameworkOptions: localOptions
742
+ });
743
+ }
744
+ let compose = async (outputDir, preparedSource) => {
745
+ let { composeFrameworkSource } = await import("./compose-NN23UJGC.js");
746
+ await composeFrameworkSource({
747
+ request: {
748
+ ...options.request,
749
+ paths: { source: lifetime.sourceDir, output: outputDir },
750
+ context: {
751
+ ...options.request.context,
752
+ previewUrl: url,
753
+ sourcePath: options.request.context?.sourcePath ?? "publish.os",
754
+ sourceRevision: "local-development"
755
+ }
756
+ },
757
+ source: preparedSource,
758
+ signal: lifetime.signal,
759
+ onProgress: (message) => options.onEvent?.({ type: "progress", message })
760
+ });
761
+ }, search = async (outputDir) => {
762
+ options.onEvent?.({
763
+ type: "progress",
764
+ message: "Refreshing search index"
765
+ }), await startLocalProcess({
766
+ command: process.execPath,
767
+ args: [join5(outputDir, "scripts/build-search-index.mjs")],
768
+ cwd: outputDir,
769
+ signal: lifetime.signal,
770
+ onShutdown: lifetime.onShutdown,
771
+ environment: localProcessEnvironment({ mode: "development" })
772
+ }).completion;
773
+ };
774
+ prepared && (await approveLocalComposition({ options: localOptions }), await lifetime.replaceOutput(async (outputDir) => {
775
+ options.onEvent?.({ type: "progress", message: "Preparing preview" }), await compose(outputDir, prepared.source), await installLocalApp({
776
+ outputDir,
777
+ framework: prepared.framework,
778
+ options: localOptions,
779
+ lifetime
780
+ }), await search(outputDir), await assertSelection(), await recordPreviewCache({
781
+ outputDir,
782
+ revision: initialRevision,
783
+ runtime: selection.runtime ?? "",
784
+ frameworkIdentity,
785
+ compilerRevision: initialCompilerRevision,
786
+ checkoutDependencyRevision: initialDependencyRevision,
787
+ inputKind,
788
+ url,
789
+ sourcePath: options.request.context?.sourcePath ?? "publish.os"
790
+ });
791
+ }));
792
+ let outputIdentity = await assertLocalDirectory(lifetime.outputDir), assertOutput = async () => {
793
+ await assertLocalDirectory(lifetime.outputDir, outputIdentity), await assertOperationOutput({
794
+ sourceRoot: lifetime.sourceRoot,
795
+ outputDir: lifetime.outputDir,
796
+ operation: "dev",
797
+ scope
798
+ });
799
+ }, next, resolveSession = () => {
800
+ }, ended = new Promise((resolve) => {
801
+ resolveSession = resolve;
802
+ }), stopNext = async () => {
803
+ let current = next;
804
+ next = void 0, ready = !1, await current?.stop();
805
+ }, startNext = async (verifyStartup = !1) => {
806
+ let log = "", resolveReady = () => {
807
+ }, rejectReady = () => {
808
+ }, started = new Promise((resolve, reject) => {
809
+ resolveReady = resolve, rejectReady = reject;
810
+ }), observedReady = !1, observe = (value) => {
811
+ log = (log + value).slice(-4096), !(observedReady || !/Ready in\s+\S+/i.test(stripVTControlCharacters(log))) && (observedReady = !0, startupReconciliation = (async () => {
812
+ if (verifyStartup) {
813
+ let response = await fetch(
814
+ `${url}/_next/static/__publishos_ready__`,
815
+ {
816
+ signal: AbortSignal.any([
817
+ lifetime.signal,
818
+ AbortSignal.timeout(15e3)
819
+ ])
820
+ }
821
+ );
822
+ if (await response.body?.cancel(), response.status >= 500)
823
+ throw new AppError({
824
+ code: "FRAMEWORK_PREVIEW_START_FAILED",
825
+ message: "Next could not serve the restarted preview."
826
+ });
827
+ }
828
+ await sourceWatch.reconcileStartup(), await checkoutWatch?.reconcileStartup(), lifetime.signal.throwIfAborted(), !stopped && (ready = !0, options.onEvent?.({ type: "ready", url }), resolveReady(), drain());
829
+ })().catch(rejectReady));
830
+ }, nextExecutable = await realpath2(
831
+ join5(lifetime.outputDir, "node_modules/next/dist/bin/next")
832
+ );
833
+ options.onEvent?.({ type: "progress", message: "Starting Next" });
834
+ let current = startLocalProcess({
835
+ command: process.execPath,
836
+ args: [nextExecutable, "dev", "--port", String(port)],
837
+ cwd: lifetime.outputDir,
838
+ signal: lifetime.signal,
839
+ onShutdown: lifetime.onShutdown,
840
+ environment: localProcessEnvironment({ mode: "development" }),
841
+ onStdout: observe,
842
+ onStderr: observe
843
+ });
844
+ next = current, current.completion.then(
845
+ () => {
846
+ rejectReady(
847
+ new AppError({
848
+ code: "FRAMEWORK_PREVIEW_START_FAILED",
849
+ message: "Next stopped before preview readiness."
850
+ })
851
+ ), next === current && ready && resolveSession();
852
+ },
853
+ (error) => {
854
+ rejectReady(error), next === current && ready && !lifetime.signal.aborted && rejectSession(error);
855
+ }
856
+ );
857
+ let deadline = new AbortController();
858
+ try {
859
+ await Promise.race([
860
+ started,
861
+ delay(6e4, void 0, { signal: deadline.signal }).then(() => {
862
+ throw new AppError({
863
+ code: "FRAMEWORK_PREVIEW_START_FAILED",
864
+ message: "Next did not become ready within 60 seconds."
865
+ });
866
+ })
867
+ ]);
868
+ } finally {
869
+ deadline.abort();
870
+ }
871
+ }, refresh = async (compilerChanges) => {
872
+ checkoutDependenciesDirty ||= compilerChanges.some(
873
+ (change) => change.dependency
874
+ );
875
+ let revisionBefore = await sourceWatch.revision(), compilerRevisionBefore = await checkoutWatch?.revision(), dependencyRevisionBefore = await checkoutWatch?.dependencyRevision(), inputsCurrent = async () => revisionBefore !== void 0 && revisionBefore === await sourceWatch.revision() && (!checkoutWatch || compilerRevisionBefore !== void 0 && compilerRevisionBefore === await checkoutWatch.revision());
876
+ await assertSelection();
877
+ let validation = checkoutWatch ? void 0 : await (await import("./validate-local-source-XRL2Y7XE.js")).validateLocalSource({
878
+ options: localOptions,
879
+ sourceDir: lifetime.sourceDir,
880
+ sourceRoot: lifetime.sourceRoot
881
+ });
882
+ await assertSelection(), await assertOutput(), await assertGeneratedOutput({ outputDir: lifetime.outputDir, scope });
883
+ let temporary = await mkdtemp2(join5(lifetime.outputDir, ".refresh-")), identity = await assertLocalDirectory(temporary), retain = !1, recordGeneratedOutput, primaryFailure, cleanup = async () => {
884
+ try {
885
+ await assertOutput(), await assertLocalDirectory(temporary, identity), await recordGeneratedOutput?.(), await rm3(temporary, { recursive: !0, force: !0 });
886
+ } catch (error) {
887
+ if (!primaryFailure) throw error;
888
+ primaryFailure.error instanceof Error && (primaryFailure.error.cause = {
889
+ previous: primaryFailure.error.cause,
890
+ cleanup: error,
891
+ retained: temporary
892
+ });
893
+ }
894
+ }, acceptCompilation = (response) => {
895
+ for (let event of response.events)
896
+ (event.type === "diagnostics" || event.type === "progress") && options.onEvent?.(event);
897
+ if (response.result.status !== "success")
898
+ throw new AppError({
899
+ code: response.result.error?.code ?? "FRAMEWORK_CHECKOUT_COMPILE_FAILED",
900
+ message: response.result.error?.message ?? "The checkout compiler did not complete the update.",
901
+ fix: response.result.error?.fix ?? "Correct the reported error and save again. The previous preview remains available."
902
+ });
903
+ };
904
+ try {
905
+ let incoming = join5(temporary, "app");
906
+ if (checkoutWatch) {
907
+ compilerChanges.length && options.onEvent?.({
908
+ type: "restart",
909
+ target: "compiler",
910
+ reason: "Compiler inputs changed."
911
+ }), checkoutDependenciesDirty && (await prepareCheckoutDependencies({
912
+ packageRoot: framework.packageRoot,
913
+ workspaceRoot: checkoutWatch.workspaceRoot,
914
+ pnpmExecutable: options.request.context?.pnpmExecutable,
915
+ lifetime
916
+ }), checkoutDependenciesDirty = !1);
917
+ let request = {
918
+ ...options.request,
919
+ operation: "compose",
920
+ paths: { source: lifetime.sourceDir, output: incoming },
921
+ context: {
922
+ ...options.request.context,
923
+ previewUrl: url,
924
+ sourceRevision: "local-development",
925
+ sourcePath: options.request.context?.sourcePath ?? "publish.os"
926
+ }
927
+ }, response = await runCheckoutCompiler({ request, lifetime });
928
+ if (!await inputsCurrent())
929
+ return dirty = !0, !1;
930
+ acceptCompilation(response), framework = await readInstalledFramework();
931
+ } else validation && await compose(incoming, validation.source);
932
+ if (!await inputsCurrent())
933
+ return dirty = !0, !1;
934
+ await assertSelection(), await assertOutput();
935
+ let changed = async (name) => !(await readFile5(join5(incoming, name))).equals(
936
+ await readFile5(join5(lifetime.outputDir, name))
937
+ ), dependenciesChanged = checkoutWatch && (await changed("package.json") || await changed("pnpm-workspace.yaml") || await changed("pnpm-lock.yaml")), configurationChanged = checkoutWatch && (await changed("next.config.mjs") || await changed("next.config.base.mjs") || await changed("postcss.config.mjs"));
938
+ dependenciesChanged && await installLocalApp({
939
+ outputDir: incoming,
940
+ framework,
941
+ options: localOptions,
942
+ lifetime
943
+ });
944
+ let nextFrameworkIdentity = checkoutWatch ? await assertFrameworkSelection({
945
+ context: options.request.context,
946
+ framework,
947
+ runtime: void 0
948
+ }) : frameworkIdentity;
949
+ if (checkoutWatch && options.request.context?.ide && JSON.parse(
950
+ await readFile5(
951
+ join5(lifetime.sourceRoot, ".publish.os/ide/metadata.json"),
952
+ "utf8"
953
+ )
954
+ ).selection?.integrity !== nextFrameworkIdentity) {
955
+ let ide = await runCheckoutCompiler({
956
+ request: {
957
+ ...options.request,
958
+ operation: "validate",
959
+ paths: { source: lifetime.sourceRoot, output: incoming }
960
+ },
961
+ lifetime
962
+ });
963
+ acceptCompilation(ide);
964
+ }
965
+ if (!await inputsCurrent())
966
+ return dirty = !0, !1;
967
+ if (recordGeneratedOutput = await prepareGeneratedOutputUpdate({
968
+ sourceRoot: lifetime.sourceRoot,
969
+ outputDir: lifetime.outputDir,
970
+ scope,
971
+ incoming,
972
+ stagingDir: temporary
973
+ }), dependenciesChanged || configurationChanged) {
974
+ let serving = !!next;
975
+ serving && options.onEvent?.({
976
+ type: "restart",
977
+ target: "next",
978
+ reason: dependenciesChanged ? "App dependencies changed." : "Next startup configuration changed."
979
+ }), await restartPreview({
980
+ incoming,
981
+ outputDir: lifetime.outputDir,
982
+ dependencies: !!dependenciesChanged,
983
+ signal: lifetime.signal,
984
+ stop: stopNext,
985
+ start: async () => {
986
+ await search(lifetime.outputDir), serving && await startNext(!0);
987
+ }
988
+ });
989
+ } else
990
+ await refreshPreview({
991
+ incoming,
992
+ outputDir: lifetime.outputDir,
993
+ signal: lifetime.signal
994
+ }), await search(lifetime.outputDir);
995
+ return frameworkIdentity = nextFrameworkIdentity, await recordGeneratedOutput?.(), recordGeneratedOutput = void 0, revisionBefore && await inputsCurrent() && await recordPreviewCache({
996
+ outputDir: lifetime.outputDir,
997
+ revision: revisionBefore,
998
+ runtime: selection.runtime ?? "",
999
+ frameworkIdentity,
1000
+ compilerRevision: compilerRevisionBefore,
1001
+ checkoutDependencyRevision: dependencyRevisionBefore,
1002
+ inputKind,
1003
+ url,
1004
+ sourcePath: options.request.context?.sourcePath ?? "publish.os"
1005
+ }), !0;
1006
+ } catch (error) {
1007
+ if (error instanceof AppError && (error.code === "FRAMEWORK_PROCESS_SHUTDOWN_FAILED" || error.code === "FRAMEWORK_PREVIEW_RECOVERY_FAILED") && (retain = !0), !retain && !lifetime.signal.aborted && !await inputsCurrent())
1008
+ return dirty = !0, !1;
1009
+ throw primaryFailure = { error }, error;
1010
+ } finally {
1011
+ retain || await cleanup();
1012
+ }
1013
+ };
1014
+ function drain() {
1015
+ refreshing || stopped || !ready || lifetime.signal.aborted || (refreshing = (async () => {
1016
+ for (; dirty && !stopped; ) {
1017
+ dirty = !1;
1018
+ let changes = await sourceWatch.takeChanges(), compilerChanges = await checkoutWatch?.takeChanges() ?? [];
1019
+ changes.length && options.onEvent?.({ type: "changes", changes });
1020
+ try {
1021
+ await refresh(compilerChanges) && options.onEvent?.({ type: "updated" });
1022
+ } catch (error) {
1023
+ if (lifetime.signal.aborted) return;
1024
+ if (error instanceof AppError && (error.code === "FRAMEWORK_PREVIEW_RESTART_REQUIRED" || error.code === "FRAMEWORK_PROCESS_SHUTDOWN_FAILED" || error.code === "FRAMEWORK_PREVIEW_RECOVERY_FAILED" || error.code.startsWith("FRAMEWORK_LOCAL_OUTPUT_"))) {
1025
+ rejectSession(error);
1026
+ return;
1027
+ }
1028
+ if (error instanceof AppError && error.code === "FRAMEWORK_SOURCE_INVALID")
1029
+ continue;
1030
+ options.onEvent?.({
1031
+ type: "diagnostics",
1032
+ diagnostics: {
1033
+ diagnostics: [
1034
+ {
1035
+ severity: "error",
1036
+ code: "FRAMEWORK_PREVIEW_REFRESH_FAILED",
1037
+ message: `Preview artifact refresh failed: ${error instanceof Error ? error.message : String(error)}`,
1038
+ correction: error instanceof AppError && error.fix ? error.fix : "Correct the source error and save again. The previous preview remains available."
1039
+ }
1040
+ ]
1041
+ }
1042
+ });
1043
+ }
1044
+ }
1045
+ })().finally(() => {
1046
+ refreshing = void 0, dirty && drain();
1047
+ }));
1048
+ }
1049
+ return reuse && !reuse.current && await refresh([]), await startNext(), await Promise.race([ended, failed]), { type: "result", status: "success" };
1050
+ }
1051
+ });
1052
+ }
1053
+ export {
1054
+ runDevelopment
1055
+ };