gutterpress 0.11.23-alpha.4 → 0.11.23-alpha.5

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.
Files changed (38) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/api/index.js +6 -4
  3. package/dist/{build-c48eer6f.js → build-4qv9wvrx.js} +7 -7
  4. package/dist/{cli-pspjxnc8.js → cli-2t3krcfy.js} +1 -1
  5. package/dist/{cli-54xt7pjg.js → cli-58fsk6d7.js} +2 -2
  6. package/dist/{cli-rqh295j9.js → cli-de8ydmm7.js} +1 -1
  7. package/dist/{cli-d9mm3vvh.js → cli-nk0efg2x.js} +1 -1
  8. package/dist/{cli-93mkaw6v.js → cli-pth362d8.js} +51 -21
  9. package/dist/{cli-y6d1arem.js → cli-w97xcpag.js} +2 -2
  10. package/dist/{cli-gnpea9dx.js → cli-yxfznmsq.js} +1 -1
  11. package/dist/cli.js +12 -12
  12. package/dist/{doctor-ptb346k8.js → doctor-5nh3t346.js} +3 -3
  13. package/dist/{engine-4rzdx6af.js → engine-4rabsgwq.js} +1 -1
  14. package/dist/{engine-6txhxmmv.js → engine-wm4fggac.js} +2 -2
  15. package/dist/{ext-gy8szg3x.js → ext-nhcep6h6.js} +7 -7
  16. package/dist/{extension-restore-dymzcasz.js → extension-restore-55kp0ksq.js} +2 -2
  17. package/dist/{extension-restore-m8tj43e7.js → extension-restore-x3mtn844.js} +4 -4
  18. package/dist/{index-5kh4c78h.js → index-2vxzxyyj.js} +2 -2
  19. package/dist/{index-8ywkd2sv.js → index-9ye22m7r.js} +1 -1
  20. package/dist/{index-ea94zbq4.js → index-agrkfbkv.js} +91 -22
  21. package/dist/{index-kaks3mm2.js → index-t3jkavdz.js} +1 -1
  22. package/dist/{index-yc3xj266.js → index-wm4x7xbf.js} +1 -1
  23. package/dist/index.js +7 -5
  24. package/dist/lib/publish/connect.d.ts +8 -1
  25. package/dist/lib/publish/manifest-publish.d.ts +26 -2
  26. package/dist/lib/publish/selections.d.ts +12 -1
  27. package/dist/lib/publish/types.d.ts +15 -5
  28. package/dist/{manifest.schema-w86c1xw1.json → manifest.schema-93sd7zje.json} +13 -6
  29. package/dist/{new-t2t28ccb.js → new-5a4w2vkh.js} +7 -7
  30. package/dist/{plugins-sqa4msdk.js → plugins-cfzf26b8.js} +3 -3
  31. package/dist/{plugins-fec8t2bh.js → plugins-mm8270tn.js} +1 -1
  32. package/dist/{preflight-srq8fktp.js → preflight-jma71n0j.js} +7 -7
  33. package/dist/{preview-interface-nnmrxyqm.js → preview-interface-0xdh0r5b.js} +3 -66
  34. package/dist/{preview-zsp9hstd.js → preview-kmx4h7gv.js} +7 -7
  35. package/dist/{publish-hhy31gr9.js → publish-62843020.js} +7 -7
  36. package/dist/schema/manifest.types.d.ts +18 -3
  37. package/dist/{validate-r9jdz85h.js → validate-vvmrd85g.js} +7 -7
  38. package/package.json +1 -1
@@ -37,7 +37,7 @@ import {
37
37
  validatePageMargin,
38
38
  withFetchTimeout,
39
39
  writeManifestDoc
40
- } from "./index-kaks3mm2.js";
40
+ } from "./index-t3jkavdz.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-8ywkd2sv.js";
76
+ } from "./index-9ye22m7r.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-5kh4c78h.js";
87
+ } from "./index-2vxzxyyj.js";
88
88
  import {
89
89
  BuildError
90
90
  } from "./index-46ycxe6r.js";
