@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,156 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isSameOrDescendant
|
|
3
|
+
} from "./chunk-YLTOLYWM.js";
|
|
4
|
+
|
|
5
|
+
// src/lib/compiler/source/diagnostics/errors/publish-os-source-error.ts
|
|
6
|
+
var ERROR_CODES = {
|
|
7
|
+
CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
|
|
8
|
+
CONFIG_INVALID_JSON: "CONFIG_INVALID_JSON",
|
|
9
|
+
CONFIG_SCHEMA_INVALID: "CONFIG_SCHEMA_INVALID",
|
|
10
|
+
CONFIG_MOUNT_NOT_FOUND: "CONFIG_MOUNT_NOT_FOUND",
|
|
11
|
+
CONFIG_MOUNT_INVALID_JSON: "CONFIG_MOUNT_INVALID_JSON",
|
|
12
|
+
CONFIG_MOUNT_INVALID_SCHEMA: "CONFIG_MOUNT_INVALID_SCHEMA",
|
|
13
|
+
CONFIG_MOUNT_NOT_FILE: "CONFIG_MOUNT_NOT_FILE",
|
|
14
|
+
CONFIG_MOUNT_PATH_INVALID: "CONFIG_MOUNT_PATH_INVALID",
|
|
15
|
+
CONFIG_GROUP_INVALID_SCHEMA: "CONFIG_GROUP_INVALID_SCHEMA",
|
|
16
|
+
CONFIG_GROUP_INVALID_MOUNT: "CONFIG_GROUP_INVALID_MOUNT",
|
|
17
|
+
CONFIG_PATH_EMPTY: "CONFIG_PATH_EMPTY",
|
|
18
|
+
CONFIG_PATH_ABSOLUTE: "CONFIG_PATH_ABSOLUTE",
|
|
19
|
+
CONFIG_PATH_PROTOCOL: "CONFIG_PATH_PROTOCOL",
|
|
20
|
+
CONFIG_PATH_OUT_OF_SCOPE: "CONFIG_PATH_OUT_OF_SCOPE",
|
|
21
|
+
CONFIG_FILE_INVALID_PATH: "CONFIG_FILE_INVALID_PATH",
|
|
22
|
+
CONFIG_FILE_MISSING: "CONFIG_FILE_MISSING",
|
|
23
|
+
CONFIG_FILE_NOT_REGULAR: "CONFIG_FILE_NOT_REGULAR",
|
|
24
|
+
CONFIG_CONTENT_PATH_INVALID: "CONFIG_CONTENT_PATH_INVALID",
|
|
25
|
+
CONFIG_CONTENT_MISSING: "CONFIG_CONTENT_MISSING",
|
|
26
|
+
CONFIG_CONTENT_NOT_DIRECTORY: "CONFIG_CONTENT_NOT_DIRECTORY",
|
|
27
|
+
CONTENT_FRONTMATTER_INVALID_JSON: "CONTENT_FRONTMATTER_INVALID_JSON",
|
|
28
|
+
CONTENT_FRONTMATTER_REQUIRED: "CONTENT_FRONTMATTER_REQUIRED",
|
|
29
|
+
CONTENT_FRONTMATTER_ID_INVALID: "CONTENT_FRONTMATTER_ID_INVALID",
|
|
30
|
+
CONTENT_FILE_PARSE_FAILED: "CONTENT_FILE_PARSE_FAILED",
|
|
31
|
+
CONTENT_DUPLICATE_ID: "CONTENT_DUPLICATE_ID",
|
|
32
|
+
CONTENT_DUPLICATE_ROUTE: "CONTENT_DUPLICATE_ROUTE",
|
|
33
|
+
CONTENT_SLUG_INVALID: "CONTENT_SLUG_INVALID",
|
|
34
|
+
CONTENT_TREE_MISMATCH: "CONTENT_TREE_MISMATCH",
|
|
35
|
+
CONTENT_MANIFEST_GENERATION_FAILED: "CONTENT_MANIFEST_GENERATION_FAILED"
|
|
36
|
+
}, AppError = class extends Error {
|
|
37
|
+
code;
|
|
38
|
+
details;
|
|
39
|
+
constructor({ code, message, details }) {
|
|
40
|
+
super(message), this.name = "AppError", this.code = code, this.details = details;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// src/lib/compiler/source/assert-publish-os-source-boundary.ts
|
|
45
|
+
import { lstat, readdir, realpath } from "fs/promises";
|
|
46
|
+
import { basename, dirname, join, relative, resolve, sep } from "path";
|
|
47
|
+
function displayPath(root, path) {
|
|
48
|
+
return relative(root, path).split(sep).join("/") || ".";
|
|
49
|
+
}
|
|
50
|
+
function sourceBoundaryError(options) {
|
|
51
|
+
return new AppError({
|
|
52
|
+
code: options.code,
|
|
53
|
+
message: options.message,
|
|
54
|
+
details: { file: displayPath(options.root, options.path) }
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function assertEntry(options) {
|
|
58
|
+
let entry = await lstat(options.path);
|
|
59
|
+
if (entry.isSymbolicLink())
|
|
60
|
+
throw sourceBoundaryError({
|
|
61
|
+
code: "FRAMEWORK_SOURCE_SYMLINK",
|
|
62
|
+
message: "Symbolic links are not allowed inside publish.os.",
|
|
63
|
+
path: options.path,
|
|
64
|
+
root: options.root
|
|
65
|
+
});
|
|
66
|
+
if (!entry.isDirectory() && !entry.isFile())
|
|
67
|
+
throw sourceBoundaryError({
|
|
68
|
+
code: "FRAMEWORK_SOURCE_ENTRY_NOT_REGULAR",
|
|
69
|
+
message: "publish.os may only contain directories and regular files.",
|
|
70
|
+
path: options.path,
|
|
71
|
+
root: options.root
|
|
72
|
+
});
|
|
73
|
+
let realEntry = await realpath(options.path);
|
|
74
|
+
if (!isSameOrDescendant(options.realRoot, realEntry))
|
|
75
|
+
throw sourceBoundaryError({
|
|
76
|
+
code: "FRAMEWORK_SOURCE_PATH_ESCAPE",
|
|
77
|
+
message: "A publish.os entry resolves outside the source directory.",
|
|
78
|
+
path: options.path,
|
|
79
|
+
root: options.root
|
|
80
|
+
});
|
|
81
|
+
if (entry.isDirectory()) {
|
|
82
|
+
if (basename(options.path) === "publish.os") {
|
|
83
|
+
options.nestedSources.push(displayPath(options.root, options.path));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
for (let child of await readdir(options.path))
|
|
87
|
+
await assertEntry({
|
|
88
|
+
nestedSources: options.nestedSources,
|
|
89
|
+
path: resolve(options.path, child),
|
|
90
|
+
root: options.root,
|
|
91
|
+
realRoot: options.realRoot
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function assertPublishOsSourceBoundary(publishOsDir, sourceIdentity) {
|
|
96
|
+
let root = resolve(publishOsDir), authoredRoot = resolve(sourceIdentity?.sourceRoot ?? root);
|
|
97
|
+
if (basename(authoredRoot) !== "publish.os")
|
|
98
|
+
throw sourceBoundaryError({
|
|
99
|
+
code: "SOURCE_ROOT_NAME_INVALID",
|
|
100
|
+
message: "The authored source folder must be named publish.os.",
|
|
101
|
+
path: root,
|
|
102
|
+
root
|
|
103
|
+
});
|
|
104
|
+
for (let ancestor = authoredRoot; ; ancestor = dirname(ancestor)) {
|
|
105
|
+
if (await lstat(join(ancestor, ".git")).then(() => !0).catch((error) => {
|
|
106
|
+
if (error.code === "ENOENT" || error.code === "ENOTDIR") return !1;
|
|
107
|
+
throw error;
|
|
108
|
+
})) {
|
|
109
|
+
if (ancestor !== authoredRoot) break;
|
|
110
|
+
throw sourceBoundaryError({
|
|
111
|
+
code: "SOURCE_ROOT_IS_REPOSITORY",
|
|
112
|
+
message: "The repository root cannot be an authored source root.",
|
|
113
|
+
path: root,
|
|
114
|
+
root
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (ancestor !== authoredRoot && basename(ancestor) === "publish.os")
|
|
118
|
+
throw sourceBoundaryError({
|
|
119
|
+
code: "SOURCE_ROOT_NESTED",
|
|
120
|
+
message: "Select the outer publish.os source instead of a nested source.",
|
|
121
|
+
path: root,
|
|
122
|
+
root
|
|
123
|
+
});
|
|
124
|
+
if (dirname(ancestor) === ancestor) break;
|
|
125
|
+
}
|
|
126
|
+
let rootEntry = await lstat(root);
|
|
127
|
+
if (rootEntry.isSymbolicLink())
|
|
128
|
+
throw sourceBoundaryError({
|
|
129
|
+
code: "FRAMEWORK_SOURCE_SYMLINK",
|
|
130
|
+
message: "The publish.os source directory must not be a symbolic link.",
|
|
131
|
+
path: root,
|
|
132
|
+
root
|
|
133
|
+
});
|
|
134
|
+
if (!rootEntry.isDirectory())
|
|
135
|
+
throw sourceBoundaryError({
|
|
136
|
+
code: "FRAMEWORK_SOURCE_ROOT_NOT_DIRECTORY",
|
|
137
|
+
message: "The publish.os source path must be a directory.",
|
|
138
|
+
path: root,
|
|
139
|
+
root
|
|
140
|
+
});
|
|
141
|
+
let realRoot = await realpath(root), nestedSources = [];
|
|
142
|
+
for (let child of await readdir(root))
|
|
143
|
+
child === ".publish.os" || child === "tsconfig.json" || await assertEntry({
|
|
144
|
+
nestedSources,
|
|
145
|
+
path: resolve(root, child),
|
|
146
|
+
root,
|
|
147
|
+
realRoot
|
|
148
|
+
});
|
|
149
|
+
return { nestedSources: nestedSources.sort() };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export {
|
|
153
|
+
ERROR_CODES,
|
|
154
|
+
AppError,
|
|
155
|
+
assertPublishOsSourceBoundary
|
|
156
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/lib/compiler/source/config/runtime-package.ts
|
|
2
|
+
var exactRuntimePackage = /^@publish\.os\/nextjs@((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)$/u;
|
|
3
|
+
function runtimePackageVersion(value) {
|
|
4
|
+
return typeof value == "string" ? exactRuntimePackage.exec(value)?.[1] : void 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
runtimePackageVersion
|
|
9
|
+
};
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import {
|
|
2
|
+
acquireOperationLock,
|
|
3
|
+
assertGeneratedOutput,
|
|
4
|
+
assertLocalDirectory,
|
|
5
|
+
assertOperationOutput,
|
|
6
|
+
ensureOutputOwnership,
|
|
7
|
+
localOperationName,
|
|
8
|
+
markOperationOutput
|
|
9
|
+
} from "./chunk-GGKFQ3MA.js";
|
|
10
|
+
import {
|
|
11
|
+
assertPublishOsSourceBoundary
|
|
12
|
+
} from "./chunk-7OGTPSKI.js";
|
|
13
|
+
import {
|
|
14
|
+
isExcludedSourcePath
|
|
15
|
+
} from "./chunk-YLTOLYWM.js";
|
|
16
|
+
import {
|
|
17
|
+
AppError
|
|
18
|
+
} from "./chunk-WDY4IK6Z.js";
|
|
19
|
+
|
|
20
|
+
// src/lib/compiler/lifecycle/local-operation.ts
|
|
21
|
+
import { mkdir as mkdir2, mkdtemp, realpath as realpath2, rename, rm } from "fs/promises";
|
|
22
|
+
import { isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "path";
|
|
23
|
+
|
|
24
|
+
// src/lib/compiler/lifecycle/capture-local-source.ts
|
|
25
|
+
import { createHash } from "crypto";
|
|
26
|
+
import { constants } from "fs";
|
|
27
|
+
import {
|
|
28
|
+
lstat,
|
|
29
|
+
mkdir,
|
|
30
|
+
open,
|
|
31
|
+
readdir,
|
|
32
|
+
readFile,
|
|
33
|
+
realpath,
|
|
34
|
+
writeFile
|
|
35
|
+
} from "fs/promises";
|
|
36
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "path";
|
|
37
|
+
function isInside({ root, path }) {
|
|
38
|
+
let value = relative(root, path);
|
|
39
|
+
return value !== "" && value !== ".." && !value.startsWith(`..${sep}`) && !isAbsolute(value);
|
|
40
|
+
}
|
|
41
|
+
async function captureLocalSource({
|
|
42
|
+
sourceRoot,
|
|
43
|
+
captureDir,
|
|
44
|
+
signal
|
|
45
|
+
}) {
|
|
46
|
+
signal?.throwIfAborted(), await assertPublishOsSourceBoundary(sourceRoot), signal?.throwIfAborted();
|
|
47
|
+
let root = await realpath(sourceRoot), destination = resolve(captureDir), outputRoot = join(root, ".publish.os");
|
|
48
|
+
if (!isInside({ root: outputRoot, path: destination }) || await realpath(dirname(destination)) !== dirname(destination))
|
|
49
|
+
throw new AppError({
|
|
50
|
+
code: "FRAMEWORK_CAPTURE_OUTPUT_INVALID",
|
|
51
|
+
message: "Source capture requires an owned path inside source output."
|
|
52
|
+
});
|
|
53
|
+
await mkdir(destination).catch((error) => {
|
|
54
|
+
if (error.code !== "EEXIST") throw error;
|
|
55
|
+
});
|
|
56
|
+
let destinationEntry = await lstat(destination);
|
|
57
|
+
if (!destinationEntry.isDirectory() || destinationEntry.isSymbolicLink() || await realpath(destination) !== destination || (await readdir(destination)).length > 0)
|
|
58
|
+
throw new AppError({
|
|
59
|
+
code: "FRAMEWORK_CAPTURE_OUTPUT_INVALID",
|
|
60
|
+
message: "Source capture requires an empty owned directory."
|
|
61
|
+
});
|
|
62
|
+
let capturedFiles = [], copyDirectory = async (relativeDirectory) => {
|
|
63
|
+
signal?.throwIfAborted();
|
|
64
|
+
let directory = join(root, relativeDirectory);
|
|
65
|
+
for (let name of (await readdir(directory)).sort()) {
|
|
66
|
+
signal?.throwIfAborted();
|
|
67
|
+
let path = relativeDirectory ? `${relativeDirectory}/${name}` : name;
|
|
68
|
+
if (isExcludedSourcePath(path) || relativeDirectory === "" && name.startsWith(".env"))
|
|
69
|
+
continue;
|
|
70
|
+
let sourcePath = join(root, path), outputPath = join(destination, path), entry = await lstat(sourcePath);
|
|
71
|
+
if (entry.isSymbolicLink())
|
|
72
|
+
throw new AppError({
|
|
73
|
+
code: "FRAMEWORK_SOURCE_SYMLINK",
|
|
74
|
+
message: "Symbolic links are not allowed inside publish.os."
|
|
75
|
+
});
|
|
76
|
+
if (!isInside({ root, path: await realpath(sourcePath) }))
|
|
77
|
+
throw new AppError({
|
|
78
|
+
code: "FRAMEWORK_SOURCE_PATH_ESCAPE",
|
|
79
|
+
message: "A source entry resolves outside the selected source."
|
|
80
|
+
});
|
|
81
|
+
if (entry.isDirectory()) {
|
|
82
|
+
await mkdir(outputPath), await copyDirectory(path);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (!entry.isFile())
|
|
86
|
+
throw new AppError({
|
|
87
|
+
code: "FRAMEWORK_SOURCE_ENTRY_NOT_REGULAR",
|
|
88
|
+
message: "Source capture accepts only directories and regular files."
|
|
89
|
+
});
|
|
90
|
+
let file = await open(
|
|
91
|
+
sourcePath,
|
|
92
|
+
constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0)
|
|
93
|
+
);
|
|
94
|
+
try {
|
|
95
|
+
let opened = await file.stat();
|
|
96
|
+
if (!opened.isFile() || opened.dev !== entry.dev || opened.ino !== entry.ino)
|
|
97
|
+
throw new AppError({
|
|
98
|
+
code: "FRAMEWORK_CAPTURE_SOURCE_CHANGED",
|
|
99
|
+
message: "A source entry changed before capture could read it."
|
|
100
|
+
});
|
|
101
|
+
signal?.throwIfAborted();
|
|
102
|
+
let contents = await file.readFile({ signal });
|
|
103
|
+
signal?.throwIfAborted(), await writeFile(outputPath, contents, { flag: "wx", signal }), capturedFiles.push(path);
|
|
104
|
+
} finally {
|
|
105
|
+
await file.close();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
await copyDirectory("");
|
|
110
|
+
let hash = createHash("sha256");
|
|
111
|
+
for (let path of capturedFiles.sort()) {
|
|
112
|
+
signal?.throwIfAborted();
|
|
113
|
+
let contents = await readFile(join(destination, path), { signal });
|
|
114
|
+
hash.update(JSON.stringify([path, contents.byteLength])), hash.update("\0"), hash.update(contents);
|
|
115
|
+
}
|
|
116
|
+
return signal?.throwIfAborted(), {
|
|
117
|
+
sourceDir: captureDir,
|
|
118
|
+
sourceRevision: `sha256:${hash.digest("hex")}`
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/lib/compiler/lifecycle/local-operation.ts
|
|
123
|
+
async function withLocalOperation(options) {
|
|
124
|
+
let operation = await openLocalOperation(options);
|
|
125
|
+
try {
|
|
126
|
+
operation.context.signal.throwIfAborted();
|
|
127
|
+
let result = await options.run(operation.context);
|
|
128
|
+
return options.signal?.throwIfAborted(), result;
|
|
129
|
+
} finally {
|
|
130
|
+
await operation.close();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function openLocalOperation(options) {
|
|
134
|
+
if (options.signal?.throwIfAborted(), options.operation !== "build" && options.operation !== "dev")
|
|
135
|
+
throw new AppError({
|
|
136
|
+
code: "FRAMEWORK_LOCAL_OPERATION_INVALID",
|
|
137
|
+
message: "Select a build or development operation."
|
|
138
|
+
});
|
|
139
|
+
if (!isAbsolute2(options.sourceRoot))
|
|
140
|
+
throw new AppError({
|
|
141
|
+
code: "FRAMEWORK_LOCAL_SOURCE_INVALID",
|
|
142
|
+
message: "Supply an absolute publish.os source path."
|
|
143
|
+
});
|
|
144
|
+
await assertPublishOsSourceBoundary(options.sourceRoot);
|
|
145
|
+
let operationName = localOperationName(options), sourceRoot = await realpath2(options.sourceRoot), outputRoot = join2(sourceRoot, ".publish.os"), outputDir = join2(outputRoot, operationName);
|
|
146
|
+
if (options.outputDir && resolve2(options.outputDir) !== outputDir)
|
|
147
|
+
throw new AppError({
|
|
148
|
+
code: "FRAMEWORK_LOCAL_OUTPUT_INVALID",
|
|
149
|
+
message: "Local output must use the selected source and operation directory."
|
|
150
|
+
});
|
|
151
|
+
let ownership = await ensureOutputOwnership({ sourceRoot }), output = {
|
|
152
|
+
sourceRoot,
|
|
153
|
+
outputDir,
|
|
154
|
+
operation: options.operation,
|
|
155
|
+
scope: options.scope
|
|
156
|
+
};
|
|
157
|
+
await assertOperationOutput(output), await assertGeneratedOutput(output);
|
|
158
|
+
let releaseLock = await acquireOperationLock({
|
|
159
|
+
sourceRoot,
|
|
160
|
+
outputRoot,
|
|
161
|
+
operation: options.operation,
|
|
162
|
+
scope: options.scope,
|
|
163
|
+
signal: options.signal
|
|
164
|
+
}), stagingRoot;
|
|
165
|
+
try {
|
|
166
|
+
await mkdir2(join2(outputRoot, ".stages"), { recursive: !0 }), stagingRoot = await mkdtemp(
|
|
167
|
+
join2(outputRoot, ".stages", `${operationName}-`)
|
|
168
|
+
);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
throw await releaseLock(), error;
|
|
171
|
+
}
|
|
172
|
+
let stagingIdentity = await assertLocalDirectory(stagingRoot), retainStaging = !1, assertStaging = async () => {
|
|
173
|
+
try {
|
|
174
|
+
await ownership.assertCurrent(), await assertLocalDirectory(stagingRoot, stagingIdentity);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
throw retainStaging = !0, error;
|
|
177
|
+
}
|
|
178
|
+
}, controller = new AbortController(), signal = options.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal, sourceDir = sourceRoot, sourceRevision;
|
|
179
|
+
try {
|
|
180
|
+
if (options.operation === "build") {
|
|
181
|
+
let capture = await captureLocalSource({
|
|
182
|
+
sourceRoot,
|
|
183
|
+
captureDir: join2(stagingRoot, "source"),
|
|
184
|
+
signal
|
|
185
|
+
});
|
|
186
|
+
sourceDir = capture.sourceDir, sourceRevision = capture.sourceRevision;
|
|
187
|
+
}
|
|
188
|
+
} catch (error) {
|
|
189
|
+
throw await assertStaging(), await rm(stagingRoot, { recursive: !0, force: !0 }), await releaseLock(), error;
|
|
190
|
+
}
|
|
191
|
+
let shutdown = [], shutdownFailures = [], acceptsShutdownRegistrations = !0, stopping, stopCallbacks = async (callbacks) => {
|
|
192
|
+
let results = await Promise.allSettled(
|
|
193
|
+
callbacks.map((callback) => Promise.resolve().then(callback))
|
|
194
|
+
);
|
|
195
|
+
shutdownFailures.push(
|
|
196
|
+
...results.filter((result) => result.status === "rejected").map((result) => result.reason)
|
|
197
|
+
);
|
|
198
|
+
}, stop = async () => {
|
|
199
|
+
stopping ??= stopCallbacks(shutdown);
|
|
200
|
+
let active = stopping;
|
|
201
|
+
for (; await active, active !== stopping; )
|
|
202
|
+
active = stopping;
|
|
203
|
+
if (shutdownFailures.length)
|
|
204
|
+
throw new AppError({
|
|
205
|
+
code: "FRAMEWORK_PROCESS_SHUTDOWN_FAILED",
|
|
206
|
+
message: "Owned resources did not stop. Output and locks remain in place. Confirm that all operation processes have stopped before recovery.",
|
|
207
|
+
details: { failures: shutdownFailures }
|
|
208
|
+
});
|
|
209
|
+
}, abort = () => {
|
|
210
|
+
stop().catch(() => {
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
signal.addEventListener("abort", abort, { once: !0 });
|
|
214
|
+
let replacementWork, replaceOutput = async (run) => {
|
|
215
|
+
signal.throwIfAborted(), await assertStaging();
|
|
216
|
+
let replacement = await mkdtemp(join2(stagingRoot, "output-")), replacementIdentity = await assertLocalDirectory(replacement), assertReplacement = async () => {
|
|
217
|
+
try {
|
|
218
|
+
await assertStaging(), await assertLocalDirectory(replacement, replacementIdentity);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
throw retainStaging = !0, error;
|
|
221
|
+
}
|
|
222
|
+
}, incoming = join2(replacement, "app"), previous = join2(replacement, "previous"), movedPrevious = !1, published = !1;
|
|
223
|
+
try {
|
|
224
|
+
await mkdir2(incoming), await run(incoming), signal.throwIfAborted(), await assertReplacement(), await assertLocalDirectory(incoming), await assertOperationOutput(output), await assertGeneratedOutput(output), await markOperationOutput({ ...output, outputDir: incoming }), signal.throwIfAborted();
|
|
225
|
+
try {
|
|
226
|
+
await rename(outputDir, previous), movedPrevious = !0;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
if (error.code !== "ENOENT") throw error;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
signal.throwIfAborted(), await rename(incoming, outputDir), published = !0;
|
|
232
|
+
} catch (error) {
|
|
233
|
+
if (movedPrevious)
|
|
234
|
+
try {
|
|
235
|
+
await assertReplacement(), await rename(previous, outputDir);
|
|
236
|
+
} catch (rollbackError) {
|
|
237
|
+
throw retainStaging = !0, new AggregateError(
|
|
238
|
+
[error, rollbackError],
|
|
239
|
+
`Output replacement failed. Recover the prior output from ${previous}.`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
} finally {
|
|
245
|
+
published && (await assertReplacement(), await rm(replacement, { recursive: !0, force: !0 }));
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
return {
|
|
249
|
+
context: {
|
|
250
|
+
sourceRoot,
|
|
251
|
+
sourceDir,
|
|
252
|
+
sourceRevision,
|
|
253
|
+
outputDir,
|
|
254
|
+
signal,
|
|
255
|
+
onShutdown: (callback) => acceptsShutdownRegistrations ? stopping ? (stopping = stopping.then(() => stopCallbacks([callback])), () => {
|
|
256
|
+
}) : (shutdown.push(callback), () => {
|
|
257
|
+
let index = shutdown.indexOf(callback);
|
|
258
|
+
index !== -1 && shutdown.splice(index, 1);
|
|
259
|
+
}) : (signal.throwIfAborted(), () => {
|
|
260
|
+
}),
|
|
261
|
+
replaceOutput: (run) => {
|
|
262
|
+
if (replacementWork)
|
|
263
|
+
return Promise.reject(
|
|
264
|
+
new AppError({
|
|
265
|
+
code: "FRAMEWORK_LOCAL_REPLACEMENT_ACTIVE",
|
|
266
|
+
message: "Wait for the current output replacement to finish."
|
|
267
|
+
})
|
|
268
|
+
);
|
|
269
|
+
let work = replaceOutput(run);
|
|
270
|
+
return replacementWork = work, work.finally(() => {
|
|
271
|
+
replacementWork === work && (replacementWork = void 0);
|
|
272
|
+
}).catch(() => {
|
|
273
|
+
}), work;
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
close: async () => {
|
|
277
|
+
if (controller.abort(), acceptsShutdownRegistrations = !1, await stop().catch(async (error) => {
|
|
278
|
+
try {
|
|
279
|
+
await releaseLock({ shutdownUnverified: !0 });
|
|
280
|
+
} catch (retentionFailure) {
|
|
281
|
+
error instanceof AppError && error.details && (error.details.lockRetentionFailure = retentionFailure);
|
|
282
|
+
}
|
|
283
|
+
throw error;
|
|
284
|
+
}), await replacementWork?.catch(() => {
|
|
285
|
+
}), signal.removeEventListener("abort", abort), await assertStaging(), retainStaging)
|
|
286
|
+
throw new AppError({
|
|
287
|
+
code: "FRAMEWORK_LOCAL_OUTPUT_REDIRECTED",
|
|
288
|
+
message: `Output cleanup stopped to preserve unverified data. Inspect ${stagingRoot} before recovery.`
|
|
289
|
+
});
|
|
290
|
+
await rm(stagingRoot, { recursive: !0, force: !0 }), await releaseLock();
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export {
|
|
296
|
+
withLocalOperation
|
|
297
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runtimePackageVersion
|
|
3
|
+
} from "./chunk-AI2UULNX.js";
|
|
4
|
+
import {
|
|
5
|
+
AppError,
|
|
6
|
+
readInstalledFrameworkLocation
|
|
7
|
+
} from "./chunk-WDY4IK6Z.js";
|
|
8
|
+
|
|
9
|
+
// src/lib/compiler/release/framework-selection.ts
|
|
10
|
+
import { createHash } from "crypto";
|
|
11
|
+
import { readFile, realpath, stat } from "fs/promises";
|
|
12
|
+
import { isAbsolute, join, relative, resolve, sep } from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
|
|
15
|
+
// src/lib/compiler/release/framework-archive.ts
|
|
16
|
+
import { posix } from "path";
|
|
17
|
+
import { isDeepStrictEqual } from "util";
|
|
18
|
+
import { Parser } from "tar";
|
|
19
|
+
function invalidArchive(message) {
|
|
20
|
+
return new AppError({ code: "FRAMEWORK_ARCHIVE_INVALID", message });
|
|
21
|
+
}
|
|
22
|
+
async function readArchiveManifest(archive) {
|
|
23
|
+
return await new Promise((resolve2, reject) => {
|
|
24
|
+
let manifestFound = !1, manifestSource, parser = new Parser({
|
|
25
|
+
strict: !0,
|
|
26
|
+
onReadEntry: (entry) => {
|
|
27
|
+
if (posix.normalize(entry.path.replaceAll("\\", "/")) !== "package/package.json") {
|
|
28
|
+
entry.resume();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (manifestFound || entry.path !== "package/package.json" || entry.type !== "File" || entry.size > 1048576) {
|
|
32
|
+
parser.abort(
|
|
33
|
+
invalidArchive(
|
|
34
|
+
"The framework archive must contain one regular package manifest."
|
|
35
|
+
)
|
|
36
|
+
), entry.resume();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
manifestFound = !0;
|
|
40
|
+
let chunks = [];
|
|
41
|
+
entry.on("data", (chunk) => {
|
|
42
|
+
chunks.push(chunk);
|
|
43
|
+
}), entry.on("end", () => {
|
|
44
|
+
manifestSource = Buffer.concat(chunks).toString("utf8");
|
|
45
|
+
}), entry.resume();
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
parser.on("error", (error) => {
|
|
49
|
+
reject(
|
|
50
|
+
error instanceof AppError ? error : invalidArchive("The framework archive is malformed.")
|
|
51
|
+
);
|
|
52
|
+
}), parser.on("end", () => {
|
|
53
|
+
try {
|
|
54
|
+
let manifest = JSON.parse(manifestSource ?? "");
|
|
55
|
+
if (!manifest || typeof manifest != "object" || Array.isArray(manifest))
|
|
56
|
+
throw invalidArchive(
|
|
57
|
+
"The framework archive package manifest is invalid."
|
|
58
|
+
);
|
|
59
|
+
resolve2(manifest);
|
|
60
|
+
} catch {
|
|
61
|
+
reject(
|
|
62
|
+
invalidArchive(
|
|
63
|
+
"The framework archive package manifest is missing or invalid."
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}), parser.end(archive);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function assertFrameworkArchiveIdentity({
|
|
71
|
+
archive,
|
|
72
|
+
framework
|
|
73
|
+
}) {
|
|
74
|
+
let manifest = await readArchiveManifest(archive);
|
|
75
|
+
if (manifest.name !== framework.packageName || manifest.version !== framework.version)
|
|
76
|
+
throw invalidArchive(
|
|
77
|
+
"The framework archive identity does not match the executing release."
|
|
78
|
+
);
|
|
79
|
+
let installed = readInstalledFrameworkLocation();
|
|
80
|
+
if (installed.packageRoot !== framework.packageRoot || installed.manifest.version !== framework.version)
|
|
81
|
+
throw invalidArchive(
|
|
82
|
+
"The executing framework identity changed during archive validation."
|
|
83
|
+
);
|
|
84
|
+
for (let field of [
|
|
85
|
+
"dependencies",
|
|
86
|
+
"optionalDependencies",
|
|
87
|
+
"peerDependencies",
|
|
88
|
+
"peerDependenciesMeta",
|
|
89
|
+
"engines"
|
|
90
|
+
])
|
|
91
|
+
if (!isDeepStrictEqual(manifest[field] ?? {}, installed.manifest[field] ?? {}))
|
|
92
|
+
throw invalidArchive(
|
|
93
|
+
`The framework archive field ${field} does not match the executing release.`
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/lib/compiler/release/framework-selection.ts
|
|
98
|
+
async function readCheckoutTypeScriptConfig({
|
|
99
|
+
packageRoot
|
|
100
|
+
}) {
|
|
101
|
+
try {
|
|
102
|
+
let source = await readFile(join(packageRoot, "tsconfig.json")), paths = JSON.parse(source.toString("utf8"))?.compilerOptions?.paths;
|
|
103
|
+
if (!paths || typeof paths != "object" || Array.isArray(paths) || !Object.values(paths).every(
|
|
104
|
+
(targets) => Array.isArray(targets) && targets.length > 0 && targets.every(
|
|
105
|
+
(target) => typeof target == "string" && target.length > 0
|
|
106
|
+
)
|
|
107
|
+
))
|
|
108
|
+
throw new Error("Invalid checkout paths");
|
|
109
|
+
let aliases = paths;
|
|
110
|
+
if (!aliases["@/*"] || aliases["@/*"].some(
|
|
111
|
+
(target) => resolve(packageRoot, target) !== join(packageRoot, "src/*")
|
|
112
|
+
))
|
|
113
|
+
throw new Error("Missing compiler source alias");
|
|
114
|
+
return { source, paths: aliases };
|
|
115
|
+
} catch {
|
|
116
|
+
throw new AppError({
|
|
117
|
+
code: "FRAMEWORK_SELECTION_INVALID",
|
|
118
|
+
message: "The selected checkout TypeScript configuration is missing or invalid.",
|
|
119
|
+
fix: "Restore the checkout tsconfig.json and its source paths, then repeat the operation. No registry fallback is available."
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function assertFrameworkSelection({
|
|
124
|
+
context,
|
|
125
|
+
framework,
|
|
126
|
+
runtime
|
|
127
|
+
}) {
|
|
128
|
+
let selected = context?.framework;
|
|
129
|
+
if (selected !== void 0) {
|
|
130
|
+
if (!selected || !["checkout", "candidate"].includes(selected.kind) || selected.packageName !== framework.packageName || selected.version !== framework.version)
|
|
131
|
+
throw new AppError({
|
|
132
|
+
code: "FRAMEWORK_SELECTION_INVALID",
|
|
133
|
+
message: "The selected local framework does not match the executing input.",
|
|
134
|
+
fix: "Select a valid local checkout or package candidate and repeat the operation. No registry fallback is available."
|
|
135
|
+
});
|
|
136
|
+
if (selected.kind === "checkout") {
|
|
137
|
+
let root = typeof selected.packageRoot == "string" && isAbsolute(selected.packageRoot) ? await realpath(selected.packageRoot).catch(() => {
|
|
138
|
+
}) : void 0;
|
|
139
|
+
if (!root || !relative(root, fileURLToPath(import.meta.url)).startsWith(
|
|
140
|
+
`src${sep}`
|
|
141
|
+
) || !fileURLToPath(import.meta.url).endsWith(".ts") || root !== await realpath(framework.packageRoot) || !(await stat(join(root, "src/compiler.ts")).catch(() => {
|
|
142
|
+
}))?.isFile() || context?.archive !== void 0)
|
|
143
|
+
throw new AppError({
|
|
144
|
+
code: "FRAMEWORK_SELECTION_INVALID",
|
|
145
|
+
message: "The selected checkout is missing or does not contain the executing compiler.",
|
|
146
|
+
fix: "Invoke src/compiler.ts from the selected editable checkout without a package archive. No registry fallback is available."
|
|
147
|
+
});
|
|
148
|
+
let config = await readCheckoutTypeScriptConfig({ packageRoot: root }), manifest = await readFile(join(root, "package.json")).catch(() => {
|
|
149
|
+
throw new AppError({
|
|
150
|
+
code: "FRAMEWORK_SELECTION_INVALID",
|
|
151
|
+
message: "The selected checkout package metadata is unreadable.",
|
|
152
|
+
fix: "Restore the checkout package.json, then repeat the operation. No registry fallback is available."
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
return `checkout:${createHash("sha256").update(root).update(manifest).update(config.source).update(JSON.stringify(framework.release)).digest("hex")}`;
|
|
156
|
+
}
|
|
157
|
+
if (typeof selected.integrity != "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/u.test(selected.integrity) || selected.integrity !== context?.archive?.integrity)
|
|
158
|
+
throw new AppError({
|
|
159
|
+
code: "FRAMEWORK_SELECTION_INVALID",
|
|
160
|
+
message: "The selected local framework does not match the executing input.",
|
|
161
|
+
fix: "Select a valid local checkout or package candidate and repeat the operation. No registry fallback is available."
|
|
162
|
+
});
|
|
163
|
+
let archive = await readFile(context?.archive?.path ?? "").catch(() => {
|
|
164
|
+
throw new AppError({
|
|
165
|
+
code: "FRAMEWORK_SELECTION_INVALID",
|
|
166
|
+
message: "The selected local framework archive is missing or unreadable.",
|
|
167
|
+
fix: "Prepare the selected local framework again. No registry fallback is available."
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
if (`sha512-${createHash("sha512").update(archive).digest("base64")}` !== selected.integrity)
|
|
171
|
+
throw new AppError({
|
|
172
|
+
code: "FRAMEWORK_SELECTION_INVALID",
|
|
173
|
+
message: "The selected local framework archive does not match its integrity.",
|
|
174
|
+
fix: "Prepare the selected local framework again. No registry fallback is available."
|
|
175
|
+
});
|
|
176
|
+
return await assertFrameworkArchiveIdentity({ archive, framework }), selected.integrity;
|
|
177
|
+
}
|
|
178
|
+
if (runtimePackageVersion(runtime) !== framework.version)
|
|
179
|
+
throw new AppError({
|
|
180
|
+
code: "FRAMEWORK_SOURCE_PIN_MISMATCH",
|
|
181
|
+
message: "The source pin does not match the executing framework release.",
|
|
182
|
+
fix: "Invoke the exact framework version selected in publish.os.config.json."
|
|
183
|
+
});
|
|
184
|
+
return context?.archive?.integrity ?? "";
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export {
|
|
188
|
+
assertFrameworkArchiveIdentity,
|
|
189
|
+
readCheckoutTypeScriptConfig,
|
|
190
|
+
assertFrameworkSelection
|
|
191
|
+
};
|