mechanica 2.1.0-beta.5 → 2.1.0-beta.7
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/README.md +1 -1
- package/dist/chunks/{assets-C7yHGJBU.js → assets-nujjbCx8.js} +1 -1
- package/dist/chunks/{node-adapter-GZZrfGSz.js → node-adapter-CSkDXYGO.js} +5 -36
- package/dist/chunks/{rich-text-codec-BXOKV94u.js → rich-text-codec-BSD35k2U.js} +69 -1
- package/dist/chunks/{site-Co04D3rB.js → site-DfazSr3_.js} +1 -1
- package/dist/cli.js +58 -13
- package/dist/export.js +65 -39
- package/dist/plugin.js +4 -4
- package/dist/server.js +4 -4
- package/dist/types/cli/export.d.ts +27 -1
- package/dist/types/cli/platform/push.d.ts +11 -1
- package/dist/types/cli/run-export.d.ts +9 -0
- package/dist/types/server/assets-store.d.ts +19 -0
- package/dist/types/server/index.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -361,7 +361,7 @@ These drive a locally installed Chrome or Edge (or `--browser <path>`) and need
|
|
|
361
361
|
| `mechanica images` | Generate image dimensions and blur-up previews for `.mech/assets` (needs `sharp`; `--force` redoes all) |
|
|
362
362
|
| `mechanica login` | Sign in to the Mechanica platform and save an access token for this machine (`--host`, `--token`) |
|
|
363
363
|
| `mechanica link <slug>` | Point this repository at a site on the platform (`--create` makes the site); uploads are then kept by the platform, so `.mech/assets/` goes into `.gitignore` |
|
|
364
|
-
| `mechanica push` | Publish the committed project to the platform: pull what was edited online, send the uploads it lacks, `git push`, build and upload the bundle when the code changed, wait for the deploy |
|
|
364
|
+
| `mechanica push` | Publish the committed project to the platform: pull what was edited online, send the uploads it lacks, `git push`, build and upload the bundle when the code changed, wait for the deploy. It pushes the branch that is checked out, under its own name: the first branch a site is pushed is the site itself, any other is deployed to an address of its own (`<slug>--<branch>`) with its own online editor — a branch name is lowercase letters, digits and single hyphens |
|
|
365
365
|
| `mechanica assets pull` | Download the uploads made in the platform's online editor that this project lacks (the dev server fetches them one by one on demand) |
|
|
366
366
|
|
|
367
367
|
## Plugin options
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { G as isAssetName, J as readImageManifest, X as updateImageManifest } from "./rich-text-codec-BSD35k2U.js";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { chmod, mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import os from "node:os";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { n as configureSite, r as indexGeneratedPages } from "./site-
|
|
2
|
-
import { A as pageVersion, C as harvestPageImages, D as movePage, E as listPages, I as setPageDraft,
|
|
1
|
+
import { n as configureSite, r as indexGeneratedPages } from "./site-DfazSr3_.js";
|
|
2
|
+
import { A as pageVersion, C as harvestPageImages, D as movePage, E as listPages, I as setPageDraft, L as translationsOf, M as renamePage, N as savePage, Q as uploadResponse, R as contentFilesOf, T as listFolders, U as contentTypeOf, W as fsAssetStore, Y as storeUpload, _ as deletePage, a as folderOf, b as fillContentDefaults, c as mergeLocaleSiteData, f as readSiteData, g as createTranslation, h as createPage, j as readPage, l as mergeSiteData, m as PageExistsError, o as mergeFolderData, q as listUploads, s as mergeLocaleFolderData, u as readFolderData, v as deleteTranslation, w as imageNamesOf, x as fillImageMeta, y as duplicatePage } from "./rich-text-codec-BSD35k2U.js";
|
|
3
3
|
import fs, { readFileSync, readdirSync } from "node:fs";
|
|
4
|
-
import { basename,
|
|
4
|
+
import { basename, join, resolve, sep } from "node:path";
|
|
5
5
|
import { EDITOR_DIST_DIR, mergeTranslation, parseLocalePath, passDataToHTML, resolveQueryKey, serializeState } from "mechanica-shared";
|
|
6
6
|
import { parseComposedBlock, serializeComposedBlock } from "mechanica-shared/block-format";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
@@ -362,25 +362,6 @@ var json = (data, status = 200) => new Response(JSON.stringify(data), {
|
|
|
362
362
|
status,
|
|
363
363
|
headers: { "content-type": "application/json" }
|
|
364
364
|
});
|
|
365
|
-
/** Content types of the files a site stores — browsers don't sniff SVG or fonts. */
|
|
366
|
-
var MIME = {
|
|
367
|
-
".png": "image/png",
|
|
368
|
-
".jpg": "image/jpeg",
|
|
369
|
-
".jpeg": "image/jpeg",
|
|
370
|
-
".gif": "image/gif",
|
|
371
|
-
".webp": "image/webp",
|
|
372
|
-
".avif": "image/avif",
|
|
373
|
-
".svg": "image/svg+xml",
|
|
374
|
-
".ico": "image/x-icon",
|
|
375
|
-
".mp4": "video/mp4",
|
|
376
|
-
".webm": "video/webm",
|
|
377
|
-
".mp3": "audio/mpeg",
|
|
378
|
-
".pdf": "application/pdf",
|
|
379
|
-
".json": "application/json",
|
|
380
|
-
".txt": "text/plain; charset=utf-8",
|
|
381
|
-
".woff": "font/woff",
|
|
382
|
-
".woff2": "font/woff2"
|
|
383
|
-
};
|
|
384
365
|
/**
|
|
385
366
|
* Stream a file from `dir`, containing the resolved path so an encoded `..`
|
|
386
367
|
* (or an absolute path) cannot escape it.
|
|
@@ -395,7 +376,7 @@ function serveFile(dir, relative, headers = {}) {
|
|
|
395
376
|
const file = resolve(dir, decoded);
|
|
396
377
|
if (file !== dir && !file.startsWith(dir + sep)) return new Response("Forbidden", { status: 403 });
|
|
397
378
|
if (!fs.existsSync(file) || !fs.statSync(file).isFile()) return new Response("Not found", { status: 404 });
|
|
398
|
-
const type =
|
|
379
|
+
const type = contentTypeOf(file);
|
|
399
380
|
return new Response(Readable.toWeb(fs.createReadStream(file)), { headers: {
|
|
400
381
|
...type ? { "content-type": type } : {},
|
|
401
382
|
...headers
|
|
@@ -422,19 +403,7 @@ function validateComposed(def) {
|
|
|
422
403
|
function createEditorService(mech, options = {}) {
|
|
423
404
|
const mechDir = typeof mech === "string" ? mech : null;
|
|
424
405
|
const assets = options.assets ?? (mechDir ? fsAssetStore(mechDir) : null);
|
|
425
|
-
const asset =
|
|
426
|
-
let name;
|
|
427
|
-
try {
|
|
428
|
-
name = decodeURIComponent(encoded);
|
|
429
|
-
} catch {
|
|
430
|
-
return new Response("Bad request", { status: 400 });
|
|
431
|
-
}
|
|
432
|
-
if (!assets || !isAssetName(name)) return null;
|
|
433
|
-
const body = await assets.open(name);
|
|
434
|
-
if (!body) return null;
|
|
435
|
-
const type = MIME[extname(name).toLowerCase()];
|
|
436
|
-
return new Response(body, { headers: type ? { "content-type": type } : {} });
|
|
437
|
-
};
|
|
406
|
+
const asset = (encoded) => uploadResponse(assets, encoded);
|
|
438
407
|
let configured = null;
|
|
439
408
|
let generatedIndex = null;
|
|
440
409
|
const currentSite = async () => {
|
|
@@ -273,6 +273,74 @@ async function listUploads(assets) {
|
|
|
273
273
|
src: assetUrl(name)
|
|
274
274
|
}));
|
|
275
275
|
}
|
|
276
|
+
/** Content types of the files a site stores — browsers don't sniff SVG or fonts. */
|
|
277
|
+
var MIME = {
|
|
278
|
+
".png": "image/png",
|
|
279
|
+
".jpg": "image/jpeg",
|
|
280
|
+
".jpeg": "image/jpeg",
|
|
281
|
+
".gif": "image/gif",
|
|
282
|
+
".webp": "image/webp",
|
|
283
|
+
".avif": "image/avif",
|
|
284
|
+
".svg": "image/svg+xml",
|
|
285
|
+
".ico": "image/x-icon",
|
|
286
|
+
".mp4": "video/mp4",
|
|
287
|
+
".webm": "video/webm",
|
|
288
|
+
".mp3": "audio/mpeg",
|
|
289
|
+
".pdf": "application/pdf",
|
|
290
|
+
".json": "application/json",
|
|
291
|
+
".txt": "text/plain; charset=utf-8",
|
|
292
|
+
".woff": "font/woff",
|
|
293
|
+
".woff2": "font/woff2"
|
|
294
|
+
};
|
|
295
|
+
/** The content type a stored file is served with, when its extension says. */
|
|
296
|
+
var contentTypeOf = (fileName) => MIME[parse(fileName).ext.toLowerCase()];
|
|
297
|
+
/**
|
|
298
|
+
* The HTTP answer for an upload asked for by its address — the part of
|
|
299
|
+
* `/media/<name>` after the prefix, still percent-encoded. null when it is not
|
|
300
|
+
* an upload of this store, so the caller can fall through; a 400 for a name
|
|
301
|
+
* that is not valid encoding. One function for every host that serves uploads:
|
|
302
|
+
* the dev server, an editing host, a site's live host.
|
|
303
|
+
*/
|
|
304
|
+
async function uploadResponse(assets, encodedName) {
|
|
305
|
+
let name;
|
|
306
|
+
try {
|
|
307
|
+
name = decodeURIComponent(encodedName);
|
|
308
|
+
} catch {
|
|
309
|
+
return new Response("Bad request", { status: 400 });
|
|
310
|
+
}
|
|
311
|
+
if (!assets || !isAssetName(name)) return null;
|
|
312
|
+
const body = await assets.open(name);
|
|
313
|
+
if (!body) return null;
|
|
314
|
+
const type = contentTypeOf(name);
|
|
315
|
+
return new Response(body, { headers: type ? { "content-type": type } : {} });
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* A store for rendering a site whose uploads the host keeps and serves itself.
|
|
319
|
+
* `hosted` is what the host knows about them — a name with its image info. The
|
|
320
|
+
* result knows those names (`list`, `info`) but cannot open them: an export
|
|
321
|
+
* over it fills in their dimensions and previews, copies no bytes, and reports
|
|
322
|
+
* them as the host's to serve (see `ExportResult.uploads`). Whatever the local
|
|
323
|
+
* store has is used as before.
|
|
324
|
+
*/
|
|
325
|
+
function withHostedAssets(local, hosted) {
|
|
326
|
+
const names = Object.keys(hosted).filter(isAssetName);
|
|
327
|
+
return {
|
|
328
|
+
write: (name, data) => local.write(name, data),
|
|
329
|
+
open: (name) => local.open(name),
|
|
330
|
+
saveInfo: (entries) => local.saveInfo(entries),
|
|
331
|
+
async list() {
|
|
332
|
+
return [.../* @__PURE__ */ new Set([...await local.list(), ...names])];
|
|
333
|
+
},
|
|
334
|
+
async info(wanted) {
|
|
335
|
+
const known = await local.info(wanted);
|
|
336
|
+
for (const name of wanted) {
|
|
337
|
+
const entry = hosted[name];
|
|
338
|
+
if (entry && !known[name]) known[name] = entry;
|
|
339
|
+
}
|
|
340
|
+
return known;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
276
344
|
var MISS_TTL_MS = 3e4;
|
|
277
345
|
var MEMORY_LIMIT = 67108864;
|
|
278
346
|
/**
|
|
@@ -1203,4 +1271,4 @@ function findRichTextProps(props) {
|
|
|
1203
1271
|
return found;
|
|
1204
1272
|
}
|
|
1205
1273
|
//#endregion
|
|
1206
|
-
export {
|
|
1274
|
+
export { withHostedAssets as $, pageVersion as A, memoryContentFiles as B, harvestPageImages as C, movePage as D, listPages as E, setPageCodec as F, isAssetName as G, assetFileOf as H, setPageDraft as I, readImageManifest as J, isDerivedAsset as K, translationsOf as L, renamePage as M, savePage as N, pageOfFile as O, setPageBlocks as P, uploadResponse as Q, contentFilesOf as R, getPagePath as S, listFolders as T, contentTypeOf as U, UPLOADS_PREFIX$1 as V, fsAssetStore as W, updateImageManifest as X, storeUpload as Y, uploadName as Z, deletePage as _, folderOf as a, fillContentDefaults as b, mergeLocaleSiteData as c, readFoldersData as d, withRemoteAssets as et, readSiteData as f, createTranslation as g, createPage as h, toBlockMeta as i, isRasterImage as it, readPage as j, pageUrlOf as k, mergeSiteData as l, PageExistsError as m, richTextCodecFromBlocks as n, analyzeImageBuffer as nt, mergeFolderData as o, readSiteLocaleOverride as p, listUploads as q, composedBlockMeta as r, hasSharp as rt, mergeLocaleFolderData as s, buildRichTextCodec as t, wasRecentlyMutated as tt, readFolderData as u, deleteTranslation as v, imageNamesOf as w, fillImageMeta as x, duplicatePage as y, fsContentFiles as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as setPageCodec, P as setPageBlocks, i as toBlockMeta, n as richTextCodecFromBlocks, r as composedBlockMeta } from "./rich-text-codec-
|
|
1
|
+
import { F as setPageCodec, P as setPageBlocks, i as toBlockMeta, n as richTextCodecFromBlocks, r as composedBlockMeta } from "./rich-text-codec-BSD35k2U.js";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { SITE_MANIFEST_FILE, areFieldSchemasRegistered, localePath, registerFieldSchemas } from "mechanica-shared";
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as buildSiteManifest } from "./chunks/site-
|
|
2
|
-
import {
|
|
3
|
-
import { a as git, c as PlatformError, d as request, f as requireToken, l as REMOTE_NAME, m as saveToken, o as gitAuthEnv, p as hostOrigin, r as runAssetsPull, s as gitOk, t as pushUploads, u as parseRemoteUrl } from "./chunks/assets-
|
|
1
|
+
import { t as buildSiteManifest } from "./chunks/site-DfazSr3_.js";
|
|
2
|
+
import { J as readImageManifest, K as isDerivedAsset, W as fsAssetStore, X as updateImageManifest, et as withRemoteAssets, it as isRasterImage, nt as analyzeImageBuffer, rt as hasSharp } from "./chunks/rich-text-codec-BSD35k2U.js";
|
|
3
|
+
import { a as git, c as PlatformError, d as request, f as requireToken, i as uploadsIgnored, l as REMOTE_NAME, m as saveToken, n as remoteAssetsFor, o as gitAuthEnv, p as hostOrigin, r as runAssetsPull, s as gitOk, t as pushUploads, u as parseRemoteUrl } from "./chunks/assets-nujjbCx8.js";
|
|
4
4
|
import { exportBuilt } from "./export.js";
|
|
5
5
|
import fs, { readFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
@@ -128,13 +128,31 @@ async function writeSiteManifest(distDir) {
|
|
|
128
128
|
//#endregion
|
|
129
129
|
//#region src/cli/run-export.ts
|
|
130
130
|
/**
|
|
131
|
+
* The uploads a local export reads: the project's `.mech/assets`, and — for a
|
|
132
|
+
* project linked to a hosted platform — the uploads kept there, fetched as the
|
|
133
|
+
* pages turn out to need them (and kept in `.mech/assets` when git ignores it).
|
|
134
|
+
* Only local files are *listed*: the uploads the platform holds that no page
|
|
135
|
+
* here refers to are not this export's to warn about.
|
|
136
|
+
*/
|
|
137
|
+
function exportAssets(cwd) {
|
|
138
|
+
const local = fsAssetStore(join(cwd, ".mech"));
|
|
139
|
+
return {
|
|
140
|
+
...withRemoteAssets(local, remoteAssetsFor(cwd), { cache: () => uploadsIgnored(cwd) }),
|
|
141
|
+
list: () => local.list()
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
131
145
|
* `mechanica export`: build the project, then statically render every page
|
|
132
146
|
* into `export/`. Kept apart from `export.ts` so that module never imports
|
|
133
147
|
* Vite — `mechanica/export` runs where only a built bundle exists.
|
|
134
148
|
*/
|
|
135
149
|
async function runExport(options = {}) {
|
|
136
150
|
await runBuild();
|
|
137
|
-
const
|
|
151
|
+
const cwd = process.cwd();
|
|
152
|
+
const { pages } = await exportBuilt(cwd, {
|
|
153
|
+
assets: exportAssets(cwd),
|
|
154
|
+
...options
|
|
155
|
+
});
|
|
138
156
|
for (const path of pages) console.info("Generated", path);
|
|
139
157
|
console.info(`Exported ${pages.length} page(s) → ${options.outDir ?? "export"}/`);
|
|
140
158
|
}
|
|
@@ -410,7 +428,20 @@ var POLL_MS = 1e3;
|
|
|
410
428
|
var DEPLOY_TIMEOUT_MS = 3e5;
|
|
411
429
|
var AUTO_DEPLOY_WAIT_MS = 1e4;
|
|
412
430
|
/**
|
|
413
|
-
*
|
|
431
|
+
* Why a branch cannot be pushed under its name, or null when it can. On the platform a branch
|
|
432
|
+
* is served at an address of its own (`<slug>--<branch>`), so its name must be able to be part
|
|
433
|
+
* of one: lowercase letters, digits and single hyphens. The platform checks the same (and how
|
|
434
|
+
* long the name may be for the site) — this only says it before anything is sent.
|
|
435
|
+
*/
|
|
436
|
+
function branchProblem(name) {
|
|
437
|
+
if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(name) || name.length > 40 || name.includes("--") || name === "edit") return `The branch "${name}" cannot be pushed under this name: on the platform a branch's name becomes part of its address, so it is up to 40 lowercase letters, digits and single hyphens (and not "edit"). Rename it — \`git branch -m new-name\` — and push again.`;
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* `mechanica push`: publish the committed project to the platform — the branch that is checked
|
|
442
|
+
* out, under its own name. The first branch a site is pushed becomes the site itself; any
|
|
443
|
+
* other is deployed to an address of its own, with its own online editor, and never touches
|
|
444
|
+
* the site.
|
|
414
445
|
*
|
|
415
446
|
* 1. bring in what was published online since the last pull (`pull --rebase`),
|
|
416
447
|
* 2. send the uploads the platform lacks (they are not in git), then `git push`
|
|
@@ -445,18 +476,30 @@ async function runPush() {
|
|
|
445
476
|
])).code !== 0) throw new Error("Nothing to push yet — commit your project first");
|
|
446
477
|
const dirty = await gitOk(cwd, ["status", "--porcelain"]);
|
|
447
478
|
if (dirty) throw new Error(`Commit or stash your changes first — the working tree is not clean:\n${dirty}`);
|
|
479
|
+
const current = await git(cwd, [
|
|
480
|
+
"symbolic-ref",
|
|
481
|
+
"--quiet",
|
|
482
|
+
"--short",
|
|
483
|
+
"HEAD"
|
|
484
|
+
]);
|
|
485
|
+
if (current.code !== 0 || !current.stdout) throw new Error("No branch is checked out (a detached HEAD) — switch to the branch you want to push");
|
|
486
|
+
const branch = current.stdout;
|
|
487
|
+
const problem = branchProblem(branch);
|
|
488
|
+
if (problem) throw new Error(problem);
|
|
489
|
+
const ref = `refs/heads/${branch}`;
|
|
490
|
+
const query = `?branch=${encodeURIComponent(branch)}`;
|
|
448
491
|
if (await gitOk(cwd, [
|
|
449
492
|
"ls-remote",
|
|
450
493
|
"--heads",
|
|
451
494
|
"mechanica",
|
|
452
|
-
|
|
495
|
+
ref
|
|
453
496
|
], auth)) {
|
|
454
497
|
console.info("Pulling changes from the platform…");
|
|
455
498
|
const pulled = await git(cwd, [
|
|
456
499
|
"pull",
|
|
457
500
|
"--rebase",
|
|
458
501
|
REMOTE_NAME,
|
|
459
|
-
|
|
502
|
+
branch
|
|
460
503
|
], auth);
|
|
461
504
|
if (pulled.code !== 0) throw new Error(`Could not rebase onto the platform's changes:\n${pulled.stderr || pulled.stdout}\nResolve the conflict (\`git rebase --continue\`), then run \`mechanica push\` again.`);
|
|
462
505
|
}
|
|
@@ -466,14 +509,14 @@ async function runPush() {
|
|
|
466
509
|
token
|
|
467
510
|
});
|
|
468
511
|
const head = await gitOk(cwd, ["rev-parse", "HEAD"]);
|
|
469
|
-
console.info(`Pushing ${head.slice(0, 8)} to ${link.slug}…`);
|
|
512
|
+
console.info(`Pushing ${head.slice(0, 8)} to ${link.slug} (${branch})…`);
|
|
470
513
|
const pushed = await git(cwd, [
|
|
471
514
|
"push",
|
|
472
515
|
REMOTE_NAME,
|
|
473
|
-
|
|
516
|
+
`HEAD:${ref}`
|
|
474
517
|
], auth);
|
|
475
518
|
if (pushed.code !== 0) throw new Error(`git push failed:\n${pushed.stderr || pushed.stdout}`);
|
|
476
|
-
const statusPath = `/api/sites/${site.uuid}/status`;
|
|
519
|
+
const statusPath = `/api/sites/${site.uuid}/status${query}`;
|
|
477
520
|
let status = await request(link.origin, "GET", statusPath, { token });
|
|
478
521
|
let deployId = null;
|
|
479
522
|
if (status.needsBundle) {
|
|
@@ -483,7 +526,7 @@ async function runPush() {
|
|
|
483
526
|
engine: engineVersion()
|
|
484
527
|
});
|
|
485
528
|
console.info(`Uploading the bundle (${(body.length / 1024 / 1024).toFixed(1)} MB)…`);
|
|
486
|
-
const uploaded = await request(link.origin, "POST", `/api/sites/${site.uuid}/bundles`, {
|
|
529
|
+
const uploaded = await request(link.origin, "POST", `/api/sites/${site.uuid}/bundles${query}`, {
|
|
487
530
|
token,
|
|
488
531
|
raw: body
|
|
489
532
|
});
|
|
@@ -513,7 +556,7 @@ async function runPush() {
|
|
|
513
556
|
if (deploy.log) console.error(`\n${deploy.log}\n`);
|
|
514
557
|
throw new Error(`Deploy failed: ${deploy.error ?? "unknown error"}. The previous version stays live.`);
|
|
515
558
|
}
|
|
516
|
-
console.info(`\
|
|
559
|
+
console.info(`\n${branch} is live at ${deploy.url ?? status.url} — ${deploy.pages} page(s)`);
|
|
517
560
|
}
|
|
518
561
|
//#endregion
|
|
519
562
|
//#region src/cli/headless.ts
|
|
@@ -1200,7 +1243,9 @@ Usage:
|
|
|
1200
1243
|
(--create makes the site, --name "Site name")
|
|
1201
1244
|
mechanica push Publish the committed project: pull what was edited
|
|
1202
1245
|
online, git push, build + upload the bundle when the
|
|
1203
|
-
code changed, and wait for the deploy
|
|
1246
|
+
code changed, and wait for the deploy. Pushes the
|
|
1247
|
+
branch that is checked out: the first one pushed is
|
|
1248
|
+
the site, any other gets an address of its own
|
|
1204
1249
|
mechanica shot <blockId> Screenshot one block via the dev preview route
|
|
1205
1250
|
mechanica shot </path> Screenshot a whole page (editor overlay stripped)
|
|
1206
1251
|
(--page </path>, --data <json|@file>, --width 1440,768,
|
package/dist/export.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as withHostedAssets, E as listPages, F as setPageCodec, H as assetFileOf, K as isDerivedAsset, S as getPagePath, V as UPLOADS_PREFIX$1, W as fsAssetStore, d as readFoldersData, f as readSiteData, i as toBlockMeta, nt as analyzeImageBuffer, p as readSiteLocaleOverride, r as composedBlockMeta, rt as hasSharp, t as buildRichTextCodec, u as readFolderData } from "./chunks/rich-text-codec-BSD35k2U.js";
|
|
2
2
|
import { n as blockAssetLinks, t as BLOCKS_MANIFEST_FILE } from "./chunks/page-assets-DsJXmoDs.js";
|
|
3
3
|
import { dirname, join, parse, relative, resolve } from "node:path";
|
|
4
4
|
import { EDITOR_DIST_DIR, SITE_MANIFEST_FILE, applySeoTags, auditPageHtml, buildRobotsTxt, buildSitemap, findUnknownBlocks, generateProject, isPaginatedQuery, localePath, mergeTranslation, migrateContent, paginationVariantPath, registerFieldSchemas, resolveQueryKey, templateBlockIds, validateLinks, walkSchema, walkTree } from "mechanica-shared";
|
|
@@ -218,45 +218,52 @@ function fillImageValue(value, entry) {
|
|
|
218
218
|
if (entry.width && !value.width) value.width = entry.width;
|
|
219
219
|
if (entry.height && !value.height) value.height = entry.height;
|
|
220
220
|
}
|
|
221
|
+
/** Everything an upload's bytes come as, in one buffer. */
|
|
222
|
+
var bytesOf = async (body) => body instanceof Uint8Array ? Buffer.from(body) : Buffer.from(await new Response(body).arrayBuffer());
|
|
221
223
|
/**
|
|
222
224
|
* Fill missing image metadata — LQIP `previewSrc` + intrinsic dimensions —
|
|
223
225
|
* into the state being exported (page files are never touched). Sources, in
|
|
224
|
-
* order: the
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* Without sharp, leftover gaps get a one-time hint.
|
|
226
|
+
* order: what the asset store knows (written by uploads, editor saves and
|
|
227
|
+
* `mechanica images`), then the optional `sharp` dependency for anything still
|
|
228
|
+
* missing that the store can open — those computed entries are saved back to
|
|
229
|
+
* it. Without sharp, leftover gaps get a one-time hint.
|
|
228
230
|
*/
|
|
229
|
-
async function backfillImageMeta(pages, blocksMap,
|
|
230
|
-
const
|
|
231
|
-
const incomplete = /* @__PURE__ */ new Map();
|
|
231
|
+
async function backfillImageMeta(pages, blocksMap, assets, warn) {
|
|
232
|
+
const values = /* @__PURE__ */ new Map();
|
|
232
233
|
for (const page of pages) walkTree(page.content, (block) => {
|
|
233
234
|
const meta = blocksMap.get(block.blockId);
|
|
234
235
|
if (!meta) return;
|
|
235
236
|
walkSchema(block.data, meta.props, (value, schema) => {
|
|
236
237
|
if (schema.format !== "image") return;
|
|
237
238
|
const file = assetFileOf(value?.src);
|
|
238
|
-
if (
|
|
239
|
-
const entry = manifest[file];
|
|
240
|
-
if (entry) fillImageValue(value, entry);
|
|
241
|
-
if (!value.previewSrc || value.previewSrc === value.src || !value.width || !value.height) incomplete.set(file, [...incomplete.get(file) ?? [], value]);
|
|
239
|
+
if (file) values.set(file, [...values.get(file) ?? [], value]);
|
|
242
240
|
});
|
|
243
241
|
});
|
|
242
|
+
if (!values.size) return;
|
|
243
|
+
const known = await assets.info([...values.keys()]);
|
|
244
|
+
const incomplete = /* @__PURE__ */ new Map();
|
|
245
|
+
for (const [file, list] of values) {
|
|
246
|
+
const entry = known[file];
|
|
247
|
+
const lacking = list.filter((value) => {
|
|
248
|
+
if (entry) fillImageValue(value, entry);
|
|
249
|
+
return !value.previewSrc || value.previewSrc === value.src || !value.width || !value.height;
|
|
250
|
+
});
|
|
251
|
+
if (lacking.length) incomplete.set(file, lacking);
|
|
252
|
+
}
|
|
244
253
|
if (!incomplete.size) return;
|
|
245
254
|
if (!await hasSharp()) {
|
|
246
255
|
warn(`[mechanica] ${incomplete.size} image(s) lack a preview or dimensions — install the optional "sharp" dependency or run \`mechanica images\` to generate them`);
|
|
247
256
|
return;
|
|
248
257
|
}
|
|
249
258
|
const computed = {};
|
|
250
|
-
for (const [file,
|
|
251
|
-
const
|
|
252
|
-
const info =
|
|
259
|
+
for (const [file, list] of incomplete) {
|
|
260
|
+
const body = await assets.open(file).catch(() => null);
|
|
261
|
+
const info = body ? await analyzeImageBuffer(await bytesOf(body)) : null;
|
|
253
262
|
if (!info) continue;
|
|
254
263
|
computed[file] = info;
|
|
255
|
-
for (const value of
|
|
264
|
+
for (const value of list) fillImageValue(value, info);
|
|
256
265
|
}
|
|
257
|
-
|
|
258
|
-
updateImageManifest(mechDir, computed);
|
|
259
|
-
} catch {}
|
|
266
|
+
await assets.saveInfo(computed).catch(() => {});
|
|
260
267
|
}
|
|
261
268
|
/**
|
|
262
269
|
* Statically render every page of an already-built project into `export/`,
|
|
@@ -277,6 +284,7 @@ async function backfillImageMeta(pages, blocksMap, mechDir, warn) {
|
|
|
277
284
|
*/
|
|
278
285
|
async function exportProject(cwd, ssr, options = {}) {
|
|
279
286
|
const warn = options.onWarn ?? ((message) => console.warn(message));
|
|
287
|
+
const assets = options.assets ?? fsAssetStore(join(cwd, ".mech"));
|
|
280
288
|
const index = await readFile(join(cwd, "dist/index.html"), "utf-8");
|
|
281
289
|
const siteUrl = options.siteUrl ?? ssr.site?.url;
|
|
282
290
|
const siteName = options.siteName ?? ssr.site?.name;
|
|
@@ -374,7 +382,7 @@ async function exportProject(cwd, ssr, options = {}) {
|
|
|
374
382
|
}
|
|
375
383
|
if (!pages.some((page) => page.logicalPath === "/404")) warn("[mechanica] No /404 page — the static host will show its own error page. Create a page at /404 (it exports as 404.html and is noindexed automatically).");
|
|
376
384
|
for (const issue of validateLinks(pages, blocksMap)) warn(`[mechanica] Broken link on ${issue.page}: ${issue.url} has no matching page`);
|
|
377
|
-
await backfillImageMeta(pages, blocksMap,
|
|
385
|
+
await backfillImageMeta(pages, blocksMap, assets, warn);
|
|
378
386
|
const exportDir = resolve(cwd, options.outDir ?? "export");
|
|
379
387
|
await mkdir(exportDir, { recursive: true });
|
|
380
388
|
for (const entry of await readdir(exportDir)) await rm(join(exportDir, entry), {
|
|
@@ -435,8 +443,9 @@ async function exportProject(cwd, ssr, options = {}) {
|
|
|
435
443
|
onFile,
|
|
436
444
|
pageLinks
|
|
437
445
|
};
|
|
446
|
+
const stored = await assets.list();
|
|
438
447
|
const unclaimed = /* @__PURE__ */ new Map();
|
|
439
|
-
for (const name of
|
|
448
|
+
for (const name of stored) {
|
|
440
449
|
const spellings = [
|
|
441
450
|
name,
|
|
442
451
|
encodeURI(name),
|
|
@@ -550,26 +559,41 @@ async function exportProject(cwd, ssr, options = {}) {
|
|
|
550
559
|
}));
|
|
551
560
|
recordSitemap(path, source, source.page.pagination.page);
|
|
552
561
|
}
|
|
553
|
-
await copyUploads(
|
|
562
|
+
const uploads = await copyUploads(assets, new Set(stored), join(exportDir, MEDIA_DIR), referenced, warn);
|
|
554
563
|
if (written.includes("/404")) await copyFile(join(exportDir, "404/index.html"), join(exportDir, "404.html"));
|
|
555
564
|
if (siteUrl) {
|
|
556
565
|
await writeFile(join(exportDir, "sitemap.xml"), buildSitemap(siteUrl, sitemapEntries));
|
|
557
566
|
const robotsPath = join(exportDir, "robots.txt");
|
|
558
567
|
if (!await access(robotsPath).then(() => true, () => false)) await writeFile(robotsPath, buildRobotsTxt(siteUrl));
|
|
559
568
|
}
|
|
560
|
-
return
|
|
569
|
+
return {
|
|
570
|
+
pages: written,
|
|
571
|
+
uploads
|
|
572
|
+
};
|
|
561
573
|
}
|
|
562
|
-
/**
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
574
|
+
/**
|
|
575
|
+
* Put the referenced uploads into the export: copy the ones the store can open,
|
|
576
|
+
* leave to the host the ones it only knows about, warn about the ones it does
|
|
577
|
+
* not know — and about uploads no page refers to.
|
|
578
|
+
*/
|
|
579
|
+
async function copyUploads(assets, stored, outDir, referenced, warn) {
|
|
580
|
+
const uploads = {
|
|
581
|
+
copied: [],
|
|
582
|
+
hosted: []
|
|
583
|
+
};
|
|
584
|
+
for (const name of referenced) {
|
|
585
|
+
const body = await assets.open(name).catch(() => null);
|
|
586
|
+
if (body) {
|
|
587
|
+
const target = join(outDir, name);
|
|
588
|
+
await mkdir(dirname(target), { recursive: true });
|
|
589
|
+
await writeFile(target, await bytesOf(body));
|
|
590
|
+
uploads.copied.push(name);
|
|
591
|
+
} else if (stored.has(name)) uploads.hosted.push(name);
|
|
592
|
+
else warn(`[mechanica] Missing upload: ${name} is referenced by a page but is not among the site's uploads`);
|
|
570
593
|
}
|
|
571
|
-
const orphans =
|
|
572
|
-
if (orphans.length) warn(`[mechanica] ${orphans.length} unused upload(s)
|
|
594
|
+
const orphans = [...stored].filter((name) => /\.\w+$/.test(name) && !referenced.has(name) && !isDerivedAsset(name));
|
|
595
|
+
if (orphans.length) warn(`[mechanica] ${orphans.length} unused upload(s) (not exported): ${orphans.join(", ")}`);
|
|
596
|
+
return uploads;
|
|
573
597
|
}
|
|
574
598
|
/**
|
|
575
599
|
* Statically render an already-built project: load `<cwd>/dist/ssr.js` and run
|
|
@@ -585,13 +609,15 @@ async function exportBuilt(cwd, options = {}) {
|
|
|
585
609
|
warnings.push(message);
|
|
586
610
|
(options.onWarn ?? console.warn)(message);
|
|
587
611
|
};
|
|
612
|
+
const { pages, uploads } = await exportProject(cwd, await import(pathToFileURL(join(cwd, "dist/ssr.js")).href), {
|
|
613
|
+
...options,
|
|
614
|
+
onWarn
|
|
615
|
+
});
|
|
588
616
|
return {
|
|
589
|
-
pages
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}),
|
|
593
|
-
warnings
|
|
617
|
+
pages,
|
|
618
|
+
warnings,
|
|
619
|
+
uploads
|
|
594
620
|
};
|
|
595
621
|
}
|
|
596
622
|
//#endregion
|
|
597
|
-
export { exportBuilt, exportProject };
|
|
623
|
+
export { exportBuilt, exportProject, fsAssetStore, withHostedAssets };
|
package/dist/plugin.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as collectGeneratedPages, n as configureSite, r as indexGeneratedPages, t as buildSiteManifest } from "./chunks/site-
|
|
2
|
-
import { a as renderEditablePage, c as fillStateImages, d as loadComposedDefinitions, n as toNodeMiddleware, o as buildGeneratedState, r as createEditorService, s as buildPageState, t as toAssetMiddleware, u as collectComposed } from "./chunks/node-adapter-
|
|
3
|
-
import {
|
|
4
|
-
import { i as uploadsIgnored, n as remoteAssetsFor } from "./chunks/assets-
|
|
1
|
+
import { a as collectGeneratedPages, n as configureSite, r as indexGeneratedPages, t as buildSiteManifest } from "./chunks/site-DfazSr3_.js";
|
|
2
|
+
import { a as renderEditablePage, c as fillStateImages, d as loadComposedDefinitions, n as toNodeMiddleware, o as buildGeneratedState, r as createEditorService, s as buildPageState, t as toAssetMiddleware, u as collectComposed } from "./chunks/node-adapter-CSkDXYGO.js";
|
|
3
|
+
import { W as fsAssetStore, et as withRemoteAssets, k as pageUrlOf, tt as wasRecentlyMutated } from "./chunks/rich-text-codec-BSD35k2U.js";
|
|
4
|
+
import { i as uploadsIgnored, n as remoteAssetsFor } from "./chunks/assets-nujjbCx8.js";
|
|
5
5
|
import { t as BLOCKS_MANIFEST_FILE } from "./chunks/page-assets-DsJXmoDs.js";
|
|
6
6
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
7
7
|
import { join, relative } from "node:path";
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as readSiteManifest, n as configureSite, t as buildSiteManifest } from "./chunks/site-
|
|
2
|
-
import { a as renderEditablePage, i as readEditorTemplate, n as toNodeMiddleware, r as createEditorService, t as toAssetMiddleware } from "./chunks/node-adapter-
|
|
3
|
-
import { B as memoryContentFiles, G as isDerivedAsset, O as pageOfFile, U as fsAssetStore,
|
|
1
|
+
import { i as readSiteManifest, n as configureSite, t as buildSiteManifest } from "./chunks/site-DfazSr3_.js";
|
|
2
|
+
import { a as renderEditablePage, i as readEditorTemplate, n as toNodeMiddleware, r as createEditorService, t as toAssetMiddleware } from "./chunks/node-adapter-CSkDXYGO.js";
|
|
3
|
+
import { $ as withHostedAssets, B as memoryContentFiles, G as isAssetName, K as isDerivedAsset, O as pageOfFile, Q as uploadResponse, U as contentTypeOf, W as fsAssetStore, Z as uploadName, et as withRemoteAssets, z as fsContentFiles } from "./chunks/rich-text-codec-BSD35k2U.js";
|
|
4
4
|
import { EDITOR_DIST_DIR, SITE_MANIFEST_FILE, UPLOADS_PREFIX, uploadNameOf } from "mechanica-shared";
|
|
5
|
-
export { EDITOR_DIST_DIR, SITE_MANIFEST_FILE, UPLOADS_PREFIX, buildSiteManifest, configureSite, createEditorService, fsAssetStore, fsContentFiles, isDerivedAsset, memoryContentFiles, pageOfFile, readEditorTemplate, readSiteManifest, renderEditablePage, toAssetMiddleware, toNodeMiddleware, uploadName, uploadNameOf, withRemoteAssets };
|
|
5
|
+
export { EDITOR_DIST_DIR, SITE_MANIFEST_FILE, UPLOADS_PREFIX, buildSiteManifest, configureSite, contentTypeOf, createEditorService, fsAssetStore, fsContentFiles, isAssetName, isDerivedAsset, memoryContentFiles, pageOfFile, readEditorTemplate, readSiteManifest, renderEditablePage, toAssetMiddleware, toNodeMiddleware, uploadName, uploadNameOf, uploadResponse, withHostedAssets, withRemoteAssets };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ComposedBlockDefinition, type LocalesConfig, type RenderResult, type VirtualPage } from 'mechanica-shared';
|
|
2
2
|
import { type BlockComponent } from '../editor/lib/block-meta';
|
|
3
|
+
import { fsAssetStore, withHostedAssets, type AssetStore, type ImageManifest } from '../server/assets-store';
|
|
3
4
|
/** An already-built SSR bundle (`dist/ssr.js`) exposes these. */
|
|
4
5
|
export interface SsrBundle {
|
|
5
6
|
/**
|
|
@@ -69,6 +70,24 @@ export interface ExportOptions {
|
|
|
69
70
|
fetchJson?: (options: {
|
|
70
71
|
url: string;
|
|
71
72
|
} & Record<string, unknown>) => Promise<unknown>;
|
|
73
|
+
/**
|
|
74
|
+
* Where the site's uploads are: their bytes and their image info. Defaults to
|
|
75
|
+
* the project's `.mech/assets` + `.mech/images.json`. The export reads uploads
|
|
76
|
+
* only through this — a linked project passes a store that also fetches the
|
|
77
|
+
* ones kept by its platform, and a hosted render one that knows uploads it
|
|
78
|
+
* cannot open (`withHostedAssets`): those are not copied, the host serves them.
|
|
79
|
+
*/
|
|
80
|
+
assets?: AssetStore;
|
|
81
|
+
}
|
|
82
|
+
/** What became of the uploads the pages refer to. */
|
|
83
|
+
export interface ExportedUploads {
|
|
84
|
+
/** Copied into the export's `media/` directory. */
|
|
85
|
+
copied: string[];
|
|
86
|
+
/**
|
|
87
|
+
* Known to the store but not readable through it — left for the host to
|
|
88
|
+
* serve at `/media/<name>`. Empty for an export over a plain directory.
|
|
89
|
+
*/
|
|
90
|
+
hosted: string[];
|
|
72
91
|
}
|
|
73
92
|
/**
|
|
74
93
|
* Statically render every page of an already-built project into `export/`,
|
|
@@ -87,13 +106,18 @@ export interface ExportOptions {
|
|
|
87
106
|
* absolute social-image URLs, pagination prev/next, JSON-LD) and emits
|
|
88
107
|
* `sitemap.xml` + `robots.txt`.
|
|
89
108
|
*/
|
|
90
|
-
export declare function exportProject(cwd: string, ssr: SsrBundle, options?: ExportOptions): Promise<
|
|
109
|
+
export declare function exportProject(cwd: string, ssr: SsrBundle, options?: ExportOptions): Promise<{
|
|
110
|
+
pages: string[];
|
|
111
|
+
uploads: ExportedUploads;
|
|
112
|
+
}>;
|
|
91
113
|
/** What {@link exportBuilt} produced. */
|
|
92
114
|
export interface ExportResult {
|
|
93
115
|
/** The generated page paths, in render order. */
|
|
94
116
|
pages: string[];
|
|
95
117
|
/** Everything the export warned about (broken links, missing uploads, SEO lint). */
|
|
96
118
|
warnings: string[];
|
|
119
|
+
/** The uploads the pages refer to: which were copied, which the host is to serve. */
|
|
120
|
+
uploads: ExportedUploads;
|
|
97
121
|
}
|
|
98
122
|
/**
|
|
99
123
|
* Statically render an already-built project: load `<cwd>/dist/ssr.js` and run
|
|
@@ -103,3 +127,5 @@ export interface ExportResult {
|
|
|
103
127
|
* Warnings are collected into the result and still forwarded to `onWarn`.
|
|
104
128
|
*/
|
|
105
129
|
export declare function exportBuilt(cwd: string, options?: ExportOptions): Promise<ExportResult>;
|
|
130
|
+
export { fsAssetStore, withHostedAssets };
|
|
131
|
+
export type { AssetStore, ImageManifest };
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Why a branch cannot be pushed under its name, or null when it can. On the platform a branch
|
|
3
|
+
* is served at an address of its own (`<slug>--<branch>`), so its name must be able to be part
|
|
4
|
+
* of one: lowercase letters, digits and single hyphens. The platform checks the same (and how
|
|
5
|
+
* long the name may be for the site) — this only says it before anything is sent.
|
|
6
|
+
*/
|
|
7
|
+
export declare function branchProblem(name: string): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* `mechanica push`: publish the committed project to the platform — the branch that is checked
|
|
10
|
+
* out, under its own name. The first branch a site is pushed becomes the site itself; any
|
|
11
|
+
* other is deployed to an address of its own, with its own online editor, and never touches
|
|
12
|
+
* the site.
|
|
3
13
|
*
|
|
4
14
|
* 1. bring in what was published online since the last pull (`pull --rebase`),
|
|
5
15
|
* 2. send the uploads the platform lacks (they are not in git), then `git push`
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
import { type AssetStore } from '../server/assets-store';
|
|
1
2
|
import { type ExportOptions } from './export';
|
|
3
|
+
/**
|
|
4
|
+
* The uploads a local export reads: the project's `.mech/assets`, and — for a
|
|
5
|
+
* project linked to a hosted platform — the uploads kept there, fetched as the
|
|
6
|
+
* pages turn out to need them (and kept in `.mech/assets` when git ignores it).
|
|
7
|
+
* Only local files are *listed*: the uploads the platform holds that no page
|
|
8
|
+
* here refers to are not this export's to warn about.
|
|
9
|
+
*/
|
|
10
|
+
export declare function exportAssets(cwd: string): AssetStore;
|
|
2
11
|
/**
|
|
3
12
|
* `mechanica export`: build the project, then statically render every page
|
|
4
13
|
* into `export/`. Kept apart from `export.ts` so that module never imports
|
|
@@ -84,6 +84,25 @@ export declare function listUploads(assets: AssetStore): Promise<{
|
|
|
84
84
|
name: string;
|
|
85
85
|
src: string;
|
|
86
86
|
}[]>;
|
|
87
|
+
/** The content type a stored file is served with, when its extension says. */
|
|
88
|
+
export declare const contentTypeOf: (fileName: string) => string | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* The HTTP answer for an upload asked for by its address — the part of
|
|
91
|
+
* `/media/<name>` after the prefix, still percent-encoded. null when it is not
|
|
92
|
+
* an upload of this store, so the caller can fall through; a 400 for a name
|
|
93
|
+
* that is not valid encoding. One function for every host that serves uploads:
|
|
94
|
+
* the dev server, an editing host, a site's live host.
|
|
95
|
+
*/
|
|
96
|
+
export declare function uploadResponse(assets: AssetStore | null | undefined, encodedName: string): Promise<Response | null>;
|
|
97
|
+
/**
|
|
98
|
+
* A store for rendering a site whose uploads the host keeps and serves itself.
|
|
99
|
+
* `hosted` is what the host knows about them — a name with its image info. The
|
|
100
|
+
* result knows those names (`list`, `info`) but cannot open them: an export
|
|
101
|
+
* over it fills in their dimensions and previews, copies no bytes, and reports
|
|
102
|
+
* them as the host's to serve (see `ExportResult.uploads`). Whatever the local
|
|
103
|
+
* store has is used as before.
|
|
104
|
+
*/
|
|
105
|
+
export declare function withHostedAssets(local: AssetStore, hosted: ImageManifest): AssetStore;
|
|
87
106
|
/**
|
|
88
107
|
* Where a project's uploads also live — a hosted platform the project is linked
|
|
89
108
|
* to. Uploads made in its online editor are not in the project's directory
|
|
@@ -8,7 +8,7 @@ export { createEditorService, type EditorService, type EditorServiceOptions, typ
|
|
|
8
8
|
export { toNodeMiddleware, toAssetMiddleware, type NodeMiddleware } from './node-adapter';
|
|
9
9
|
export { fsContentFiles, memoryContentFiles, type ContentFiles, type ContentChanges, type MemoryContentFiles, type Mech, } from './content-files';
|
|
10
10
|
export { pageOfFile } from './pages-store';
|
|
11
|
-
export { fsAssetStore, withRemoteAssets, uploadName, isDerivedAsset, type AssetStore, type RemoteAssets, type RemoteAssetsOptions, type ImageManifest, type ImageManifestEntry, } from './assets-store';
|
|
11
|
+
export { fsAssetStore, withRemoteAssets, withHostedAssets, uploadResponse, contentTypeOf, isAssetName, uploadName, isDerivedAsset, type AssetStore, type RemoteAssets, type RemoteAssetsOptions, type ImageManifest, type ImageManifestEntry, } from './assets-store';
|
|
12
12
|
export { buildSiteManifest, readSiteManifest, configureSite, type SiteManifestInput } from './site';
|
|
13
13
|
export { renderEditablePage, readEditorTemplate, type EditablePageOptions } from './editor-page';
|
|
14
14
|
export { SITE_MANIFEST_FILE, EDITOR_DIST_DIR, UPLOADS_PREFIX, uploadNameOf, type SiteManifest, type EditorHostConfig, } from 'mechanica-shared';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mechanica",
|
|
3
|
-
"version": "2.1.0-beta.
|
|
3
|
+
"version": "2.1.0-beta.7",
|
|
4
4
|
"description": "Build Vue 3 websites with a visual block editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"prepublishOnly": "bun ../../scripts/ensure-bun-publish.js && bun run build"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"mechanica-shared": "2.1.0-beta.
|
|
69
|
+
"mechanica-shared": "2.1.0-beta.7",
|
|
70
70
|
"@vue/compiler-sfc": "^3.5.38",
|
|
71
71
|
"compact-json-schema": "^0.1.5",
|
|
72
72
|
"estree-walker": "^3.0.3",
|