@xtrable-ltd/nanoesis 0.1.26 → 0.1.28
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-BCWZRKMF.js} +48 -14
- package/dist/{chunk-H6ZHZWDJ.js → chunk-GFQT7BYP.js} +209 -96
- package/dist/editor-api.d.ts +29 -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-CtPr1oUg.js +4 -0
- package/editor/assets/{TemplatesPane-Dt8Z7trK.js → TemplatesPane-TAfekASM.js} +116 -116
- package/editor/assets/{cssMode-D9n2swjt.js → cssMode-BcU22nqp.js} +1 -1
- package/editor/assets/{freemarker2-DPD1J29I.js → freemarker2-B-QbEUNh.js} +1 -1
- package/editor/assets/{handlebars-D3A5tmfF.js → handlebars-DV6BwKT-.js} +1 -1
- package/editor/assets/{html-ChVj5GP3.js → html-BC8FYPjv.js} +1 -1
- package/editor/assets/{htmlMode-BLNw3RHS.js → htmlMode-CuTG0OKP.js} +1 -1
- package/editor/assets/index-BGqgRhO7.js +142 -0
- package/editor/assets/{index-D4IOSCAV.css → index-CUG-24-D.css} +1 -1
- package/editor/assets/{javascript-DNcoKqyy.js → javascript-Dkg4BI3B.js} +1 -1
- package/editor/assets/{jsonMode-DMU6Vb_m.js → jsonMode-GEjr-YmZ.js} +1 -1
- package/editor/assets/{liquid-BXHGTS2v.js → liquid-Xm_A7c9U.js} +1 -1
- package/editor/assets/{mdx-BV8b_dZV.js → mdx-BVQuw7Zm.js} +1 -1
- package/editor/assets/{python-C4cGrrAN.js → python-8sgL70mf.js} +1 -1
- package/editor/assets/{razor-DW1FX8pl.js → razor-Dc1MxAkI.js} +1 -1
- package/editor/assets/{tsMode-C141_BK1.js → tsMode-DHtFLIS4.js} +1 -1
- package/editor/assets/{typescript-CakAGQIi.js → typescript-D88EeJzi.js} +1 -1
- package/editor/assets/{xml-BbYDGoTr.js → xml-CBE14H0l.js} +1 -1
- package/editor/assets/{yaml-CSwnT3wl.js → yaml-OUgHM8CE.js} +1 -1
- package/editor/index.html +2 -2
- package/package.json +1 -1
- package/editor/assets/MigrationsPane-BEY3O03s.js +0 -4
- package/editor/assets/index-DbxwBEBR.js +0 -145
|
@@ -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-GFQT7BYP.js";
|
|
21
22
|
|
|
22
23
|
// ../editor-api/src/scaffold.ts
|
|
23
24
|
var HOME_HTML = `<!doctype html>
|
|
@@ -531,6 +532,20 @@ async function dispatchApi(deps, req) {
|
|
|
531
532
|
const status = result.reason === "exists" ? 409 : 404;
|
|
532
533
|
return json(status, { ok: false, error: result.reason });
|
|
533
534
|
}
|
|
535
|
+
case "/api/publish/plan": {
|
|
536
|
+
if (req.method !== "GET") return json(405, { ok: false, error: "GET only" });
|
|
537
|
+
return json(200, await planPublish(deps.store));
|
|
538
|
+
}
|
|
539
|
+
case "/api/publish/progress": {
|
|
540
|
+
if (req.method !== "GET") return json(405, { ok: false, error: "GET only" });
|
|
541
|
+
const since = Number.parseInt(get("since"), 10);
|
|
542
|
+
const snapshot = deps.publishProgress?.(Number.isFinite(since) ? since : 0) ?? {
|
|
543
|
+
running: false,
|
|
544
|
+
total: 0,
|
|
545
|
+
events: []
|
|
546
|
+
};
|
|
547
|
+
return json(200, snapshot);
|
|
548
|
+
}
|
|
534
549
|
case "/api/publish": {
|
|
535
550
|
if (req.method !== "POST") return methodNotAllowed();
|
|
536
551
|
const result = await deps.publish();
|
|
@@ -923,26 +938,45 @@ function createEditor(config) {
|
|
|
923
938
|
const sink = asSink(config.website);
|
|
924
939
|
const wipeBeforePublish = config.wipeBeforePublish ?? true;
|
|
925
940
|
const reconcile = config.enumerate === void 0 ? void 0 : async () => working.reconcile([...await config.enumerate()]);
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
941
|
+
let progressEvents = [];
|
|
942
|
+
let progressRunning = false;
|
|
943
|
+
const publish = async (options) => {
|
|
944
|
+
progressEvents = [];
|
|
945
|
+
progressRunning = true;
|
|
946
|
+
const record = (event) => {
|
|
947
|
+
progressEvents.push(event);
|
|
948
|
+
options?.onProgress?.(event);
|
|
949
|
+
};
|
|
950
|
+
try {
|
|
951
|
+
const validation = await validateSite(working);
|
|
952
|
+
if (validation.ok && wipeBeforePublish && config.website.wipe !== void 0) {
|
|
953
|
+
await config.website.wipe();
|
|
954
|
+
}
|
|
955
|
+
const dir = config.users === void 0 ? void 0 : authorDirectory(await config.users());
|
|
956
|
+
const prebuild = typeof config.prebuild === "function" ? await config.prebuild() : config.prebuild;
|
|
957
|
+
return await publishSite(working, sink, {
|
|
958
|
+
...config.images !== void 0 && { imageEncoder: config.images },
|
|
959
|
+
...config.purge !== void 0 && { purge: config.purge },
|
|
960
|
+
...config.baseUrl !== void 0 && { baseUrl: config.baseUrl },
|
|
961
|
+
...dir !== void 0 && { authorDirectory: dir },
|
|
962
|
+
...prebuild !== void 0 && { prebuild },
|
|
963
|
+
onProgress: record
|
|
964
|
+
});
|
|
965
|
+
} finally {
|
|
966
|
+
progressRunning = false;
|
|
930
967
|
}
|
|
931
|
-
const dir = config.users === void 0 ? void 0 : authorDirectory(await config.users());
|
|
932
|
-
const prebuild = typeof config.prebuild === "function" ? await config.prebuild() : config.prebuild;
|
|
933
|
-
return publishSite(working, sink, {
|
|
934
|
-
...config.images !== void 0 && { imageEncoder: config.images },
|
|
935
|
-
...config.purge !== void 0 && { purge: config.purge },
|
|
936
|
-
...config.baseUrl !== void 0 && { baseUrl: config.baseUrl },
|
|
937
|
-
...dir !== void 0 && { authorDirectory: dir },
|
|
938
|
-
...prebuild !== void 0 && { prebuild }
|
|
939
|
-
});
|
|
940
968
|
};
|
|
969
|
+
const publishProgress = (since) => ({
|
|
970
|
+
running: progressRunning,
|
|
971
|
+
total: progressEvents.length,
|
|
972
|
+
events: progressEvents.slice(Math.max(0, since))
|
|
973
|
+
});
|
|
941
974
|
const users = config.users;
|
|
942
975
|
const deps = {
|
|
943
976
|
store: working,
|
|
944
977
|
identity: config.login,
|
|
945
978
|
publish,
|
|
979
|
+
publishProgress,
|
|
946
980
|
diagnostics: config.diagnostics ?? buildDefaultDiagnostics(),
|
|
947
981
|
...reconcile !== void 0 && { reconcile },
|
|
948
982
|
...config.authEndpoints !== void 0 && { authEndpoints: config.authEndpoints },
|
|
@@ -2052,26 +2052,7 @@ function urlForItem(contentPath) {
|
|
|
2052
2052
|
|
|
2053
2053
|
// ../engine/src/compile/site.ts
|
|
2054
2054
|
var DEFAULT_IMAGE_CONCURRENCY = 4;
|
|
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;
|
|
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, PublishProgress, 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
|
/**
|
|
@@ -94,13 +94,39 @@ interface ApiResponse {
|
|
|
94
94
|
readonly headers?: Record<string, string>;
|
|
95
95
|
readonly body?: string | Uint8Array;
|
|
96
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* A snapshot of the publish progress log from a cursor (DESIGN §11): the events a poller
|
|
99
|
+
* has not seen yet (`events`, those at index `since` onward), the running total so the
|
|
100
|
+
* client can advance its cursor, and whether a publish is still in flight. The editor polls
|
|
101
|
+
* `GET /api/publish/progress` for this and folds the events into its timeline. This is the
|
|
102
|
+
* progress transport for hosts that cannot stream an HTTP response (Azure Consumption).
|
|
103
|
+
*/
|
|
104
|
+
interface PublishProgressLog {
|
|
105
|
+
readonly running: boolean;
|
|
106
|
+
readonly total: number;
|
|
107
|
+
readonly events: readonly PublishProgress[];
|
|
108
|
+
}
|
|
97
109
|
interface ApiDeps {
|
|
98
110
|
/** The editor working store (read + write/delete/rename), any {@link WorkingStore}. */
|
|
99
111
|
readonly store: WorkingStore;
|
|
100
112
|
/** Who is calling, gates every editing route (DESIGN §11). */
|
|
101
113
|
readonly identity: IdentityProvider;
|
|
102
|
-
/**
|
|
103
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Run the publish pipeline (host binds source/sink/purge). The optional `onProgress`
|
|
116
|
+
* callback receives {@link PublishProgress} events as the publish runs; a caller that
|
|
117
|
+
* ignores it (the MCP publish tool, tests) still gets the buffered {@link PublishResult}.
|
|
118
|
+
*/
|
|
119
|
+
readonly publish: (options?: {
|
|
120
|
+
onProgress?: ProgressReporter;
|
|
121
|
+
}) => Promise<PublishResult>;
|
|
122
|
+
/**
|
|
123
|
+
* Optional live-progress snapshot for the editor's publish timeline (DESIGN §11). The
|
|
124
|
+
* running publish records its events; `GET /api/publish/progress?since=N` returns the
|
|
125
|
+
* events from cursor `N` plus whether it is still running, so the client polls instead of
|
|
126
|
+
* relying on HTTP streaming (which Azure Consumption does not support). Omitted on a host
|
|
127
|
+
* that does not track progress; the route then reports an idle log.
|
|
128
|
+
*/
|
|
129
|
+
readonly publishProgress?: (since: number) => PublishProgressLog;
|
|
104
130
|
/**
|
|
105
131
|
* Optional index-reconcile (DESIGN §11d): rebuild the working store's content index
|
|
106
132
|
* 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-BCWZRKMF.js";
|
|
25
|
+
import "./chunk-GFQT7BYP.js";
|
|
26
26
|
export {
|
|
27
27
|
FileBrandingStore,
|
|
28
28
|
InMemoryBrandingStore,
|