@seed-hypermedia/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.
Files changed (2) hide show
  1. package/dist/index.js +164 -121
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6032,6 +6032,87 @@ function isSurrogate(s, i) {
6032
6032
  const code = s.charCodeAt(i);
6033
6033
  return 55296 <= code && code <= 56319;
6034
6034
  }
6035
+ async function resolveHypermediaUrl(url) {
6036
+ let latest = false;
6037
+ let blockRef = null;
6038
+ let blockRange = null;
6039
+ let panel = null;
6040
+ try {
6041
+ const parsedUrl = new URL(url);
6042
+ const hasVersion = parsedUrl.searchParams.has("v");
6043
+ const hasLatest = parsedUrl.searchParams.has("l");
6044
+ panel = parsedUrl.searchParams.get("panel");
6045
+ if (parsedUrl.hash) {
6046
+ const fragment = parseFragment(parsedUrl.hash.slice(1));
6047
+ if (fragment) {
6048
+ blockRef = fragment.blockId;
6049
+ if ("start" in fragment && fragment.start !== undefined) {
6050
+ blockRange = { start: fragment.start, end: fragment.end };
6051
+ } else if ("expanded" in fragment && fragment.expanded) {
6052
+ blockRange = { expanded: fragment.expanded };
6053
+ }
6054
+ }
6055
+ }
6056
+ latest = blockRef ? false : hasLatest || !hasVersion;
6057
+ } catch {}
6058
+ const response = await fetch(url, {
6059
+ method: "OPTIONS"
6060
+ });
6061
+ if (response.status === 200) {
6062
+ const rawId = response.headers.get("x-hypermedia-id");
6063
+ const id = rawId ? decodeURIComponent(rawId) : null;
6064
+ const version = response.headers.get("x-hypermedia-version");
6065
+ const encodedTitle = response.headers.get("x-hypermedia-title");
6066
+ const title = encodedTitle ? decodeURIComponent(encodedTitle) : null;
6067
+ const rawTarget = response.headers.get("x-hypermedia-target");
6068
+ const target = rawTarget ? unpackHmId(decodeURIComponent(rawTarget)) : null;
6069
+ const rawAuthors = response.headers.get("x-hypermedia-authors");
6070
+ const authors = rawAuthors ? decodeURIComponent(rawAuthors).split(",").map((author) => unpackHmId(author)) : null;
6071
+ const type = response.headers.get("x-hypermedia-type");
6072
+ if (id) {
6073
+ const hmId = unpackHmId(id);
6074
+ const resolvedVersion = version ?? hmId?.version ?? null;
6075
+ let siteHostname = null;
6076
+ try {
6077
+ const inputUrl = new URL(url);
6078
+ if (!inputUrl.pathname.startsWith("/hm/")) {
6079
+ siteHostname = inputUrl.origin;
6080
+ }
6081
+ } catch {}
6082
+ return {
6083
+ id,
6084
+ hmId: hmId ? {
6085
+ ...hmId,
6086
+ version: resolvedVersion,
6087
+ latest,
6088
+ blockRef,
6089
+ blockRange,
6090
+ hostname: siteHostname || hmId.hostname
6091
+ } : null,
6092
+ version,
6093
+ title,
6094
+ target,
6095
+ authors,
6096
+ type,
6097
+ panel
6098
+ };
6099
+ }
6100
+ return null;
6101
+ }
6102
+ return null;
6103
+ }
6104
+ async function resolveId(input) {
6105
+ const parsed = unpackHmId(input);
6106
+ if (parsed)
6107
+ return parsed;
6108
+ if (input.startsWith("http://") || input.startsWith("https://")) {
6109
+ const resolved = await resolveHypermediaUrl(input);
6110
+ if (resolved?.hmId)
6111
+ return resolved.hmId;
6112
+ throw new Error(`URL does not appear to be a Seed Hypermedia resource: ${input}`);
6113
+ }
6114
+ throw new Error(`Invalid Hypermedia ID: ${input}`);
6115
+ }
6035
6116
  var BlockRangeSchema, unpackedHmIdSchema, HMBlockChildrenTypeSchema, HMEmbedViewSchema, HMQueryStyleSchema, baseAnnotationProperties, BoldAnnotationSchema, ItalicAnnotationSchema, UnderlineAnnotationSchema, StrikeAnnotationSchema, CodeAnnotationSchema, LinkAnnotationSchema, InlineEmbedAnnotationSchema, HighlightAnnotationSchema, HMAnnotationSchema, HMAnnotationsSchema, blockBaseProperties, textBlockProperties, parentBlockAttributes, HMBlockParagraphSchema, HMBlockHeadingSchema, HMBlockCodeSchema, HMBlockMathSchema, HMBlockImageSchema, HMBlockVideoSchema, HMBlockFileSchema, HMBlockButtonAlignmentSchema, HMBlockButtonSchema, HMBlockEmbedSchema, HMBlockWebEmbedSchema, HMBlockNostrSchema, HMTimestampSchema, HMBlockNodeSchema, HMDocumentMetadataSchema, visibilityMap, HMResourceVisibilitySchema, HMCommentSchema, HMBreadcrumbSchema, HMCommentGroupSchema, HMExternalCommentGroupSchema, HMActivitySummarySchema, HMGenerationInfoSchema, HMRedirectInfoSchema, HMDocumentInfoSchema, HMQueryResultSchema, HMRoleSchema, HMMetadataPayloadSchema, HMAccountPayloadSchema, HMAccountNotFoundSchema, HMAccountResultSchema, HMSiteMemberSchema, HMAccountsMetadataSchema, HMQueryInclusionSchema, HMQuerySortSchema, HMQuerySchema, HMBlockQuerySchema, HMBlockGroupSchema, HMBlockLinkSchema, HMBlockKnownSchema, HMBlockUnknownSchema, HMBlockSchema, knownBlockTypes, HMDocumentSchema, HMResourceDocumentSchema, HMResourceCommentSchema, HMResourceRedirectSchema, HMResourceNotFoundSchema, HMResourceTombstoneSchema, HMResourceErrorSchema, HMResourceSchema, HMResolvedResourceSchema, HMContactSubscribeSchema, HMContactRecordSchema, HMAccountContactsRequestSchema, HMCommentDraftSchema, HMListedCommentDraftSchema, HMHostConfigSchema, HMContactSchema, HMContactItemSchema, HMCapabilitySchema, siteDiscoverRequestSchema, HMPeerConnectionRequestSchema, ParsedFragmentSchema, HMCitationCommentSourceSchema, HMCitationDocumentSourceSchema, HMCitationSchema, DeviceLinkSessionSchema, HMNavigationItemSchema, HMDraftContentSchema, HMDraftMetaBaseSchema, draftLocationRefinement = (data) => data.editUid || data.locationUid, HMDraftMetaSchema, HMListedDraftSchema, HMListedDraftReadSchema, HMSubjectContactsRequestSchema, HMResourceRequestSchema, HMResourceMetadataRequestSchema, HMAccountRequestSchema, HMCommentRequestSchema, HMSearchInputSchema, HMSearchResultItemSchema, HMSearchPayloadSchema, HMSearchRequestSchema, HMQueryRequestSchema, HMListCommentsInputSchema, HMListCommentsOutputSchema, HMListCommentsRequestSchema, HMListDiscussionsInputSchema, HMListDiscussionsOutputSchema, HMListDiscussionsRequestSchema, HMListCommentsByReferenceInputSchema, HMListCommentsByReferenceRequestSchema, HMGetCommentReplyCountInputSchema, HMGetCommentReplyCountRequestSchema, HMListEventsInputSchema, HMLoadedEventSchema, HMListEventsOutputSchema, HMListEventsRequestSchema, HMListAccountsOutputSchema, HMListAccountsInputSchema, HMListAccountsRequestSchema, HMGetCIDOutputSchema, HMGetCIDInputSchema, HMGetCIDRequestSchema, HMListCommentsByAuthorOutputSchema, HMListCommentsByAuthorInputSchema, HMListCommentsByAuthorRequestSchema, HMRawMentionSchema, HMListCitationsOutputSchema, HMListCitationsInputSchema, HMListCitationsRequestSchema, HMRawDocumentChangeSchema, HMListChangesOutputSchema, HMListChangesInputSchema, HMListChangesRequestSchema, HMRawCapabilitySchema, HMListCapabilitiesOutputSchema, HMListCapabilitiesInputSchema, HMListCapabilitiesRequestSchema, HMInteractionSummaryInputSchema, HMInteractionSummaryOutputSchema, HMInteractionSummaryRequestSchema, HMPublishBlobsOutputSchema, HMPublishBlobsInputSchema, HMPublishBlobsRequestSchema, ProtoAnnotationSchema, ProtoBlockSchema, ProtoSetAttributeValueSchema, ProtoDocumentChangeSchema, HMPrepareDocumentChangeInputSchema, HMPrepareDocumentChangeOutputSchema, HMPrepareDocumentChangeRequestSchema, HMListCommentVersionsInputSchema, HMListCommentVersionsOutputSchema, HMListCommentVersionsRequestSchema, HMGetRequestSchema, HMActionSchema, HMRequestSchema, HYPERMEDIA_SCHEME = "hm", STATIC_HM_PATHS;
