gutterpress 0.11.23-alpha.4 → 0.11.23-alpha.6
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/api/index.d.ts +5 -3
- package/dist/api/index.js +17 -7
- package/dist/{build-c48eer6f.js → build-py643c5a.js} +8 -8
- package/dist/{cli-93mkaw6v.js → cli-09jj8w5g.js} +63 -31
- package/dist/{cli-a35w7wzg.js → cli-31anr0r9.js} +107 -56
- package/dist/{cli-y6d1arem.js → cli-55br530w.js} +4 -4
- package/dist/{cli-54xt7pjg.js → cli-58fsk6d7.js} +2 -2
- package/dist/{cli-d9mm3vvh.js → cli-bnf7eb38.js} +1 -1
- package/dist/{cli-gnpea9dx.js → cli-qzkq9em8.js} +1 -1
- package/dist/{cli-pspjxnc8.js → cli-tf9tw6at.js} +1 -1
- package/dist/{cli-rqh295j9.js → cli-x777v272.js} +3 -3
- package/dist/cli.js +12 -12
- package/dist/{doctor-ptb346k8.js → doctor-tyrzqphh.js} +3 -3
- package/dist/{engine-4rzdx6af.js → engine-4rabsgwq.js} +1 -1
- package/dist/{engine-6txhxmmv.js → engine-wm4fggac.js} +2 -2
- package/dist/{ext-gy8szg3x.js → ext-70kt3eft.js} +8 -8
- package/dist/{extension-restore-m8tj43e7.js → extension-restore-fjfn1hrk.js} +4 -4
- package/dist/{extension-restore-dymzcasz.js → extension-restore-whag4sm0.js} +2 -2
- package/dist/{index-8ywkd2sv.js → index-1zqkfzcd.js} +3 -3
- package/dist/{index-5kh4c78h.js → index-2vxzxyyj.js} +2 -2
- package/dist/{index-kaks3mm2.js → index-cmakyf43.js} +3 -3
- package/dist/{index-h6yk5tjx.js → index-cw03e9p4.js} +107 -56
- package/dist/{index-ea94zbq4.js → index-ejbfetdn.js} +327 -86
- package/dist/{index-yc3xj266.js → index-wm4x7xbf.js} +1 -1
- package/dist/index.js +18 -8
- package/dist/lib/publish/connect.d.ts +8 -1
- package/dist/lib/publish/manifest-publish.d.ts +26 -2
- package/dist/lib/publish/selections.d.ts +12 -1
- package/dist/lib/publish/types.d.ts +15 -5
- package/dist/lib/remote-auth/repair.d.ts +2 -2
- package/dist/lib/remote-auth/revisions.d.ts +60 -0
- package/dist/lib/remote-auth/scorched-earth.d.ts +2 -2
- package/dist/lib/remote-auth/sync-messages.d.ts +28 -27
- package/dist/lib/remote-auth/sync-types.d.ts +3 -0
- package/dist/lib/remote-auth/sync.d.ts +7 -8
- package/dist/lib/remote-auth/transport.d.ts +8 -1
- package/dist/lib/source-provider.d.ts +80 -35
- package/dist/{manifest.schema-w86c1xw1.json → manifest.schema-93sd7zje.json} +13 -6
- package/dist/{new-t2t28ccb.js → new-b27kyr02.js} +11 -11
- package/dist/{plugins-fec8t2bh.js → plugins-racab3cj.js} +1 -1
- package/dist/{plugins-sqa4msdk.js → plugins-vpx7c53c.js} +3 -3
- package/dist/{preflight-srq8fktp.js → preflight-akdqz9v8.js} +8 -8
- package/dist/{preview-zsp9hstd.js → preview-bck9f88w.js} +8 -8
- package/dist/{preview-interface-nnmrxyqm.js → preview-interface-0xdh0r5b.js} +3 -66
- package/dist/{publish-hhy31gr9.js → publish-keyp8rh4.js} +8 -8
- package/dist/render.js +2 -2
- package/dist/schema/manifest.types.d.ts +18 -3
- package/dist/{source-provider-knmcam50.js → source-provider-n7vehh6t.js} +15 -3
- package/dist/{source-provider-98k5deda.js → source-provider-tgzet3j5.js} +15 -3
- package/dist/{validate-r9jdz85h.js → validate-z28cvr5x.js} +8 -8
- package/package.json +1 -1
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
validatePageMargin,
|
|
38
38
|
withFetchTimeout,
|
|
39
39
|
writeManifestDoc
|
|
40
|
-
} from "./index-
|
|
40
|
+
} from "./index-cmakyf43.js";
|
|
41
41
|
import {
|
|
42
42
|
EXTENSION_MANIFEST_FILENAME,
|
|
43
43
|
GUTTERPRESS_CSS,
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
setLogLevel,
|
|
74
74
|
slugify,
|
|
75
75
|
warn
|
|
76
|
-
} from "./index-
|
|
76
|
+
} from "./index-1zqkfzcd.js";
|
|
77
77
|
import {
|
|
78
78
|
blackTextToGray
|
|
79
79
|
} from "./index-ht1bcqdd.js";
|
|
@@ -84,7 +84,7 @@ import {
|
|
|
84
84
|
getAssetPath,
|
|
85
85
|
lastPageMode,
|
|
86
86
|
resolvePage
|
|
87
|
-
} from "./index-
|
|
87
|
+
} from "./index-2vxzxyyj.js";
|
|
88
88
|
import {
|
|
89
89
|
BuildError
|
|
90
90
|
} from "./index-46ycxe6r.js";
|
|
@@ -115,18 +115,23 @@ import {
|
|
|
115
115
|
spawnCapture
|
|
116
116
|
} from "./index-bt0qws5c.js";
|
|
117
117
|
import {
|
|
118
|
+
NO_VERSION_HISTORY,
|
|
119
|
+
assertFreeRevisionName,
|
|
118
120
|
errorLogData,
|
|
119
121
|
gitFs,
|
|
120
122
|
gitScopeFor,
|
|
121
123
|
hasPendingChanges,
|
|
122
124
|
hasUncommittedChanges,
|
|
125
|
+
isContained,
|
|
123
126
|
listWorkdirChanges,
|
|
127
|
+
readRevisionRefs,
|
|
124
128
|
resolveGitAuthor,
|
|
125
129
|
resolveLogger,
|
|
130
|
+
revisionNameFrom,
|
|
126
131
|
snapshotStagingMarkerPath,
|
|
127
132
|
snapshotWorkingTreeUnlocked,
|
|
128
133
|
withRepoLock
|
|
129
|
-
} from "./index-
|
|
134
|
+
} from "./index-cw03e9p4.js";
|
|
130
135
|
import {
|
|
131
136
|
EXTENSIONS_DIR,
|
|
132
137
|
resolveVendoredPluginInstallRoot,
|
|
@@ -153,21 +158,21 @@ import { randomBytes } from "node:crypto";
|
|
|
153
158
|
import { readdir as readdir2, readFile as readFile2, writeFile, mkdir } from "node:fs/promises";
|
|
154
159
|
|
|
155
160
|
// src/lib/remote-auth/sync-messages.ts
|
|
156
|
-
var MSG_UP_TO_DATE = "
|
|
157
|
-
var MSG_UP_TO_DATE_PULLED = "
|
|
161
|
+
var MSG_UP_TO_DATE = "You're up to date with the online copy.";
|
|
162
|
+
var MSG_UP_TO_DATE_PULLED = "You're up to date. The latest changes from the online copy were downloaded to this computer.";
|
|
158
163
|
var MSG_SYNCED = "Your changes are online.";
|
|
159
164
|
var MSG_SYNCED_MERGED = "Your changes are online, combined with changes from the online copy.";
|
|
160
|
-
var MSG_OFFLINE = "Your changes are saved on this computer. Gutterpress couldn't reach the online
|
|
161
|
-
var MSG_AUTH = "The online
|
|
162
|
-
var MSG_INSECURE_TRANSPORT = "This book's online address isn't secure, so the saved
|
|
163
|
-
var MSG_BUSY = "The online copy is changing very quickly right now. Your work is saved on this computer — try
|
|
164
|
-
var MSG_HISTORY_UNREADABLE =
|
|
165
|
-
var MSG_UNRELATED =
|
|
166
|
-
var MSG_NO_REMOTE = "This book
|
|
167
|
-
var MSG_SSH_REMOTE = "This book's online
|
|
168
|
-
var MSG_NO_BRANCH = "This book
|
|
169
|
-
var SYNC_SNAPSHOT_MESSAGE = "Automatic
|
|
170
|
-
var SYNC_LATE_EDIT_MESSAGE = "Saved the edit you made while
|
|
165
|
+
var MSG_OFFLINE = "Your changes are saved on this computer. Gutterpress couldn't reach the online copy — try again when you're back online.";
|
|
166
|
+
var MSG_AUTH = "The online copy didn't accept the saved sign-in. Sign in again and try again.";
|
|
167
|
+
var MSG_INSECURE_TRANSPORT = "This book's online copy is at an address that isn't secure, so the saved sign-in wasn't sent — sign-ins are never sent over an insecure address. Switch the address to a secure one (starting with https), or to a local loopback address for a server on this computer, to back up.";
|
|
168
|
+
var MSG_BUSY = "The online copy is changing very quickly right now. Your work is saved on this computer — try again in a moment.";
|
|
169
|
+
var MSG_HISTORY_UNREADABLE = `This book's versions can't be read, so backing up can't continue. Your writing is safe — every file is still here on this computer. Use "Repair the online copy" (in Book setup → Online copy) to get versions and backing up working again.`;
|
|
170
|
+
var MSG_UNRELATED = `This book and the online copy have no versions in common, so they can't be combined. Either the online copy's address points at a different book, or this book's own versions were lost and started over. Your writing is safe — every file is still here on this computer. Check the online copy's address; if it is correct, use "Repair the online copy" (in Book setup → Online copy).`;
|
|
171
|
+
var MSG_NO_REMOTE = "This book doesn't have an online copy yet.";
|
|
172
|
+
var MSG_SSH_REMOTE = "This book's online copy uses an SSH address (git@…), which Gutterpress can't back up to. Switch it to the web (HTTPS) address to back up from here.";
|
|
173
|
+
var MSG_NO_BRANCH = "This book isn't on a named revision, so it can't be backed up right now.";
|
|
174
|
+
var SYNC_SNAPSHOT_MESSAGE = "Automatic version before backing up";
|
|
175
|
+
var SYNC_LATE_EDIT_MESSAGE = "Saved the edit you made while backing up";
|
|
171
176
|
function onlineSiblingPath(filepath) {
|
|
172
177
|
const dot = filepath.lastIndexOf(".");
|
|
173
178
|
const slash = filepath.lastIndexOf("/");
|
|
@@ -4019,8 +4024,8 @@ function withoutOnlineTag(relPath) {
|
|
|
4019
4024
|
}
|
|
4020
4025
|
var check27 = {
|
|
4021
4026
|
id: "source.sync.merge-markers",
|
|
4022
|
-
name: "Combined
|
|
4023
|
-
description: "Finds passages and files still holding two
|
|
4027
|
+
name: "Combined Takes",
|
|
4028
|
+
description: "Finds passages and files still holding two takes (yours and the online copy's) after getting the latest changes",
|
|
4024
4029
|
category: "source",
|
|
4025
4030
|
phase: "pre-build",
|
|
4026
4031
|
async run(ctx) {
|
|
@@ -4046,7 +4051,7 @@ var check27 = {
|
|
|
4046
4051
|
results.push(finding(check27.id, {
|
|
4047
4052
|
severity: "error",
|
|
4048
4053
|
code: "two-versions-passage",
|
|
4049
|
-
message: "This passage has two
|
|
4054
|
+
message: "This passage has two takes — yours and the online copy's. Choose one in the editor's Two takes panel, or keep the text you want and delete the marker lines.",
|
|
4050
4055
|
file,
|
|
4051
4056
|
line: i + 1
|
|
4052
4057
|
}));
|
|
@@ -4055,7 +4060,7 @@ var check27 = {
|
|
|
4055
4060
|
results.push(finding(check27.id, {
|
|
4056
4061
|
severity: "error",
|
|
4057
4062
|
code: "leftover-version-marker",
|
|
4058
|
-
message: "This marker line is left over from combining two
|
|
4063
|
+
message: "This marker line is left over from combining two takes — delete it.",
|
|
4059
4064
|
file,
|
|
4060
4065
|
line: i + 1
|
|
4061
4066
|
}));
|
|
@@ -4076,7 +4081,7 @@ var check27 = {
|
|
|
4076
4081
|
results.push(finding(check27.id, {
|
|
4077
4082
|
severity: "warning",
|
|
4078
4083
|
code: "kept-both-versions",
|
|
4079
|
-
message: `Two
|
|
4084
|
+
message: `Two takes of ${withoutOnlineTag(rel)} are in your book — keep the one you want, then delete the other.`,
|
|
4080
4085
|
file: sibling
|
|
4081
4086
|
}));
|
|
4082
4087
|
}
|
|
@@ -5527,7 +5532,7 @@ class PdfOutput {
|
|
|
5527
5532
|
const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
|
|
5528
5533
|
await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
|
|
5529
5534
|
log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
|
|
5530
|
-
const { buildNativePdf } = await import("./engine-
|
|
5535
|
+
const { buildNativePdf } = await import("./engine-wm4fggac.js");
|
|
5531
5536
|
const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
|
|
5532
5537
|
title: config.title,
|
|
5533
5538
|
author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
|
|
@@ -7356,7 +7361,7 @@ async function scaffoldProject(options) {
|
|
|
7356
7361
|
let versionHistoryError;
|
|
7357
7362
|
if (requested === "local-git") {
|
|
7358
7363
|
try {
|
|
7359
|
-
const { providerFor } = await import("./source-provider-
|
|
7364
|
+
const { providerFor } = await import("./source-provider-tgzet3j5.js");
|
|
7360
7365
|
const provider = providerFor({ type: "local-folder", path: projectDir });
|
|
7361
7366
|
await provider.initVersionHistory({
|
|
7362
7367
|
projectDir,
|
|
@@ -7368,7 +7373,7 @@ async function scaffoldProject(options) {
|
|
|
7368
7373
|
versionHistory = "none";
|
|
7369
7374
|
const { findEnclosingRepoDir } = await import("./project-source-ekcyp63q.js");
|
|
7370
7375
|
const enclosingRepoDir = await findEnclosingRepoDir(projectDir);
|
|
7371
|
-
versionHistoryError = enclosingRepoDir ? `This book was added to ${path14.basename(enclosingRepoDir)}'s shared version history; save a
|
|
7376
|
+
versionHistoryError = enclosingRepoDir ? `This book was added to ${path14.basename(enclosingRepoDir)}'s shared version history; save a version to record it.` : e instanceof Error ? e.message : String(e);
|
|
7372
7377
|
}
|
|
7373
7378
|
}
|
|
7374
7379
|
const result = {
|
|
@@ -7447,7 +7452,7 @@ styles:
|
|
|
7447
7452
|
let versionHistoryError;
|
|
7448
7453
|
if (requested === "local-git") {
|
|
7449
7454
|
try {
|
|
7450
|
-
const { providerFor } = await import("./source-provider-
|
|
7455
|
+
const { providerFor } = await import("./source-provider-tgzet3j5.js");
|
|
7451
7456
|
const provider = providerFor({ type: "local-folder", path: dir });
|
|
7452
7457
|
await provider.initVersionHistory({
|
|
7453
7458
|
projectDir: dir,
|
|
@@ -8644,7 +8649,7 @@ function isCredentialTransmissionSafe(url) {
|
|
|
8644
8649
|
class InsecureTransportError extends Error {
|
|
8645
8650
|
code = "InsecureTransport";
|
|
8646
8651
|
constructor() {
|
|
8647
|
-
super("This online address isn't secure, so the saved
|
|
8652
|
+
super("This online copy's address isn't secure, so the saved sign-in wasn't sent — " + "sign-ins are never sent over an insecure address. Switch the address " + "to a secure one (starting with https) to use a saved sign-in.");
|
|
8648
8653
|
this.name = "InsecureTransportError";
|
|
8649
8654
|
}
|
|
8650
8655
|
}
|
|
@@ -8726,7 +8731,7 @@ function failureOutcome(e, snapshotId) {
|
|
|
8726
8731
|
}
|
|
8727
8732
|
return {
|
|
8728
8733
|
status: "error",
|
|
8729
|
-
message: "
|
|
8734
|
+
message: "Backing up didn't finish. Your work is saved on this computer — please try again.",
|
|
8730
8735
|
...base
|
|
8731
8736
|
};
|
|
8732
8737
|
}
|
|
@@ -8805,8 +8810,11 @@ async function fetchRemoteTip(dir, branch, transport, http2, cache2) {
|
|
|
8805
8810
|
const code = e?.code;
|
|
8806
8811
|
if (code === "NoRefspecError")
|
|
8807
8812
|
return null;
|
|
8813
|
+
if (code === "NotFoundError" && e.data?.what === branch) {
|
|
8814
|
+
return null;
|
|
8815
|
+
}
|
|
8808
8816
|
if (code === "NotFoundError" || e?.data?.statusCode === 404) {
|
|
8809
|
-
const err = new Error("The online
|
|
8817
|
+
const err = new Error("The online copy couldn't be reached with the saved sign-in. Sign in again and try again.", { cause: e });
|
|
8810
8818
|
err.code = "HttpError";
|
|
8811
8819
|
err.data = { statusCode: 401 };
|
|
8812
8820
|
throw err;
|
|
@@ -8814,6 +8822,16 @@ async function fetchRemoteTip(dir, branch, transport, http2, cache2) {
|
|
|
8814
8822
|
throw e;
|
|
8815
8823
|
}
|
|
8816
8824
|
}
|
|
8825
|
+
async function serverTip(transport, branch, http2) {
|
|
8826
|
+
const refs = await git2.listServerRefs({
|
|
8827
|
+
http: http2,
|
|
8828
|
+
url: transport.url,
|
|
8829
|
+
prefix: `refs/heads/${branch}`,
|
|
8830
|
+
...onAuthFor(transport.credential),
|
|
8831
|
+
...transport.credential ? { onAuthFailure: () => ({ cancel: true }) } : {}
|
|
8832
|
+
});
|
|
8833
|
+
return refs.find((r) => r.ref === `refs/heads/${branch}`)?.oid;
|
|
8834
|
+
}
|
|
8817
8835
|
function short(oid) {
|
|
8818
8836
|
return oid ? oid.slice(0, 8) : "none";
|
|
8819
8837
|
}
|
|
@@ -9827,7 +9845,7 @@ var API_BASE2 = "https://api.github.com";
|
|
|
9827
9845
|
var REQUEST_TIMEOUT_MS3 = 15000;
|
|
9828
9846
|
var PER_PAGE = 100;
|
|
9829
9847
|
var MAX_PAGES = 50;
|
|
9830
|
-
var RECONNECT_MESSAGE2 = "Your GitHub
|
|
9848
|
+
var RECONNECT_MESSAGE2 = "Your GitHub sign-in has expired. Sign in to GitHub again and try again.";
|
|
9831
9849
|
async function apiGet(fetchImpl, url, token) {
|
|
9832
9850
|
const res = await withFetchTimeout({ timeoutMs: REQUEST_TIMEOUT_MS3, offlineMessage: OFFLINE_MESSAGE }, (signal) => fetchImpl(url, { method: "GET", headers: githubApiHeaders(token), signal }));
|
|
9833
9851
|
if (res.status === 401 || res.status === 403) {
|
|
@@ -10341,6 +10359,7 @@ async function syncProject(options) {
|
|
|
10341
10359
|
return {
|
|
10342
10360
|
status: "up-to-date",
|
|
10343
10361
|
message: pulled ? MSG_UP_TO_DATE_PULLED : MSG_UP_TO_DATE,
|
|
10362
|
+
pushDeferred: true,
|
|
10344
10363
|
...convergeExtras(),
|
|
10345
10364
|
...base()
|
|
10346
10365
|
};
|
|
@@ -10435,14 +10454,7 @@ async function checkRemoteUpdates(options) {
|
|
|
10435
10454
|
...options.tokenStore ? { tokenStore: options.tokenStore } : {}
|
|
10436
10455
|
});
|
|
10437
10456
|
const branch = await currentBranchOrThrow(dir);
|
|
10438
|
-
const
|
|
10439
|
-
http: http3,
|
|
10440
|
-
url: transport.url,
|
|
10441
|
-
prefix: `refs/heads/${branch}`,
|
|
10442
|
-
...onAuthFor(transport.credential),
|
|
10443
|
-
...transport.credential ? { onAuthFailure: () => ({ cancel: true }) } : {}
|
|
10444
|
-
});
|
|
10445
|
-
const remoteTip = refs.find((r) => r.ref === `refs/heads/${branch}`)?.oid;
|
|
10457
|
+
const remoteTip = await serverTip(transport, branch, http3);
|
|
10446
10458
|
if (!remoteTip)
|
|
10447
10459
|
return { available: false };
|
|
10448
10460
|
const known = async (ref) => {
|
|
@@ -10473,20 +10485,20 @@ var API_BASE3 = "https://api.github.com";
|
|
|
10473
10485
|
var REQUEST_TIMEOUT_MS4 = 15000;
|
|
10474
10486
|
var MAX_NAME_LENGTH = 100;
|
|
10475
10487
|
var MSG = {
|
|
10476
|
-
notConnected: "Connect your GitHub account first (Settings > Accounts), then set up online
|
|
10477
|
-
auth: "GitHub didn't accept the saved
|
|
10488
|
+
notConnected: "Connect your GitHub account first (Settings > Accounts), then set up the online copy.",
|
|
10489
|
+
auth: "GitHub didn't accept the saved sign-in. Sign in to GitHub again in Settings > Accounts and try again.",
|
|
10478
10490
|
offline: "Gutterpress couldn't reach GitHub. Check your internet connection and try again. Nothing was changed.",
|
|
10479
|
-
noHistory: "Turn on version history for this book first.
|
|
10491
|
+
noHistory: "Turn on version history for this book first. The online copy holds the versions Gutterpress keeps on this computer.",
|
|
10480
10492
|
alreadyHasRemote: "This book already has an online copy.",
|
|
10481
10493
|
noName: "Give the online copy a name.",
|
|
10482
|
-
badName: "
|
|
10483
|
-
notFound: "Gutterpress couldn't find that
|
|
10484
|
-
noPermission: "Your GitHub account isn't allowed to add to that
|
|
10485
|
-
noCreatePermission: "GitHub wouldn't let Gutterpress create
|
|
10486
|
-
notEmpty: "That
|
|
10487
|
-
pushFailed: "Your book couldn't be
|
|
10494
|
+
badName: "An online copy's name can only use letters, numbers, hyphens (-), underscores (_) and dots (.), and be at most 100 characters.",
|
|
10495
|
+
notFound: "Gutterpress couldn't find that online copy on GitHub, or your account can't see it. Choose another one.",
|
|
10496
|
+
noPermission: "Your GitHub account isn't allowed to add to that online copy (it may be archived or read-only). Choose another one.",
|
|
10497
|
+
noCreatePermission: "GitHub wouldn't let Gutterpress create an online copy with this sign-in. Create an empty one on github.com yourself (GitHub calls it a repository), then choose it from your existing empty online copies here.",
|
|
10498
|
+
notEmpty: "That online copy already has files in it, and a new online copy needs to be empty. Choose an empty one, or create a new one.",
|
|
10499
|
+
pushFailed: "Your book couldn't be sent to GitHub. Your writing is safe on this computer. Please try again."
|
|
10488
10500
|
};
|
|
10489
|
-
var nameTaken = (name) => `You already have
|
|
10501
|
+
var nameTaken = (name) => `You already have an online copy named "${name}" on GitHub. Pick a different name, or choose that one from your existing empty online copies.`;
|
|
10490
10502
|
|
|
10491
10503
|
class BackupFailure extends Error {
|
|
10492
10504
|
reason;
|
|
@@ -10528,7 +10540,7 @@ async function createRepository(fetchImpl, token, name, isPrivate) {
|
|
|
10528
10540
|
name,
|
|
10529
10541
|
private: isPrivate,
|
|
10530
10542
|
auto_init: false,
|
|
10531
|
-
description: "Online
|
|
10543
|
+
description: "Online copy made with Gutterpress"
|
|
10532
10544
|
});
|
|
10533
10545
|
if (res.status === 201 || res.status === 200)
|
|
10534
10546
|
return await res.json();
|
|
@@ -10541,7 +10553,7 @@ async function createRepository(fetchImpl, token, name, isPrivate) {
|
|
|
10541
10553
|
const taken = (body.errors ?? []).some((e) => /already exists/i.test(e.message ?? ""));
|
|
10542
10554
|
throw new BackupFailure("name-taken", taken ? nameTaken(name) : MSG.badName);
|
|
10543
10555
|
}
|
|
10544
|
-
throw new BackupFailure("push-failed", `GitHub couldn't create the
|
|
10556
|
+
throw new BackupFailure("push-failed", `GitHub couldn't create the online copy (error ${res.status}). Please try again.`);
|
|
10545
10557
|
}
|
|
10546
10558
|
async function loadEmptyRepository(fetchImpl, credential, owner, name) {
|
|
10547
10559
|
const path21 = `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`;
|
|
@@ -10561,7 +10573,7 @@ async function loadEmptyRepository(fetchImpl, credential, owner, name) {
|
|
|
10561
10573
|
}
|
|
10562
10574
|
const branches = await listGitHubBranches(credential, owner, name, { fetchImpl }).catch((e) => {
|
|
10563
10575
|
const msg = e instanceof Error ? e.message : "";
|
|
10564
|
-
throw new BackupFailure(/
|
|
10576
|
+
throw new BackupFailure(/sign in/i.test(msg) ? "auth" : /reach/i.test(msg) ? "offline" : "push-failed", msg || MSG.pushFailed);
|
|
10565
10577
|
});
|
|
10566
10578
|
if (branches.length > 0)
|
|
10567
10579
|
throw new BackupFailure("not-empty", MSG.notEmpty, toRemoteRepository(repo));
|
|
@@ -10652,14 +10664,14 @@ async function assertCloneTarget(dir) {
|
|
|
10652
10664
|
}
|
|
10653
10665
|
function friendlyCloneError(e) {
|
|
10654
10666
|
if (isInsecureTransportError(e)) {
|
|
10655
|
-
return new Error("That
|
|
10667
|
+
return new Error("That address isn't secure, so the saved sign-in wasn't sent — sign-ins are never sent over an insecure address. Use a secure address (starting with https), or a local loopback address for a server on this computer.", { cause: e });
|
|
10656
10668
|
}
|
|
10657
10669
|
const msg = e instanceof Error ? e.message : String(e);
|
|
10658
10670
|
if (/401|403|auth|credential/i.test(msg)) {
|
|
10659
|
-
return new Error("GitHub didn't accept the
|
|
10671
|
+
return new Error("GitHub didn't accept the saved sign-in for this book. Sign in to GitHub again and try again.", { cause: e });
|
|
10660
10672
|
}
|
|
10661
10673
|
if (/404|not found/i.test(msg)) {
|
|
10662
|
-
return new Error("That
|
|
10674
|
+
return new Error("That online copy couldn't be found. It may have been renamed or you may no longer have access.", { cause: e });
|
|
10663
10675
|
}
|
|
10664
10676
|
if (/ENOTFOUND|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|network|fetch failed/i.test(msg)) {
|
|
10665
10677
|
return new Error(OFFLINE_MESSAGE, { cause: e });
|
|
@@ -10678,10 +10690,10 @@ async function cloneRepository(options) {
|
|
|
10678
10690
|
try {
|
|
10679
10691
|
parsed = new URL(options.url);
|
|
10680
10692
|
} catch {
|
|
10681
|
-
throw new Error("That
|
|
10693
|
+
throw new Error("That address is not a valid web address.");
|
|
10682
10694
|
}
|
|
10683
10695
|
if (!/^https?:$/.test(parsed.protocol)) {
|
|
10684
|
-
throw new Error("Only
|
|
10696
|
+
throw new Error("Only secure web (https) addresses are supported. SSH addresses (git@…) can't be used here.");
|
|
10685
10697
|
}
|
|
10686
10698
|
const { cleanUrl, credential: urlCredential } = extractUrlCredential(options.url);
|
|
10687
10699
|
const credential = options.credential ?? urlCredential;
|
|
@@ -10740,11 +10752,11 @@ function isSshRemoteUrl(url) {
|
|
|
10740
10752
|
return /^[\w.-]+@[\w.][\w.-]*:/.test(trimmed) || /^[\w.-]+@\[/.test(trimmed);
|
|
10741
10753
|
}
|
|
10742
10754
|
var FAILURE_MESSAGES = {
|
|
10743
|
-
auth: "The Git server didn't accept the saved
|
|
10744
|
-
"not-found": "The server answered, but no
|
|
10755
|
+
auth: "The Git server didn't accept the saved sign-in. Sign in to this server again with a current access token and try again.",
|
|
10756
|
+
"not-found": "The server answered, but no online copy was found at that address. It may have been moved, renamed, or you may no longer have access.",
|
|
10745
10757
|
unreachable: "Couldn't reach the Git server. Check your internet connection (and VPN, if this is a private server), then try again.",
|
|
10746
|
-
"ssh-unsupported": "This book's online
|
|
10747
|
-
"insecure-transport": "This address isn't secure, so the saved
|
|
10758
|
+
"ssh-unsupported": "This book's online copy uses an SSH address (git@…), which Gutterpress can't check or back up to. Everything on this computer still works — back up with your usual Git tool.",
|
|
10759
|
+
"insecure-transport": "This address isn't secure, so the saved sign-in wasn't sent — sign-ins are never sent over an insecure address. Switch the address to a secure one (starting with https), or to a local loopback address for a server on this computer, to use a saved sign-in.",
|
|
10748
10760
|
tls: "The server's security certificate couldn't be verified. If this is a private server with its own certificate, ask its administrator about trusting it (NODE_EXTRA_CA_CERTS).",
|
|
10749
10761
|
unknown: "The connection test failed unexpectedly. The server may not be a Git server, or it may be temporarily unavailable."
|
|
10750
10762
|
};
|
|
@@ -10848,7 +10860,7 @@ function connectError(result, host) {
|
|
|
10848
10860
|
case "tls":
|
|
10849
10861
|
return new Error(result.message);
|
|
10850
10862
|
case "not-found":
|
|
10851
|
-
return new Error("The server answered, but that
|
|
10863
|
+
return new Error("The server answered, but that online copy wasn't found. Check its address and that the token has access to it.");
|
|
10852
10864
|
default:
|
|
10853
10865
|
return new Error(`Couldn't verify the connection to ${host}. Check the server address and try again.`);
|
|
10854
10866
|
}
|
|
@@ -10858,6 +10870,9 @@ async function connectGenericHost(input, options = {}) {
|
|
|
10858
10870
|
if (!host) {
|
|
10859
10871
|
throw new Error("Enter your Git server's web address (like https://git.example.com).");
|
|
10860
10872
|
}
|
|
10873
|
+
if (host === GITHUB_HOST) {
|
|
10874
|
+
throw new Error("GitHub has its own sign-in. Use Connect GitHub instead of a Git server.");
|
|
10875
|
+
}
|
|
10861
10876
|
const token = input.token?.trim();
|
|
10862
10877
|
if (!token) {
|
|
10863
10878
|
throw new Error("Paste an access token from your Git server to connect.");
|
|
@@ -10979,11 +10994,171 @@ async function diagnoseProjectRemote(projectDir, options = {}) {
|
|
|
10979
10994
|
guidance
|
|
10980
10995
|
};
|
|
10981
10996
|
}
|
|
10982
|
-
// src/lib/remote-auth/
|
|
10997
|
+
// src/lib/remote-auth/revisions.ts
|
|
10983
10998
|
import git9 from "isomorphic-git";
|
|
10999
|
+
function onlineFailure(e, unchanged) {
|
|
11000
|
+
const setup = setupErrorMessage(e);
|
|
11001
|
+
if (setup)
|
|
11002
|
+
return new Error(setup, { cause: e });
|
|
11003
|
+
switch (classifyTransportFailure(e)) {
|
|
11004
|
+
case "network_unavailable":
|
|
11005
|
+
return new Error(`Couldn't reach the online copy, so ${unchanged}. Try again when you're back online.`, { cause: e });
|
|
11006
|
+
case "auth_required":
|
|
11007
|
+
return new Error(`The online copy didn't accept the saved sign-in, so ${unchanged}. Sign in again and try again.`, { cause: e });
|
|
11008
|
+
case "insecure_transport":
|
|
11009
|
+
return new Error(MSG_INSECURE_TRANSPORT, { cause: e });
|
|
11010
|
+
default:
|
|
11011
|
+
return new Error(`The online copy didn't allow that, so ${unchanged}. Some online copies don't allow changing their main revision.`, { cause: e });
|
|
11012
|
+
}
|
|
11013
|
+
}
|
|
11014
|
+
function localTip(refs, name) {
|
|
11015
|
+
const tip = refs.local.get(name);
|
|
11016
|
+
if (tip)
|
|
11017
|
+
return tip;
|
|
11018
|
+
throw new Error(refs.online.has(name) ? `"${name}" is only in the online copy so far. Switch to it first.` : `Couldn't find a revision named "${name}" — it may have been renamed or deleted.`);
|
|
11019
|
+
}
|
|
11020
|
+
async function reachOnline(dir, name, tip, open, options, unchanged) {
|
|
11021
|
+
const http3 = options.httpClient ?? defaultGitHttp;
|
|
11022
|
+
let transport;
|
|
11023
|
+
let onlineTip;
|
|
11024
|
+
try {
|
|
11025
|
+
transport = await resolveTransport(dir, options);
|
|
11026
|
+
onlineTip = await serverTip(transport, name, http3);
|
|
11027
|
+
} catch (e) {
|
|
11028
|
+
throw onlineFailure(e, unchanged);
|
|
11029
|
+
}
|
|
11030
|
+
if (!onlineTip)
|
|
11031
|
+
return null;
|
|
11032
|
+
if (!await isContained(dir, onlineTip, tip, {})) {
|
|
11033
|
+
throw new Error(`The online copy has versions of "${name}" that this computer doesn't have yet. ` + `${open ? "Get" : `Switch to "${name}" and get`} the latest first, then try again.`);
|
|
11034
|
+
}
|
|
11035
|
+
return { transport, http: http3 };
|
|
11036
|
+
}
|
|
11037
|
+
async function sendRef(dir, { transport, http: http3 }, ref, remoteName, remove2 = false) {
|
|
11038
|
+
await git9.push({
|
|
11039
|
+
fs: gitFs,
|
|
11040
|
+
http: http3,
|
|
11041
|
+
dir,
|
|
11042
|
+
remote: transport.remote,
|
|
11043
|
+
ref,
|
|
11044
|
+
remoteRef: `refs/heads/${remoteName}`,
|
|
11045
|
+
delete: remove2,
|
|
11046
|
+
...onAuthFor(transport.credential)
|
|
11047
|
+
});
|
|
11048
|
+
if (remove2)
|
|
11049
|
+
await git9.deleteRef({ fs: gitFs, dir, ref: `refs/remotes/${transport.remote}/${remoteName}` });
|
|
11050
|
+
}
|
|
11051
|
+
async function renameRevision(options) {
|
|
11052
|
+
const source = await detectProjectSource(options.projectDir);
|
|
11053
|
+
if (source.type !== "local-git-folder")
|
|
11054
|
+
throw new Error(NO_VERSION_HISTORY);
|
|
11055
|
+
const dir = gitScopeFor(source);
|
|
11056
|
+
const { from } = options;
|
|
11057
|
+
const to = revisionNameFrom(options.to);
|
|
11058
|
+
return withRepoLock(dir, async () => {
|
|
11059
|
+
const refs = await readRevisionRefs(dir);
|
|
11060
|
+
const tip = localTip(refs, from);
|
|
11061
|
+
const current = refs.current === from ? to : refs.current;
|
|
11062
|
+
if (to === from)
|
|
11063
|
+
return { current, name: to };
|
|
11064
|
+
await assertFreeRevisionName(dir, to);
|
|
11065
|
+
const unchanged = `"${from}" wasn't renamed`;
|
|
11066
|
+
const online = refs.online.has(from) ? await reachOnline(dir, from, tip, refs.current === from, options, unchanged) : null;
|
|
11067
|
+
if (online) {
|
|
11068
|
+
const here = `refs/heads/${from}`;
|
|
11069
|
+
try {
|
|
11070
|
+
await sendRef(dir, online, here, to);
|
|
11071
|
+
} catch (e) {
|
|
11072
|
+
throw onlineFailure(e, unchanged);
|
|
11073
|
+
}
|
|
11074
|
+
try {
|
|
11075
|
+
await sendRef(dir, online, here, from, true);
|
|
11076
|
+
} catch (e) {
|
|
11077
|
+
const undone = await sendRef(dir, online, `refs/remotes/${online.transport.remote}/${to}`, to, true).then(() => true, () => false);
|
|
11078
|
+
throw undone ? onlineFailure(e, unchanged) : new Error(`"${from}" couldn't be renamed in the online copy, which now has both "${from}" and "${to}". ` + `Your work is safe on this computer. Delete the one you don't want, or try again later.`, { cause: e });
|
|
11079
|
+
}
|
|
11080
|
+
}
|
|
11081
|
+
await git9.renameBranch({ fs: gitFs, dir, ref: to, oldref: from });
|
|
11082
|
+
return { current, name: to };
|
|
11083
|
+
});
|
|
11084
|
+
}
|
|
11085
|
+
async function countVersionsOnlyIn(dir, tip, others, limit = 5000) {
|
|
11086
|
+
const cache2 = {};
|
|
11087
|
+
const waiting = new Map;
|
|
11088
|
+
const visited = new Set;
|
|
11089
|
+
const reach = async (oid, shared) => {
|
|
11090
|
+
const known = waiting.get(oid);
|
|
11091
|
+
if (known) {
|
|
11092
|
+
known.shared ||= shared;
|
|
11093
|
+
return;
|
|
11094
|
+
}
|
|
11095
|
+
if (visited.has(oid))
|
|
11096
|
+
return;
|
|
11097
|
+
const read = await git9.readCommit({ fs: gitFs, dir, cache: cache2, oid }).catch(() => {
|
|
11098
|
+
return;
|
|
11099
|
+
});
|
|
11100
|
+
if (read) {
|
|
11101
|
+
waiting.set(oid, { time: read.commit.committer.timestamp, parents: read.commit.parent, shared });
|
|
11102
|
+
}
|
|
11103
|
+
};
|
|
11104
|
+
await git9.readCommit({ fs: gitFs, dir, cache: cache2, oid: tip });
|
|
11105
|
+
await reach(tip, false);
|
|
11106
|
+
for (const oid of others)
|
|
11107
|
+
await reach(oid, true);
|
|
11108
|
+
let onlyHere = 0;
|
|
11109
|
+
for (let walked = 0;walked < limit; walked++) {
|
|
11110
|
+
const entries = [...waiting];
|
|
11111
|
+
if (entries.every(([, v]) => v.shared))
|
|
11112
|
+
break;
|
|
11113
|
+
const [oid, version] = entries.reduce((a, b) => b[1].time > a[1].time ? b : a);
|
|
11114
|
+
waiting.delete(oid);
|
|
11115
|
+
visited.add(oid);
|
|
11116
|
+
if (!version.shared)
|
|
11117
|
+
onlyHere++;
|
|
11118
|
+
for (const parent of version.parents)
|
|
11119
|
+
await reach(parent, version.shared);
|
|
11120
|
+
}
|
|
11121
|
+
return onlyHere;
|
|
11122
|
+
}
|
|
11123
|
+
async function deleteRevision(options) {
|
|
11124
|
+
const source = await detectProjectSource(options.projectDir);
|
|
11125
|
+
if (source.type !== "local-git-folder")
|
|
11126
|
+
throw new Error(NO_VERSION_HISTORY);
|
|
11127
|
+
const dir = gitScopeFor(source);
|
|
11128
|
+
const { name } = options;
|
|
11129
|
+
return withRepoLock(dir, async () => {
|
|
11130
|
+
const refs = await readRevisionRefs(dir);
|
|
11131
|
+
if (name === refs.current) {
|
|
11132
|
+
throw new Error(`You're working on "${name}" right now. Switch to another revision first, then delete it.`);
|
|
11133
|
+
}
|
|
11134
|
+
const tip = localTip(refs, name);
|
|
11135
|
+
const everywhere = options.everywhere === true && refs.online.has(name);
|
|
11136
|
+
const online = everywhere ? await reachOnline(dir, name, tip, false, options, `"${name}" wasn't deleted`) : null;
|
|
11137
|
+
if (!options.discard) {
|
|
11138
|
+
const others = [
|
|
11139
|
+
...[...refs.local].filter(([n]) => n !== name),
|
|
11140
|
+
...[...refs.online].filter(([n]) => !(everywhere && n === name))
|
|
11141
|
+
].map(([, otherTip]) => otherTip);
|
|
11142
|
+
const versionsOnlyHere = await countVersionsOnlyIn(dir, tip, others);
|
|
11143
|
+
if (versionsOnlyHere > 0)
|
|
11144
|
+
return { deleted: false, versionsOnlyHere };
|
|
11145
|
+
}
|
|
11146
|
+
if (online) {
|
|
11147
|
+
try {
|
|
11148
|
+
await sendRef(dir, online, `refs/heads/${name}`, name, true);
|
|
11149
|
+
} catch (e) {
|
|
11150
|
+
throw onlineFailure(e, `"${name}" wasn't deleted`);
|
|
11151
|
+
}
|
|
11152
|
+
}
|
|
11153
|
+
await git9.deleteBranch({ fs: gitFs, dir, ref: name });
|
|
11154
|
+
return { deleted: true };
|
|
11155
|
+
});
|
|
11156
|
+
}
|
|
11157
|
+
// src/lib/remote-auth/repair.ts
|
|
11158
|
+
import git10 from "isomorphic-git";
|
|
10984
11159
|
import { cp as cp4, mkdir as mkdir13, rename as rename3, rm as rm4 } from "node:fs/promises";
|
|
10985
11160
|
import path22 from "node:path";
|
|
10986
|
-
var REPAIR_SNAPSHOT_MESSAGE = "Repaired online
|
|
11161
|
+
var REPAIR_SNAPSHOT_MESSAGE = "Repaired the online copy";
|
|
10987
11162
|
async function moveDir(from, to) {
|
|
10988
11163
|
await mkdir13(path22.dirname(to), { recursive: true });
|
|
10989
11164
|
try {
|
|
@@ -11005,7 +11180,7 @@ async function repairOnlineBackup(options) {
|
|
|
11005
11180
|
const transport = await resolveTransport(dir, options);
|
|
11006
11181
|
let branch;
|
|
11007
11182
|
try {
|
|
11008
|
-
branch = await
|
|
11183
|
+
branch = await git10.currentBranch({ fs: gitFs, dir }) ?? undefined;
|
|
11009
11184
|
} catch {
|
|
11010
11185
|
branch = undefined;
|
|
11011
11186
|
}
|
|
@@ -11031,10 +11206,10 @@ async function repairOnlineBackup(options) {
|
|
|
11031
11206
|
const ref = fresh.branch ?? "HEAD";
|
|
11032
11207
|
let missing = [];
|
|
11033
11208
|
try {
|
|
11034
|
-
const tracked = await
|
|
11209
|
+
const tracked = await git10.listFiles({ fs: gitFs, dir, ref });
|
|
11035
11210
|
missing = tracked.filter((f) => !gitFs.existsSync(path22.join(dir, f)));
|
|
11036
11211
|
if (missing.length > 0) {
|
|
11037
|
-
await
|
|
11212
|
+
await git10.checkout({ fs: gitFs, dir, ref, filepaths: missing, force: true });
|
|
11038
11213
|
logger.info("restore", "restored files missing on this computer", { files: missing });
|
|
11039
11214
|
}
|
|
11040
11215
|
} catch (e) {
|
|
@@ -11061,7 +11236,7 @@ async function repairOnlineBackup(options) {
|
|
|
11061
11236
|
return { outcome, movedGitTo, restoredFiles };
|
|
11062
11237
|
}
|
|
11063
11238
|
// src/lib/remote-auth/scorched-earth.ts
|
|
11064
|
-
import
|
|
11239
|
+
import git11 from "isomorphic-git";
|
|
11065
11240
|
import { cp as cp5, mkdir as mkdir14, readdir as readdir10, rm as rm5 } from "node:fs/promises";
|
|
11066
11241
|
import path23 from "node:path";
|
|
11067
11242
|
async function emptyDir(dir) {
|
|
@@ -11087,7 +11262,7 @@ async function scorchedEarth(options) {
|
|
|
11087
11262
|
const transport2 = await resolveTransport(dir, options);
|
|
11088
11263
|
let branch2;
|
|
11089
11264
|
try {
|
|
11090
|
-
branch2 = await
|
|
11265
|
+
branch2 = await git11.currentBranch({ fs: gitFs, dir }) ?? undefined;
|
|
11091
11266
|
} catch {
|
|
11092
11267
|
branch2 = undefined;
|
|
11093
11268
|
}
|
|
@@ -12417,7 +12592,7 @@ function publishProviderFor(id) {
|
|
|
12417
12592
|
}
|
|
12418
12593
|
|
|
12419
12594
|
// src/lib/publish/plugin-provider.ts
|
|
12420
|
-
var RESERVED_SETTINGS = new Set(["format", "credential"]);
|
|
12595
|
+
var RESERVED_SETTINGS = new Set(["format", "credential", "enabled"]);
|
|
12421
12596
|
var isBuiltIn = (id) => listPublishProviders().some((p) => p.id === id);
|
|
12422
12597
|
var messageOf = (e) => e instanceof Error ? e.message : String(e);
|
|
12423
12598
|
async function bookExtensions(book) {
|
|
@@ -12473,7 +12648,7 @@ async function resolvePublishProvider(id, book) {
|
|
|
12473
12648
|
const ext = await bookExtensions(book);
|
|
12474
12649
|
const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
|
|
12475
12650
|
if (npmEntry) {
|
|
12476
|
-
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-
|
|
12651
|
+
const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-whag4sm0.js");
|
|
12477
12652
|
await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
|
|
12478
12653
|
}
|
|
12479
12654
|
const publishers = await discover(ext);
|
|
@@ -12511,7 +12686,7 @@ function infoFor(p) {
|
|
|
12511
12686
|
}
|
|
12512
12687
|
function pluginProvider(p) {
|
|
12513
12688
|
let loading;
|
|
12514
|
-
const load = () => loading ??= import("./plugins-
|
|
12689
|
+
const load = () => loading ??= import("./plugins-racab3cj.js").then((m) => m.loadPublishFunction(p));
|
|
12515
12690
|
return {
|
|
12516
12691
|
info: infoFor(p),
|
|
12517
12692
|
async authenticate() {
|
|
@@ -12578,7 +12753,10 @@ async function requestFor(provider, options, deps) {
|
|
|
12578
12753
|
const { manifest, manifestDir } = await loadManifestWithPath(options.manifestPath ?? options.projectDir, { explicit: options.manifestPath !== undefined });
|
|
12579
12754
|
const config = resolveConfig({}, manifest);
|
|
12580
12755
|
const publishSettings = manifest.publish ?? {};
|
|
12581
|
-
const providerConfig =
|
|
12756
|
+
const providerConfig = {
|
|
12757
|
+
...publishSettings[provider.info.id] ?? {},
|
|
12758
|
+
...(await deps.selections?.settings(options.projectDir))?.[provider.info.id] ?? {}
|
|
12759
|
+
};
|
|
12582
12760
|
const bookAccount = typeof providerConfig.credential === "string" ? providerConfig.credential.trim() : "";
|
|
12583
12761
|
const effectiveAccount = bookAccount || deps.credentialAccount;
|
|
12584
12762
|
const effectiveDeps = effectiveAccount ? { ...deps, credentialAccount: effectiveAccount } : deps;
|
|
@@ -12754,11 +12932,20 @@ async function connectPublishProvider(options, deps) {
|
|
|
12754
12932
|
label: account || info10.label,
|
|
12755
12933
|
createdAt: Date.now()
|
|
12756
12934
|
};
|
|
12757
|
-
const
|
|
12935
|
+
const shop = (options.shop ?? "").trim();
|
|
12936
|
+
if (!options.projectDir && info10.id === "shopify" && !shop) {
|
|
12937
|
+
throw new Error("Enter your Shopify store's address (like my-store.myshopify.com) to check the key.");
|
|
12938
|
+
}
|
|
12939
|
+
const req = options.projectDir ? await resolvePublishRequest({
|
|
12758
12940
|
projectDir: options.projectDir,
|
|
12759
12941
|
providerId: info10.id,
|
|
12760
12942
|
...options.manifestPath ? { manifestPath: options.manifestPath } : {}
|
|
12761
|
-
}, deps)
|
|
12943
|
+
}, deps) : {
|
|
12944
|
+
project: { projectDir: "", title: "", authors: [] },
|
|
12945
|
+
config: shop ? { shop } : {},
|
|
12946
|
+
artifact: { path: "", format: info10.format },
|
|
12947
|
+
deps
|
|
12948
|
+
};
|
|
12762
12949
|
const trialDeps = {
|
|
12763
12950
|
...deps,
|
|
12764
12951
|
env: {},
|
|
@@ -12822,7 +13009,7 @@ class PublishSelectionsStore {
|
|
|
12822
13009
|
resolve(providerId, projectDir) {
|
|
12823
13010
|
return this.enqueue(async () => {
|
|
12824
13011
|
const data = await this.read();
|
|
12825
|
-
const proj = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId] : undefined;
|
|
13012
|
+
const proj = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId]?.credential : undefined;
|
|
12826
13013
|
return proj && proj.trim() || data.global[providerId]?.trim() || undefined;
|
|
12827
13014
|
});
|
|
12828
13015
|
}
|
|
@@ -12830,7 +13017,7 @@ class PublishSelectionsStore {
|
|
|
12830
13017
|
return this.enqueue(async () => {
|
|
12831
13018
|
const data = await this.read();
|
|
12832
13019
|
const global = data.global[providerId];
|
|
12833
|
-
const project = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId] : undefined;
|
|
13020
|
+
const project = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId]?.credential : undefined;
|
|
12834
13021
|
return {
|
|
12835
13022
|
...project ? { project } : {},
|
|
12836
13023
|
...global ? { global } : {}
|
|
@@ -12849,17 +13036,35 @@ class PublishSelectionsStore {
|
|
|
12849
13036
|
});
|
|
12850
13037
|
}
|
|
12851
13038
|
setProject(projectDir, providerId, account) {
|
|
13039
|
+
return this.setSettings(projectDir, providerId, { credential: account });
|
|
13040
|
+
}
|
|
13041
|
+
settings(projectDir) {
|
|
13042
|
+
return this.enqueue(async () => {
|
|
13043
|
+
const data = await this.read();
|
|
13044
|
+
return data.projects[normalizeProjectKey(projectDir)] ?? {};
|
|
13045
|
+
});
|
|
13046
|
+
}
|
|
13047
|
+
setSettings(projectDir, providerId, values) {
|
|
12852
13048
|
return this.enqueue(async () => {
|
|
12853
13049
|
const data = await this.read();
|
|
12854
13050
|
const key = normalizeProjectKey(projectDir);
|
|
12855
|
-
const
|
|
12856
|
-
const
|
|
12857
|
-
|
|
12858
|
-
|
|
13051
|
+
const book = data.projects[key] ?? {};
|
|
13052
|
+
const mine = { ...book[providerId] };
|
|
13053
|
+
for (const [k, v] of Object.entries(values)) {
|
|
13054
|
+
const text = (v ?? "").trim();
|
|
13055
|
+
if (text)
|
|
13056
|
+
mine[k] = text;
|
|
13057
|
+
else
|
|
13058
|
+
delete mine[k];
|
|
13059
|
+
}
|
|
13060
|
+
if (JSON.stringify(mine) === JSON.stringify(book[providerId] ?? {}))
|
|
13061
|
+
return;
|
|
13062
|
+
if (Object.keys(mine).length > 0)
|
|
13063
|
+
book[providerId] = mine;
|
|
12859
13064
|
else
|
|
12860
|
-
delete
|
|
12861
|
-
if (Object.keys(
|
|
12862
|
-
data.projects[key] =
|
|
13065
|
+
delete book[providerId];
|
|
13066
|
+
if (Object.keys(book).length > 0)
|
|
13067
|
+
data.projects[key] = book;
|
|
12863
13068
|
else
|
|
12864
13069
|
delete data.projects[key];
|
|
12865
13070
|
await this.write(data);
|
|
@@ -12870,6 +13075,7 @@ function normalizeProjectKey(projectDir) {
|
|
|
12870
13075
|
return projectDir.replace(/[\\/]+$/, "");
|
|
12871
13076
|
}
|
|
12872
13077
|
// src/lib/publish/manifest-publish.ts
|
|
13078
|
+
import path31 from "node:path";
|
|
12873
13079
|
import { isMap as isMap4 } from "yaml";
|
|
12874
13080
|
function settingsFromDoc(doc) {
|
|
12875
13081
|
const node = doc.get("publish", true);
|
|
@@ -12884,9 +13090,13 @@ function settingsFromDoc(doc) {
|
|
|
12884
13090
|
}
|
|
12885
13091
|
return out;
|
|
12886
13092
|
}
|
|
12887
|
-
async function readPublishSettings(projectDir) {
|
|
13093
|
+
async function readPublishSettings(projectDir, selections) {
|
|
12888
13094
|
const { doc } = await loadManifestDoc(projectDir);
|
|
12889
|
-
|
|
13095
|
+
const settings = settingsFromDoc(doc);
|
|
13096
|
+
for (const [id, mine] of Object.entries(await selections?.settings(projectDir) ?? {})) {
|
|
13097
|
+
settings[id] = { ...settings[id], ...mine };
|
|
13098
|
+
}
|
|
13099
|
+
return settings;
|
|
12890
13100
|
}
|
|
12891
13101
|
async function setPublishProviderConfig(projectDir, providerId, values) {
|
|
12892
13102
|
const { doc, file } = await loadManifestDoc(projectDir);
|
|
@@ -12908,4 +13118,35 @@ async function setPublishProviderConfig(projectDir, providerId, values) {
|
|
|
12908
13118
|
await writeManifestDoc(file, doc);
|
|
12909
13119
|
return settingsFromDoc(doc);
|
|
12910
13120
|
}
|
|
12911
|
-
|
|
13121
|
+
function insideBook(projectDir, dir) {
|
|
13122
|
+
const rel = path31.relative(projectDir, path31.resolve(projectDir, dir));
|
|
13123
|
+
if (rel === ".." || rel.startsWith(`..${path31.sep}`) || path31.isAbsolute(rel))
|
|
13124
|
+
return null;
|
|
13125
|
+
return rel.split(path31.sep).join("/") || ".";
|
|
13126
|
+
}
|
|
13127
|
+
async function savePublishSettings(projectDir, providerId, values, selections) {
|
|
13128
|
+
const shared = {};
|
|
13129
|
+
const mine = {};
|
|
13130
|
+
for (const [key, value] of Object.entries(values)) {
|
|
13131
|
+
const text = value === undefined || value === null ? "" : String(value).trim();
|
|
13132
|
+
const isDir = providerId === "local" && key === "dir";
|
|
13133
|
+
const inside = isDir && text ? insideBook(projectDir, text) : null;
|
|
13134
|
+
if (inside !== null) {
|
|
13135
|
+
shared[key] = inside;
|
|
13136
|
+
mine[key] = "";
|
|
13137
|
+
} else if (isDir || key === "credential") {
|
|
13138
|
+
mine[key] = isDir && text ? path31.resolve(projectDir, text) : text;
|
|
13139
|
+
shared[key] = "";
|
|
13140
|
+
} else {
|
|
13141
|
+
shared[key] = value;
|
|
13142
|
+
}
|
|
13143
|
+
}
|
|
13144
|
+
if (Object.keys(mine).length > 0)
|
|
13145
|
+
await selections.setSettings(projectDir, providerId, mine);
|
|
13146
|
+
const inManifest = (await readPublishSettings(projectDir))[providerId] ?? {};
|
|
13147
|
+
const changes = Object.fromEntries(Object.entries(shared).filter(([key, value]) => value !== "" || (key in inManifest)));
|
|
13148
|
+
if (Object.keys(changes).length > 0)
|
|
13149
|
+
await setPublishProviderConfig(projectDir, providerId, changes);
|
|
13150
|
+
return readPublishSettings(projectDir, selections);
|
|
13151
|
+
}
|
|
13152
|
+
export { SYNC_SNAPSHOT_MESSAGE, resolveActiveStyles, listProjectStyles, getChecks, getCheckById, resolveCheckSelectors, formatReport, ruleRemoteUrls, ruleRiskyProps, ruleSyntax, checkCss, inspectImage, runChecks, checkToolAvailability, reportMissingTools, executeValidation, executeAndReport, splitOutPath, runBuild, openPath, startPreviewServer, defaultConfigDir, FileTokenStore, extractUrlCredential, getSystemDiagnostics, readPageSetup, setPageSetup, slugifyProjectName, escapeYamlScalar, scaffoldProject, adoptFolder, EXTENSION_KINDS, RESERVED_PREFIX, resolveExtensionPrefix, scaffoldExtension, BUILT_IN_TEMPLATE_IDS, listBuiltInTemplates, saveProjectAsTemplate, listCustomTemplates, importTemplateFromFolder, SNIPPETS_DIR, extractVariables, substituteVariables, listSnippets, saveSnippet, deleteSnippet, listMergedSnippets, listMarkerComponents, listLocationVariants, importExtensionFromFile, importExtensionFromUrl, MAX_SEARCH_BYTES, SEARCH_KEYWORDS, searchNpmExtensions, setManifestFields, readManifestFields, setActiveStyles, VERSION_CHANGES_SHOWN, describeVersions, listOnlineVersions, compareVersionFile, exportVersionTree, AUTO_SNAPSHOT_DEFAULT_MINUTES, AUTO_SYNC_MIN_MINUTES, AUTO_SYNC_MAX_MINUTES, AUTO_SYNC_DEFAULT_MINUTES, AUTO_SYNC_PUSH_INTERVAL_MINUTES, autoSnapshotDelayMs, autoSyncDelayMs, isGitInternalPath, resolveGitHubClientId, GITHUB_HOST, GitHubAuthProvider, GDRIVE_HOST, resolveGoogleClientId, resolveGoogleClientSecret, GOOGLE_NOT_CONFIGURED_MESSAGE, requireGoogleClientCredentials, pkceChallengeFromVerifier, GoogleAuthProvider, revokeGoogleCredential, publishCredentialKey, publishConnectionStatus, listPublishAccounts, connectGoogleDrive, listGitHubRepositories, listRepoBooks, listGitHubBranches, syncProject, refreshRemoteCopies, checkRemoteUpdates, isValidRepositoryName, setUpOnlineBackup, sanitizeCloneFolderName, cloneRepository, isSshRemoteUrl, testRemoteAccess, knownForgeTokenUrl, connectGenericHost, parseRemoteOrigin, forgeKindForHost, diagnoseProjectRemote, renameRevision, deleteRevision, REPAIR_SNAPSHOT_MESSAGE, repairOnlineBackup, scorchedEarth, listPublishProviders, publishProviderFor, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, resolvePublishRequest, runPublish, connectPublishProvider, disconnectPublishCredential, PublishSelectionsStore, readPublishSettings, setPublishProviderConfig, savePublishSettings };
|