@@ -5527,7 +5527,7 @@ class PdfOutput {
5527
5527
  const rawPdf = pdfxMode ? path7.join(stage, "raw.pdf") : path7.resolve(pdfFile);
5528
5528
  await fsp2.mkdir(path7.dirname(path7.resolve(pdfFile)), { recursive: true });
5529
5529
  log.info("Rendering HTML to PDF via the Gutterpress engine (native Chromium pagination)");
5530
- const { buildNativePdf } = await import("./engine-6txhxmmv.js");
5530
+ const { buildNativePdf } = await import("./engine-wm4fggac.js");
5531
5531
  const engineDiagnostics = await buildNativePdf(htmlFile, rawPdf, {
5532
5532
  title: config.title,
5533
5533
  author: config.authors.length > 0 ? config.authors.join(", ") : undefined,
@@ -10858,6 +10858,9 @@ async function connectGenericHost(input, options = {}) {
10858
10858
  if (!host) {
10859
10859
  throw new Error("Enter your Git server's web address (like https://git.example.com).");
10860
10860
  }
10861
+ if (host === GITHUB_HOST) {
10862
+ throw new Error("GitHub has its own sign-in. Use Connect GitHub instead of a Git server.");
10863
+ }
10861
10864
  const token = input.token?.trim();
10862
10865
  if (!token) {
10863
10866
  throw new Error("Paste an access token from your Git server to connect.");
@@ -12417,7 +12420,7 @@ function publishProviderFor(id) {
12417
12420
  }
12418
12421
 
12419
12422
  // src/lib/publish/plugin-provider.ts
12420
- var RESERVED_SETTINGS = new Set(["format", "credential"]);
12423
+ var RESERVED_SETTINGS = new Set(["format", "credential", "enabled"]);
12421
12424
  var isBuiltIn = (id) => listPublishProviders().some((p) => p.id === id);
12422
12425
  var messageOf = (e) => e instanceof Error ? e.message : String(e);
12423
12426
  async function bookExtensions(book) {
@@ -12473,7 +12476,7 @@ async function resolvePublishProvider(id, book) {
12473
12476
  const ext = await bookExtensions(book);
12474
12477
  const npmEntry = ext.extensions.some((c) => !c.path && c.name === id);
12475
12478
  if (npmEntry) {
12476
- const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-dymzcasz.js");
12479
+ const { restoreForCommand: restoreForCommand2 } = await import("./extension-restore-55kp0ksq.js");
12477
12480
  await restoreForCommand2(book.projectDir, { manifestPath: book.manifestPath, failFast: true });
12478
12481
  }
12479
12482
  const publishers = await discover(ext);
@@ -12511,7 +12514,7 @@ function infoFor(p) {
12511
12514
  }
12512
12515
  function pluginProvider(p) {
12513
12516
  let loading;
12514
- const load = () => loading ??= import("./plugins-fec8t2bh.js").then((m) => m.loadPublishFunction(p));
12517
+ const load = () => loading ??= import("./plugins-mm8270tn.js").then((m) => m.loadPublishFunction(p));
12515
12518
  return {
12516
12519
  info: infoFor(p),
12517
12520
  async authenticate() {
@@ -12578,7 +12581,10 @@ async function requestFor(provider, options, deps) {
12578
12581
  const { manifest, manifestDir } = await loadManifestWithPath(options.manifestPath ?? options.projectDir, { explicit: options.manifestPath !== undefined });
12579
12582
  const config = resolveConfig({}, manifest);
12580
12583
  const publishSettings = manifest.publish ?? {};
12581
- const providerConfig = publishSettings[provider.info.id] ?? {};
12584
+ const providerConfig = {
12585
+ ...publishSettings[provider.info.id] ?? {},
12586
+ ...(await deps.selections?.settings(options.projectDir))?.[provider.info.id] ?? {}
12587
+ };
12582
12588
  const bookAccount = typeof providerConfig.credential === "string" ? providerConfig.credential.trim() : "";
12583
12589
  const effectiveAccount = bookAccount || deps.credentialAccount;
12584
12590
  const effectiveDeps = effectiveAccount ? { ...deps, credentialAccount: effectiveAccount } : deps;
@@ -12754,11 +12760,20 @@ async function connectPublishProvider(options, deps) {
12754
12760
  label: account || info10.label,
12755
12761
  createdAt: Date.now()
12756
12762
  };
12757
- const req = await resolvePublishRequest({
12763
+ const shop = (options.shop ?? "").trim();
12764
+ if (!options.projectDir && info10.id === "shopify" && !shop) {
12765
+ throw new Error("Enter your Shopify store's address (like my-store.myshopify.com) to check the key.");
12766
+ }
12767
+ const req = options.projectDir ? await resolvePublishRequest({
12758
12768
  projectDir: options.projectDir,
12759
12769
  providerId: info10.id,
12760
12770
  ...options.manifestPath ? { manifestPath: options.manifestPath } : {}
12761
- }, deps);
12771
+ }, deps) : {
12772
+ project: { projectDir: "", title: "", authors: [] },
12773
+ config: shop ? { shop } : {},
12774
+ artifact: { path: "", format: info10.format },
12775
+ deps
12776
+ };
12762
12777
  const trialDeps = {
12763
12778
  ...deps,
12764
12779
  env: {},
@@ -12822,7 +12837,7 @@ class PublishSelectionsStore {
12822
12837
  resolve(providerId, projectDir) {
12823
12838
  return this.enqueue(async () => {
12824
12839
  const data = await this.read();
12825
- const proj = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId] : undefined;
12840
+ const proj = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId]?.credential : undefined;
12826
12841
  return proj && proj.trim() || data.global[providerId]?.trim() || undefined;
12827
12842
  });
12828
12843
  }
@@ -12830,7 +12845,7 @@ class PublishSelectionsStore {
12830
12845
  return this.enqueue(async () => {
12831
12846
  const data = await this.read();
12832
12847
  const global = data.global[providerId];
12833
- const project = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId] : undefined;
12848
+ const project = projectDir ? data.projects[normalizeProjectKey(projectDir)]?.[providerId]?.credential : undefined;
12834
12849
  return {
12835
12850
  ...project ? { project } : {},
12836
12851
  ...global ? { global } : {}
@@ -12849,17 +12864,35 @@ class PublishSelectionsStore {
12849
12864
  });
12850
12865
  }
12851
12866
  setProject(projectDir, providerId, account) {
12867
+ return this.setSettings(projectDir, providerId, { credential: account });
12868
+ }
12869
+ settings(projectDir) {
12870
+ return this.enqueue(async () => {
12871
+ const data = await this.read();
12872
+ return data.projects[normalizeProjectKey(projectDir)] ?? {};
12873
+ });
12874
+ }
12875
+ setSettings(projectDir, providerId, values) {
12852
12876
  return this.enqueue(async () => {
12853
12877
  const data = await this.read();
12854
12878
  const key = normalizeProjectKey(projectDir);
12855
- const a = (account ?? "").trim();
12856
- const bucket = data.projects[key] ?? {};
12857
- if (a)
12858
- bucket[providerId] = a;
12879
+ const book = data.projects[key] ?? {};
12880
+ const mine = { ...book[providerId] };
12881
+ for (const [k, v] of Object.entries(values)) {
12882
+ const text = (v ?? "").trim();
12883
+ if (text)
12884
+ mine[k] = text;
12885
+ else
12886
+ delete mine[k];
12887
+ }
12888
+ if (JSON.stringify(mine) === JSON.stringify(book[providerId] ?? {}))
12889
+ return;
12890
+ if (Object.keys(mine).length > 0)
12891
+ book[providerId] = mine;
12859
12892
  else
12860
- delete bucket[providerId];
12861
- if (Object.keys(bucket).length > 0)
12862
- data.projects[key] = bucket;
12893
+ delete book[providerId];
12894
+ if (Object.keys(book).length > 0)
12895
+ data.projects[key] = book;
12863
12896
  else
12864
12897
  delete data.projects[key];
12865
12898
  await this.write(data);
@@ -12870,6 +12903,7 @@ function normalizeProjectKey(projectDir) {
12870
12903
  return projectDir.replace(/[\\/]+$/, "");
12871
12904
  }
12872
12905
  // src/lib/publish/manifest-publish.ts
12906
+ import path31 from "node:path";
12873
12907
  import { isMap as isMap4 } from "yaml";
12874
12908
  function settingsFromDoc(doc) {
12875
12909
  const node = doc.get("publish", true);
@@ -12884,9 +12918,13 @@ function settingsFromDoc(doc) {
12884
12918
  }
12885
12919
  return out;
12886
12920
  }
12887
- async function readPublishSettings(projectDir) {
12921
+ async function readPublishSettings(projectDir, selections) {
12888
12922
  const { doc } = await loadManifestDoc(projectDir);
12889
- return settingsFromDoc(doc);
12923
+ const settings = settingsFromDoc(doc);
12924
+ for (const [id, mine] of Object.entries(await selections?.settings(projectDir) ?? {})) {
12925
+ settings[id] = { ...settings[id], ...mine };
12926
+ }
12927
+ return settings;
12890
12928
  }
12891
12929
  async function setPublishProviderConfig(projectDir, providerId, values) {
12892
12930
  const { doc, file } = await loadManifestDoc(projectDir);
@@ -12908,4 +12946,35 @@ async function setPublishProviderConfig(projectDir, providerId, values) {
12908
12946
  await writeManifestDoc(file, doc);
12909
12947
  return settingsFromDoc(doc);
12910
12948
  }
12911
- 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, REPAIR_SNAPSHOT_MESSAGE, repairOnlineBackup, scorchedEarth, listPublishProviders, publishProviderFor, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, resolvePublishRequest, runPublish, connectPublishProvider, disconnectPublishCredential, PublishSelectionsStore, readPublishSettings, setPublishProviderConfig };
12949
+ function insideBook(projectDir, dir) {
12950
+ const rel = path31.relative(projectDir, path31.resolve(projectDir, dir));
12951
+ if (rel === ".." || rel.startsWith(`..${path31.sep}`) || path31.isAbsolute(rel))
12952
+ return null;
12953
+ return rel.split(path31.sep).join("/") || ".";
12954
+ }
12955
+ async function savePublishSettings(projectDir, providerId, values, selections) {
12956
+ const shared = {};
12957
+ const mine = {};
12958
+ for (const [key, value] of Object.entries(values)) {
12959
+ const text = value === undefined || value === null ? "" : String(value).trim();
12960
+ const isDir = providerId === "local" && key === "dir";
12961
+ const inside = isDir && text ? insideBook(projectDir, text) : null;
12962
+ if (inside !== null) {
12963
+ shared[key] = inside;
12964
+ mine[key] = "";
12965
+ } else if (isDir || key === "credential") {
12966
+ mine[key] = isDir && text ? path31.resolve(projectDir, text) : text;
12967
+ shared[key] = "";
12968
+ } else {
12969
+ shared[key] = value;
12970
+ }
12971
+ }
12972
+ if (Object.keys(mine).length > 0)
12973
+ await selections.setSettings(projectDir, providerId, mine);
12974
+ const inManifest = (await readPublishSettings(projectDir))[providerId] ?? {};
12975
+ const changes = Object.fromEntries(Object.entries(shared).filter(([key, value]) => value !== "" || (key in inManifest)));
12976
+ if (Object.keys(changes).length > 0)
12977
+ await setPublishProviderConfig(projectDir, providerId, changes);
12978
+ return readPublishSettings(projectDir, selections);
12979
+ }
12980
+ 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, REPAIR_SNAPSHOT_MESSAGE, repairOnlineBackup, scorchedEarth, listPublishProviders, publishProviderFor, listBookPublishProviders, resolvePublishProvider, resolvePublishFormat, resolvePublishRequest, runPublish, connectPublishProvider, disconnectPublishCredential, PublishSelectionsStore, readPublishSettings, setPublishProviderConfig, savePublishSettings };
@@ -14,7 +14,7 @@ import {
14
14
  readExtensionMeta,
15
15
  resolveExtension,
16
16
  slugify
17
- } from "./index-8ywkd2sv.js";
17
+ } from "./index-9ye22m7r.js";
18
18
  import {
19
19
  BuildError,
20
20
  EXIT_CODES
@@ -19,7 +19,7 @@ import {
19
19
  stringValueAt,
20
20
  toFolioPage,
21
21
  wantsRecto
22
- } from "./index-5kh4c78h.js";
22
+ } from "./index-2vxzxyyj.js";
23
23
  import {
24
24
  launchChromium
25
25
  } from "./index-bt0qws5c.js";
package/dist/index.js CHANGED
@@ -100,6 +100,7 @@ import {
100
100
  runPublish,
101
101
  sanitizeCloneFolderName,
102
102
  saveProjectAsTemplate,
103
+ savePublishSettings,
103
104
  saveSnippet,
104
105
  scaffoldExtension,
105
106
  scaffoldProject,
@@ -116,7 +117,7 @@ import {
116
117
  substituteVariables,
117
118
  syncProject,
118
119
  testRemoteAccess
119
- } from "./index-ea94zbq4.js";
120
+ } from "./index-agrkfbkv.js";
120
121
  import {
121
122
  DEFAULT_NPM_REGISTRY,
122
123
  MANIFEST_FILENAMES,
@@ -146,7 +147,7 @@ import {
146
147
  setExtensionEnabled,
147
148
  updateExtensions,
148
149
  validateProjectExtensions
149
- } from "./index-kaks3mm2.js";
150
+ } from "./index-t3jkavdz.js";
150
151
  import {
151
152
  BUNDLED_EXTENSIONS,
152
153
  EXTENSION_MANIFEST_FILENAME,
@@ -162,12 +163,12 @@ import {
162
163
  pathEscapesFolder,
163
164
  readExtensionMeta,
164
165
  resolveExtension
165
- } from "./index-8ywkd2sv.js";
166
+ } from "./index-9ye22m7r.js";
166
167
  import"./index-ht1bcqdd.js";
167
168
  import {
168
169
  BUILD_DIAGNOSTIC_CODES
169
- } from "./index-yc3xj266.js";
170
- import"./index-5kh4c78h.js";
170
+ } from "./index-wm4x7xbf.js";
171
+ import"./index-2vxzxyyj.js";
171
172
  import {
172
173
  BuildError
173
174
  } from "./index-46ycxe6r.js";
@@ -224,6 +225,7 @@ export {
224
225
  scaffoldProject,
225
226
  scaffoldExtension,
226
227
  saveSnippet,
228
+ savePublishSettings,
227
229
  saveProjectAsTemplate,
228
230
  sanitizeCloneFolderName,
229
231
  sameExtension,
@@ -1,6 +1,7 @@
1
1
  import { type PublishDeps } from "./types.ts";
2
2
  export interface ConnectPublishProviderOptions {
3
- projectDir: string;
3
+ /** The book whose manifest settings the check reads; omit to connect with no book open. */
4
+ projectDir?: string;
4
5
  providerId: string;
5
6
  /** The pasted API key. NEVER log this. */
6
7
  token: string;
@@ -11,6 +12,12 @@ export interface ConnectPublishProviderOptions {
11
12
  */
12
13
  account?: string;
13
14
  manifestPath?: string;
15
+ /**
16
+ * With no `projectDir` only: Shopify's store address (`publish.shopify.shop`
17
+ * in a book's manifest), which its key check needs. Used for the check and
18
+ * never stored; ignored when a book supplies its own settings.
19
+ */
20
+ shop?: string;
14
21
  }
15
22
  /**
16
23
  * Verify `token` with the platform, then store it. Throws a friendly,
@@ -1,5 +1,10 @@
1
- /** All `publish.*` sections, as plain JSON keyed by provider id (absent → {}). */
2
- export declare function readPublishSettings(projectDir: string): Promise<Record<string, Record<string, unknown>>>;
1
+ import type { PublishSelectionsStore } from "./selections.ts";
2
+ /**
3
+ * All `publish.*` sections, as plain JSON keyed by provider id (absent → {}).
4
+ * With the person's private store, what they see: their own values for the
5
+ * book laid over the manifest's.
6
+ */
7
+ export declare function readPublishSettings(projectDir: string, selections?: Pick<PublishSelectionsStore, "settings">): Promise<Record<string, Record<string, unknown>>>;
3
8
  /**
4
9
  * Merge `values` into `publish.<providerId>`. A value of `undefined`, `null`
5
10
  * or `""` deletes that key; emptied sections (and an emptied `publish:` map)
@@ -7,3 +12,22 @@ export declare function readPublishSettings(projectDir: string): Promise<Record<
7
12
  * from the in-memory document — no re-read.
8
13
  */
9
14
  export declare function setPublishProviderConfig(projectDir: string, providerId: string, values: Record<string, unknown>): Promise<Record<string, Record<string, unknown>>>;
15
+ /**
16
+ * Save a provider's settings where each belongs. The team decides where the
17
+ * book is published, so that is shared and goes in the manifest
18
+ * ({@link setPublishProviderConfig}): which destinations, each one's target,
19
+ * store, folder, environment and format. Only what is one person's own goes in
20
+ * their private store, keyed to this book, and is removed from the manifest if
21
+ * an older book kept it there:
22
+ *
23
+ * - `credential`: which of their saved accounts the book publishes with.
24
+ * - the local output folder `dir`, when it lies outside the book (a personal
25
+ * override). A folder inside the book is shared, and is written relative to
26
+ * it (an absolute in-book path is rewritten) so it means the same thing on
27
+ * every computer. An absolute path is never written to the manifest.
28
+ *
29
+ * Only the values passed are classified; the manifest is not rewritten unless
30
+ * one of them changes it. Empty values clear. Returns the settings as the
31
+ * person now sees them ({@link readPublishSettings}).
32
+ */
33
+ export declare function savePublishSettings(projectDir: string, providerId: string, values: Record<string, unknown>, selections: Pick<PublishSelectionsStore, "settings" | "setSettings">): Promise<Record<string, Record<string, unknown>>>;
@@ -1,3 +1,5 @@
1
+ /** One provider's private values for a book (strings only, as the manifest's are). */
2
+ type BookSettings = Record<string, string>;
1
3
  /** Both levels' explicit selections for a provider (for the UI). */
2
4
  export interface PublishAccountSelection {
3
5
  project?: string;
@@ -20,6 +22,15 @@ export declare class PublishSelectionsStore {
20
22
  levels(providerId: string, projectDir?: string): Promise<PublishAccountSelection>;
21
23
  /** Set (or clear, with an empty account) the global default for a provider. */
22
24
  setGlobal(providerId: string, account: string | null): Promise<void>;
23
- /** Set (or clear) the default for one provider within one project. */
25
+ /** Set (or clear) the saved account one provider uses within one project. */
24
26
  setProject(projectDir: string, providerId: string, account: string | null): Promise<void>;
27
+ /** Every private value for one book, by provider id (empty when none). */
28
+ settings(projectDir: string): Promise<Record<string, BookSettings>>;
29
+ /**
30
+ * Merge `values` into one provider's private values for one book. A value of
31
+ * `null` or `""` clears that key; an emptied provider (and book) entry is
32
+ * removed rather than left dangling. Nothing is written when nothing changes.
33
+ */
34
+ setSettings(projectDir: string, providerId: string, values: Record<string, string | null>): Promise<void>;
25
35
  }
36
+ export {};
@@ -19,6 +19,7 @@
19
19
  * host responses.
20
20
  */
21
21
  import type { HostCredential, TokenStore } from "../remote-auth/token-store.ts";
22
+ import type { PublishSelectionsStore } from "./selections.ts";
22
23
  /**
23
24
  * One author-editable, NON-SECRET settings field (stored in the manifest's
24
25
  * `publish.<id>` section). Declared by each provider so settings UIs are
@@ -123,8 +124,9 @@ export interface PublishPluginContext {
123
124
  /** The one build output validated for this run: a PDF file, or the
124
125
  * website export directory. */
125
126
  artifact: PublishArtifact;
126
- /** The manifest's `publish.<package-name>` section, minus the two keys core
127
- * reads from it: `format` (which build to publish) and `credential`. */
127
+ /** The manifest's `publish.<package-name>` section, minus the keys core
128
+ * reads from it: `format` (which build to publish), `credential` and
129
+ * `enabled` (whether the desktop's Publish view ticks it). */
128
130
  settings: Record<string, unknown>;
129
131
  /** Progress line sink. Use this, never `console.log`: stdout carries
130
132
  * `--json` output. */
@@ -197,11 +199,19 @@ export interface PublishDeps {
197
199
  * keyed by a compound `<host>#<account>` for named accounts (see
198
200
  * {@link publishCredentialKey}); empty/undefined resolves the legacy
199
201
  * bare-host entry, so existing single-credential setups keep working. The
200
- * orchestrator sets this from the effective selection (book manifest →
201
- * project/global default); providers read it transparently via
202
- * {@link resolvePublishCredential}.
202
+ * orchestrator sets this from the effective selection (the person's private
203
+ * choice for the book → the book manifest → this front-end default);
204
+ * providers read it transparently via {@link resolvePublishCredential}.
203
205
  */
204
206
  credentialAccount?: string;
207
+ /**
208
+ * The person's PRIVATE publishing values for a book (see
209
+ * {@link PublishSelectionsStore}): which saved account to use and an output
210
+ * folder outside the book. When given, they win over the manifest's
211
+ * `publish.<id>` values in every request. Absent (the CLI today): the
212
+ * manifest alone.
213
+ */
214
+ selections?: Pick<PublishSelectionsStore, "settings">;
205
215
  }
206
216
  /**
207
217
  * The TokenStore key for a publishing provider credential. Named accounts use a
@@ -262,7 +262,7 @@
262
262
  "type": "object",
263
263
  "description": "A folder on this computer — where the desktop's Publish builds the book before sending it anywhere else (default: `dist` inside the book)",
264
264
  "properties": {
265
- "dir": { "type": "string", "description": "Output folder, relative to the book or absolute. Default: dist" },
265
+ "dir": { "type": "string", "description": "Output folder inside the book, relative to it (default: dist). The desktop app keeps a folder outside the book in the person's own settings, not here; an absolute path written here still works." },
266
266
  "format": { "type": "string", "enum": ["pdf", "html"], "description": "Which build to save (default: pdf)" }
267
267
  },
268
268
  "additionalProperties": true
@@ -271,6 +271,7 @@
271
271
  "type": "object",
272
272
  "description": "itch.io publishing (uploaded with butler)",
273
273
  "properties": {
274
+ "enabled": { "type": "boolean", "description": "Whether the desktop app's Publish view ticks this destination for the book. The team decides where the book is published, so this is shared; each person connects their own account." },
274
275
  "target": {
275
276
  "type": "string",
276
277
  "description": "itch.io project as user/game (the butler push target)",
@@ -284,7 +285,7 @@
284
285
  },
285
286
  "credential": {
286
287
  "type": "string",
287
- "description": "Label of the saved credential to use when more than one is stored for this provider. Not a secret — just a reference into the host credential store. Empty or absent uses the default credential."
288
+ "description": "Label of the saved credential to use when more than one is stored for this provider. Not a secret — just a reference into the host credential store. Empty or absent uses the default credential. The desktop app keeps this choice in the person's own settings, not here; a value written here still applies to a book that has none (older books, the CLI)."
288
289
  }
289
290
  }
290
291
  },
@@ -292,6 +293,7 @@
292
293
  "type": "object",
293
294
  "description": "DriveThruRPG guided publishing (export package + open the publisher hub)",
294
295
  "properties": {
296
+ "enabled": { "type": "boolean", "description": "Whether the desktop app's Publish view ticks this destination for the book. The team decides where the book is published, so this is shared; each person connects their own account." },
295
297
  "productUrl": {
296
298
  "type": "string",
297
299
  "description": "Existing product page URL, when updating a published title"
@@ -301,12 +303,15 @@
301
303
  "kdp": {
302
304
  "type": "object",
303
305
  "description": "Amazon KDP guided publishing (export package + open kdp.amazon.com)",
304
- "properties": {}
306
+ "properties": {
307
+ "enabled": { "type": "boolean", "description": "Whether the desktop app's Publish view ticks this destination for the book. The team decides where the book is published, so this is shared; each person connects their own account." }
308
+ }
305
309
  },
306
310
  "azure-swa": {
307
311
  "type": "object",
308
312
  "description": "Azure Static Web Apps deployment of the HTML export",
309
313
  "properties": {
314
+ "enabled": { "type": "boolean", "description": "Whether the desktop app's Publish view ticks this destination for the book. The team decides where the book is published, so this is shared; each person connects their own account." },
310
315
  "env": {
311
316
  "type": "string",
312
317
  "description": "Deploy environment",
@@ -314,7 +319,7 @@
314
319
  },
315
320
  "credential": {
316
321
  "type": "string",
317
- "description": "Label of the saved credential to use when more than one is stored for this provider."
322
+ "description": "Label of the saved credential to use when more than one is stored for this provider. The desktop app keeps this choice in the person's own settings, not here; a value written here still applies to a book that has none (older books, the CLI)."
318
323
  }
319
324
  }
320
325
  },
@@ -322,6 +327,7 @@
322
327
  "type": "object",
323
328
  "description": "Shopify product publishing (Admin GraphQL API)",
324
329
  "properties": {
330
+ "enabled": { "type": "boolean", "description": "Whether the desktop app's Publish view ticks this destination for the book. The team decides where the book is published, so this is shared; each person connects their own account." },
325
331
  "shop": {
326
332
  "type": "string",
327
333
  "description": "Store domain, e.g. my-store.myshopify.com"
@@ -337,7 +343,7 @@
337
343
  },
338
344
  "credential": {
339
345
  "type": "string",
340
- "description": "Label of the saved credential to use when more than one is stored for this provider."
346
+ "description": "Label of the saved credential to use when more than one is stored for this provider. The desktop app keeps this choice in the person's own settings, not here; a value written here still applies to a book that has none (older books, the CLI)."
341
347
  }
342
348
  }
343
349
  },
@@ -345,6 +351,7 @@
345
351
  "type": "object",
346
352
  "description": "Google Drive publishing (uploads the finished PDF or zipped HTML export to a Drive folder)",
347
353
  "properties": {
354
+ "enabled": { "type": "boolean", "description": "Whether the desktop app's Publish view ticks this destination for the book. The team decides where the book is published, so this is shared; each person connects their own account." },
348
355
  "folder": {
349
356
  "type": "string",
350
357
  "description": "Drive folder name to find-or-create at My Drive root. Ignored once folderId is recorded.",
@@ -356,7 +363,7 @@
356
363
  },
357
364
  "credential": {
358
365
  "type": "string",
359
- "description": "Label of the saved credential to use when more than one Google account is connected. Not a secret — just a reference into the host credential store. Empty or absent uses the default credential."
366
+ "description": "Label of the saved credential to use when more than one Google account is connected. Not a secret — just a reference into the host credential store. Empty or absent uses the default credential. The desktop app keeps this choice in the person's own settings, not here; a value written here still applies to a book that has none (older books, the CLI)."
360
367
  },
361
368
  "format": {
362
369
  "type": "string",
@@ -3,12 +3,12 @@ import {
3
3
  EXTENSION_KINDS,
4
4
  scaffoldExtension,
5
5
  scaffoldProject
6
- } from "./cli-93mkaw6v.js";
6
+ } from "./cli-pth362d8.js";
7
7
  import {
8
8
  resolveGhostscript
9
- } from "./cli-d9mm3vvh.js";
9
+ } from "./cli-nk0efg2x.js";
10
10
  import"./cli-ht1bcqdd.js";
11
- import"./cli-54xt7pjg.js";
11
+ import"./cli-58fsk6d7.js";
12
12
  import"./cli-5crpmz42.js";
13
13
  import"./cli-eyyggect.js";
14
14
  import {
@@ -22,15 +22,15 @@ import {
22
22
  TARGET_IDS,
23
23
  loadManifest,
24
24
  resolveConfig
25
- } from "./cli-y6d1arem.js";
26
- import"./cli-rqh295j9.js";
27
- import"./cli-pspjxnc8.js";
25
+ } from "./cli-w97xcpag.js";
26
+ import"./cli-de8ydmm7.js";
27
+ import"./cli-2t3krcfy.js";
28
28
  import {
29
29
  UsageError,
30
30
  rejectExtraPositionals,
31
31
  rejectUnknownFlags
32
32
  } from "./cli-d8xjns66.js";
33
- import"./cli-gnpea9dx.js";
33
+ import"./cli-yxfznmsq.js";
34
34
  import {
35
35
  EXIT_CODES
36
36
  } from "./cli-46ycxe6r.js";
@@ -8,9 +8,9 @@ import {
8
8
  loadPlugins,
9
9
  loadPluginsWithCss,
10
10
  loadPublishFunction
11
- } from "./cli-rqh295j9.js";
12
- import"./cli-pspjxnc8.js";
13
- import"./cli-gnpea9dx.js";
11
+ } from "./cli-de8ydmm7.js";
12
+ import"./cli-2t3krcfy.js";
13
+ import"./cli-yxfznmsq.js";
14
14
  import"./cli-y28j019d.js";
15
15
  import"./cli-37x76zdn.js";
16
16
  export {
@@ -8,7 +8,7 @@ import {
8
8
  loadPlugins,
9
9
  loadPluginsWithCss,
10
10
  loadPublishFunction
11
- } from "./index-8ywkd2sv.js";
11
+ } from "./index-9ye22m7r.js";
12
12
  import"./index-5x42amh8.js";
13
13
  import"./index-37x76zdn.js";
14
14
  export {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  executeValidation,
3
3
  reportMissingTools
4
- } from "./cli-93mkaw6v.js";
5
- import"./cli-d9mm3vvh.js";
4
+ } from "./cli-pth362d8.js";
5
+ import"./cli-nk0efg2x.js";
6
6
  import"./cli-ht1bcqdd.js";
7
- import"./cli-54xt7pjg.js";
7
+ import"./cli-58fsk6d7.js";
8
8
  import"./cli-5crpmz42.js";
9
9
  import"./cli-eyyggect.js";
10
10
  import"./cli-asap4t1z.js";
@@ -12,17 +12,17 @@ import"./cli-a35w7wzg.js";
12
12
  import"./cli-v5mp7a6q.js";
13
13
  import {
14
14
  publishTargetFor
15
- } from "./cli-y6d1arem.js";
16
- import"./cli-rqh295j9.js";
15
+ } from "./cli-w97xcpag.js";
16
+ import"./cli-de8ydmm7.js";
17
17
  import {
18
18
  log
19
- } from "./cli-pspjxnc8.js";
19
+ } from "./cli-2t3krcfy.js";
20
20
  import {
21
21
  UsageError,
22
22
  rejectExtraPositionals,
23
23
  rejectUnknownFlags
24
24
  } from "./cli-d8xjns66.js";
25
- import"./cli-gnpea9dx.js";
25
+ import"./cli-yxfznmsq.js";
26
26
  import {
27
27
  BuildError,
28
28
  EXIT_CODES