@xtrable-ltd/nanoesis 0.1.25 → 0.1.27
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/dist/adapter-azure-blob.js +1 -1
- package/dist/{chunk-TEIQFPNO.js → chunk-CH4DCPNN.js} +50 -3
- package/dist/{chunk-H6ZHZWDJ.js → chunk-EGQLAHLP.js} +210 -97
- package/dist/editor-api.d.ts +17 -3
- package/dist/editor-api.js +2 -2
- package/dist/index.d.ts +107 -2
- package/dist/index.js +3 -1
- package/dist/mcp.js +3 -3
- package/editor/assets/MigrationsPane-eijyEoIw.js +4 -0
- package/editor/assets/{TemplatesPane-CIpyieRF.js → TemplatesPane-DjFFkccd.js} +116 -116
- package/editor/assets/{cssMode-DhaV27rt.js → cssMode-BNSyZV7c.js} +1 -1
- package/editor/assets/{freemarker2-DokFNyj0.js → freemarker2-B8rz05rs.js} +1 -1
- package/editor/assets/{handlebars-Dw9FmLS4.js → handlebars-B3M9DD2d.js} +1 -1
- package/editor/assets/{html-CMqaP5wp.js → html-BajOMTpc.js} +1 -1
- package/editor/assets/{htmlMode-CDxfYToP.js → htmlMode-Cqrnk3KF.js} +1 -1
- package/editor/assets/index-BtwjABtU.js +145 -0
- package/editor/assets/{index-BOZboKLR.css → index-CUG-24-D.css} +1 -1
- package/editor/assets/{javascript-B4MO-q5P.js → javascript-CgKgaKRj.js} +1 -1
- package/editor/assets/{jsonMode-DavXHLfw.js → jsonMode-B4i8iNyO.js} +1 -1
- package/editor/assets/{liquid-1A6xvXiH.js → liquid-DJaUoyuM.js} +1 -1
- package/editor/assets/{mdx-CdGqZmKc.js → mdx-DBfFAeUj.js} +1 -1
- package/editor/assets/{python-xlLpeYr9.js → python-ClvSkGDd.js} +1 -1
- package/editor/assets/{razor-DYPAhJKR.js → razor-BJcU60fL.js} +1 -1
- package/editor/assets/{tsMode-DSEeCQ6X.js → tsMode-8Lhfeq5V.js} +1 -1
- package/editor/assets/{typescript-CgJRoqTj.js → typescript-D3i2tBiq.js} +1 -1
- package/editor/assets/{xml-BnuD7ypQ.js → xml-CXwucYqL.js} +1 -1
- package/editor/assets/{yaml-BzsAd7-q.js → yaml-D48SS_IL.js} +1 -1
- package/editor/index.html +2 -2
- package/package.json +1 -1
- package/editor/assets/MigrationsPane-B0x1iqiv.js +0 -4
- package/editor/assets/index-oaWmlNac.js +0 -143
|
@@ -13,11 +13,12 @@ import {
|
|
|
13
13
|
loadComponents,
|
|
14
14
|
loadTemplate,
|
|
15
15
|
pendingMigrations,
|
|
16
|
+
planPublish,
|
|
16
17
|
publishSite,
|
|
17
18
|
renderReferenceMarkdown,
|
|
18
19
|
validateSite,
|
|
19
20
|
workingStoreRoundTripDiagnostic
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-EGQLAHLP.js";
|
|
21
22
|
|
|
22
23
|
// ../editor-api/src/scaffold.ts
|
|
23
24
|
var HOME_HTML = `<!doctype html>
|
|
@@ -111,6 +112,46 @@ function json(status, data) {
|
|
|
111
112
|
function methodNotAllowed() {
|
|
112
113
|
return json(405, { ok: false, error: "POST only" });
|
|
113
114
|
}
|
|
115
|
+
var NDJSON = "application/x-ndjson";
|
|
116
|
+
function streamingPublish(deps) {
|
|
117
|
+
const stream = async function* () {
|
|
118
|
+
const encoder = new TextEncoder();
|
|
119
|
+
const line = (event) => encoder.encode(`${JSON.stringify(event)}
|
|
120
|
+
`);
|
|
121
|
+
const queue = [];
|
|
122
|
+
let wake;
|
|
123
|
+
let settled = false;
|
|
124
|
+
let thrown;
|
|
125
|
+
const onProgress = (event) => {
|
|
126
|
+
queue.push(event);
|
|
127
|
+
wake?.();
|
|
128
|
+
};
|
|
129
|
+
const running = deps.publish({ onProgress }).then(
|
|
130
|
+
() => void 0,
|
|
131
|
+
(error) => {
|
|
132
|
+
thrown = error;
|
|
133
|
+
}
|
|
134
|
+
).finally(() => {
|
|
135
|
+
settled = true;
|
|
136
|
+
wake?.();
|
|
137
|
+
});
|
|
138
|
+
for (; ; ) {
|
|
139
|
+
if (queue.length === 0 && !settled) {
|
|
140
|
+
await new Promise((resolve2) => {
|
|
141
|
+
wake = resolve2;
|
|
142
|
+
});
|
|
143
|
+
wake = void 0;
|
|
144
|
+
}
|
|
145
|
+
while (queue.length > 0) yield line(queue.shift());
|
|
146
|
+
if (settled && queue.length === 0) break;
|
|
147
|
+
}
|
|
148
|
+
await running;
|
|
149
|
+
if (thrown !== void 0) {
|
|
150
|
+
yield line({ phase: "error", message: thrown instanceof Error ? thrown.message : String(thrown) });
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
return { status: 200, headers: { "content-type": NDJSON, "cache-control": "no-store" }, stream };
|
|
154
|
+
}
|
|
114
155
|
function withDefaultHeaders(response) {
|
|
115
156
|
const headers = { ...response.headers ?? {} };
|
|
116
157
|
if (headers["cache-control"] === void 0) {
|
|
@@ -531,8 +572,13 @@ async function dispatchApi(deps, req) {
|
|
|
531
572
|
const status = result.reason === "exists" ? 409 : 404;
|
|
532
573
|
return json(status, { ok: false, error: result.reason });
|
|
533
574
|
}
|
|
575
|
+
case "/api/publish/plan": {
|
|
576
|
+
if (req.method !== "GET") return json(405, { ok: false, error: "GET only" });
|
|
577
|
+
return json(200, await planPublish(deps.store));
|
|
578
|
+
}
|
|
534
579
|
case "/api/publish": {
|
|
535
580
|
if (req.method !== "POST") return methodNotAllowed();
|
|
581
|
+
if ((req.getHeader("accept") ?? "").includes(NDJSON)) return streamingPublish(deps);
|
|
536
582
|
const result = await deps.publish();
|
|
537
583
|
if (result.ok) {
|
|
538
584
|
return json(200, {
|
|
@@ -923,7 +969,7 @@ function createEditor(config) {
|
|
|
923
969
|
const sink = asSink(config.website);
|
|
924
970
|
const wipeBeforePublish = config.wipeBeforePublish ?? true;
|
|
925
971
|
const reconcile = config.enumerate === void 0 ? void 0 : async () => working.reconcile([...await config.enumerate()]);
|
|
926
|
-
const publish = async () => {
|
|
972
|
+
const publish = async (options) => {
|
|
927
973
|
const validation = await validateSite(working);
|
|
928
974
|
if (validation.ok && wipeBeforePublish && config.website.wipe !== void 0) {
|
|
929
975
|
await config.website.wipe();
|
|
@@ -935,7 +981,8 @@ function createEditor(config) {
|
|
|
935
981
|
...config.purge !== void 0 && { purge: config.purge },
|
|
936
982
|
...config.baseUrl !== void 0 && { baseUrl: config.baseUrl },
|
|
937
983
|
...dir !== void 0 && { authorDirectory: dir },
|
|
938
|
-
...prebuild !== void 0 && { prebuild }
|
|
984
|
+
...prebuild !== void 0 && { prebuild },
|
|
985
|
+
...options?.onProgress !== void 0 && { onProgress: options.onProgress }
|
|
939
986
|
});
|
|
940
987
|
};
|
|
941
988
|
const users = config.users;
|
|
@@ -2051,27 +2051,8 @@ function urlForItem(contentPath) {
|
|
|
2051
2051
|
}
|
|
2052
2052
|
|
|
2053
2053
|
// ../engine/src/compile/site.ts
|
|
2054
|
-
var DEFAULT_IMAGE_CONCURRENCY =
|
|
2055
|
-
async function
|
|
2056
|
-
const [
|
|
2057
|
-
tree,
|
|
2058
|
-
components,
|
|
2059
|
-
componentStyles,
|
|
2060
|
-
componentScripts,
|
|
2061
|
-
documentShell,
|
|
2062
|
-
redirects,
|
|
2063
|
-
siteConfig
|
|
2064
|
-
] = await Promise.all([
|
|
2065
|
-
loadContentTree(source),
|
|
2066
|
-
loadComponents(source),
|
|
2067
|
-
loadComponentStyles(source),
|
|
2068
|
-
loadComponentScripts(source),
|
|
2069
|
-
loadDocumentShell(source),
|
|
2070
|
-
loadRedirects(source),
|
|
2071
|
-
loadSiteConfig(source)
|
|
2072
|
-
]);
|
|
2073
|
-
const context = buildResolveContext(tree);
|
|
2074
|
-
const baseUrl = options.baseUrl ?? siteConfig.baseUrl;
|
|
2054
|
+
var DEFAULT_IMAGE_CONCURRENCY = 16;
|
|
2055
|
+
async function planPages(tree, source, components) {
|
|
2075
2056
|
const templateCache = /* @__PURE__ */ new Map();
|
|
2076
2057
|
const getTemplate = async (name) => {
|
|
2077
2058
|
const cached = templateCache.get(name);
|
|
@@ -2080,16 +2061,6 @@ async function compileSite(source, options = {}) {
|
|
|
2080
2061
|
templateCache.set(name, loaded);
|
|
2081
2062
|
return loaded;
|
|
2082
2063
|
};
|
|
2083
|
-
const styleCache = /* @__PURE__ */ new Map();
|
|
2084
|
-
const scriptCache = /* @__PURE__ */ new Map();
|
|
2085
|
-
const getStyle = async (name) => {
|
|
2086
|
-
if (!styleCache.has(name)) styleCache.set(name, await loadTemplateStyle(source, name));
|
|
2087
|
-
return styleCache.get(name);
|
|
2088
|
-
};
|
|
2089
|
-
const getScript = async (name) => {
|
|
2090
|
-
if (!scriptCache.has(name)) scriptCache.set(name, await loadTemplateScript(source, name));
|
|
2091
|
-
return scriptCache.get(name);
|
|
2092
|
-
};
|
|
2093
2064
|
const analysisCache = /* @__PURE__ */ new Map();
|
|
2094
2065
|
const getAnalysis = (name, templateSource) => {
|
|
2095
2066
|
const cached = analysisCache.get(name);
|
|
@@ -2098,8 +2069,7 @@ async function compileSite(source, options = {}) {
|
|
|
2098
2069
|
analysisCache.set(name, analysis);
|
|
2099
2070
|
return analysis;
|
|
2100
2071
|
};
|
|
2101
|
-
const
|
|
2102
|
-
const entries = [];
|
|
2072
|
+
const plans = [];
|
|
2103
2073
|
const walk = async (dir, inheritedTemplate) => {
|
|
2104
2074
|
const dirTemplate = dir.defaultTemplate ?? inheritedTemplate;
|
|
2105
2075
|
for (const child of dir.children) {
|
|
@@ -2116,34 +2086,126 @@ async function compileSite(source, options = {}) {
|
|
|
2116
2086
|
}
|
|
2117
2087
|
const template = await getTemplate(templateName);
|
|
2118
2088
|
const analysis = getAnalysis(templateName, template);
|
|
2119
|
-
|
|
2120
|
-
source,
|
|
2121
|
-
child,
|
|
2122
|
-
analysis,
|
|
2123
|
-
options.imageEncoder,
|
|
2124
|
-
options.imageConcurrency ?? DEFAULT_IMAGE_CONCURRENCY
|
|
2125
|
-
);
|
|
2126
|
-
artifacts.push(...mediaArtifacts);
|
|
2127
|
-
const templateStyle = await getStyle(templateName);
|
|
2128
|
-
const templateScript = await getScript(templateName);
|
|
2129
|
-
const contents = compileTemplate({
|
|
2130
|
-
template,
|
|
2131
|
-
scope: buildScope(child.item),
|
|
2132
|
-
components,
|
|
2133
|
-
context,
|
|
2134
|
-
media,
|
|
2135
|
-
componentStyles,
|
|
2136
|
-
componentScripts,
|
|
2137
|
-
...options.authorDirectory !== void 0 && { authorDirectory: options.authorDirectory },
|
|
2138
|
-
...documentShell !== void 0 && { document: documentShell },
|
|
2139
|
-
...templateStyle !== void 0 && { templateStyle },
|
|
2140
|
-
...templateScript !== void 0 && { templateScript }
|
|
2141
|
-
});
|
|
2142
|
-
artifacts.push({ path: outputPathForItem(child.path), contents });
|
|
2143
|
-
entries.push(toEntry(child));
|
|
2089
|
+
plans.push({ node: child, templateName, template, refs: itemMediaRefs(child, analysis) });
|
|
2144
2090
|
}
|
|
2145
2091
|
};
|
|
2146
2092
|
await walk(tree, void 0);
|
|
2093
|
+
return plans;
|
|
2094
|
+
}
|
|
2095
|
+
function assetLabel(published) {
|
|
2096
|
+
const slash = published.lastIndexOf("/");
|
|
2097
|
+
return slash === -1 ? published : published.slice(slash + 1);
|
|
2098
|
+
}
|
|
2099
|
+
function buildPublishPlan(plans) {
|
|
2100
|
+
const images = [];
|
|
2101
|
+
const files = [];
|
|
2102
|
+
const imageSeen = /* @__PURE__ */ new Set();
|
|
2103
|
+
const fileSeen = /* @__PURE__ */ new Set();
|
|
2104
|
+
for (const plan of plans) {
|
|
2105
|
+
for (const { published } of plan.refs.images) {
|
|
2106
|
+
if (imageSeen.has(published)) continue;
|
|
2107
|
+
imageSeen.add(published);
|
|
2108
|
+
images.push({ kind: "image", id: published, label: assetLabel(published) });
|
|
2109
|
+
}
|
|
2110
|
+
for (const { published } of plan.refs.files) {
|
|
2111
|
+
if (fileSeen.has(published)) continue;
|
|
2112
|
+
fileSeen.add(published);
|
|
2113
|
+
files.push({ kind: "file", id: published, label: assetLabel(published) });
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
const pages = plans.map((plan) => ({
|
|
2117
|
+
kind: "page",
|
|
2118
|
+
id: outputPathForItem(plan.node.path),
|
|
2119
|
+
label: plan.node.item.title
|
|
2120
|
+
}));
|
|
2121
|
+
return {
|
|
2122
|
+
resources: [...images, ...files, ...pages],
|
|
2123
|
+
images: images.length,
|
|
2124
|
+
files: files.length,
|
|
2125
|
+
pages: pages.length
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
async function planPublish(source) {
|
|
2129
|
+
const [tree, components] = await Promise.all([loadContentTree(source), loadComponents(source)]);
|
|
2130
|
+
return buildPublishPlan(await planPages(tree, source, components));
|
|
2131
|
+
}
|
|
2132
|
+
async function compileSite(source, options = {}) {
|
|
2133
|
+
const [
|
|
2134
|
+
tree,
|
|
2135
|
+
components,
|
|
2136
|
+
componentStyles,
|
|
2137
|
+
componentScripts,
|
|
2138
|
+
documentShell,
|
|
2139
|
+
redirects,
|
|
2140
|
+
siteConfig
|
|
2141
|
+
] = await Promise.all([
|
|
2142
|
+
loadContentTree(source),
|
|
2143
|
+
loadComponents(source),
|
|
2144
|
+
loadComponentStyles(source),
|
|
2145
|
+
loadComponentScripts(source),
|
|
2146
|
+
loadDocumentShell(source),
|
|
2147
|
+
loadRedirects(source),
|
|
2148
|
+
loadSiteConfig(source)
|
|
2149
|
+
]);
|
|
2150
|
+
const context = buildResolveContext(tree);
|
|
2151
|
+
const baseUrl = options.baseUrl ?? siteConfig.baseUrl;
|
|
2152
|
+
const styleCache = /* @__PURE__ */ new Map();
|
|
2153
|
+
const scriptCache = /* @__PURE__ */ new Map();
|
|
2154
|
+
const getStyle = async (name) => {
|
|
2155
|
+
if (!styleCache.has(name)) styleCache.set(name, await loadTemplateStyle(source, name));
|
|
2156
|
+
return styleCache.get(name);
|
|
2157
|
+
};
|
|
2158
|
+
const getScript = async (name) => {
|
|
2159
|
+
if (!scriptCache.has(name)) scriptCache.set(name, await loadTemplateScript(source, name));
|
|
2160
|
+
return scriptCache.get(name);
|
|
2161
|
+
};
|
|
2162
|
+
const artifacts = [];
|
|
2163
|
+
const entries = [];
|
|
2164
|
+
const plans = await planPages(tree, source, components);
|
|
2165
|
+
const onProgress = options.onProgress;
|
|
2166
|
+
let done = 0;
|
|
2167
|
+
let resourceById;
|
|
2168
|
+
if (onProgress !== void 0) {
|
|
2169
|
+
const publishPlan = buildPublishPlan(plans);
|
|
2170
|
+
resourceById = new Map(publishPlan.resources.map((resource) => [resource.id, resource]));
|
|
2171
|
+
onProgress({ phase: "plan", plan: publishPlan });
|
|
2172
|
+
}
|
|
2173
|
+
const report = (id) => {
|
|
2174
|
+
if (onProgress === void 0 || resourceById === void 0) return;
|
|
2175
|
+
const resource = resourceById.get(id);
|
|
2176
|
+
if (resource === void 0) return;
|
|
2177
|
+
done += 1;
|
|
2178
|
+
onProgress({ phase: "resource", resource, done, total: resourceById.size });
|
|
2179
|
+
};
|
|
2180
|
+
const { mediaArtifacts, imageInfoByPublished, fileUrlByPublished } = await collectSiteMedia(
|
|
2181
|
+
source,
|
|
2182
|
+
plans.map((p) => p.refs),
|
|
2183
|
+
options.imageEncoder,
|
|
2184
|
+
options.imageConcurrency ?? DEFAULT_IMAGE_CONCURRENCY,
|
|
2185
|
+
onProgress === void 0 ? void 0 : (published) => report(published)
|
|
2186
|
+
);
|
|
2187
|
+
artifacts.push(...mediaArtifacts);
|
|
2188
|
+
for (const { node, templateName, template, refs } of plans) {
|
|
2189
|
+
const templateStyle = await getStyle(templateName);
|
|
2190
|
+
const templateScript = await getScript(templateName);
|
|
2191
|
+
const contents = compileTemplate({
|
|
2192
|
+
template,
|
|
2193
|
+
scope: buildScope(node.item),
|
|
2194
|
+
components,
|
|
2195
|
+
context,
|
|
2196
|
+
media: resolverFor(refs, imageInfoByPublished, fileUrlByPublished),
|
|
2197
|
+
componentStyles,
|
|
2198
|
+
componentScripts,
|
|
2199
|
+
...options.authorDirectory !== void 0 && { authorDirectory: options.authorDirectory },
|
|
2200
|
+
...documentShell !== void 0 && { document: documentShell },
|
|
2201
|
+
...templateStyle !== void 0 && { templateStyle },
|
|
2202
|
+
...templateScript !== void 0 && { templateScript }
|
|
2203
|
+
});
|
|
2204
|
+
const outputPath = outputPathForItem(node.path);
|
|
2205
|
+
artifacts.push({ path: outputPath, contents });
|
|
2206
|
+
entries.push(toEntry(node));
|
|
2207
|
+
report(outputPath);
|
|
2208
|
+
}
|
|
2147
2209
|
const redirectArtifact = buildRedirects(redirects, new Set(entries.map((entry) => entry.url)));
|
|
2148
2210
|
if (redirectArtifact !== void 0) artifacts.push(redirectArtifact);
|
|
2149
2211
|
if (options.contentIndex !== false) artifacts.push(buildContentIndex(entries));
|
|
@@ -2189,14 +2251,14 @@ async function compilePage(source, itemPath, options = {}) {
|
|
|
2189
2251
|
if (options.media !== void 0) {
|
|
2190
2252
|
media = options.media;
|
|
2191
2253
|
} else {
|
|
2192
|
-
const
|
|
2254
|
+
const refs = itemMediaRefs(node, analysis);
|
|
2255
|
+
const collected = await collectSiteMedia(
|
|
2193
2256
|
source,
|
|
2194
|
-
|
|
2195
|
-
analysis,
|
|
2257
|
+
[refs],
|
|
2196
2258
|
options.imageEncoder,
|
|
2197
2259
|
DEFAULT_IMAGE_CONCURRENCY
|
|
2198
2260
|
);
|
|
2199
|
-
media = collected.
|
|
2261
|
+
media = resolverFor(refs, collected.imageInfoByPublished, collected.fileUrlByPublished);
|
|
2200
2262
|
mediaArtifacts = collected.mediaArtifacts;
|
|
2201
2263
|
}
|
|
2202
2264
|
const html = compileTemplate({
|
|
@@ -2244,48 +2306,91 @@ function inCollection(entry, collectionPath) {
|
|
|
2244
2306
|
if (collection === "") return true;
|
|
2245
2307
|
return entry.path === collection || entry.path.startsWith(`${collection}/`);
|
|
2246
2308
|
}
|
|
2247
|
-
|
|
2309
|
+
function itemMediaRefs(node, analysis) {
|
|
2248
2310
|
const itemDir = parentPath(node.path);
|
|
2249
2311
|
const fields = node.item.fields;
|
|
2250
|
-
const
|
|
2251
|
-
const files = /* @__PURE__ */ new Map();
|
|
2252
|
-
const mediaArtifacts = [];
|
|
2312
|
+
const files = [];
|
|
2253
2313
|
for (const field of analysis.fileFields) {
|
|
2254
2314
|
for (const ref of assetRefs(fields[field])) {
|
|
2255
|
-
|
|
2256
|
-
const bytes = await tryReadBytes(source, `content/${published}`);
|
|
2257
|
-
if (bytes === void 0) continue;
|
|
2258
|
-
mediaArtifacts.push({ path: published, contents: bytes });
|
|
2259
|
-
files.set(ref, `/${published}`);
|
|
2315
|
+
files.push({ ref, published: joinAsset(itemDir, ref) });
|
|
2260
2316
|
}
|
|
2261
2317
|
}
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2318
|
+
const images = [];
|
|
2319
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2320
|
+
const addImage = (ref) => {
|
|
2321
|
+
if (seen.has(ref)) return;
|
|
2322
|
+
seen.add(ref);
|
|
2323
|
+
images.push({ ref, published: joinAsset(itemDir, ref) });
|
|
2324
|
+
};
|
|
2325
|
+
for (const field of analysis.imageFields) {
|
|
2326
|
+
for (const ref of assetRefs(fields[field])) addImage(ref);
|
|
2327
|
+
}
|
|
2328
|
+
for (const field of analysis.richTextFields) {
|
|
2329
|
+
const value = fields[field];
|
|
2330
|
+
if (typeof value === "string") {
|
|
2331
|
+
for (const ref of inlineImageRefs(value)) addImage(ref);
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
return { images, files };
|
|
2335
|
+
}
|
|
2336
|
+
async function collectSiteMedia(source, itemRefs, encoder, imageConcurrency, onAsset) {
|
|
2337
|
+
const uniqueOrdered = (pick) => {
|
|
2338
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2339
|
+
const order = [];
|
|
2340
|
+
for (const refs of itemRefs) {
|
|
2341
|
+
for (const { published } of pick(refs)) {
|
|
2342
|
+
if (!seen.has(published)) {
|
|
2343
|
+
seen.add(published);
|
|
2344
|
+
order.push(published);
|
|
2345
|
+
}
|
|
2271
2346
|
}
|
|
2272
2347
|
}
|
|
2273
|
-
|
|
2274
|
-
|
|
2348
|
+
return order;
|
|
2349
|
+
};
|
|
2350
|
+
const mediaArtifacts = [];
|
|
2351
|
+
const filePaths = uniqueOrdered((r) => r.files);
|
|
2352
|
+
const fileBytes = await mapWithConcurrency(filePaths, imageConcurrency, async (published) => {
|
|
2353
|
+
const bytes = await tryReadBytes(source, `content/${published}`);
|
|
2354
|
+
onAsset?.(published);
|
|
2355
|
+
return bytes;
|
|
2356
|
+
});
|
|
2357
|
+
const fileUrlByPublished = /* @__PURE__ */ new Map();
|
|
2358
|
+
filePaths.forEach((published, index) => {
|
|
2359
|
+
const bytes = fileBytes[index];
|
|
2360
|
+
if (bytes === void 0) return;
|
|
2361
|
+
mediaArtifacts.push({ path: published, contents: bytes });
|
|
2362
|
+
fileUrlByPublished.set(published, `/${published}`);
|
|
2363
|
+
});
|
|
2364
|
+
const imageInfoByPublished = /* @__PURE__ */ new Map();
|
|
2365
|
+
if (encoder !== void 0) {
|
|
2366
|
+
const imagePaths = uniqueOrdered((r) => r.images);
|
|
2367
|
+
const encoded = await mapWithConcurrency(imagePaths, imageConcurrency, async (published) => {
|
|
2275
2368
|
const bytes = await tryReadBytes(source, `content/${published}`);
|
|
2276
|
-
|
|
2277
|
-
|
|
2369
|
+
const result = bytes === void 0 ? void 0 : await processImage(bytes, published, encoder);
|
|
2370
|
+
onAsset?.(published);
|
|
2371
|
+
return result;
|
|
2278
2372
|
});
|
|
2279
|
-
|
|
2280
|
-
|
|
2373
|
+
imagePaths.forEach((published, index) => {
|
|
2374
|
+
const result = encoded[index];
|
|
2375
|
+
if (result === void 0) return;
|
|
2281
2376
|
mediaArtifacts.push(...result.artifacts);
|
|
2282
|
-
|
|
2283
|
-
}
|
|
2377
|
+
imageInfoByPublished.set(published, result.info);
|
|
2378
|
+
});
|
|
2284
2379
|
}
|
|
2285
|
-
return {
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2380
|
+
return { mediaArtifacts, imageInfoByPublished, fileUrlByPublished };
|
|
2381
|
+
}
|
|
2382
|
+
function resolverFor(refs, imageInfoByPublished, fileUrlByPublished) {
|
|
2383
|
+
const imageByRef = /* @__PURE__ */ new Map();
|
|
2384
|
+
for (const { ref, published } of refs.images) {
|
|
2385
|
+
const info = imageInfoByPublished.get(published);
|
|
2386
|
+
if (info !== void 0) imageByRef.set(ref, info);
|
|
2387
|
+
}
|
|
2388
|
+
const fileByRef = /* @__PURE__ */ new Map();
|
|
2389
|
+
for (const { ref, published } of refs.files) {
|
|
2390
|
+
const url = fileUrlByPublished.get(published);
|
|
2391
|
+
if (url !== void 0) fileByRef.set(ref, url);
|
|
2392
|
+
}
|
|
2393
|
+
return { image: (ref) => imageByRef.get(ref), file: (ref) => fileByRef.get(ref) };
|
|
2289
2394
|
}
|
|
2290
2395
|
async function tryReadBytes(source, path) {
|
|
2291
2396
|
try {
|
|
@@ -3078,9 +3183,12 @@ var noopPurgeService = {
|
|
|
3078
3183
|
// ../engine/src/publish/publish.ts
|
|
3079
3184
|
var DEFAULT_WRITE_CONCURRENCY = 8;
|
|
3080
3185
|
async function publishSite(source, sink, options = {}) {
|
|
3186
|
+
const onProgress = options.onProgress;
|
|
3187
|
+
onProgress?.({ phase: "validate" });
|
|
3081
3188
|
const validation = await validateSite(source);
|
|
3082
3189
|
const summary = summarizeTree(await loadContentTree(source));
|
|
3083
3190
|
if (!validation.ok) {
|
|
3191
|
+
onProgress?.({ phase: "blocked", errors: validation.errors.map((error) => error.message) });
|
|
3084
3192
|
return { ok: false, validation, written: [], summary };
|
|
3085
3193
|
}
|
|
3086
3194
|
const {
|
|
@@ -3104,12 +3212,16 @@ async function publishSite(source, sink, options = {}) {
|
|
|
3104
3212
|
);
|
|
3105
3213
|
const byPath = /* @__PURE__ */ new Map();
|
|
3106
3214
|
for (const artifact of [...stamped, ...passthrough]) byPath.set(artifact.path, artifact);
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3215
|
+
const uploadTotal = byPath.size;
|
|
3216
|
+
let uploaded = 0;
|
|
3217
|
+
await mapWithConcurrency([...byPath.values()], writeConcurrency, async (artifact) => {
|
|
3218
|
+
await sink.write(artifact.path, artifact.contents, cacheControlFor(artifact));
|
|
3219
|
+
uploaded += 1;
|
|
3220
|
+
onProgress?.({ phase: "upload", written: uploaded, total: uploadTotal });
|
|
3221
|
+
});
|
|
3222
|
+
if (purge !== noopPurgeService) onProgress?.({ phase: "purge" });
|
|
3112
3223
|
await purge.purgeAll();
|
|
3224
|
+
onProgress?.({ phase: "done", written: uploadTotal, summary });
|
|
3113
3225
|
return { ok: true, validation, written: [...byPath.keys()].sort(), summary };
|
|
3114
3226
|
}
|
|
3115
3227
|
function asBytes(contents) {
|
|
@@ -3420,6 +3532,7 @@ export {
|
|
|
3420
3532
|
buildContentIndex,
|
|
3421
3533
|
outputPathForItem,
|
|
3422
3534
|
urlForItem,
|
|
3535
|
+
planPublish,
|
|
3423
3536
|
compileSite,
|
|
3424
3537
|
compilePage,
|
|
3425
3538
|
buildResolveContext,
|
package/dist/editor-api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WorkingStore, IdentityProvider, PublishResult, ReconcileResult, AuthEndpoints, UserAdminEndpoints, AuthorOption, DiagnosticRegistry, Storage, ImageEncoder, PurgeService, UserSummary, PreBuildHook, AuthorDirectory, Repair, DiagnosticCheck } from '@nanoesis/engine';
|
|
1
|
+
import { WorkingStore, IdentityProvider, ProgressReporter, PublishResult, ReconcileResult, AuthEndpoints, UserAdminEndpoints, AuthorOption, DiagnosticRegistry, Storage, ImageEncoder, PurgeService, UserSummary, PreBuildHook, AuthorDirectory, Repair, DiagnosticCheck } from '@nanoesis/engine';
|
|
2
2
|
export { Storage } from '@nanoesis/engine';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -93,14 +93,28 @@ interface ApiResponse {
|
|
|
93
93
|
readonly status: number;
|
|
94
94
|
readonly headers?: Record<string, string>;
|
|
95
95
|
readonly body?: string | Uint8Array;
|
|
96
|
+
/**
|
|
97
|
+
* A streaming body (DESIGN §11): when present, the host writes these chunks as they are
|
|
98
|
+
* produced instead of `body`, for the publish-progress NDJSON stream. A host that cannot
|
|
99
|
+
* stream may buffer the chunks and send them as one body, the client decodes the same
|
|
100
|
+
* NDJSON either way. `body` is ignored when `stream` is set.
|
|
101
|
+
*/
|
|
102
|
+
readonly stream?: () => AsyncIterable<Uint8Array>;
|
|
96
103
|
}
|
|
97
104
|
interface ApiDeps {
|
|
98
105
|
/** The editor working store (read + write/delete/rename), any {@link WorkingStore}. */
|
|
99
106
|
readonly store: WorkingStore;
|
|
100
107
|
/** Who is calling, gates every editing route (DESIGN §11). */
|
|
101
108
|
readonly identity: IdentityProvider;
|
|
102
|
-
/**
|
|
103
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Run the publish pipeline (host binds source/sink/purge). The optional `onProgress`
|
|
111
|
+
* callback receives {@link PublishProgress} events as the publish runs, so the streaming
|
|
112
|
+
* `/api/publish` route can relay a live timeline; a caller that ignores it (the MCP
|
|
113
|
+
* publish tool, tests) gets the same buffered {@link PublishResult}.
|
|
114
|
+
*/
|
|
115
|
+
readonly publish: (options?: {
|
|
116
|
+
onProgress?: ProgressReporter;
|
|
117
|
+
}) => Promise<PublishResult>;
|
|
104
118
|
/**
|
|
105
119
|
* Optional index-reconcile (DESIGN §11d): rebuild the working store's content index
|
|
106
120
|
* from the keys actually present, recovering files that arrived by a path that
|
package/dist/editor-api.js
CHANGED
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
serveEditorAsset,
|
|
22
22
|
templateSnapshotIntegrityDiagnostic,
|
|
23
23
|
templateSuffixConflictDiagnostic
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-CH4DCPNN.js";
|
|
25
|
+
import "./chunk-EGQLAHLP.js";
|
|
26
26
|
export {
|
|
27
27
|
FileBrandingStore,
|
|
28
28
|
InMemoryBrandingStore,
|