6036
6117
  var init_hm_types = __esm(() => {
6037
6118
  init_zod();
@@ -138238,6 +138319,8 @@ __export(exports_src2, {
138238
138319
  signDocumentChange: () => signDocumentChange,
138239
138320
  shouldAutoLinkParent: () => shouldAutoLinkParent2,
138240
138321
  serializeBlockRange: () => serializeBlockRange,
138322
+ resolveId: () => resolveId,
138323
+ resolveHypermediaUrl: () => resolveHypermediaUrl,
138241
138324
  resolveFileLinksInBlocks: () => resolveFileLinksInBlocks2,
138242
138325
  resolveDocumentState: () => resolveDocumentState2,
138243
138326
  pushSpanToAnnotation: () => pushSpanToAnnotation2,
@@ -161018,43 +161101,52 @@ __export(exports_nanoid, {
161018
161101
  customRandom: () => customRandom,
161019
161102
  customAlphabet: () => customAlphabet
161020
161103
  });
161021
- import { randomFillSync } from "crypto";
161022
- var POOL_SIZE_MULTIPLIER = 128, pool2, poolOffset, fillPool = (bytes) => {
161104
+ import { webcrypto as crypto4 } from "node:crypto";
161105
+ function fillPool(bytes) {
161023
161106
  if (!pool2 || pool2.length < bytes) {
161024
161107
  pool2 = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
161025
- randomFillSync(pool2);
161108
+ crypto4.getRandomValues(pool2);
161026
161109
  poolOffset = 0;
161027
161110
  } else if (poolOffset + bytes > pool2.length) {
161028
- randomFillSync(pool2);
161111
+ crypto4.getRandomValues(pool2);
161029
161112
  poolOffset = 0;
161030
161113
  }
161031
161114
  poolOffset += bytes;
161032
- }, random = (bytes) => {
161033
- fillPool(bytes -= 0);
161115
+ }
161116
+ function random(bytes) {
161117
+ fillPool(bytes |= 0);
161034
161118
  return pool2.subarray(poolOffset - bytes, poolOffset);
161035
- }, customRandom = (alphabet2, defaultSize, getRandom) => {
161119
+ }
161120
+ function customRandom(alphabet2, defaultSize, getRandom) {
161036
161121
  let mask = (2 << 31 - Math.clz32(alphabet2.length - 1 | 1)) - 1;
161037
161122
  let step = Math.ceil(1.6 * mask * defaultSize / alphabet2.length);
161038
161123
  return (size = defaultSize) => {
161124
+ if (!size)
161125
+ return "";
161039
161126
  let id = "";
161040
161127
  while (true) {
161041
161128
  let bytes = getRandom(step);
161042
161129
  let i = step;
161043
161130
  while (i--) {
161044
161131
  id += alphabet2[bytes[i] & mask] || "";
161045
- if (id.length === size)
161132
+ if (id.length >= size)
161046
161133
  return id;
161047
161134
  }
161048
161135
  }
161049
161136
  };
161050
- }, customAlphabet = (alphabet2, size = 21) => customRandom(alphabet2, size, random), nanoid = (size = 21) => {
161051
- fillPool(size -= 0);
161137
+ }
161138
+ function customAlphabet(alphabet2, size = 21) {
161139
+ return customRandom(alphabet2, size, random);
161140
+ }
161141
+ function nanoid(size = 21) {
161142
+ fillPool(size |= 0);
161052
161143
  let id = "";
161053
161144
  for (let i = poolOffset - size;i < poolOffset; i++) {
161054
161145
  id += urlAlphabet[pool2[i] & 63];
161055
161146
  }
161056
161147
  return id;
161057
- };
161148
+ }
161149
+ var POOL_SIZE_MULTIPLIER = 128, pool2, poolOffset;
161058
161150
  var init_nanoid = () => {};
161059
161151
 
161060
161152
  // node_modules/commander/esm.mjs
@@ -165376,6 +165468,18 @@ function esc(s) {
165376
165468
  return `'${s.replace(/'/g, "'\\''")}'`;
165377
165469
  }
165378
165470
 
165471
+ // src/utils/resolve-id.ts
165472
+ init_src16();
165473
+ async function resolveIdWithClient(rawId, globalOpts) {
165474
+ const parsed = unpackHmId(rawId);
165475
+ if (parsed) {
165476
+ return { id: parsed, client: getClient(globalOpts) };
165477
+ }
165478
+ const id = await resolveId(rawId);
165479
+ const origin = new URL(rawId).origin;
165480
+ return { id, client: createSeedClient(origin) };
165481
+ }
165482
+
165379
165483
  // src/utils/signer.ts
165380
165484
  function createSignerFromKey(key) {
165381
165485
  return {
@@ -165420,6 +165524,16 @@ async function resolveFileLinks(nodes) {
165420
165524
  }
165421
165525
 
165422
165526
  // src/commands/document.ts
165527
+ async function resolveCapability(client, targetAccount, signerAccount) {
165528
+ if (targetAccount === signerAccount)
165529
+ return;
165530
+ const targetId = unpackHmId3(`hm://${targetAccount}`);
165531
+ if (!targetId)
165532
+ return;
165533
+ const caps = await client.request("ListCapabilities", { targetId });
165534
+ const match = caps.capabilities.find((c) => c.delegate === signerAccount && (c.role === "WRITER" || c.role === "AGENT"));
165535
+ return match?.id;
165536
+ }
165423
165537
  async function readStdinBinary() {
165424
165538
  const chunks = [];
165425
165539
  for await (const chunk of process.stdin) {
@@ -165524,9 +165638,8 @@ async function readInput(options2) {
165524
165638
  }
165525
165639
  function registerDocumentCommands(program2) {
165526
165640
  const doc = program2.command("document").description("Manage documents (get, create, update, delete, fork, move, redirect, changes, stats, cid)");
165527
- doc.command("get <id>").description("Fetch a document, comment, or entity by Hypermedia ID").option("-m, --metadata", "Fetch metadata only").option("-r, --resolve", "Resolve embeds, mentions, and queries in markdown output").option("-o, --output <file>", "Write output to file instead of stdout").option("-q, --quiet", "Output minimal info").action(async (id, options2, cmd) => {
165641
+ doc.command("get <id>").description("Fetch a document, comment, or entity by Hypermedia ID or URL").option("-m, --metadata", "Fetch metadata only").option("-r, --resolve", "Resolve embeds, mentions, and queries in markdown output").option("-o, --output <file>", "Write output to file instead of stdout").option("-q, --quiet", "Output minimal info").action(async (id, options2, cmd) => {
165528
165642
  const globalOpts = cmd.optsWithGlobals();
165529
- const client = getClient(globalOpts);
165530
165643
  const format2 = getOutputFormat(globalOpts);
165531
165644
  const pretty = isPretty(globalOpts);
165532
165645
  const useStructuredOutput = !!(globalOpts.json || globalOpts.yaml);
@@ -165541,13 +165654,9 @@ function registerDocumentCommands(program2) {
165541
165654
  }
165542
165655
  }
165543
165656
  try {
165657
+ const { id: resolvedId, client } = await resolveIdWithClient(id, globalOpts);
165544
165658
  if (options2.metadata) {
165545
- const unpacked = unpackHmId3(id);
165546
- if (!unpacked) {
165547
- printError2(`Invalid Hypermedia ID: ${id}`);
165548
- process.exit(1);
165549
- }
165550
- const result2 = await client.request("ResourceMetadata", unpacked);
165659
+ const result2 = await client.request("ResourceMetadata", resolvedId);
165551
165660
  if (globalOpts.quiet || options2.quiet) {
165552
165661
  emit(result2.metadata?.name || result2.id.id);
165553
165662
  } else {
@@ -165555,12 +165664,7 @@ function registerDocumentCommands(program2) {
165555
165664
  }
165556
165665
  return;
165557
165666
  }
165558
- const resourceId = unpackHmId3(id);
165559
- if (!resourceId) {
165560
- printError2(`Invalid Hypermedia ID: ${id}`);
165561
- process.exit(1);
165562
- }
165563
- const result = await client.request("Resource", resourceId);
165667
+ const result = await client.request("Resource", resolvedId);
165564
165668
  if (globalOpts.quiet || options2.quiet) {
165565
165669
  if (result.type === "document") {
165566
165670
  emit(result.document.metadata?.name || result.id.id);
@@ -165604,7 +165708,7 @@ function registerDocumentCommands(program2) {
165604
165708
  process.exit(1);
165605
165709
  }
165606
165710
  });
165607
- doc.command("create").description("Create a new document from markdown, JSON blocks, or PDF").option("-f, --file <path>", "Input file (format detected by extension: .md, .json, .pdf)").option("-p, --path <path>", 'Document path (e.g. "my-document")').option("--name <value>", "Document title (overrides frontmatter)").option("--summary <value>", "Document summary").option("--display-author <value>", 'Display author name (e.g. "Jane Doe")').option("--display-publish-time <value>", "Display publish time (YYYY-MM-DD)").option("--icon <value>", "Document icon (ipfs:// or file:// URL)").option("--cover <value>", "Cover image (ipfs:// or file:// URL)").option("--site-url <value>", "Site URL").option("--layout <value>", 'Document layout (e.g. "Seed/Experimental/Newspaper")').option("--show-outline", "Show document outline").option("--no-show-outline", "Hide document outline").option("--show-activity", "Show document activity").option("--no-show-activity", "Hide document activity").option("--content-width <value>", "Content width (S, M, L)").option("--seed-experimental-logo <value>", "Experimental logo (ipfs:// or file:// URL)").option("--seed-experimental-home-order <value>", "Home ordering (UpdatedFirst, CreatedFirst)").option("--import-categories <value>", "Import categories (comma-separated)").option("--import-tags <value>", "Import tags (comma-separated)").option("--grobid-url <url>", "GROBID server URL for PDF extraction").option("--dry-run", "Preview extracted content without publishing").option("--force", "Overwrite existing document at the same path (creates new lineage)").option("-k, --key <name>", "Signing key name or account ID").action(async (options2, cmd) => {
165711
+ doc.command("create").description("Create a new document from markdown, JSON blocks, or PDF").option("-f, --file <path>", "Input file (format detected by extension: .md, .json, .pdf)").option("-p, --path <path>", 'Document path (e.g. "my-document")').option("--name <value>", "Document title (overrides frontmatter)").option("--summary <value>", "Document summary").option("--display-author <value>", 'Display author name (e.g. "Jane Doe")').option("--display-publish-time <value>", "Display publish time (YYYY-MM-DD)").option("--icon <value>", "Document icon (ipfs:// or file:// URL)").option("--cover <value>", "Cover image (ipfs:// or file:// URL)").option("--site-url <value>", "Site URL").option("--layout <value>", 'Document layout (e.g. "Seed/Experimental/Newspaper")').option("--show-outline", "Show document outline").option("--no-show-outline", "Hide document outline").option("--show-activity", "Show document activity").option("--no-show-activity", "Hide document activity").option("--content-width <value>", "Content width (S, M, L)").option("--seed-experimental-logo <value>", "Experimental logo (ipfs:// or file:// URL)").option("--seed-experimental-home-order <value>", "Home ordering (UpdatedFirst, CreatedFirst)").option("--import-categories <value>", "Import categories (comma-separated)").option("--import-tags <value>", "Import tags (comma-separated)").option("--grobid-url <url>", "GROBID server URL for PDF extraction").option("--dry-run", "Preview extracted content without publishing").option("--force", "Overwrite existing document at the same path (creates new lineage)").option("-k, --key <name>", "Signing key name or account ID").option("-a, --account <uid>", "Target space/account UID (publish under a different account using a capability)").action(async (options2, cmd) => {
165608
165712
  const globalOpts = cmd.optsWithGlobals();
165609
165713
  const dev = !!globalOpts.dev;
165610
165714
  try {
@@ -165636,7 +165740,14 @@ function registerDocumentCommands(program2) {
165636
165740
  }
165637
165741
  const client = getClient(globalOpts);
165638
165742
  const key = resolveKey(options2.key, dev);
165639
- const account = key.accountId;
165743
+ const account = options2.account || key.accountId;
165744
+ let capability;
165745
+ if (options2.account && options2.account !== key.accountId) {
165746
+ capability = await resolveCapability(client, options2.account, key.accountId);
165747
+ if (!capability) {
165748
+ throw new Error(`No WRITER or AGENT capability found for key ${key.accountId} on account ${options2.account}. ` + `Use "account capabilities hm://${options2.account}" to check available capabilities.`);
165749
+ }
165750
+ }
165640
165751
  const { metadata: resolvedMeta, blobs: metaBlobs } = await resolveMetadataFileLinks(metadata);
165641
165752
  const rawPath = options2.path || slugify2(resolvedMeta.name || "Untitled");
165642
165753
  const path = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
@@ -165674,7 +165785,8 @@ function registerDocumentCommands(program2) {
165674
165785
  path,
165675
165786
  genesis: genesisBlock.cid.toString(),
165676
165787
  version: changeBlock.cid.toString(),
165677
- generation
165788
+ generation,
165789
+ capability
165678
165790
  }, signer);
165679
165791
  await client.publish({
165680
165792
  blobs: [
@@ -165707,18 +165819,13 @@ function registerDocumentCommands(program2) {
165707
165819
  doc.command("update <id>").description("Update document content and metadata (smart diff — only changed blocks are submitted)").option("-f, --file <path>", "Input file (format detected by extension: .md, .json). Diffs against existing content.").option("--name <value>", "Set document title").option("--summary <value>", "Set document summary").option("--display-author <value>", "Display author name").option("--display-publish-time <value>", "Display publish time (YYYY-MM-DD)").option("--icon <value>", "Document icon (ipfs:// or file:// URL)").option("--cover <value>", "Cover image (ipfs:// or file:// URL)").option("--site-url <value>", "Site URL").option("--layout <value>", "Document layout").option("--show-outline", "Show document outline").option("--no-show-outline", "Hide document outline").option("--show-activity", "Show document activity").option("--no-show-activity", "Hide document activity").option("--content-width <value>", "Content width (S, M, L)").option("--seed-experimental-logo <value>", "Experimental logo (ipfs:// or file:// URL)").option("--seed-experimental-home-order <value>", "Home ordering (UpdatedFirst, CreatedFirst)").option("--import-categories <value>", "Import categories (comma-separated)").option("--import-tags <value>", "Import tags (comma-separated)").option("--parent <blockId>", "Parent block ID for new content (default: root)").option("--delete-blocks <ids>", "Comma-separated block IDs to delete").option("-k, --key <name>", "Signing key name or account ID").action(async (id, options2, cmd) => {
165708
165820
  const globalOpts = cmd.optsWithGlobals();
165709
165821
  const dev = !!globalOpts.dev;
165710
- const client = getClient(globalOpts);
165711
165822
  try {
165823
+ const { id: resourceId, client } = await resolveIdWithClient(id, globalOpts);
165712
165824
  const key = resolveKey(options2.key, dev);
165713
165825
  const hasFileInput = !!options2.file;
165714
165826
  const ops = [];
165715
165827
  let fileBlobs = [];
165716
165828
  let metaBlobs = [];
165717
- const resourceId = unpackHmId3(id);
165718
- if (!resourceId) {
165719
- printError2(`Invalid Hypermedia ID: ${id}`);
165720
- process.exit(1);
165721
- }
165722
165829
  const resource = await client.request("Resource", resourceId);
165723
165830
  if (resource.type !== "document") {
165724
165831
  printError2(`Resource is ${resource.type}, not a document.`);
@@ -165767,6 +165874,7 @@ function registerDocumentCommands(program2) {
165767
165874
  const depCids = state.heads.map((h2) => CID.parse(h2));
165768
165875
  const newDepth = state.headDepth + 1;
165769
165876
  const signer = createSignerFromKey(key);
165877
+ const capability = await resolveCapability(client, docAccount, key.accountId);
165770
165878
  const { unsignedBytes, ts } = createChangeOps({ ops, genesisCid, deps: depCids, depth: newDepth });
165771
165879
  const changeBlock = await createChange(unsignedBytes, signer);
165772
165880
  const generation = Number(ts);
@@ -165775,7 +165883,8 @@ function registerDocumentCommands(program2) {
165775
165883
  path: docPath,
165776
165884
  genesis: state.genesis,
165777
165885
  version: changeBlock.cid.toString(),
165778
- generation
165886
+ generation,
165887
+ capability
165779
165888
  }, signer);
165780
165889
  await client.publish({
165781
165890
  blobs: [
@@ -165798,15 +165907,10 @@ function registerDocumentCommands(program2) {
165798
165907
  doc.command("delete <id>").description("Delete a document by publishing a tombstone ref").option("-k, --key <name>", "Signing key name or account ID").action(async (id, _options, cmd) => {
165799
165908
  const globalOpts = cmd.optsWithGlobals();
165800
165909
  const dev = !!globalOpts.dev;
165801
- const client = getClient(globalOpts);
165802
165910
  try {
165911
+ const { id: unpacked, client } = await resolveIdWithClient(id, globalOpts);
165803
165912
  const key = resolveKey(_options.key, dev);
165804
165913
  const signer = createSignerFromKey(key);
165805
- const unpacked = unpackHmId3(id);
165806
- if (!unpacked) {
165807
- printError2(`Invalid Hypermedia ID: ${id}`);
165808
- process.exit(1);
165809
- }
165810
165914
  const resource = await client.request("Resource", unpacked);
165811
165915
  if (resource.type !== "document") {
165812
165916
  printError2(`Cannot delete: resource is ${resource.type}, not a document.`);
@@ -165814,11 +165918,13 @@ function registerDocumentCommands(program2) {
165814
165918
  }
165815
165919
  const doc2 = resource.document;
165816
165920
  const generation = doc2.generationInfo ? Number(doc2.generationInfo.generation) : 0;
165921
+ const capability = await resolveCapability(client, unpacked.uid, key.accountId);
165817
165922
  const refInput = await createTombstoneRef({
165818
165923
  space: unpacked.uid,
165819
165924
  path: hmIdPathToEntityQueryPath3(unpacked.path),
165820
165925
  genesis: doc2.genesis,
165821
- generation
165926
+ generation,
165927
+ capability
165822
165928
  }, signer);
165823
165929
  await client.publish(refInput);
165824
165930
  if (!globalOpts.quiet)
@@ -165831,15 +165937,11 @@ function registerDocumentCommands(program2) {
165831
165937
  doc.command("fork <sourceId> <destinationId>").description("Fork a document to a new location (creates a copy)").option("-k, --key <name>", "Signing key name or account ID").action(async (sourceId, destinationId, _options, cmd) => {
165832
165938
  const globalOpts = cmd.optsWithGlobals();
165833
165939
  const dev = !!globalOpts.dev;
165834
- const client = getClient(globalOpts);
165835
165940
  try {
165941
+ const { id: sourceUnpacked, client } = await resolveIdWithClient(sourceId, globalOpts);
165942
+ const { id: dest } = await resolveIdWithClient(destinationId, globalOpts);
165836
165943
  const key = resolveKey(_options.key, dev);
165837
165944
  const signer = createSignerFromKey(key);
165838
- const sourceUnpacked = unpackHmId3(sourceId);
165839
- if (!sourceUnpacked) {
165840
- printError2(`Invalid source Hypermedia ID: ${sourceId}`);
165841
- process.exit(1);
165842
- }
165843
165945
  const resource = await client.request("Resource", sourceUnpacked);
165844
165946
  if (resource.type !== "document") {
165845
165947
  printError2(`Cannot fork: source is ${resource.type}, not a document.`);
@@ -165848,11 +165950,6 @@ function registerDocumentCommands(program2) {
165848
165950
  const doc2 = resource.document;
165849
165951
  if (!doc2.generationInfo)
165850
165952
  throw new Error("No generation info for source document");
165851
- const dest = unpackHmId3(destinationId);
165852
- if (!dest) {
165853
- printError2(`Invalid destination Hypermedia ID: ${destinationId}`);
165854
- process.exit(1);
165855
- }
165856
165953
  const refInput = await createVersionRef({
165857
165954
  space: dest.uid,
165858
165955
  path: hmIdPathToEntityQueryPath3(dest.path),
@@ -165873,20 +165970,11 @@ function registerDocumentCommands(program2) {
165873
165970
  doc.command("move <sourceId> <destinationId>").description("Move a document to a new location (creates redirect at source)").option("-k, --key <name>", "Signing key name or account ID").action(async (sourceId, destinationId, _options, cmd) => {
165874
165971
  const globalOpts = cmd.optsWithGlobals();
165875
165972
  const dev = !!globalOpts.dev;
165876
- const client = getClient(globalOpts);
165877
165973
  try {
165974
+ const { id: source, client } = await resolveIdWithClient(sourceId, globalOpts);
165975
+ const { id: dest } = await resolveIdWithClient(destinationId, globalOpts);
165878
165976
  const key = resolveKey(_options.key, dev);
165879
165977
  const signer = createSignerFromKey(key);
165880
- const source = unpackHmId3(sourceId);
165881
- const dest = unpackHmId3(destinationId);
165882
- if (!source) {
165883
- printError2(`Invalid source Hypermedia ID: ${sourceId}`);
165884
- process.exit(1);
165885
- }
165886
- if (!dest) {
165887
- printError2(`Invalid destination Hypermedia ID: ${destinationId}`);
165888
- process.exit(1);
165889
- }
165890
165978
  const resource = await client.request("Resource", source);
165891
165979
  if (resource.type !== "document") {
165892
165980
  printError2(`Cannot move: source is ${resource.type}, not a document.`);
@@ -165924,20 +166012,11 @@ function registerDocumentCommands(program2) {
165924
166012
  doc.command("redirect <id>").description("Create a redirect from one document to another").requiredOption("--to <targetId>", "Target Hypermedia ID to redirect to").option("--republish", "Republish target content at this location").option("-k, --key <name>", "Signing key name or account ID").action(async (id, _options, cmd) => {
165925
166013
  const globalOpts = cmd.optsWithGlobals();
165926
166014
  const dev = !!globalOpts.dev;
165927
- const client = getClient(globalOpts);
165928
166015
  try {
166016
+ const { id: source, client } = await resolveIdWithClient(id, globalOpts);
166017
+ const { id: target } = await resolveIdWithClient(_options.to, globalOpts);
165929
166018
  const key = resolveKey(_options.key, dev);
165930
166019
  const signer = createSignerFromKey(key);
165931
- const source = unpackHmId3(id);
165932
- const target = unpackHmId3(_options.to);
165933
- if (!source) {
165934
- printError2(`Invalid source Hypermedia ID: ${id}`);
165935
- process.exit(1);
165936
- }
165937
- if (!target) {
165938
- printError2(`Invalid target Hypermedia ID: ${_options.to}`);
165939
- process.exit(1);
165940
- }
165941
166020
  const resource = await client.request("Resource", source);
165942
166021
  if (resource.type !== "document") {
165943
166022
  printError2(`Cannot redirect: resource is ${resource.type}, not a document.`);
@@ -165964,15 +166043,10 @@ function registerDocumentCommands(program2) {
165964
166043
  });
165965
166044
  doc.command("changes <targetId>").description("List document change history").option("-q, --quiet", "Output CIDs and authors only").action(async (targetId, _options, cmd) => {
165966
166045
  const globalOpts = cmd.optsWithGlobals();
165967
- const client = getClient(globalOpts);
165968
166046
  const format2 = getOutputFormat(globalOpts);
165969
166047
  const pretty = isPretty(globalOpts);
165970
166048
  try {
165971
- const unpacked = unpackHmId3(targetId);
165972
- if (!unpacked) {
165973
- printError2(`Invalid Hypermedia ID: ${targetId}`);
165974
- process.exit(1);
165975
- }
166049
+ const { id: unpacked, client } = await resolveIdWithClient(targetId, globalOpts);
165976
166050
  const result = await client.request("ListChanges", { targetId: unpacked });
165977
166051
  if (globalOpts.quiet) {
165978
166052
  result.changes.forEach((c) => {
@@ -165991,15 +166065,10 @@ function registerDocumentCommands(program2) {
165991
166065
  });
165992
166066
  doc.command("stats <id>").description("Get interaction statistics for a document").action(async (id, _options, cmd) => {
165993
166067
  const globalOpts = cmd.optsWithGlobals();
165994
- const client = getClient(globalOpts);
165995
166068
  const format2 = getOutputFormat(globalOpts);
165996
166069
  const pretty = isPretty(globalOpts);
165997
166070
  try {
165998
- const unpacked = unpackHmId3(id);
165999
- if (!unpacked) {
166000
- printError2(`Invalid Hypermedia ID: ${id}`);
166001
- process.exit(1);
166002
- }
166071
+ const { id: unpacked, client } = await resolveIdWithClient(id, globalOpts);
166003
166072
  const result = await client.request("InteractionSummary", { id: unpacked });
166004
166073
  console.log(formatOutput2(result, format2, pretty));
166005
166074
  } catch (error) {
@@ -166133,17 +166202,12 @@ function registerCommentCommands(program2) {
166133
166202
  process.exit(1);
166134
166203
  }
166135
166204
  });
166136
- comment.command("list <targetId>").description("List comments on a document").option("-q, --quiet", "Output IDs and authors only").action(async (targetId, _options, cmd) => {
166205
+ comment.command("list <targetId>").description("List comments on a document or URL").option("-q, --quiet", "Output IDs and authors only").action(async (targetId, _options, cmd) => {
166137
166206
  const globalOpts = cmd.optsWithGlobals();
166138
- const client = getClient(globalOpts);
166139
166207
  const format2 = getOutputFormat(globalOpts);
166140
166208
  const pretty = isPretty(globalOpts);
166141
166209
  try {
166142
- const unpacked = unpackHmId3(targetId);
166143
- if (!unpacked) {
166144
- printError2(`Invalid Hypermedia ID: ${targetId}`);
166145
- process.exit(1);
166146
- }
166210
+ const { id: unpacked, client } = await resolveIdWithClient(targetId, globalOpts);
166147
166211
  const result = await client.request("ListComments", { targetId: unpacked });
166148
166212
  if (globalOpts.quiet) {
166149
166213
  result.comments.forEach((c) => {
@@ -166158,17 +166222,13 @@ function registerCommentCommands(program2) {
166158
166222
  process.exit(1);
166159
166223
  }
166160
166224
  });
166161
- comment.command("create <targetId>").description("Create a comment on a document").option("--body <text>", "Comment text").option("--file <path>", "Read comment text from file").option("--reply <commentId>", "Reply to an existing comment").option("-k, --key <name>", "Signing key name or account ID").action(async (targetId, options2, cmd) => {
166225
+ comment.command("create <targetId>").description("Create a comment on a document or URL").option("--body <text>", "Comment text").option("--file <path>", "Read comment text from file").option("--reply <commentId>", "Reply to an existing comment").option("-k, --key <name>", "Signing key name or account ID").action(async (targetId, options2, cmd) => {
166162
166226
  const globalOpts = cmd.optsWithGlobals();
166163
166227
  const dev = !!globalOpts.dev;
166164
- const client = getClient(globalOpts);
166165
166228
  try {
166229
+ const { id: unpacked, client } = await resolveIdWithClient(targetId, globalOpts);
166166
166230
  const key = resolveKey(options2.key, dev);
166167
166231
  const text3 = readCommentText(options2);
166168
- const unpacked = unpackHmId3(targetId);
166169
- if (!unpacked) {
166170
- throw new Error(`Invalid Hypermedia ID: ${targetId}`);
166171
- }
166172
166232
  const blockRef = unpacked.blockRef;
166173
166233
  const resourceId = { ...unpacked, blockRef: null };
166174
166234
  const resource = await client.request("Resource", resourceId);
@@ -166290,17 +166350,12 @@ function registerCommentCommands(program2) {
166290
166350
  process.exit(1);
166291
166351
  }
166292
166352
  });
166293
- comment.command("discussions <targetId>").description("List threaded discussions on a document").option("-c, --comment <id>", "Filter to specific thread").action(async (targetId, options2, cmd) => {
166353
+ comment.command("discussions <targetId>").description("List threaded discussions on a document or URL").option("-c, --comment <id>", "Filter to specific thread").action(async (targetId, options2, cmd) => {
166294
166354
  const globalOpts = cmd.optsWithGlobals();
166295
- const client = getClient(globalOpts);
166296
166355
  const format2 = getOutputFormat(globalOpts);
166297
166356
  const pretty = isPretty(globalOpts);
166298
166357
  try {
166299
- const unpacked = unpackHmId3(targetId);
166300
- if (!unpacked) {
166301
- printError2(`Invalid Hypermedia ID: ${targetId}`);
166302
- process.exit(1);
166303
- }
166358
+ const { id: unpacked, client } = await resolveIdWithClient(targetId, globalOpts);
166304
166359
  const result = await client.request("ListDiscussions", { targetId: unpacked, commentId: options2.comment });
166305
166360
  console.log(formatOutput2(result, format2, pretty));
166306
166361
  } catch (error) {
@@ -166532,7 +166587,6 @@ Examples:
166532
166587
  }
166533
166588
 
166534
166589
  // src/commands/account.ts
166535
- init_entity_id_url();
166536
166590
  function registerAccountCommands(program2) {
166537
166591
  const account = program2.command("account").description("Manage accounts (get, list, contacts, capabilities)");
166538
166592
  account.command("get <uid>").description("Get account information").option("-q, --quiet", "Output ID only").action(async (uid, _options, cmd) => {
@@ -166597,15 +166651,10 @@ function registerAccountCommands(program2) {
166597
166651
  });
166598
166652
  account.command("capabilities <id>").description("List access control capabilities").action(async (id, _options, cmd) => {
166599
166653
  const globalOpts = cmd.optsWithGlobals();
166600
- const client = getClient(globalOpts);
166601
166654
  const format2 = getOutputFormat(globalOpts);
166602
166655
  const pretty = isPretty(globalOpts);
166603
166656
  try {
166604
- const unpacked = unpackHmId3(id);
166605
- if (!unpacked) {
166606
- printError2(`Invalid Hypermedia ID: ${id}`);
166607
- process.exit(1);
166608
- }
166657
+ const { id: unpacked, client } = await resolveIdWithClient(id, globalOpts);
166609
166658
  const result = await client.request("ListCapabilities", { targetId: unpacked });
166610
166659
  console.log(formatOutput2(result, format2, pretty));
166611
166660
  } catch (error) {
@@ -166658,7 +166707,6 @@ function registerSearchCommand(program2) {
166658
166707
  }
166659
166708
 
166660
166709
  // src/commands/query.ts
166661
- init_entity_id_url();
166662
166710
  function registerQueryCommands(program2) {
166663
166711
  program2.command("query <space>").description("List documents in a space").option("-p, --path <path>", "Path prefix").option("-m, --mode <mode>", "Query mode: Children or AllDescendants", "Children").option("-l, --limit <n>", "Limit results", parseInt).option("--sort <term>", "Sort by: Path, Title, CreateTime, UpdateTime, DisplayTime").option("--reverse", "Reverse sort order").option("-q, --quiet", "Output IDs and names only").action(async (space, options2, cmd) => {
166664
166712
  const globalOpts = cmd.optsWithGlobals();
@@ -166723,15 +166771,10 @@ function registerQueryCommands(program2) {
166723
166771
  });
166724
166772
  program2.command("citations <id>").description("List documents citing this resource").option("-q, --quiet", "Output source IDs only").action(async (id, _options, cmd) => {
166725
166773
  const globalOpts = cmd.optsWithGlobals();
166726
- const client = getClient(globalOpts);
166727
166774
  const format2 = getOutputFormat(globalOpts);
166728
166775
  const pretty = isPretty(globalOpts);
166729
166776
  try {
166730
- const unpacked = unpackHmId3(id);
166731
- if (!unpacked) {
166732
- printError2(`Invalid Hypermedia ID: ${id}`);
166733
- process.exit(1);
166734
- }
166777
+ const { id: unpacked, client } = await resolveIdWithClient(id, globalOpts);
166735
166778
  const result = await client.request("ListCitations", { targetId: unpacked });
166736
166779
  if (globalOpts.quiet) {
166737
166780
  result.citations.forEach((c) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seed-hypermedia/cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/seed-hypermedia/seed.git",