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