@p11-core/cli 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3521,7 +3521,12 @@ var docsTopics = /* @__PURE__ */ new Map([
3521
3521
  ["components", "docs/components.md"],
3522
3522
  ["sharing", "docs/sharing.md"]
3523
3523
  ]);
3524
- var exampleFiles = /* @__PURE__ */ new Map([["all-components", "examples/all-components.tsx"]]);
3524
+ var exampleFiles = /* @__PURE__ */ new Map([
3525
+ ["minimal", "examples/minimal.tsx"],
3526
+ ["all", "examples/all-components.tsx"],
3527
+ ["all-components", "examples/all-components.tsx"]
3528
+ ]);
3529
+ var publicExampleNames = ["minimal", "all"];
3525
3530
  var allowedDocumentComponents = /* @__PURE__ */ new Set([
3526
3531
  "Document",
3527
3532
  "Page",
@@ -3625,6 +3630,11 @@ async function main() {
3625
3630
  return;
3626
3631
  }
3627
3632
  const command = process.argv[2];
3633
+ if (isVersionFlag(command)) {
3634
+ await warnIfUpdateAvailable({ force: true });
3635
+ console.log(packageJson.version);
3636
+ return;
3637
+ }
3628
3638
  if (!isKnownTopLevelCommand(program2, command)) throw new Error(`Unknown command: ${command}`);
3629
3639
  await program2.parseAsync(process.argv);
3630
3640
  }
@@ -3632,13 +3642,21 @@ function createCliProgram(options = {}) {
3632
3642
  const program2 = new Command();
3633
3643
  const warnBeforeAction = options.warnIfUpdateAvailable ?? warnIfUpdateAvailable;
3634
3644
  program2.name("p11").description("Share and inspect p11 document pages.");
3635
- program2.hook("preAction", async () => {
3645
+ program2.version(packageJson.version);
3646
+ program2.hook("preAction", async (_thisCommand, actionCommand) => {
3647
+ if (actionCommand.name() === "version") return;
3636
3648
  await warnBeforeAction();
3637
3649
  });
3638
3650
  program2.addHelpText(
3639
3651
  "after",
3640
3652
  `
3641
3653
 
3654
+ Examples:
3655
+ p11 example minimal --output ./page.tsx
3656
+ p11 example all
3657
+ p11 share ./page.tsx
3658
+ p11 docs components
3659
+
3642
3660
  Environment:
3643
3661
  P11_API_URL Defaults to ${builtDefaultApiUrl}
3644
3662
  P11_BUILD_DIR Directory for temporary share build files. Defaults to the OS temp directory.`
@@ -3655,6 +3673,10 @@ Environment:
3655
3673
  await deleteDocument(target, normalizeDeleteOptions(options2));
3656
3674
  });
3657
3675
  allowLegacyParserBehavior(deleteCommand);
3676
+ program2.command("version").description("Print the p11 CLI version.").action(async () => {
3677
+ await warnBeforeAction({ force: true });
3678
+ console.log(packageJson.version);
3679
+ });
3658
3680
  program2.command("history").description("List saved read/edit links.").option("--json", "Print saved history as JSON.").action(async (options2) => {
3659
3681
  await history(normalizeHistoryOptions(options2));
3660
3682
  });
@@ -3662,14 +3684,17 @@ Environment:
3662
3684
  await docs(topic);
3663
3685
  });
3664
3686
  allowLegacyParserBehavior(docsCommand);
3665
- const exampleCommand = program2.command("example").description("Print or write a p11 example document.").argument("[name]", "Example name: all-components.").option("--output [file]", "Write the example to a file.").action(async (name, options2) => {
3687
+ const exampleCommand = program2.command("example").description("Print or write a p11 example document.").argument("[name]", "Example name: minimal or all.").option("--output [file]", "Write the example to a file.").action(async (name, options2) => {
3666
3688
  await example(name, normalizeExampleOptions(options2));
3667
3689
  });
3668
3690
  allowLegacyParserBehavior(exampleCommand);
3669
3691
  return program2;
3670
3692
  }
3671
3693
  function isKnownTopLevelCommand(program2, command) {
3672
- return command === "--help" || command === "-h" || command === "help" || program2.commands.some((subcommand) => subcommand.name() === command);
3694
+ return command === "--help" || command === "-h" || isVersionFlag(command) || command === "help" || program2.commands.some((subcommand) => subcommand.name() === command);
3695
+ }
3696
+ function isVersionFlag(command) {
3697
+ return command === "--version" || command === "-V";
3673
3698
  }
3674
3699
  function allowLegacyParserBehavior(command) {
3675
3700
  return command.allowUnknownOption().allowExcessArguments();
@@ -3735,7 +3760,7 @@ async function publish(input, options) {
3735
3760
  const url = editTarget ? new URL(`/api/edit/${encodeURIComponent(editTarget.editId)}/page`, apiUrl) : new URL("/api/pages", apiUrl);
3736
3761
  const uploadBody = new ArrayBuffer(zipBytes.byteLength);
3737
3762
  new Uint8Array(uploadBody).set(zipBytes);
3738
- const response = await fetch(url, {
3763
+ const response = await fetchForOperation("Share", url, {
3739
3764
  method: "POST",
3740
3765
  headers: {
3741
3766
  "content-type": "application/zip"
@@ -3756,19 +3781,26 @@ async function publish(input, options) {
3756
3781
  if (options.json) {
3757
3782
  console.log(JSON.stringify(data, null, 2));
3758
3783
  } else {
3759
- console.log(data.readUrl ?? data.url);
3760
- if (data.editUrl) console.log(`editUrl: ${data.editUrl}`);
3761
- if (data.docId) console.log(`docId: ${data.docId}`);
3762
- if (data.readId) console.log(`readId: ${data.readId}`);
3763
- if (data.editId) console.log(`editId: ${data.editId}`);
3764
- if (data.version) console.log(`version: ${data.version}`);
3765
- if (data.latestVersion) console.log(`latestVersion: ${data.latestVersion}`);
3766
- if (data.createdAt) console.log(`createdAt: ${data.createdAt}`);
3784
+ for (const line of publishOutputLines(data)) console.log(line);
3767
3785
  }
3768
3786
  } finally {
3769
3787
  if (cleanupDir) await rm(cleanupDir, { recursive: true, force: true });
3770
3788
  }
3771
3789
  }
3790
+ function publishOutputLines(data) {
3791
+ const lines = [];
3792
+ const readUrl = data.readUrl ?? data.url;
3793
+ if (readUrl) lines.push(`readUrl: ${readUrl}`);
3794
+ if (data.editUrl) lines.push(`editUrl: ${data.editUrl}`);
3795
+ if (readUrl && data.editUrl) lines.push("Note: share readUrl for comments; keep editUrl private for updates and deletion.");
3796
+ if (data.docId) lines.push(`docId: ${data.docId}`);
3797
+ if (data.readId) lines.push(`readId: ${data.readId}`);
3798
+ if (data.editId) lines.push(`editId: ${data.editId}`);
3799
+ if (data.version) lines.push(`version: ${data.version}`);
3800
+ if (data.latestVersion) lines.push(`latestVersion: ${data.latestVersion}`);
3801
+ if (data.createdAt) lines.push(`createdAt: ${data.createdAt}`);
3802
+ return lines;
3803
+ }
3772
3804
  async function history(options) {
3773
3805
  const entries = await readHistoryEntries();
3774
3806
  if (options.json) {
@@ -3788,14 +3820,15 @@ async function docs(topic) {
3788
3820
  async function example(name, options) {
3789
3821
  if (!name) {
3790
3822
  console.log("Available examples:");
3791
- for (const exampleName of exampleFiles.keys()) console.log(` ${exampleName}`);
3823
+ for (const exampleName of publicExampleNames) console.log(` ${exampleName}`);
3792
3824
  console.log("");
3793
- console.log("Usage: p11 example all-components [--output FILE]");
3825
+ console.log("Usage: p11 example minimal [--output FILE]");
3826
+ console.log(" p11 example all [--output FILE]");
3794
3827
  return;
3795
3828
  }
3796
3829
  const relativePath = exampleFiles.get(name);
3797
3830
  if (!relativePath) {
3798
- throw new Error(`Unknown example: ${name}. Available examples: ${Array.from(exampleFiles.keys()).join(", ")}`);
3831
+ throw new Error(`Unknown example: ${name}. Available examples: ${publicExampleNames.join(", ")}`);
3799
3832
  }
3800
3833
  const contents = await readCliAsset(relativePath);
3801
3834
  if (options.output) {
@@ -3813,7 +3846,7 @@ async function comments(target, options) {
3813
3846
  apiUrl: options.apiUrl,
3814
3847
  version
3815
3848
  });
3816
- const response = await fetch(url);
3849
+ const response = await fetchForOperation("Fetch comments", url);
3817
3850
  const text = await response.text();
3818
3851
  if (!response.ok) {
3819
3852
  throw new Error(`Fetch comments failed (${response.status}): ${text}`);
@@ -3836,7 +3869,7 @@ async function deleteDocument(target, options) {
3836
3869
  const url = deleteApiUrlForTarget(target, {
3837
3870
  apiUrl: options.apiUrl
3838
3871
  });
3839
- const response = await fetch(url, {
3872
+ const response = await fetchForOperation("Delete", url, {
3840
3873
  method: "DELETE"
3841
3874
  });
3842
3875
  const text = await response.text();
@@ -4053,9 +4086,34 @@ function responseErrorMessage(text) {
4053
4086
  }
4054
4087
  return text;
4055
4088
  }
4089
+ async function fetchForOperation(operation, url, init) {
4090
+ try {
4091
+ return await fetch(url, init);
4092
+ } catch (error) {
4093
+ throw new Error(formatNetworkError(operation, url, error));
4094
+ }
4095
+ }
4096
+ function formatNetworkError(operation, url, error) {
4097
+ return `${operation} request failed before receiving a response: ${fetchFailureDetails(error)}. API URL: ${url.origin}. ${networkErrorHint()}`;
4098
+ }
4099
+ function fetchFailureDetails(error) {
4100
+ const message = errorMessage(error);
4101
+ const cause = errorCause(error);
4102
+ if (!cause) return message;
4103
+ const causeCode = errorCode(cause);
4104
+ const causeMessage = errorMessage(cause);
4105
+ const causeDetails = causeCode && !causeMessage.includes(causeCode) ? `${causeCode} ${causeMessage}` : causeMessage;
4106
+ return `${message} (cause: ${causeDetails})`;
4107
+ }
4108
+ function networkErrorHint() {
4109
+ return "If running in an agent sandbox, retry with network access outside the sandbox or with escalated network permissions.";
4110
+ }
4056
4111
  function errorMessage(error) {
4057
4112
  return error instanceof Error ? error.message : String(error);
4058
4113
  }
4114
+ function errorCause(error) {
4115
+ return typeof error === "object" && error !== null && "cause" in error ? error.cause : null;
4116
+ }
4059
4117
  async function readCliAsset(relativePath) {
4060
4118
  return readFile(path.join(cliPackageRoot, relativePath), "utf8");
4061
4119
  }
@@ -4417,12 +4475,12 @@ function validateAccessTarget(target, expected) {
4417
4475
  function normalizeApiUrl(value) {
4418
4476
  return value.endsWith("/") ? value.slice(0, -1) : value;
4419
4477
  }
4420
- async function warnIfUpdateAvailable() {
4478
+ async function warnIfUpdateAvailable(options = {}) {
4421
4479
  if (process.env.P11_DISABLE_UPDATE_CHECK) return;
4422
4480
  try {
4423
4481
  const cachePath = updateCheckCachePath();
4424
4482
  const checkedAt = await readUpdateCheckTime(cachePath);
4425
- if (checkedAt && Date.now() - checkedAt.getTime() < updateCheckIntervalMs) return;
4483
+ if (!options.force && checkedAt && Date.now() - checkedAt.getTime() < updateCheckIntervalMs) return;
4426
4484
  await writeUpdateCheckTime(cachePath);
4427
4485
  const latestVersion = await fetchLatestVersion();
4428
4486
  if (!latestVersion || !isNewerVersion(latestVersion, packageJson.version)) return;
@@ -4493,10 +4551,12 @@ export {
4493
4551
  commentsExportJson,
4494
4552
  createCliProgram,
4495
4553
  deleteApiUrlForTarget,
4554
+ formatNetworkError,
4496
4555
  isNewerVersion,
4497
4556
  parseCommentsTarget,
4498
4557
  parseEditId,
4499
4558
  parseReadId,
4559
+ publishOutputLines,
4500
4560
  readHistoryEntries,
4501
4561
  resolveBuildParentDir,
4502
4562
  validatePageSource
package/docs/index.md CHANGED
@@ -5,6 +5,8 @@ p11 shares reviewable, public-but-unlisted document pages from React files.
5
5
  ## Common Commands
6
6
 
7
7
  ```bash
8
+ p11 example minimal --output ./page.tsx
9
+ p11 example all
8
10
  p11 share <page.tsx>
9
11
  p11 share <page.tsx> --edit-url <editUrl>
10
12
  p11 history
@@ -25,8 +27,9 @@ p11 docs sharing
25
27
 
26
28
  ```bash
27
29
  p11 example
28
- p11 example all-components
29
- p11 example all-components --output ./all-components.tsx
30
+ p11 example minimal --output ./page.tsx
31
+ p11 example all
32
+ p11 example all --output ./all.tsx
30
33
  ```
31
34
 
32
35
  Use `p11 share --help`, `p11 comments --help`, `p11 delete --help`, and `p11 history --help` for command-specific flags.
@@ -271,7 +271,7 @@ export default function All() {
271
271
  <CodeBlock language="json">
272
272
  {code`
273
273
  {
274
- "docId": "all-components",
274
+ "docId": "all",
275
275
  "version": 2,
276
276
  "comments": true,
277
277
  "languages": ["typescript", "javascript", "python", "rust", "html", "css", "json", "yaml", "bash"]
@@ -285,7 +285,7 @@ export default function All() {
285
285
  <CodeBlock language="yaml">
286
286
  {code`
287
287
  document:
288
- id: all-components
288
+ id: all
289
289
  version: 2
290
290
  comments: true
291
291
  retentionDays: 7
@@ -307,7 +307,7 @@ export default function All() {
307
307
  <Heading>14. Bash</Heading>
308
308
  <CodeBlock language="bash">
309
309
  {code`
310
- p11 share ./all-components.tsx
310
+ p11 share ./all.tsx
311
311
  p11 comments <readUrl> --version 1
312
312
  `}
313
313
  </CodeBlock>
@@ -0,0 +1,21 @@
1
+ import { Document, Heading, Page, Section, Text } from "@p11-core/components";
2
+
3
+ // For the full component set, run:
4
+ // p11 docs components
5
+ // p11 example all
6
+
7
+ export default function Minimal() {
8
+ return (
9
+ <Document mode="page">
10
+ <Page>
11
+ <Section>
12
+ <Heading level={1}>Review Brief</Heading>
13
+ <Text>
14
+ This is a minimal p11 document. Replace this text with the content
15
+ you want reviewers to read and comment on.
16
+ </Text>
17
+ </Section>
18
+ </Page>
19
+ </Document>
20
+ );
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@p11-core/cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "bin": {