mechanica 2.1.0-beta.7 → 2.1.0
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 +8 -1
- package/dist/chunks/{assets-nujjbCx8.js → assets-5a2WdmFg.js} +67 -45
- package/dist/chunks/{node-adapter-CSkDXYGO.js → node-adapter-Bm_SloHQ.js} +2 -2
- package/dist/chunks/{rich-text-codec-BSD35k2U.js → rich-text-codec-DCv1X0eZ.js} +8 -2
- package/dist/chunks/{site-DfazSr3_.js → site-BVqx8iKj.js} +1 -1
- package/dist/cli.js +116 -49
- package/dist/editor.css +63 -63
- package/dist/editor.js +5 -4
- package/dist/export.js +13 -5
- package/dist/plugin.js +4 -4
- package/dist/server.js +3 -3
- package/dist/types/cli/platform/api.d.ts +0 -2
- package/dist/types/cli/platform/credentials.d.ts +22 -0
- package/dist/types/cli/platform/login.d.ts +8 -1
- package/dist/types/cli/platform/session.d.ts +31 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -359,10 +359,11 @@ These drive a locally installed Chrome or Edge (or `--browser <path>`) and need
|
|
|
359
359
|
| `mechanica shot <blockId \| /path>` | Screenshot a block or a page. Flags: `--width`, `--data`, `--out`, `--full`, `--server`, `--browser` |
|
|
360
360
|
| `mechanica thumbs [--blocks]` | Regenerate page or block thumbnails for the editor |
|
|
361
361
|
| `mechanica images` | Generate image dimensions and blur-up previews for `.mech/assets` (needs `sharp`; `--force` redoes all) |
|
|
362
|
-
| `mechanica login` | Sign in to the Mechanica platform and
|
|
362
|
+
| `mechanica login` | Sign in to the Mechanica platform: it prints a link to open and approve in the browser (signing in or registering on the way) and keeps the access token for this machine. In a terminal it waits for the approval; run from a coding agent, it prints the link and returns, and the next `link` or `push` finishes the sign-in (`--wait`, `--no-wait`, `--host`, or `--token` to store a token made in the dashboard) |
|
|
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
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
|
+
| `mechanica migrate` | Bring `.mech` content written by an older version up to the current format: uploads are addressed as `/media/<file>` (2.0 wrote `/@mechanica/assets/<file>`) |
|
|
366
367
|
|
|
367
368
|
## Plugin options
|
|
368
369
|
|
|
@@ -393,6 +394,12 @@ From `mechanica`:
|
|
|
393
394
|
|
|
394
395
|
From `mechanica/plugin`: `mechanica` and the `PageProvider` type. From `mechanica/widgets`: `defineWidget` and `useWidgetServices` (uploads and the image picker inside widget editors). `mechanica/editor` and `mechanica/composer` are loaded by the plugin in development; you don't import them. From `mechanica/export`: `exportBuilt(projectDir, options)`, which statically renders an already built project (`dist/` + `.mech/`) without running a build and resolves to `{ pages, warnings }` — for render services that receive a prebuilt bundle; `options.outDir` sets where the site is written, and `options.fetchJson` replaces how `useFetch` requests are made.
|
|
395
396
|
|
|
397
|
+
## Upgrading from 2.0
|
|
398
|
+
|
|
399
|
+
- Uploaded files are addressed as `/media/<file>` in page files, shared data and rich text; 2.0 wrote `/@mechanica/assets/<file>`. The old address still works everywhere, so nothing breaks — run `npx mechanica migrate` once to rewrite it, and don't serve anything of your own under `/media/`.
|
|
400
|
+
- A file uploaded through the editor now gets a short content hash in its name (`photo-9f2c1a7b.jpg`). Files already in `.mech/assets/` keep their names.
|
|
401
|
+
- In the page browser, "Mark as draft" / "Publish" became "Hide from site" / "Show on site". `draft: true` in the page file means the same as before.
|
|
402
|
+
|
|
396
403
|
## Upgrading from 1.x
|
|
397
404
|
|
|
398
405
|
Mechanica 2 is a rewrite, and a 1.x project has to be ported by hand; there is no automatic migration. What changes:
|
|
@@ -1,44 +1,8 @@
|
|
|
1
|
-
import { G as isAssetName, J as readImageManifest, X as updateImageManifest } from "./rich-text-codec-
|
|
1
|
+
import { G as isAssetName, J as readImageManifest, X as updateImageManifest } from "./rich-text-codec-DCv1X0eZ.js";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { chmod, mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { chmod, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
-
/** Normalize a host argument to an origin (`https://example.com`, no trailing slash or path). */
|
|
7
|
-
function hostOrigin(host) {
|
|
8
|
-
const value = host ?? process.env.MECHANICA_HOST ?? "https://mechanica.jt3.ru";
|
|
9
|
-
return new URL(/^https?:\/\//.test(value) ? value : `https://${value}`).origin;
|
|
10
|
-
}
|
|
11
|
-
/** Where access tokens are kept: one file per user, outside any project. */
|
|
12
|
-
function credentialsFile() {
|
|
13
|
-
return join(process.env.MECHANICA_CONFIG_DIR ?? join(os.homedir(), ".mechanica"), "credentials.json");
|
|
14
|
-
}
|
|
15
|
-
async function readAll() {
|
|
16
|
-
try {
|
|
17
|
-
const parsed = JSON.parse(await readFile(credentialsFile(), "utf-8"));
|
|
18
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
19
|
-
} catch {
|
|
20
|
-
return {};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* The access token for a platform origin: `MECHANICA_TOKEN` (CI) wins over the
|
|
25
|
-
* one `mechanica login` saved.
|
|
26
|
-
*/
|
|
27
|
-
async function getToken(origin) {
|
|
28
|
-
if (process.env.MECHANICA_TOKEN) return process.env.MECHANICA_TOKEN;
|
|
29
|
-
return (await readAll())[origin] ?? null;
|
|
30
|
-
}
|
|
31
|
-
/** Remember the token for an origin, in a file only the user can read. */
|
|
32
|
-
async function saveToken(origin, token) {
|
|
33
|
-
const file = credentialsFile();
|
|
34
|
-
const all = await readAll();
|
|
35
|
-
all[origin] = token;
|
|
36
|
-
await mkdir(join(file, ".."), { recursive: true });
|
|
37
|
-
await writeFile(file, JSON.stringify(all, null, 2) + "\n", { mode: 384 });
|
|
38
|
-
await chmod(file, 384).catch(() => {});
|
|
39
|
-
return file;
|
|
40
|
-
}
|
|
41
|
-
//#endregion
|
|
42
6
|
//#region src/cli/platform/api.ts
|
|
43
7
|
/** A failed platform request: the HTTP status plus the message the platform gave. */
|
|
44
8
|
var PlatformError = class extends Error {
|
|
@@ -80,12 +44,6 @@ async function request(origin, method, path, options = {}) {
|
|
|
80
44
|
if (!response.ok) throw new PlatformError(response.status, errorMessage(response.status, text));
|
|
81
45
|
return text ? JSON.parse(text) : null;
|
|
82
46
|
}
|
|
83
|
-
/** The saved token for `origin`, or an error telling the user to log in. */
|
|
84
|
-
async function requireToken(origin) {
|
|
85
|
-
const token = await getToken(origin);
|
|
86
|
-
if (!token) throw new Error(`Not logged in to ${origin} — run \`mechanica login\` first`);
|
|
87
|
-
return token;
|
|
88
|
-
}
|
|
89
47
|
/** The name of the git remote `mechanica link` manages. */
|
|
90
48
|
var REMOTE_NAME = "mechanica";
|
|
91
49
|
/**
|
|
@@ -105,6 +63,70 @@ function parseRemoteUrl(url) {
|
|
|
105
63
|
return null;
|
|
106
64
|
}
|
|
107
65
|
}
|
|
66
|
+
/** Normalize a host argument to an origin (`https://example.com`, no trailing slash or path). */
|
|
67
|
+
function hostOrigin(host) {
|
|
68
|
+
const value = host ?? process.env.MECHANICA_HOST ?? "https://mechanica.jt3.ru";
|
|
69
|
+
return new URL(/^https?:\/\//.test(value) ? value : `https://${value}`).origin;
|
|
70
|
+
}
|
|
71
|
+
/** Where the CLI keeps what it knows about the user: one folder per user, outside any project. */
|
|
72
|
+
function configDir() {
|
|
73
|
+
return process.env.MECHANICA_CONFIG_DIR ?? join(os.homedir(), ".mechanica");
|
|
74
|
+
}
|
|
75
|
+
/** Access tokens, by platform origin. */
|
|
76
|
+
var credentialsFile = () => join(configDir(), "credentials.json");
|
|
77
|
+
/** Sign-ins started by `mechanica login` that wait for their approval, by platform origin. */
|
|
78
|
+
var pendingFile = () => join(configDir(), "pending-logins.json");
|
|
79
|
+
async function readJson(file) {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(await readFile(file, "utf-8"));
|
|
82
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
83
|
+
} catch {
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Write one of the files, readable by the user alone. */
|
|
88
|
+
async function writeJson(file, value) {
|
|
89
|
+
await mkdir(join(file, ".."), { recursive: true });
|
|
90
|
+
await writeFile(file, JSON.stringify(value, null, 2) + "\n", { mode: 384 });
|
|
91
|
+
await chmod(file, 384).catch(() => {});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The access token for a platform origin: `MECHANICA_TOKEN` (CI) wins over the
|
|
95
|
+
* one `mechanica login` saved.
|
|
96
|
+
*/
|
|
97
|
+
async function getToken(origin) {
|
|
98
|
+
if (process.env.MECHANICA_TOKEN) return process.env.MECHANICA_TOKEN;
|
|
99
|
+
return (await readJson(credentialsFile()))[origin] ?? null;
|
|
100
|
+
}
|
|
101
|
+
/** Remember the token for an origin, in a file only the user can read. */
|
|
102
|
+
async function saveToken(origin, token) {
|
|
103
|
+
const file = credentialsFile();
|
|
104
|
+
const all = await readJson(file);
|
|
105
|
+
all[origin] = token;
|
|
106
|
+
await writeJson(file, all);
|
|
107
|
+
return file;
|
|
108
|
+
}
|
|
109
|
+
/** The sign-in waiting for an origin, or null. An expired one is reported too: whoever reads it says so. */
|
|
110
|
+
async function getPendingLogin(origin) {
|
|
111
|
+
const entry = (await readJson(pendingFile()))[origin];
|
|
112
|
+
return entry && typeof entry.deviceCode === "string" && typeof entry.verificationUrl === "string" ? entry : null;
|
|
113
|
+
}
|
|
114
|
+
/** Keep a started sign-in for an origin (replacing an earlier one). */
|
|
115
|
+
async function savePendingLogin(origin, login) {
|
|
116
|
+
const file = pendingFile();
|
|
117
|
+
const all = await readJson(file);
|
|
118
|
+
all[origin] = login;
|
|
119
|
+
await writeJson(file, all);
|
|
120
|
+
}
|
|
121
|
+
/** Forget the sign-in waiting for an origin — it was finished, denied or has expired. */
|
|
122
|
+
async function clearPendingLogin(origin) {
|
|
123
|
+
const file = pendingFile();
|
|
124
|
+
const all = await readJson(file);
|
|
125
|
+
if (!(origin in all)) return;
|
|
126
|
+
delete all[origin];
|
|
127
|
+
if (Object.keys(all).length) await writeJson(file, all);
|
|
128
|
+
else await rm(file, { force: true });
|
|
129
|
+
}
|
|
108
130
|
//#endregion
|
|
109
131
|
//#region src/cli/platform/git.ts
|
|
110
132
|
/**
|
|
@@ -319,4 +341,4 @@ async function runAssetsPull(options = {}) {
|
|
|
319
341
|
return done;
|
|
320
342
|
}
|
|
321
343
|
//#endregion
|
|
322
|
-
export { git as a,
|
|
344
|
+
export { request as _, git as a, clearPendingLogin as c, hostOrigin as d, savePendingLogin as f, parseRemoteUrl as g, REMOTE_NAME as h, uploadsIgnored as i, getPendingLogin as l, PlatformError as m, remoteAssetsFor as n, gitAuthEnv as o, saveToken as p, runAssetsPull as r, gitOk as s, pushUploads as t, getToken as u };
|
|
@@ -1,5 +1,5 @@
|
|
|
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, 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-
|
|
1
|
+
import { n as configureSite, r as indexGeneratedPages } from "./site-BVqx8iKj.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-DCv1X0eZ.js";
|
|
3
3
|
import fs, { readFileSync, readdirSync } from "node:fs";
|
|
4
4
|
import { basename, join, resolve, sep } from "node:path";
|
|
5
5
|
import { EDITOR_DIST_DIR, mergeTranslation, parseLocalePath, passDataToHTML, resolveQueryKey, serializeState } from "mechanica-shared";
|
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import { dirname, join, parse, relative, resolve, sep } from "node:path";
|
|
3
3
|
import { UPLOADS_PREFIX as UPLOADS_PREFIX$1, diffTranslation, migrateContent, passDefaultValue, uploadNameOf, walkSchema, walkTree } from "mechanica-shared";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
|
-
import { parsePage, serializePage } from "mechanica-shared/page-format";
|
|
5
|
+
import { PageParseError, parsePage, serializePage } from "mechanica-shared/page-format";
|
|
6
6
|
import { Readable } from "node:stream";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { unfoldSchema } from "compact-json-schema";
|
|
@@ -671,7 +671,13 @@ var emptyPage = () => ({
|
|
|
671
671
|
var fileOf = (mech, urlPath, locale) => pageFile(contentFilesOf(mech), urlPath, locale);
|
|
672
672
|
var has = (mech, file) => contentFilesOf(mech).has(file);
|
|
673
673
|
var remove = (mech, file) => contentFilesOf(mech).remove(file);
|
|
674
|
-
var readFile = (mech, file) =>
|
|
674
|
+
var readFile = (mech, file) => {
|
|
675
|
+
try {
|
|
676
|
+
return parsePage(contentFilesOf(mech).read(file) ?? "", codecOptions(mech));
|
|
677
|
+
} catch (error) {
|
|
678
|
+
throw error instanceof PageParseError ? error.inFile(file) : error;
|
|
679
|
+
}
|
|
680
|
+
};
|
|
675
681
|
var writeFile = (mech, file, page) => {
|
|
676
682
|
contentFilesOf(mech).write(file, serializePage(page, codecOptions(mech)));
|
|
677
683
|
};
|
|
@@ -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-DCv1X0eZ.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 { 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-
|
|
3
|
-
import { a as git, c as
|
|
1
|
+
import { t as buildSiteManifest } from "./chunks/site-BVqx8iKj.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-DCv1X0eZ.js";
|
|
3
|
+
import { _ as request, a as git, c as clearPendingLogin, d as hostOrigin, f as savePendingLogin, g as parseRemoteUrl, h as REMOTE_NAME, i as uploadsIgnored, l as getPendingLogin, m as PlatformError, n as remoteAssetsFor, o as gitAuthEnv, p as saveToken, r as runAssetsPull, s as gitOk, t as pushUploads, u as getToken } from "./chunks/assets-5a2WdmFg.js";
|
|
4
4
|
import { exportBuilt } from "./export.js";
|
|
5
5
|
import fs, { readFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
@@ -10,7 +10,6 @@ import os from "node:os";
|
|
|
10
10
|
import { spawn } from "node:child_process";
|
|
11
11
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
12
12
|
import { build } from "vite";
|
|
13
|
-
import readline from "node:readline";
|
|
14
13
|
//#region src/cli/args.ts
|
|
15
14
|
/** Parse `argv` (without node/script) into a command, positionals and a `--flag[=value]` map. */
|
|
16
15
|
function parseArgs(argv) {
|
|
@@ -234,6 +233,89 @@ async function runMigrate(options = {}) {
|
|
|
234
233
|
return changed;
|
|
235
234
|
}
|
|
236
235
|
//#endregion
|
|
236
|
+
//#region src/cli/platform/session.ts
|
|
237
|
+
/** Start a sign-in: the platform makes a request, its codes are kept for this origin. */
|
|
238
|
+
async function startDeviceLogin(origin) {
|
|
239
|
+
const started = await request(origin, "POST", "/api/account/device", { body: { name: `CLI on ${os.hostname()}` } });
|
|
240
|
+
const pending = {
|
|
241
|
+
deviceCode: started.deviceCode,
|
|
242
|
+
userCode: started.userCode,
|
|
243
|
+
verificationUrl: started.verificationUrl,
|
|
244
|
+
expiresAt: new Date(started.expiresAt).toISOString(),
|
|
245
|
+
interval: Math.max(1, Number(started.interval) || 3)
|
|
246
|
+
};
|
|
247
|
+
await savePendingLogin(origin, pending);
|
|
248
|
+
return pending;
|
|
249
|
+
}
|
|
250
|
+
/** What the user is shown: the link, and how long it stays open. */
|
|
251
|
+
function describeDeviceLogin(origin, pending) {
|
|
252
|
+
const minutes = Math.max(1, Math.round((Date.parse(pending.expiresAt) - Date.now()) / 6e4));
|
|
253
|
+
return [
|
|
254
|
+
`To sign in to ${origin}, open this link and approve the request:`,
|
|
255
|
+
"",
|
|
256
|
+
` ${pending.verificationUrl}`,
|
|
257
|
+
"",
|
|
258
|
+
`The link is valid for ${minutes} minute${minutes === 1 ? "" : "s"}.`
|
|
259
|
+
].join("\n");
|
|
260
|
+
}
|
|
261
|
+
/** Ask the platform once whether the request was answered. */
|
|
262
|
+
async function checkDeviceLogin(origin, pending) {
|
|
263
|
+
try {
|
|
264
|
+
const answer = await request(origin, "POST", "/api/account/device/token", { body: { deviceCode: pending.deviceCode } });
|
|
265
|
+
if (answer?.status === "approved" && typeof answer.token === "string") return {
|
|
266
|
+
status: "approved",
|
|
267
|
+
token: answer.token
|
|
268
|
+
};
|
|
269
|
+
if (answer?.status === "denied") return { status: "denied" };
|
|
270
|
+
return { status: "pending" };
|
|
271
|
+
} catch (error) {
|
|
272
|
+
if (error instanceof PlatformError && error.status === 404) return { status: "expired" };
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Finish a started sign-in if it was answered: save the token and say who
|
|
278
|
+
* signed in. Null while the request still waits. A denied or expired request
|
|
279
|
+
* is forgotten and reported — the user runs `mechanica login` for a new link.
|
|
280
|
+
*/
|
|
281
|
+
async function completeDeviceLogin(origin, pending) {
|
|
282
|
+
const outcome = await checkDeviceLogin(origin, pending);
|
|
283
|
+
if (outcome.status === "pending") return null;
|
|
284
|
+
await clearPendingLogin(origin);
|
|
285
|
+
if (outcome.status === "denied") throw new Error(`The sign-in request for ${origin} was denied in the browser. Run \`mechanica login\` for a new link.`);
|
|
286
|
+
if (outcome.status === "expired") throw new Error(`The sign-in link for ${origin} has expired (a link is valid for ten minutes). Run \`mechanica login\` for a new link.`);
|
|
287
|
+
const account = await request(origin, "GET", "/api/account", { token: outcome.token });
|
|
288
|
+
const file = await saveToken(origin, outcome.token);
|
|
289
|
+
console.info(`Signed in to ${origin} as ${account.email}`);
|
|
290
|
+
console.info(`Access token saved to ${file}`);
|
|
291
|
+
return outcome.token;
|
|
292
|
+
}
|
|
293
|
+
var sleep$1 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
294
|
+
/** Wait for the approval, asking the platform every `interval` seconds until it comes or the link expires. */
|
|
295
|
+
async function waitForDeviceLogin(origin, pending) {
|
|
296
|
+
for (;;) {
|
|
297
|
+
const token = await completeDeviceLogin(origin, pending);
|
|
298
|
+
if (token) return token;
|
|
299
|
+
await sleep$1(pending.interval * 1e3);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* The token for `origin`: the saved one, or — when `mechanica login` printed
|
|
304
|
+
* a link that has been approved since — the one the platform now hands over.
|
|
305
|
+
* Otherwise an error that says what to do next.
|
|
306
|
+
*/
|
|
307
|
+
async function requireToken(origin) {
|
|
308
|
+
const token = await getToken(origin);
|
|
309
|
+
if (token) return token;
|
|
310
|
+
const pending = await getPendingLogin(origin);
|
|
311
|
+
if (pending) {
|
|
312
|
+
const collected = await completeDeviceLogin(origin, pending);
|
|
313
|
+
if (collected) return collected;
|
|
314
|
+
throw new Error(`Not signed in to ${origin} yet — open ${pending.verificationUrl} and approve the request, then run this command again`);
|
|
315
|
+
}
|
|
316
|
+
throw new Error(`Not logged in to ${origin} — run \`mechanica login\` first`);
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
237
319
|
//#region src/cli/platform/link.ts
|
|
238
320
|
/**
|
|
239
321
|
* `mechanica link <slug>`: attach this project to a site on the platform by
|
|
@@ -317,55 +399,35 @@ async function ignoreUploads(cwd) {
|
|
|
317
399
|
}
|
|
318
400
|
//#endregion
|
|
319
401
|
//#region src/cli/platform/login.ts
|
|
320
|
-
/** Ask one line on the terminal; with `hidden`, the typed characters are not echoed. */
|
|
321
|
-
function prompt(question, hidden = false) {
|
|
322
|
-
return new Promise((resolve) => {
|
|
323
|
-
const rl = readline.createInterface({
|
|
324
|
-
input: process.stdin,
|
|
325
|
-
output: process.stdout,
|
|
326
|
-
terminal: true
|
|
327
|
-
});
|
|
328
|
-
if (hidden) {
|
|
329
|
-
const write = rl._writeToOutput.bind(rl);
|
|
330
|
-
let asked = false;
|
|
331
|
-
rl._writeToOutput = (text) => {
|
|
332
|
-
if (!asked) write(text);
|
|
333
|
-
asked = true;
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
rl.question(question, (answer) => {
|
|
337
|
-
rl.close();
|
|
338
|
-
if (hidden) process.stdout.write("\n");
|
|
339
|
-
resolve(answer.trim());
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
402
|
/**
|
|
344
403
|
* `mechanica login`: sign in to the platform and keep an access token for this
|
|
345
404
|
* machine. With `--token` the given token is stored as is (CI, or a token made
|
|
346
|
-
* in the dashboard)
|
|
405
|
+
* in the dashboard). Otherwise the sign-in happens in the browser (see
|
|
406
|
+
* `session.ts`): a link is printed, and the token arrives once it is approved.
|
|
407
|
+
*
|
|
408
|
+
* In a terminal the command waits for the approval. Without one — a coding
|
|
409
|
+
* agent runs it, and shows its output only once it has ended — it prints the
|
|
410
|
+
* link and returns: the next `mechanica link` / `push` finishes the sign-in.
|
|
411
|
+
* `--wait` / `--no-wait` decide either way.
|
|
347
412
|
*/
|
|
348
413
|
async function runLogin(options) {
|
|
349
414
|
const origin = hostOrigin(options.host);
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
console.info(`
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const session = await request(origin, "POST", "/api/account/login", { body: {
|
|
357
|
-
login,
|
|
358
|
-
password
|
|
359
|
-
} });
|
|
360
|
-
token = (await request(origin, "POST", "/api/account/tokens", {
|
|
361
|
-
token: session.accessToken,
|
|
362
|
-
body: { name: `CLI on ${os.hostname()}` }
|
|
363
|
-
})).token;
|
|
415
|
+
if (options.token) {
|
|
416
|
+
const account = await request(origin, "GET", "/api/account", { token: options.token });
|
|
417
|
+
const file = await saveToken(origin, options.token);
|
|
418
|
+
console.info(`Logged in to ${origin} as ${account.email}`);
|
|
419
|
+
console.info(`Access token saved to ${file}`);
|
|
420
|
+
return;
|
|
364
421
|
}
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
console.info(
|
|
368
|
-
|
|
422
|
+
const pending = await startDeviceLogin(origin);
|
|
423
|
+
console.info(describeDeviceLogin(origin, pending));
|
|
424
|
+
console.info("");
|
|
425
|
+
if (!(options.wait ?? process.stdin.isTTY === true)) {
|
|
426
|
+
console.info("Once it is approved, run `mechanica link <slug>` or `mechanica push`: the next command finishes the sign-in.\nWorking through a coding agent? Show the link to the person you work for, and go on when they say it is approved.");
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
console.info("Waiting for the approval in the browser… (Ctrl+C to stop; the next `mechanica` command would finish the sign-in)");
|
|
430
|
+
await waitForDeviceLogin(origin, pending);
|
|
369
431
|
}
|
|
370
432
|
//#endregion
|
|
371
433
|
//#region src/cli/platform/bundle-format.ts
|
|
@@ -1237,8 +1299,12 @@ Usage:
|
|
|
1237
1299
|
--site-name <name> adds WebSite JSON-LD;
|
|
1238
1300
|
--assets-url <origin> serves /assets and /media from
|
|
1239
1301
|
a CDN base — files still land in export/)
|
|
1240
|
-
mechanica login Sign in to the Mechanica platform
|
|
1241
|
-
|
|
1302
|
+
mechanica login Sign in to the Mechanica platform: prints a link to
|
|
1303
|
+
open and approve in the browser, and keeps the access
|
|
1304
|
+
token for this machine. In a terminal it waits for the
|
|
1305
|
+
approval; otherwise the next link/push finishes the
|
|
1306
|
+
sign-in (--wait, --no-wait, --host <url>, or
|
|
1307
|
+
--token <token> to store a token made in the dashboard)
|
|
1242
1308
|
mechanica link <slug> Point this repository at a site on the platform
|
|
1243
1309
|
(--create makes the site, --name "Site name")
|
|
1244
1310
|
mechanica push Publish the committed project: pull what was edited
|
|
@@ -1288,7 +1354,8 @@ async function run(argv) {
|
|
|
1288
1354
|
return;
|
|
1289
1355
|
case "login": return runLogin({
|
|
1290
1356
|
host: str(flags.host),
|
|
1291
|
-
token: str(flags.token)
|
|
1357
|
+
token: str(flags.token),
|
|
1358
|
+
wait: flags.wait === true ? true : flags["no-wait"] === true ? false : void 0
|
|
1292
1359
|
});
|
|
1293
1360
|
case "link": return runLink(args[0], {
|
|
1294
1361
|
host: str(flags.host),
|
package/dist/editor.css
CHANGED
|
@@ -5027,7 +5027,7 @@ from {
|
|
|
5027
5027
|
justify-content: flex-end;
|
|
5028
5028
|
gap: 8px;
|
|
5029
5029
|
margin-top: 4px;
|
|
5030
|
-
}.mech-pages[data-v-
|
|
5030
|
+
}.mech-pages[data-v-56e0f852] {
|
|
5031
5031
|
display: flex;
|
|
5032
5032
|
align-items: stretch;
|
|
5033
5033
|
justify-content: center;
|
|
@@ -5036,7 +5036,7 @@ from {
|
|
|
5036
5036
|
max-width: 1200px;
|
|
5037
5037
|
height: min(620px, 82vh);
|
|
5038
5038
|
}
|
|
5039
|
-
.mech-pages__card[data-v-
|
|
5039
|
+
.mech-pages__card[data-v-56e0f852] {
|
|
5040
5040
|
display: flex;
|
|
5041
5041
|
flex-direction: column;
|
|
5042
5042
|
flex: 0 1 840px;
|
|
@@ -5046,20 +5046,20 @@ from {
|
|
|
5046
5046
|
box-shadow: var(--mech-shadow-dialog);
|
|
5047
5047
|
overflow: hidden;
|
|
5048
5048
|
}
|
|
5049
|
-
.mech-pages__header[data-v-
|
|
5049
|
+
.mech-pages__header[data-v-56e0f852] {
|
|
5050
5050
|
display: flex;
|
|
5051
5051
|
align-items: center;
|
|
5052
5052
|
gap: 10px;
|
|
5053
5053
|
padding: 18px 14px 12px 24px;
|
|
5054
5054
|
flex: none;
|
|
5055
5055
|
}
|
|
5056
|
-
.mech-pages__title[data-v-
|
|
5056
|
+
.mech-pages__title[data-v-56e0f852] {
|
|
5057
5057
|
margin: 0;
|
|
5058
5058
|
font-size: 16px;
|
|
5059
5059
|
font-weight: 600;
|
|
5060
5060
|
letter-spacing: -0.01em;
|
|
5061
5061
|
}
|
|
5062
|
-
.mech-pages__count[data-v-
|
|
5062
|
+
.mech-pages__count[data-v-56e0f852] {
|
|
5063
5063
|
padding: 2px 8px;
|
|
5064
5064
|
border-radius: var(--mech-radius-pill);
|
|
5065
5065
|
background: var(--mech-active);
|
|
@@ -5067,7 +5067,7 @@ from {
|
|
|
5067
5067
|
font-size: 11.5px;
|
|
5068
5068
|
font-weight: 600;
|
|
5069
5069
|
}
|
|
5070
|
-
.mech-pages__close[data-v-
|
|
5070
|
+
.mech-pages__close[data-v-56e0f852] {
|
|
5071
5071
|
display: flex;
|
|
5072
5072
|
align-items: center;
|
|
5073
5073
|
justify-content: center;
|
|
@@ -5080,25 +5080,25 @@ from {
|
|
|
5080
5080
|
border-radius: var(--mech-radius-pill);
|
|
5081
5081
|
cursor: pointer;
|
|
5082
5082
|
}
|
|
5083
|
-
.mech-pages__close .vicon[data-v-
|
|
5083
|
+
.mech-pages__close .vicon[data-v-56e0f852] {
|
|
5084
5084
|
width: 18px;
|
|
5085
5085
|
height: 18px;
|
|
5086
5086
|
}
|
|
5087
|
-
.mech-pages__close[data-v-
|
|
5087
|
+
.mech-pages__close[data-v-56e0f852]:hover {
|
|
5088
5088
|
background: var(--mech-hover);
|
|
5089
5089
|
color: var(--mech-fg);
|
|
5090
5090
|
}
|
|
5091
|
-
.mech-pages__toolbar[data-v-
|
|
5091
|
+
.mech-pages__toolbar[data-v-56e0f852] {
|
|
5092
5092
|
display: flex;
|
|
5093
5093
|
gap: 8px;
|
|
5094
5094
|
padding: 0 24px 12px;
|
|
5095
5095
|
flex: none;
|
|
5096
5096
|
}
|
|
5097
|
-
.mech-pages__search-wrap[data-v-
|
|
5097
|
+
.mech-pages__search-wrap[data-v-56e0f852] {
|
|
5098
5098
|
position: relative;
|
|
5099
5099
|
flex: 1;
|
|
5100
5100
|
}
|
|
5101
|
-
.mech-pages__filters[data-v-
|
|
5101
|
+
.mech-pages__filters[data-v-56e0f852] {
|
|
5102
5102
|
display: flex;
|
|
5103
5103
|
align-items: center;
|
|
5104
5104
|
justify-content: space-between;
|
|
@@ -5106,23 +5106,23 @@ from {
|
|
|
5106
5106
|
padding: 0 24px 14px;
|
|
5107
5107
|
flex: none;
|
|
5108
5108
|
}
|
|
5109
|
-
.mech-pages__sort[data-v-
|
|
5109
|
+
.mech-pages__sort[data-v-56e0f852] {
|
|
5110
5110
|
display: flex;
|
|
5111
5111
|
align-items: center;
|
|
5112
5112
|
gap: 9px;
|
|
5113
5113
|
}
|
|
5114
|
-
.mech-pages__sort-label[data-v-
|
|
5114
|
+
.mech-pages__sort-label[data-v-56e0f852] {
|
|
5115
5115
|
font-size: 10.5px;
|
|
5116
5116
|
font-weight: 600;
|
|
5117
5117
|
text-transform: uppercase;
|
|
5118
5118
|
letter-spacing: 0.05em;
|
|
5119
5119
|
color: var(--mech-muted);
|
|
5120
5120
|
}
|
|
5121
|
-
.mech-pages__toggle[data-v-
|
|
5121
|
+
.mech-pages__toggle[data-v-56e0f852] {
|
|
5122
5122
|
flex: none;
|
|
5123
5123
|
white-space: nowrap;
|
|
5124
5124
|
}
|
|
5125
|
-
.mech-pages__search-icon[data-v-
|
|
5125
|
+
.mech-pages__search-icon[data-v-56e0f852] {
|
|
5126
5126
|
position: absolute;
|
|
5127
5127
|
left: 12px;
|
|
5128
5128
|
top: 50%;
|
|
@@ -5132,18 +5132,18 @@ from {
|
|
|
5132
5132
|
color: var(--mech-muted);
|
|
5133
5133
|
pointer-events: none;
|
|
5134
5134
|
}
|
|
5135
|
-
.mech-pages__search[data-v-
|
|
5135
|
+
.mech-pages__search[data-v-56e0f852] {
|
|
5136
5136
|
width: 100%;
|
|
5137
5137
|
padding-left: 36px;
|
|
5138
5138
|
}
|
|
5139
|
-
.mech-pages__content[data-v-
|
|
5139
|
+
.mech-pages__content[data-v-56e0f852] {
|
|
5140
5140
|
display: flex;
|
|
5141
5141
|
gap: 14px;
|
|
5142
5142
|
flex: 1;
|
|
5143
5143
|
min-height: 0;
|
|
5144
5144
|
padding: 0 24px 20px;
|
|
5145
5145
|
}
|
|
5146
|
-
.mech-pages__rail[data-v-
|
|
5146
|
+
.mech-pages__rail[data-v-56e0f852] {
|
|
5147
5147
|
flex: none;
|
|
5148
5148
|
width: 172px;
|
|
5149
5149
|
display: flex;
|
|
@@ -5152,7 +5152,7 @@ from {
|
|
|
5152
5152
|
overflow-y: auto;
|
|
5153
5153
|
padding-right: 2px;
|
|
5154
5154
|
}
|
|
5155
|
-
.mech-pages__rail-item[data-v-
|
|
5155
|
+
.mech-pages__rail-item[data-v-56e0f852] {
|
|
5156
5156
|
display: flex;
|
|
5157
5157
|
align-items: center;
|
|
5158
5158
|
gap: 8px;
|
|
@@ -5166,51 +5166,51 @@ from {
|
|
|
5166
5166
|
color: var(--mech-fg-alt);
|
|
5167
5167
|
cursor: pointer;
|
|
5168
5168
|
}
|
|
5169
|
-
.mech-pages__rail-item .vicon[data-v-
|
|
5169
|
+
.mech-pages__rail-item .vicon[data-v-56e0f852] {
|
|
5170
5170
|
flex: none;
|
|
5171
5171
|
width: 15px;
|
|
5172
5172
|
height: 15px;
|
|
5173
5173
|
color: var(--mech-muted);
|
|
5174
5174
|
}
|
|
5175
|
-
.mech-pages__rail-item[data-v-
|
|
5175
|
+
.mech-pages__rail-item[data-v-56e0f852]:hover {
|
|
5176
5176
|
background: var(--mech-hover);
|
|
5177
5177
|
}
|
|
5178
|
-
.mech-pages__rail-item.is-active[data-v-
|
|
5178
|
+
.mech-pages__rail-item.is-active[data-v-56e0f852] {
|
|
5179
5179
|
background: var(--mech-accent-soft);
|
|
5180
5180
|
color: var(--mech-accent);
|
|
5181
5181
|
font-weight: 500;
|
|
5182
5182
|
}
|
|
5183
|
-
.mech-pages__rail-item.is-active .vicon[data-v-
|
|
5183
|
+
.mech-pages__rail-item.is-active .vicon[data-v-56e0f852] {
|
|
5184
5184
|
color: var(--mech-accent);
|
|
5185
5185
|
}
|
|
5186
|
-
.mech-pages__rail-name[data-v-
|
|
5186
|
+
.mech-pages__rail-name[data-v-56e0f852] {
|
|
5187
5187
|
flex: 1;
|
|
5188
5188
|
min-width: 0;
|
|
5189
5189
|
overflow: hidden;
|
|
5190
5190
|
text-overflow: ellipsis;
|
|
5191
5191
|
white-space: nowrap;
|
|
5192
5192
|
}
|
|
5193
|
-
.mech-pages__rail-count[data-v-
|
|
5193
|
+
.mech-pages__rail-count[data-v-56e0f852] {
|
|
5194
5194
|
flex: none;
|
|
5195
5195
|
font-size: 11px;
|
|
5196
5196
|
color: var(--mech-placeholder);
|
|
5197
5197
|
}
|
|
5198
|
-
.mech-pages__rail-item.is-active .mech-pages__rail-count[data-v-
|
|
5198
|
+
.mech-pages__rail-item.is-active .mech-pages__rail-count[data-v-56e0f852] {
|
|
5199
5199
|
color: var(--mech-accent);
|
|
5200
5200
|
opacity: 0.7;
|
|
5201
5201
|
}
|
|
5202
|
-
.mech-pages__list[data-v-
|
|
5202
|
+
.mech-pages__list[data-v-56e0f852] {
|
|
5203
5203
|
flex: 1;
|
|
5204
5204
|
min-width: 0;
|
|
5205
5205
|
overflow-y: auto;
|
|
5206
5206
|
}
|
|
5207
|
-
.mech-pages__row[data-v-
|
|
5207
|
+
.mech-pages__row[data-v-56e0f852], .mech-pages__thead[data-v-56e0f852] {
|
|
5208
5208
|
display: grid;
|
|
5209
5209
|
grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) 96px;
|
|
5210
5210
|
align-items: center;
|
|
5211
5211
|
column-gap: 12px;
|
|
5212
5212
|
}
|
|
5213
|
-
.mech-pages__thead[data-v-
|
|
5213
|
+
.mech-pages__thead[data-v-56e0f852] {
|
|
5214
5214
|
position: sticky;
|
|
5215
5215
|
top: 0;
|
|
5216
5216
|
z-index: 1;
|
|
@@ -5218,14 +5218,14 @@ from {
|
|
|
5218
5218
|
background: var(--mech-bg);
|
|
5219
5219
|
box-shadow: 0 1px 0 var(--mech-border);
|
|
5220
5220
|
}
|
|
5221
|
-
.mech-pages__thead span[data-v-
|
|
5221
|
+
.mech-pages__thead span[data-v-56e0f852] {
|
|
5222
5222
|
font-size: 10.5px;
|
|
5223
5223
|
font-weight: 600;
|
|
5224
5224
|
text-transform: uppercase;
|
|
5225
5225
|
letter-spacing: 0.05em;
|
|
5226
5226
|
color: var(--mech-muted);
|
|
5227
5227
|
}
|
|
5228
|
-
.mech-pages__group[data-v-
|
|
5228
|
+
.mech-pages__group[data-v-56e0f852] {
|
|
5229
5229
|
display: flex;
|
|
5230
5230
|
align-items: center;
|
|
5231
5231
|
gap: 7px;
|
|
@@ -5244,36 +5244,36 @@ from {
|
|
|
5244
5244
|
border-radius: var(--mech-radius-sm);
|
|
5245
5245
|
cursor: pointer;
|
|
5246
5246
|
}
|
|
5247
|
-
.mech-pages__group .vicon[data-v-
|
|
5247
|
+
.mech-pages__group .vicon[data-v-56e0f852] {
|
|
5248
5248
|
width: 13px;
|
|
5249
5249
|
height: 13px;
|
|
5250
5250
|
}
|
|
5251
|
-
.mech-pages__group[data-v-
|
|
5251
|
+
.mech-pages__group[data-v-56e0f852]:hover {
|
|
5252
5252
|
color: var(--mech-fg);
|
|
5253
5253
|
}
|
|
5254
|
-
.mech-pages__row[data-v-
|
|
5254
|
+
.mech-pages__row[data-v-56e0f852] {
|
|
5255
5255
|
padding: 0 10px;
|
|
5256
5256
|
height: 38px;
|
|
5257
5257
|
border-radius: var(--mech-radius-sm);
|
|
5258
5258
|
cursor: pointer;
|
|
5259
5259
|
}
|
|
5260
|
-
.mech-pages__row.is-active[data-v-
|
|
5260
|
+
.mech-pages__row.is-active[data-v-56e0f852] {
|
|
5261
5261
|
background: var(--mech-accent-soft);
|
|
5262
5262
|
}
|
|
5263
|
-
.mech-pages__cell-name[data-v-
|
|
5263
|
+
.mech-pages__cell-name[data-v-56e0f852] {
|
|
5264
5264
|
display: flex;
|
|
5265
5265
|
align-items: center;
|
|
5266
5266
|
gap: 8px;
|
|
5267
5267
|
min-width: 0;
|
|
5268
5268
|
}
|
|
5269
|
-
.mech-pages__name[data-v-
|
|
5269
|
+
.mech-pages__name[data-v-56e0f852] {
|
|
5270
5270
|
font-size: 13.5px;
|
|
5271
5271
|
font-weight: 500;
|
|
5272
5272
|
overflow: hidden;
|
|
5273
5273
|
text-overflow: ellipsis;
|
|
5274
5274
|
white-space: nowrap;
|
|
5275
5275
|
}
|
|
5276
|
-
.mech-pages__badge[data-v-
|
|
5276
|
+
.mech-pages__badge[data-v-56e0f852] {
|
|
5277
5277
|
flex: none;
|
|
5278
5278
|
font-size: 10px;
|
|
5279
5279
|
font-weight: 600;
|
|
@@ -5285,17 +5285,17 @@ from {
|
|
|
5285
5285
|
border-radius: var(--mech-radius-pill);
|
|
5286
5286
|
padding: 1px 7px;
|
|
5287
5287
|
}
|
|
5288
|
-
.mech-pages__badge.is-draft[data-v-
|
|
5288
|
+
.mech-pages__badge.is-draft[data-v-56e0f852] {
|
|
5289
5289
|
color: var(--mech-muted);
|
|
5290
5290
|
}
|
|
5291
|
-
.mech-pages__locales[data-v-
|
|
5291
|
+
.mech-pages__locales[data-v-56e0f852] {
|
|
5292
5292
|
flex: none;
|
|
5293
5293
|
display: inline-flex;
|
|
5294
5294
|
align-items: center;
|
|
5295
5295
|
gap: 3px;
|
|
5296
5296
|
margin-left: 2px;
|
|
5297
5297
|
}
|
|
5298
|
-
.mech-pages__loc[data-v-
|
|
5298
|
+
.mech-pages__loc[data-v-56e0f852] {
|
|
5299
5299
|
min-width: 15px;
|
|
5300
5300
|
padding: 1px 4px;
|
|
5301
5301
|
border-radius: var(--mech-radius-sm);
|
|
@@ -5309,12 +5309,12 @@ from {
|
|
|
5309
5309
|
letter-spacing: 0.02em;
|
|
5310
5310
|
opacity: 0.5;
|
|
5311
5311
|
}
|
|
5312
|
-
.mech-pages__loc.is-on[data-v-
|
|
5312
|
+
.mech-pages__loc.is-on[data-v-56e0f852] {
|
|
5313
5313
|
background: var(--mech-accent-soft);
|
|
5314
5314
|
color: var(--mech-accent);
|
|
5315
5315
|
opacity: 1;
|
|
5316
5316
|
}
|
|
5317
|
-
.mech-pages__cell-path[data-v-
|
|
5317
|
+
.mech-pages__cell-path[data-v-56e0f852] {
|
|
5318
5318
|
min-width: 0;
|
|
5319
5319
|
overflow: hidden;
|
|
5320
5320
|
text-overflow: ellipsis;
|
|
@@ -5322,16 +5322,16 @@ from {
|
|
|
5322
5322
|
font-size: 12.5px;
|
|
5323
5323
|
color: var(--mech-muted);
|
|
5324
5324
|
}
|
|
5325
|
-
.mech-pages__actions[data-v-
|
|
5325
|
+
.mech-pages__actions[data-v-56e0f852] {
|
|
5326
5326
|
display: flex;
|
|
5327
5327
|
justify-content: flex-end;
|
|
5328
5328
|
gap: 1px;
|
|
5329
5329
|
opacity: 0;
|
|
5330
5330
|
}
|
|
5331
|
-
.mech-pages__row.is-active .mech-pages__actions[data-v-
|
|
5331
|
+
.mech-pages__row.is-active .mech-pages__actions[data-v-56e0f852], .mech-pages__row:hover .mech-pages__actions[data-v-56e0f852] {
|
|
5332
5332
|
opacity: 1;
|
|
5333
5333
|
}
|
|
5334
|
-
.mech-pages__actions button[data-v-
|
|
5334
|
+
.mech-pages__actions button[data-v-56e0f852] {
|
|
5335
5335
|
display: flex;
|
|
5336
5336
|
align-items: center;
|
|
5337
5337
|
justify-content: center;
|
|
@@ -5344,24 +5344,24 @@ from {
|
|
|
5344
5344
|
cursor: pointer;
|
|
5345
5345
|
line-height: 1;
|
|
5346
5346
|
}
|
|
5347
|
-
.mech-pages__actions button .vicon[data-v-
|
|
5347
|
+
.mech-pages__actions button .vicon[data-v-56e0f852] {
|
|
5348
5348
|
width: 15px;
|
|
5349
5349
|
height: 15px;
|
|
5350
5350
|
}
|
|
5351
|
-
.mech-pages__actions button[data-v-
|
|
5351
|
+
.mech-pages__actions button[data-v-56e0f852]:hover {
|
|
5352
5352
|
background: var(--mech-active);
|
|
5353
5353
|
color: var(--mech-fg);
|
|
5354
5354
|
}
|
|
5355
|
-
.mech-pages__actions button.is-danger[data-v-
|
|
5355
|
+
.mech-pages__actions button.is-danger[data-v-56e0f852]:hover {
|
|
5356
5356
|
color: var(--mech-error);
|
|
5357
5357
|
}
|
|
5358
|
-
.mech-pages__empty[data-v-
|
|
5358
|
+
.mech-pages__empty[data-v-56e0f852] {
|
|
5359
5359
|
padding: 24px 10px;
|
|
5360
5360
|
margin: 0;
|
|
5361
5361
|
color: var(--mech-muted);
|
|
5362
5362
|
font-size: 13px;
|
|
5363
5363
|
}
|
|
5364
|
-
.mech-pages__preview[data-v-
|
|
5364
|
+
.mech-pages__preview[data-v-56e0f852] {
|
|
5365
5365
|
flex: none;
|
|
5366
5366
|
align-self: flex-start;
|
|
5367
5367
|
max-height: 100%;
|
|
@@ -5373,18 +5373,18 @@ from {
|
|
|
5373
5373
|
box-shadow: var(--mech-shadow-dialog);
|
|
5374
5374
|
overflow: hidden;
|
|
5375
5375
|
}
|
|
5376
|
-
.mech-pages__preview-frame[data-v-
|
|
5376
|
+
.mech-pages__preview-frame[data-v-56e0f852] {
|
|
5377
5377
|
flex: 0 1 auto;
|
|
5378
5378
|
min-height: 0;
|
|
5379
5379
|
overflow: hidden;
|
|
5380
5380
|
background: var(--mech-app-bg);
|
|
5381
5381
|
}
|
|
5382
|
-
.mech-pages__preview-frame img[data-v-
|
|
5382
|
+
.mech-pages__preview-frame img[data-v-56e0f852] {
|
|
5383
5383
|
display: block;
|
|
5384
5384
|
width: 100%;
|
|
5385
5385
|
height: auto;
|
|
5386
5386
|
}
|
|
5387
|
-
.mech-pages__preview-empty[data-v-
|
|
5387
|
+
.mech-pages__preview-empty[data-v-56e0f852] {
|
|
5388
5388
|
display: flex;
|
|
5389
5389
|
flex-direction: column;
|
|
5390
5390
|
align-items: center;
|
|
@@ -5393,16 +5393,16 @@ from {
|
|
|
5393
5393
|
padding: 48px 16px;
|
|
5394
5394
|
color: var(--mech-muted);
|
|
5395
5395
|
}
|
|
5396
|
-
.mech-pages__preview-empty p[data-v-
|
|
5396
|
+
.mech-pages__preview-empty p[data-v-56e0f852] {
|
|
5397
5397
|
margin: 8px 0 0;
|
|
5398
5398
|
font-size: 13px;
|
|
5399
5399
|
font-weight: 500;
|
|
5400
5400
|
}
|
|
5401
|
-
.mech-pages__preview-empty code[data-v-
|
|
5401
|
+
.mech-pages__preview-empty code[data-v-56e0f852] {
|
|
5402
5402
|
font-size: 11.5px;
|
|
5403
5403
|
color: var(--mech-placeholder);
|
|
5404
5404
|
}
|
|
5405
|
-
.mech-pages__preview-monogram[data-v-
|
|
5405
|
+
.mech-pages__preview-monogram[data-v-56e0f852] {
|
|
5406
5406
|
display: flex;
|
|
5407
5407
|
align-items: center;
|
|
5408
5408
|
justify-content: center;
|
|
@@ -5413,7 +5413,7 @@ from {
|
|
|
5413
5413
|
font-size: 22px;
|
|
5414
5414
|
font-weight: 600;
|
|
5415
5415
|
}
|
|
5416
|
-
.mech-pages__preview-caption[data-v-
|
|
5416
|
+
.mech-pages__preview-caption[data-v-56e0f852] {
|
|
5417
5417
|
flex: none;
|
|
5418
5418
|
display: flex;
|
|
5419
5419
|
flex-direction: column;
|
|
@@ -5421,21 +5421,21 @@ from {
|
|
|
5421
5421
|
padding: 12px 16px 14px;
|
|
5422
5422
|
border-top: 1px solid var(--mech-border);
|
|
5423
5423
|
}
|
|
5424
|
-
.mech-pages__preview-name[data-v-
|
|
5424
|
+
.mech-pages__preview-name[data-v-56e0f852] {
|
|
5425
5425
|
font-size: 13px;
|
|
5426
5426
|
font-weight: 600;
|
|
5427
5427
|
overflow: hidden;
|
|
5428
5428
|
text-overflow: ellipsis;
|
|
5429
5429
|
white-space: nowrap;
|
|
5430
5430
|
}
|
|
5431
|
-
.mech-pages__preview-path[data-v-
|
|
5431
|
+
.mech-pages__preview-path[data-v-56e0f852] {
|
|
5432
5432
|
font-size: 11.5px;
|
|
5433
5433
|
color: var(--mech-muted);
|
|
5434
5434
|
overflow: hidden;
|
|
5435
5435
|
text-overflow: ellipsis;
|
|
5436
5436
|
white-space: nowrap;
|
|
5437
5437
|
}
|
|
5438
|
-
.mech-pages__preview-tag[data-v-
|
|
5438
|
+
.mech-pages__preview-tag[data-v-56e0f852] {
|
|
5439
5439
|
display: inline-flex;
|
|
5440
5440
|
align-items: center;
|
|
5441
5441
|
gap: 5px;
|
|
@@ -5449,13 +5449,13 @@ from {
|
|
|
5449
5449
|
color: var(--mech-fg-alt);
|
|
5450
5450
|
background: var(--mech-active);
|
|
5451
5451
|
}
|
|
5452
|
-
.mech-pages__preview-tag .vicon[data-v-
|
|
5452
|
+
.mech-pages__preview-tag .vicon[data-v-56e0f852] {
|
|
5453
5453
|
width: 12px;
|
|
5454
5454
|
height: 12px;
|
|
5455
5455
|
color: var(--mech-muted);
|
|
5456
5456
|
}
|
|
5457
5457
|
@media (max-width: 1160px) {
|
|
5458
|
-
.mech-pages__preview[data-v-
|
|
5458
|
+
.mech-pages__preview[data-v-56e0f852] {
|
|
5459
5459
|
display: none;
|
|
5460
5460
|
}
|
|
5461
5461
|
}.mech-pagebar[data-v-43756991] {
|
package/dist/editor.js
CHANGED
|
@@ -2133,7 +2133,8 @@ var _hoisted_18 = { class: "mech-pages__cell-name" };
|
|
|
2133
2133
|
var _hoisted_19 = { class: "mech-pages__name" };
|
|
2134
2134
|
var _hoisted_20 = {
|
|
2135
2135
|
key: 0,
|
|
2136
|
-
class: "mech-pages__badge is-draft"
|
|
2136
|
+
class: "mech-pages__badge is-draft",
|
|
2137
|
+
title: "Editable, but not on the site"
|
|
2137
2138
|
};
|
|
2138
2139
|
var _hoisted_21 = {
|
|
2139
2140
|
key: 1,
|
|
@@ -2318,7 +2319,7 @@ var PagesDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
|
|
|
2318
2319
|
onClick: () => startDuplicate(page)
|
|
2319
2320
|
},
|
|
2320
2321
|
{
|
|
2321
|
-
label: page.draft ? "
|
|
2322
|
+
label: page.draft ? "Show on site" : "Hide from site",
|
|
2322
2323
|
separatorBefore: true,
|
|
2323
2324
|
onClick: () => void toggleDraft(page)
|
|
2324
2325
|
},
|
|
@@ -2467,7 +2468,7 @@ var PagesDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
|
|
|
2467
2468
|
}, [
|
|
2468
2469
|
createElementVNode("span", _hoisted_18, [
|
|
2469
2470
|
createElementVNode("span", _hoisted_19, toDisplayString(page.name || page.path), 1),
|
|
2470
|
-
page.draft ? (openBlock(), createElementBlock("span", _hoisted_20, "
|
|
2471
|
+
page.draft ? (openBlock(), createElementBlock("span", _hoisted_20, "Hidden")) : createCommentVNode("", true),
|
|
2471
2472
|
page.generated ? (openBlock(), createElementBlock("span", _hoisted_21, "Generated")) : createCommentVNode("", true),
|
|
2472
2473
|
page.path === currentLogical.value ? (openBlock(), createElementBlock("span", _hoisted_22, "Current")) : createCommentVNode("", true),
|
|
2473
2474
|
unref(localeConfig) && page.locales ? (openBlock(), createElementBlock("span", _hoisted_23, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(localeCodes), (code) => {
|
|
@@ -2519,7 +2520,7 @@ var PagesDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
|
|
|
2519
2520
|
])) : createCommentVNode("", true)])]);
|
|
2520
2521
|
};
|
|
2521
2522
|
}
|
|
2522
|
-
}), [["__scopeId", "data-v-
|
|
2523
|
+
}), [["__scopeId", "data-v-56e0f852"]]);
|
|
2523
2524
|
//#endregion
|
|
2524
2525
|
//#region src/editor/components/PageBar.vue?vue&type=script&setup=true&lang.ts
|
|
2525
2526
|
var _hoisted_1$3 = { class: "mech-pagebar__icon" };
|
package/dist/export.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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-
|
|
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-DCv1X0eZ.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";
|
|
5
|
-
import { parsePage } from "mechanica-shared/page-format";
|
|
5
|
+
import { PageParseError, parsePage } from "mechanica-shared/page-format";
|
|
6
6
|
import { access, copyFile, cp, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
7
7
|
import { pathToFileURL } from "node:url";
|
|
8
8
|
//#region src/cli/export.ts
|
|
@@ -13,6 +13,14 @@ function setHtmlLang(html, lang) {
|
|
|
13
13
|
if (/<html\b[^>]*\blang\s*=/i.test(html)) return html;
|
|
14
14
|
return html.replace(/<html\b([^>]*)>/i, `<html$1 lang="${lang}">`);
|
|
15
15
|
}
|
|
16
|
+
/** Parse a page file's text, naming the file (relative to `.mech`) in a parse error. */
|
|
17
|
+
function parsePageFile(raw, file, richText) {
|
|
18
|
+
try {
|
|
19
|
+
return parsePage(raw, richText ? { richText } : void 0);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
throw error instanceof PageParseError ? error.inFile(file) : error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
16
24
|
/** Read every page JSON under `<mech>/pages` as an exportable page. */
|
|
17
25
|
async function readPages(pagesDir, foldersData = {}, richText) {
|
|
18
26
|
let entries;
|
|
@@ -30,7 +38,7 @@ async function readPages(pagesDir, foldersData = {}, richText) {
|
|
|
30
38
|
const base = parsed.base.slice(0, -8);
|
|
31
39
|
if (VARIANT_STEM_RE.test(base)) continue;
|
|
32
40
|
const filePath = join(pagesDir, relative);
|
|
33
|
-
const file =
|
|
41
|
+
const file = parsePageFile(await readFile(filePath, "utf-8"), `pages/${relative.replace(/\\/g, "/")}`, richText);
|
|
34
42
|
if (file.draft) continue;
|
|
35
43
|
const path = `/${dir}/${base === "index" ? "" : base}`.replace("//", "/").replace(/\/$/, "") || "/";
|
|
36
44
|
const data = {
|
|
@@ -71,9 +79,9 @@ async function readTranslation(mechDir, base, locale, config, richText) {
|
|
|
71
79
|
} catch {
|
|
72
80
|
return null;
|
|
73
81
|
}
|
|
74
|
-
const doc = parsePage(raw, richText ? { richText } : void 0);
|
|
75
|
-
if (doc.draft) return null;
|
|
76
82
|
const rel = relative(join(mechDir, "pages"), file).replace(/\\/g, "/");
|
|
83
|
+
const doc = parsePageFile(raw, `pages/${rel}`, richText);
|
|
84
|
+
if (doc.draft) return null;
|
|
77
85
|
const dir = dirname(rel) === "." ? "" : dirname(rel);
|
|
78
86
|
let content = doc.content ?? [];
|
|
79
87
|
let pageData = doc.data ?? {};
|
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 { W as fsAssetStore, et as withRemoteAssets, k as pageUrlOf, tt as wasRecentlyMutated } from "./chunks/rich-text-codec-
|
|
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-BVqx8iKj.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-Bm_SloHQ.js";
|
|
3
|
+
import { W as fsAssetStore, et as withRemoteAssets, k as pageUrlOf, tt as wasRecentlyMutated } from "./chunks/rich-text-codec-DCv1X0eZ.js";
|
|
4
|
+
import { i as uploadsIgnored, n as remoteAssetsFor } from "./chunks/assets-5a2WdmFg.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 { $ 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-
|
|
1
|
+
import { i as readSiteManifest, n as configureSite, t as buildSiteManifest } from "./chunks/site-BVqx8iKj.js";
|
|
2
|
+
import { a as renderEditablePage, i as readEditorTemplate, n as toNodeMiddleware, r as createEditorService, t as toAssetMiddleware } from "./chunks/node-adapter-Bm_SloHQ.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-DCv1X0eZ.js";
|
|
4
4
|
import { EDITOR_DIST_DIR, SITE_MANIFEST_FILE, UPLOADS_PREFIX, uploadNameOf } from "mechanica-shared";
|
|
5
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 };
|
|
@@ -12,8 +12,6 @@ export interface RequestOptions {
|
|
|
12
12
|
}
|
|
13
13
|
/** One request to the platform API; resolves with the parsed JSON body (or null). */
|
|
14
14
|
export declare function request<T = any>(origin: string, method: string, path: string, options?: RequestOptions): Promise<T>;
|
|
15
|
-
/** The saved token for `origin`, or an error telling the user to log in. */
|
|
16
|
-
export declare function requireToken(origin: string): Promise<string>;
|
|
17
15
|
export interface PlatformSite {
|
|
18
16
|
uuid: string;
|
|
19
17
|
slug: string;
|
|
@@ -9,3 +9,25 @@ export declare function hostOrigin(host: string | undefined): string;
|
|
|
9
9
|
export declare function getToken(origin: string): Promise<string | null>;
|
|
10
10
|
/** Remember the token for an origin, in a file only the user can read. */
|
|
11
11
|
export declare function saveToken(origin: string, token: string): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* A sign-in started by `mechanica login` and not yet approved in the browser.
|
|
14
|
+
* The device code is the secret the platform hands the token to; the user
|
|
15
|
+
* code is what the link carries. Kept so that the next command can finish
|
|
16
|
+
* the sign-in once the link was approved — a coding agent runs `login`,
|
|
17
|
+
* shows the link, and goes on with `link` or `push` after the user's click.
|
|
18
|
+
*/
|
|
19
|
+
export interface PendingLogin {
|
|
20
|
+
deviceCode: string;
|
|
21
|
+
userCode: string;
|
|
22
|
+
verificationUrl: string;
|
|
23
|
+
/** ISO date: when the platform forgets the request. */
|
|
24
|
+
expiresAt: string;
|
|
25
|
+
/** How often the platform wants to be asked, in seconds. */
|
|
26
|
+
interval: number;
|
|
27
|
+
}
|
|
28
|
+
/** The sign-in waiting for an origin, or null. An expired one is reported too: whoever reads it says so. */
|
|
29
|
+
export declare function getPendingLogin(origin: string): Promise<PendingLogin | null>;
|
|
30
|
+
/** Keep a started sign-in for an origin (replacing an earlier one). */
|
|
31
|
+
export declare function savePendingLogin(origin: string, login: PendingLogin): Promise<void>;
|
|
32
|
+
/** Forget the sign-in waiting for an origin — it was finished, denied or has expired. */
|
|
33
|
+
export declare function clearPendingLogin(origin: string): Promise<void>;
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `mechanica login`: sign in to the platform and keep an access token for this
|
|
3
3
|
* machine. With `--token` the given token is stored as is (CI, or a token made
|
|
4
|
-
* in the dashboard)
|
|
4
|
+
* in the dashboard). Otherwise the sign-in happens in the browser (see
|
|
5
|
+
* `session.ts`): a link is printed, and the token arrives once it is approved.
|
|
6
|
+
*
|
|
7
|
+
* In a terminal the command waits for the approval. Without one — a coding
|
|
8
|
+
* agent runs it, and shows its output only once it has ended — it prints the
|
|
9
|
+
* link and returns: the next `mechanica link` / `push` finishes the sign-in.
|
|
10
|
+
* `--wait` / `--no-wait` decide either way.
|
|
5
11
|
*/
|
|
6
12
|
export declare function runLogin(options: {
|
|
7
13
|
host?: string;
|
|
8
14
|
token?: string;
|
|
15
|
+
wait?: boolean;
|
|
9
16
|
}): Promise<void>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type PendingLogin } from './credentials';
|
|
2
|
+
/** Start a sign-in: the platform makes a request, its codes are kept for this origin. */
|
|
3
|
+
export declare function startDeviceLogin(origin: string): Promise<PendingLogin>;
|
|
4
|
+
/** What the user is shown: the link, and how long it stays open. */
|
|
5
|
+
export declare function describeDeviceLogin(origin: string, pending: PendingLogin): string;
|
|
6
|
+
export type DeviceLoginOutcome = {
|
|
7
|
+
status: 'pending';
|
|
8
|
+
} | {
|
|
9
|
+
status: 'approved';
|
|
10
|
+
token: string;
|
|
11
|
+
} | {
|
|
12
|
+
status: 'denied';
|
|
13
|
+
} | {
|
|
14
|
+
status: 'expired';
|
|
15
|
+
};
|
|
16
|
+
/** Ask the platform once whether the request was answered. */
|
|
17
|
+
export declare function checkDeviceLogin(origin: string, pending: PendingLogin): Promise<DeviceLoginOutcome>;
|
|
18
|
+
/**
|
|
19
|
+
* Finish a started sign-in if it was answered: save the token and say who
|
|
20
|
+
* signed in. Null while the request still waits. A denied or expired request
|
|
21
|
+
* is forgotten and reported — the user runs `mechanica login` for a new link.
|
|
22
|
+
*/
|
|
23
|
+
export declare function completeDeviceLogin(origin: string, pending: PendingLogin): Promise<string | null>;
|
|
24
|
+
/** Wait for the approval, asking the platform every `interval` seconds until it comes or the link expires. */
|
|
25
|
+
export declare function waitForDeviceLogin(origin: string, pending: PendingLogin): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* The token for `origin`: the saved one, or — when `mechanica login` printed
|
|
28
|
+
* a link that has been approved since — the one the platform now hands over.
|
|
29
|
+
* Otherwise an error that says what to do next.
|
|
30
|
+
*/
|
|
31
|
+
export declare function requireToken(origin: string): Promise<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mechanica",
|
|
3
|
-
"version": "2.1.0
|
|
3
|
+
"version": "2.1.0",
|
|
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
|
|
69
|
+
"mechanica-shared": "2.1.0",
|
|
70
70
|
"@vue/compiler-sfc": "^3.5.38",
|
|
71
71
|
"compact-json-schema": "^0.1.5",
|
|
72
72
|
"estree-walker": "^3.0.3",
|