@unbrained/pm-cli 2026.10.1 → 2026.10.3

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 (134) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +23 -0
  3. package/dist/cli/error-guidance.d.ts +5 -0
  4. package/dist/cli/error-guidance.js +1 -1
  5. package/dist/cli/main.js +2 -2
  6. package/dist/cli/register-structured-mutation.d.ts +2 -0
  7. package/dist/cli/register-structured-mutation.js +1 -1
  8. package/dist/cli/runtime/projection-retry.d.ts +9 -0
  9. package/dist/cli/runtime/projection-retry.js +2 -0
  10. package/dist/cli/runtime/selection.d.ts +5 -1
  11. package/dist/cli/runtime/selection.js +1 -1
  12. package/dist/cli-bundle/bundle-manifest.json +156 -156
  13. package/dist/cli-bundle/chunks/chunk-3AF2R3Y6.js +6 -0
  14. package/dist/cli-bundle/chunks/chunk-44UGMMQ6.js +3 -0
  15. package/dist/cli-bundle/chunks/{chunk-VWVFKPLX.js → chunk-5XKF5SQV.js} +38 -38
  16. package/dist/cli-bundle/chunks/{chunk-AYHLUJKD.js → chunk-6ST3SCQ6.js} +2 -2
  17. package/dist/cli-bundle/chunks/chunk-6Z4IV2MC.js +8 -0
  18. package/dist/cli-bundle/chunks/{chunk-A2UPOCSW.js → chunk-FW5LJXQY.js} +31 -31
  19. package/dist/cli-bundle/chunks/{chunk-SCZMJ5DC.js → chunk-H2DZW6I6.js} +2 -2
  20. package/dist/cli-bundle/chunks/chunk-H7CXQBGQ.js +2 -0
  21. package/dist/cli-bundle/chunks/{chunk-DGOIXJZJ.js → chunk-KP7NBQK3.js} +47 -47
  22. package/dist/cli-bundle/chunks/chunk-MKXBCBAN.js +20 -0
  23. package/dist/cli-bundle/chunks/chunk-QPKQKSQU.js +238 -0
  24. package/dist/cli-bundle/chunks/chunk-YCBGZF3T.js +2 -0
  25. package/dist/cli-bundle/chunks/chunk-YDWKGUQU.js +3 -0
  26. package/dist/cli-bundle/chunks/{register-list-query-L6HAHW7V.js → register-list-query-DYCGUQEW.js} +2 -2
  27. package/dist/cli-bundle/chunks/register-mutation-5PT3NW3A.js +20 -0
  28. package/dist/cli-bundle/chunks/{register-operations-3E5U4TOE.js → register-operations-QDDQOAAV.js} +2 -2
  29. package/dist/cli-bundle/chunks/{register-setup-VUD37N4A.js → register-setup-BBX67YMA.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-MOUCTR72.js → chunk-3BIYG72P.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/{chunk-T4PZJQG4.js → chunk-4FFPGNCJ.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-YBQ27KG7.js → chunk-73DA7ISY.js} +47 -47
  33. package/dist/cli-bundle/focused-chunks/{chunk-XUCXRZZZ.js → chunk-DBD4W4QP.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-6275G2AN.js → chunk-E754JDLY.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-4AORVUT4.js → chunk-EJN7DY3B.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-OMBDUJWZ.js → chunk-FKK2HI3S.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-ZJ3CLTV4.js → chunk-GMYUNHST.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-HIA2ZF64.js +12 -0
  39. package/dist/cli-bundle/focused-chunks/{chunk-RIJQQOEZ.js → chunk-UTRSM3ZK.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-EVMH4SKN.js → chunk-VVWYI2X7.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/chunk-WAJNX4RN.js +20 -0
  42. package/dist/cli-bundle/focused-chunks/chunk-WCY6HRZO.js +30 -0
  43. package/dist/cli-bundle/focused-chunks/{chunk-XB5Q2P7Z.js → chunk-XRSCIYHR.js} +2 -2
  44. package/dist/cli-bundle/focused-chunks/chunk-YC32ZSLS.js +165 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-IQBFYQF2.js → chunk-ZIXFMIUL.js} +2 -2
  46. package/dist/cli-bundle/main.js +22 -22
  47. package/dist/cli-bundle/sdk-authoring.js +1 -1
  48. package/dist/cli-bundle/sdk-contracts.js +2 -2
  49. package/dist/cli-bundle/sdk-core.js +31 -31
  50. package/dist/cli-bundle/sdk-governance.js +1 -1
  51. package/dist/cli-bundle/sdk-graph.js +1 -1
  52. package/dist/cli-bundle/sdk-merge.js +48 -48
  53. package/dist/cli-bundle/sdk-query.js +1 -1
  54. package/dist/cli-bundle/sdk-runtime.js +1 -1
  55. package/dist/cli-bundle/sdk-testing.js +1 -1
  56. package/dist/cli-bundle/sdk.js +7 -7
  57. package/dist/core/fs/fs-utils.d.ts +11 -0
  58. package/dist/core/fs/fs-utils.js +2 -2
  59. package/dist/core/shared/errors.d.ts +9 -0
  60. package/dist/core/shared/errors.js +1 -1
  61. package/dist/core/shared/secret-rules.js +1 -1
  62. package/dist/core/store/settings.d.ts +15 -5
  63. package/dist/core/store/settings.js +3 -3
  64. package/dist/core/telemetry/runtime.js +3 -3
  65. package/dist/mcp/server.js +1 -1
  66. package/dist/sdk/agent/closed-domain-contracts.js +1 -1
  67. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  68. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  69. package/dist/sdk/item-transaction.d.ts +11 -0
  70. package/dist/sdk/item-transaction.js +1 -1
  71. package/dist/sdk/linked-artifacts.d.ts +1 -1
  72. package/dist/sdk/linked-artifacts.js +1 -1
  73. package/dist/sdk/pagination.js +1 -1
  74. package/dist/sdk/public-surface.json +1 -1
  75. package/dist/sdk/query/context.d.ts +2 -0
  76. package/dist/sdk/query/context.js +1 -1
  77. package/dist/sdk/query/get.js +1 -1
  78. package/dist/sdk/query/list.js +1 -1
  79. package/dist/sdk/query/search-contracts.js +1 -1
  80. package/dist/sdk/query/search-pagination.d.ts +4 -0
  81. package/dist/sdk/query/search-pagination.js +1 -1
  82. package/dist/sdk/query/search.js +1 -1
  83. package/dist/sdk/read-output/options.d.ts +14 -0
  84. package/dist/sdk/read-output/options.js +2 -0
  85. package/dist/sdk/read-output-budget.js +1 -1
  86. package/dist/sdk/read-output-contracts.js +1 -1
  87. package/dist/sdk/read-output-rows.d.ts +4 -0
  88. package/dist/sdk/read-output-rows.js +1 -1
  89. package/dist/sdk/runtime-primitives.d.ts +2 -2
  90. package/dist/sdk/runtime-primitives.js +1 -1
  91. package/dist/sdk/runtime.js +1 -1
  92. package/dist/sdk/test/execution.js +2 -2
  93. package/dist/sdk/test/workspace-snapshot.d.ts +11 -0
  94. package/dist/sdk/test/workspace-snapshot.js +2 -0
  95. package/dist/sdk/workspace-transaction.d.ts +2 -0
  96. package/dist/sdk/workspace-transaction.js +2 -2
  97. package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +109 -0
  98. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +27 -0
  99. package/docs/SDK.md +98 -0
  100. package/docs/TESTING.md +32 -5
  101. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +5 -3
  102. package/marketplace.json +2 -2
  103. package/package.json +5 -4
  104. package/packages/pm-beads/package.json +1 -1
  105. package/packages/pm-calendar/package.json +1 -1
  106. package/packages/pm-command-kit/package.json +1 -1
  107. package/packages/pm-digital-twin/package.json +1 -1
  108. package/packages/pm-governance-audit/package.json +1 -1
  109. package/packages/pm-guide-shell/package.json +1 -1
  110. package/packages/pm-kanban/package.json +1 -1
  111. package/packages/pm-lifecycle-hooks/package.json +1 -1
  112. package/packages/pm-linked-test-adapters/package.json +1 -1
  113. package/packages/pm-search-advanced/package.json +1 -1
  114. package/packages/pm-templates/package.json +1 -1
  115. package/packages/pm-todos/package.json +1 -1
  116. package/packages/pm-vcs/package.json +1 -1
  117. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  118. package/plugins/pm-claude/package.json +2 -2
  119. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  120. package/plugins/pm-codex/package.json +2 -2
  121. package/plugins/pm-codex/plugin.json +1 -1
  122. package/dist/cli-bundle/chunks/chunk-7E2EBJLY.js +0 -3
  123. package/dist/cli-bundle/chunks/chunk-BNAT4EYR.js +0 -20
  124. package/dist/cli-bundle/chunks/chunk-HGJLVN56.js +0 -8
  125. package/dist/cli-bundle/chunks/chunk-JAVO3Z42.js +0 -6
  126. package/dist/cli-bundle/chunks/chunk-TV3YDE36.js +0 -2
  127. package/dist/cli-bundle/chunks/chunk-UIAH7UFK.js +0 -238
  128. package/dist/cli-bundle/chunks/chunk-USTAFHIM.js +0 -2
  129. package/dist/cli-bundle/chunks/chunk-YM342ELM.js +0 -3
  130. package/dist/cli-bundle/chunks/register-mutation-6OCZVTW5.js +0 -20
  131. package/dist/cli-bundle/focused-chunks/chunk-3CAZ7Z4R.js +0 -30
  132. package/dist/cli-bundle/focused-chunks/chunk-DJPP2HAK.js +0 -12
  133. package/dist/cli-bundle/focused-chunks/chunk-IDB6E3ZV.js +0 -165
  134. package/dist/cli-bundle/focused-chunks/chunk-UPOMLSW7.js +0 -20
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="bb855f72-341c-5dc3-ade5-dd3102275cd8")}catch(e2){}})();import{assertInitializedTracker}from"./environment/tracker-preflight.js";import fs from"node:fs/promises";import path from"node:path";import fg from"fast-glob";import{isFileAbsentError}from"../core/fs/fs-utils.js";import{getActiveExtensionRegistrations}from"../core/extensions/index.js";import{assertNoAmbiguousBareCommaEntry,assertNoUnknownCsvKeys,createStdinTokenResolver,looksLikeGenericKeyValueEntry,parseCsvKv}from"../core/item/parse.js";import{resolveItemTypeRegistry}from"../core/item/type-registry.js";import{isRemoteLinkedArtifactReference}from"../core/validate/linked-artifact-reference.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{stableValueEquals}from"../core/shared/serialization.js";import{locateItem,mutateItem,readLocatedItem}from"../core/store/item-store.js";import{resolvePmRoot,resolveWorkspaceRoot}from"../core/store/paths.js";import{readSettings}from"../core/store/settings.js";import{SCOPE_VALUES}from"../types/index.js";import{resolveAuthor}from"../core/shared/author.js";const LINKED_ARTIFACT_ADD_KEYS=["path","scope","note"];const LINKED_ARTIFACT_ADD_GLOB_KEYS=["pattern","glob","path","scope","note"];const LINKED_ARTIFACT_REMOVE_KEYS=["path"];const LINKED_ARTIFACT_MIGRATE_KEYS=["from","to"];const LINKED_ARTIFACT_REMOVE_UNSUPPORTED_KEYS=new Set(["note","scope"]);function ensureScope(raw){const value=raw??"project";if(!SCOPE_VALUES.includes(value)){throw new PmCliError(`Invalid scope "${raw}". Valid scopes: ${SCOPE_VALUES.join(", ")} (default: project).`,EXIT_CODE.USAGE)}return value}function looksLikeStructuredPathEntry(raw){if(raw.startsWith("```")||raw.includes("\n")){return true}if(/^(?:[-*+]\s+)?(?:path|scope|note)\s*[:=]/i.test(raw)){return true}const firstCommaIndex=raw.indexOf(",");const leadingSegment=raw.slice(0,firstCommaIndex>=0?firstCommaIndex:raw.length);const equalsIndex=leadingSegment.indexOf("=");if(equalsIndex>=0&&!/\s/u.test(raw)&&(/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(raw)||/^(?:[A-Za-z]:[\\/]|[\\/]{1,2}|\.\.?(?:[\\/]))/u.test(raw)||[raw.indexOf("/"),raw.indexOf("\\")].some(separatorIndex=>separatorIndex>=0&&separatorIndex<equalsIndex))){return false}return leadingSegment.includes("=")||looksLikeGenericKeyValueEntry(raw)}function hasBalancedParentheses(value){let depth=0;for(const character of value){if(character==="(")depth+=1;if(character===")")depth-=1;if(depth<0)return false}return depth===0}function parseDocumentationReference(trimmed){if(/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(trimmed)&&!looksLikeStructuredPathEntry(trimmed)){return{path:trimmed,scope:"project",note:void 0}}const labelEnd=trimmed.indexOf("](");if(trimmed.startsWith("[")&&labelEnd>0&&trimmed.endsWith(")")){const destination2=trimmed.slice(labelEnd+2,-1).trim();if(destination2.length>0&&hasBalancedParentheses(destination2)){return{path:destination2,scope:"project",note:trimmed.slice(1,labelEnd).trim()||void 0}}}const delimiterIndex=trimmed.indexOf(",");if(delimiterIndex<0)return void 0;const label=trimmed.slice(0,delimiterIndex).trim();const destination=trimmed.slice(delimiterIndex+1).trim();if(label.length===0||!/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(destination)){return void 0}return{path:destination,scope:"project",note:label}}function parseAddEntries(raw,bareNoun){if(!raw)return[];return raw.flatMap(entry=>{const trimmed=entry.trim();if(bareNoun==="doc"){const reference=parseDocumentationReference(trimmed);if(reference!==void 0)return[reference]}assertNoAmbiguousBareCommaEntry(trimmed,"--add",`${bareNoun} path`,looksLikeStructuredPathEntry(trimmed));const kv=looksLikeStructuredPathEntry(trimmed)?parseCsvKv(entry,"--add"):{path:trimmed};assertNoUnknownCsvKeys(kv,"--add",LINKED_ARTIFACT_ADD_KEYS);if(!kv.path){throw new PmCliError(`--add requires path=<value> or a bare ${bareNoun} path`,EXIT_CODE.USAGE)}return[{path:kv.path,scope:ensureScope(kv.scope),note:kv.note?.trim()||void 0}]})}function parseAddGlobEntries(raw){if(!raw)return[];return raw.map(entry=>{const trimmed=entry.trim();if(!trimmed){throw new PmCliError("--add-glob requires a glob pattern value",EXIT_CODE.USAGE)}if(trimmed.includes("=")||/^(?:[-*+]\s+)?(?:pattern|glob|path)\s*[:=]/i.test(trimmed)||trimmed.startsWith("```")){const kv=parseCsvKv(trimmed,"--add-glob");assertNoUnknownCsvKeys(kv,"--add-glob",LINKED_ARTIFACT_ADD_GLOB_KEYS);const pattern=kv.pattern?.trim()||kv.glob?.trim()||kv.path?.trim();if(!pattern){throw new PmCliError("--add-glob key/value form requires pattern=<glob>",EXIT_CODE.USAGE)}return{pattern,scope:ensureScope(kv.scope),note:kv.note?.trim()||void 0}}return{pattern:trimmed,scope:"project"}})}function parseRemoveEntries(raw){if(!raw)return[];return raw.map(entry=>{const trimmed=entry.trim();if(!trimmed){throw new PmCliError("--remove requires a path value",EXIT_CODE.USAGE)}if(trimmed.includes("=")||/^(?:[-*+]\s+)?path\s*[:=]/i.test(trimmed)||trimmed.startsWith("```")){const kv=parseCsvKv(trimmed,"--remove");const unsupportedRemoveKeys=Object.keys(kv).filter(key=>LINKED_ARTIFACT_REMOVE_UNSUPPORTED_KEYS.has(key.toLowerCase()));if(unsupportedRemoveKeys.length>0){throw new PmCliError(`--remove identifies a linked artifact by path only and does not accept ${unsupportedRemoveKeys.map(key=>`"${key}"`).join(", ")}. Pass just the path (path=<value>, path:<value>, or a bare path); record removal context with --message "<why removed>".`,EXIT_CODE.USAGE)}assertNoUnknownCsvKeys(kv,"--remove",LINKED_ARTIFACT_REMOVE_KEYS);if(!kv.path){throw new PmCliError("--remove key/value form requires path=<value>",EXIT_CODE.USAGE)}return kv.path}return trimmed})}function parseMigrateEntries(raw){if(!raw)return[];return raw.map(entry=>{const kv=parseCsvKv(entry,"--migrate");assertNoUnknownCsvKeys(kv,"--migrate",LINKED_ARTIFACT_MIGRATE_KEYS);const from=kv.from?.trim();const to=kv.to?.trim();if(!from||!to){throw new PmCliError("--migrate requires from=<value> and to=<value>",EXIT_CODE.USAGE)}return{from,to}})}function applyPathMigrations(artifactPath,migrations){let next=artifactPath;for(const migration of migrations){if(next.startsWith(migration.from)){next=`${migration.to}${next.slice(migration.from.length)}`}}return next}function assertLinkedArtifactMutationIsUnambiguous(adds,removes,migrations=[]){if(adds.length===0||removes.length===0){return}const addedPaths=new Set(adds.map(entry=>applyPathMigrations(entry.path,migrations)));const conflicts=[...new Set(removes.map(entry=>applyPathMigrations(entry,migrations)).filter(entry=>addedPaths.has(entry)))].sort((left,right)=>left.localeCompare(right));if(conflicts.length===0){return}throw new PmCliError(`Linked artifact mutation cannot add and remove the same normalized path in one transaction: ${conflicts.join(", ")}. Split the replacement into separate commands so each history event has one unambiguous intent.`,EXIT_CODE.USAGE,{code:"linked_artifact_mutation_conflict",reason:"same_path_added_and_removed",required:"Use distinct normalized paths for --add and --remove in one invocation.",why:"Conflicting batch intent cannot be applied deterministically without silently discarding metadata or a removal.",nextSteps:["Run the removal and addition as separate commands with a --message describing each intent."]})}function normalizeLinkedPath(value){return value.split(path.sep).join("/")}function anchorLinkedPath(value,workspaceRoot,invocationRoot=process.cwd()){const trimmed=value.trim();if(isRemoteLinkedArtifactReference(trimmed)){return trimmed}if(path.isAbsolute(trimmed)||/^[A-Za-z]:[\\/]/.test(trimmed)){return normalizeLinkedPath(trimmed.replaceAll("\\",path.sep))}const invocationRelativeToWorkspace=path.relative(workspaceRoot,invocationRoot);if(invocationRelativeToWorkspace.startsWith(`..${path.sep}`)||invocationRelativeToWorkspace===".."||path.isAbsolute(invocationRelativeToWorkspace)){return normalizeLinkedPath(path.normalize(trimmed))}return normalizeLinkedPath(path.relative(workspaceRoot,path.resolve(invocationRoot,trimmed)))}async function expandAddGlobEntries(entries,workspaceRoot=process.cwd(),invocationRoot=process.cwd()){const expanded=[];for(const entry of entries){const absolutePattern=path.isAbsolute(entry.pattern);const matches=await fg(entry.pattern,{cwd:invocationRoot,absolute:absolutePattern,onlyFiles:true,dot:true,unique:true,followSymbolicLinks:true});const sortedMatches=[...new Set(matches.map(match=>anchorLinkedPath(match,workspaceRoot,invocationRoot)))].sort((left,right)=>left.localeCompare(right));for(const matchedPath of sortedMatches){expanded.push({path:matchedPath,scope:entry.scope,note:entry.note})}}return expanded}function applyStandaloneNote(adds,note,hasAddFlags){if(note===void 0){return adds}if(!hasAddFlags){throw new PmCliError("--note requires --add or --add-glob in the same invocation (the note annotates the links being added)",EXIT_CODE.USAGE)}const trimmed=note.trim();if(trimmed.length===0){return adds}return adds.map(entry=>entry.note===void 0?{...entry,note:trimmed}:entry)}function artifactKey(value){return`${value.path}::${value.scope}`}function sortLinkedArtifacts(artifacts){return[...artifacts].sort((left,right)=>{const byPath=left.path.localeCompare(right.path);if(byPath!==0)return byPath;return left.scope.localeCompare(right.scope)})}function dedupeLinkedArtifacts(artifacts){return[...new Map(artifacts.map(entry=>[artifactKey(entry),entry])).values()].map(entry=>({...entry,note:entry.note?.trim()||void 0}))}async function validateLinkedPaths(paths,workspaceRoot=process.cwd()){const uniquePaths=[...new Set(paths)].sort((left,right)=>left.localeCompare(right));const existingFiles=[];const missingPaths=[];const nonFilePaths=[];const remoteReferences=[];for(const relativePath of uniquePaths){if(isRemoteLinkedArtifactReference(relativePath)){remoteReferences.push(relativePath.trim());continue}const resolvedPath=path.isAbsolute(relativePath)?relativePath:path.resolve(workspaceRoot,relativePath);try{const stats=await fs.stat(resolvedPath);if(stats.isFile()){existingFiles.push(relativePath)}else{nonFilePaths.push(relativePath)}}catch(error){if(typeof error==="object"&&error!==null&&"code"in error&&isFileAbsentError(error)){missingPaths.push(relativePath);continue}nonFilePaths.push(relativePath)}}return{checked:uniquePaths.length,existing_files:existingFiles,missing_paths:missingPaths,non_file_paths:nonFilePaths,remote_references:remoteReferences}}function applyLinkedArtifactMigrations(current,adds,removes,migrations){let count=0;for(let index=0;index<current.length;index+=1){const migratedPath=applyPathMigrations(current[index].path,migrations);if(migratedPath!==current[index].path){current[index]={...current[index],path:migratedPath};count+=1}}const migratedAdds=adds.map(entry=>{const migratedPath=applyPathMigrations(entry.path,migrations);if(migratedPath!==entry.path)count+=1;return{...entry,path:migratedPath}});return{adds:migratedAdds,removes:removes.map(entry=>applyPathMigrations(entry,migrations)),count}}function mergeLinkedArtifactChanges(current,adds,removes,appendStable){const merged=dedupeLinkedArtifacts(current);for(const add of adds){const index=merged.findIndex(entry=>entry.path===add.path&&entry.scope===add.scope);if(index<0){merged.push(add)}else if(add.note!==void 0){merged[index]={...merged[index],note:add.note}}}if(removes.length>0){for(let index=merged.length-1;index>=0;index-=1){if(removes.includes(merged[index].path))merged.splice(index,1)}}return appendStable?merged:sortLinkedArtifacts(merged)}async function buildLinkedArtifactResult(params){const paths=params.artifacts.map(entry=>entry.path);return{id:params.id,artifacts:params.artifacts,changed:params.changed,count:params.artifacts.length,migrations_applied:params.migrationsApplied&&params.migrationsApplied>0?params.migrationsApplied:void 0,validation:params.options.validatePaths||params.changed?await validateLinkedPaths(paths,params.workspaceRoot):void 0}}async function runLinkedArtifacts(id,options,global2,config){const{metadataKey}=config;const stdinResolver=createStdinTokenResolver();const pmRoot=resolvePmRoot(process.cwd(),global2.path);const workspaceRoot=resolveWorkspaceRoot(pmRoot);const invocationRoot=process.cwd();await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());const resolvedAdds=await stdinResolver.resolveList(options.add,"--add");const resolvedAddGlobs=await stdinResolver.resolveList(options.addGlob,"--add-glob");const resolvedRemoves=await stdinResolver.resolveList(options.remove,"--remove");const resolvedMigrations=await stdinResolver.resolveList(options.migrate,"--migrate");const parsedAdds=parseAddEntries(resolvedAdds,config.bareNoun).map(entry=>({...entry,path:anchorLinkedPath(entry.path,workspaceRoot,invocationRoot)}));const addGlobs=parseAddGlobEntries(resolvedAddGlobs);const expandedGlobAdds=await expandAddGlobEntries(addGlobs,workspaceRoot,invocationRoot);const adds=applyStandaloneNote([...parsedAdds,...expandedGlobAdds],options.note,parsedAdds.length>0||addGlobs.length>0);const removes=parseRemoveEntries(resolvedRemoves).map(entry=>anchorLinkedPath(entry,workspaceRoot,invocationRoot));const migrations=parseMigrateEntries(resolvedMigrations);assertLinkedArtifactMutationIsUnambiguous(adds,removes,migrations);const shouldMutate=adds.length>0||removes.length>0||migrations.length>0;if(!shouldMutate){const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);if(!located){throw new PmCliError(`Item ${id} not found`,EXIT_CODE.NOT_FOUND)}const loaded=await readLocatedItem(located,{schema:settings.schema});const artifacts2=loaded.document.metadata[metadataKey]??[];return buildLinkedArtifactResult({id:located.id,artifacts:artifacts2,changed:false,options,workspaceRoot})}const author=resolveAuthor(options.author,settings.author_default);const result=await mutateItem({pmRoot,settings,id,op:config.op,author,message:options.message,force:options.force,skipNoop:true,mutate(document){const metadata=document.metadata;const current=metadata[metadataKey]??[];const next=[...current];const migrated=applyLinkedArtifactMigrations(next,adds,removes,migrations);const normalized=mergeLinkedArtifactChanges(next,migrated.adds,migrated.removes,config.supportsAppendStable&&options.appendStable===true);if(normalized.length>0){metadata[metadataKey]=normalized}else{delete metadata[metadataKey]}const changed=!stableValueEquals(current,normalized);return{changedFields:changed?[metadataKey]:[],warnings:changed&&migrated.count>0?[`path_migrations_applied:${migrated.count}`]:[]}}});const artifacts=result.item[metadataKey]??[];const migrationWarning=result.warnings.find(warning=>warning.startsWith("path_migrations_applied:"));const migrationCount=migrationWarning?Number(migrationWarning.slice("path_migrations_applied:".length)):0;return buildLinkedArtifactResult({id:result.item.id,artifacts,changed:result.changedFields.includes(metadataKey),migrationsApplied:migrationCount,options,workspaceRoot})}function renameArtifactsResultKey(result,key){const out={};for(const[field,value]of Object.entries(result)){out[field==="artifacts"?key:field]=value}return out}export{LINKED_ARTIFACT_ADD_GLOB_KEYS,LINKED_ARTIFACT_ADD_KEYS,LINKED_ARTIFACT_MIGRATE_KEYS,LINKED_ARTIFACT_REMOVE_KEYS,anchorLinkedPath,applyPathMigrations,applyStandaloneNote,artifactKey,assertLinkedArtifactMutationIsUnambiguous,dedupeLinkedArtifacts,ensureScope,expandAddGlobEntries,looksLikeStructuredPathEntry,normalizeLinkedPath,parseAddEntries,parseAddGlobEntries,parseMigrateEntries,parseRemoveEntries,renameArtifactsResultKey,runLinkedArtifacts,sortLinkedArtifacts,validateLinkedPaths};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4adcee44-f1a4-5ac8-b9a9-5981a3197bce")}catch(e2){}})();import{assertInitializedTracker}from"./environment/tracker-preflight.js";import fs from"node:fs/promises";import path from"node:path";import{glob}from"tinyglobby";import{isFileAbsentError}from"../core/fs/fs-utils.js";import{getActiveExtensionRegistrations}from"../core/extensions/index.js";import{assertNoAmbiguousBareCommaEntry,assertNoUnknownCsvKeys,createStdinTokenResolver,looksLikeGenericKeyValueEntry,parseCsvKv}from"../core/item/parse.js";import{resolveItemTypeRegistry}from"../core/item/type-registry.js";import{isRemoteLinkedArtifactReference}from"../core/validate/linked-artifact-reference.js";import{EXIT_CODE}from"../core/shared/constants.js";import{PmCliError}from"../core/shared/errors.js";import{stableValueEquals}from"../core/shared/serialization.js";import{locateItem,mutateItem,readLocatedItem}from"../core/store/item-store.js";import{resolvePmRoot,resolveWorkspaceRoot}from"../core/store/paths.js";import{readSettings}from"../core/store/settings.js";import{SCOPE_VALUES}from"../types/index.js";import{resolveAuthor}from"../core/shared/author.js";const LINKED_ARTIFACT_ADD_KEYS=["path","scope","note"];const LINKED_ARTIFACT_ADD_GLOB_KEYS=["pattern","glob","path","scope","note"];const LINKED_ARTIFACT_REMOVE_KEYS=["path"];const LINKED_ARTIFACT_MIGRATE_KEYS=["from","to"];const LINKED_ARTIFACT_REMOVE_UNSUPPORTED_KEYS=new Set(["note","scope"]);function ensureScope(raw){const value=raw??"project";if(!SCOPE_VALUES.includes(value)){throw new PmCliError(`Invalid scope "${raw}". Valid scopes: ${SCOPE_VALUES.join(", ")} (default: project).`,EXIT_CODE.USAGE)}return value}function looksLikeStructuredPathEntry(raw){if(raw.startsWith("```")||raw.includes("\n")){return true}if(/^(?:[-*+]\s+)?(?:path|scope|note)\s*[:=]/i.test(raw)){return true}const firstCommaIndex=raw.indexOf(",");const leadingSegment=raw.slice(0,firstCommaIndex>=0?firstCommaIndex:raw.length);const equalsIndex=leadingSegment.indexOf("=");if(equalsIndex>=0&&!/\s/u.test(raw)&&(/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(raw)||/^(?:[A-Za-z]:[\\/]|[\\/]{1,2}|\.\.?(?:[\\/]))/u.test(raw)||[raw.indexOf("/"),raw.indexOf("\\")].some(separatorIndex=>separatorIndex>=0&&separatorIndex<equalsIndex))){return false}return leadingSegment.includes("=")||looksLikeGenericKeyValueEntry(raw)}function hasBalancedParentheses(value){let depth=0;for(const character of value){if(character==="(")depth+=1;if(character===")")depth-=1;if(depth<0)return false}return depth===0}function parseDocumentationReference(trimmed){if(/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(trimmed)&&!looksLikeStructuredPathEntry(trimmed)){return{path:trimmed,scope:"project",note:void 0}}const labelEnd=trimmed.indexOf("](");if(trimmed.startsWith("[")&&labelEnd>0&&trimmed.endsWith(")")){const destination2=trimmed.slice(labelEnd+2,-1).trim();if(destination2.length>0&&hasBalancedParentheses(destination2)){return{path:destination2,scope:"project",note:trimmed.slice(1,labelEnd).trim()||void 0}}}const delimiterIndex=trimmed.indexOf(",");if(delimiterIndex<0)return void 0;const label=trimmed.slice(0,delimiterIndex).trim();const destination=trimmed.slice(delimiterIndex+1).trim();if(label.length===0||!/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(destination)){return void 0}return{path:destination,scope:"project",note:label}}function parseAddEntries(raw,bareNoun){if(!raw)return[];return raw.flatMap(entry=>{const trimmed=entry.trim();if(bareNoun==="doc"){const reference=parseDocumentationReference(trimmed);if(reference!==void 0)return[reference]}assertNoAmbiguousBareCommaEntry(trimmed,"--add",`${bareNoun} path`,looksLikeStructuredPathEntry(trimmed));const kv=looksLikeStructuredPathEntry(trimmed)?parseCsvKv(entry,"--add"):{path:trimmed};assertNoUnknownCsvKeys(kv,"--add",LINKED_ARTIFACT_ADD_KEYS);if(!kv.path){throw new PmCliError(`--add requires path=<value> or a bare ${bareNoun} path`,EXIT_CODE.USAGE)}return[{path:kv.path,scope:ensureScope(kv.scope),note:kv.note?.trim()||void 0}]})}function parseAddGlobEntries(raw){if(!raw)return[];return raw.map(entry=>{const trimmed=entry.trim();if(!trimmed){throw new PmCliError("--add-glob requires a glob pattern value",EXIT_CODE.USAGE)}if(trimmed.includes("=")||/^(?:[-*+]\s+)?(?:pattern|glob|path)\s*[:=]/i.test(trimmed)||trimmed.startsWith("```")){const kv=parseCsvKv(trimmed,"--add-glob");assertNoUnknownCsvKeys(kv,"--add-glob",LINKED_ARTIFACT_ADD_GLOB_KEYS);const pattern=kv.pattern?.trim()||kv.glob?.trim()||kv.path?.trim();if(!pattern){throw new PmCliError("--add-glob key/value form requires pattern=<glob>",EXIT_CODE.USAGE)}return{pattern,scope:ensureScope(kv.scope),note:kv.note?.trim()||void 0}}return{pattern:trimmed,scope:"project"}})}function parseRemoveEntries(raw){if(!raw)return[];return raw.map(entry=>{const trimmed=entry.trim();if(!trimmed){throw new PmCliError("--remove requires a path value",EXIT_CODE.USAGE)}if(trimmed.includes("=")||/^(?:[-*+]\s+)?path\s*[:=]/i.test(trimmed)||trimmed.startsWith("```")){const kv=parseCsvKv(trimmed,"--remove");const unsupportedRemoveKeys=Object.keys(kv).filter(key=>LINKED_ARTIFACT_REMOVE_UNSUPPORTED_KEYS.has(key.toLowerCase()));if(unsupportedRemoveKeys.length>0){throw new PmCliError(`--remove identifies a linked artifact by path only and does not accept ${unsupportedRemoveKeys.map(key=>`"${key}"`).join(", ")}. Pass just the path (path=<value>, path:<value>, or a bare path); record removal context with --message "<why removed>".`,EXIT_CODE.USAGE)}assertNoUnknownCsvKeys(kv,"--remove",LINKED_ARTIFACT_REMOVE_KEYS);if(!kv.path){throw new PmCliError("--remove key/value form requires path=<value>",EXIT_CODE.USAGE)}return kv.path}return trimmed})}function parseMigrateEntries(raw){if(!raw)return[];return raw.map(entry=>{const kv=parseCsvKv(entry,"--migrate");assertNoUnknownCsvKeys(kv,"--migrate",LINKED_ARTIFACT_MIGRATE_KEYS);const from=kv.from?.trim();const to=kv.to?.trim();if(!from||!to){throw new PmCliError("--migrate requires from=<value> and to=<value>",EXIT_CODE.USAGE)}return{from,to}})}function applyPathMigrations(artifactPath,migrations){let next=artifactPath;for(const migration of migrations){if(next.startsWith(migration.from)){next=`${migration.to}${next.slice(migration.from.length)}`}}return next}function assertLinkedArtifactMutationIsUnambiguous(adds,removes,migrations=[]){if(adds.length===0||removes.length===0){return}const addedPaths=new Set(adds.map(entry=>applyPathMigrations(entry.path,migrations)));const conflicts=[...new Set(removes.map(entry=>applyPathMigrations(entry,migrations)).filter(entry=>addedPaths.has(entry)))].sort((left,right)=>left.localeCompare(right));if(conflicts.length===0){return}throw new PmCliError(`Linked artifact mutation cannot add and remove the same normalized path in one transaction: ${conflicts.join(", ")}. Split the replacement into separate commands so each history event has one unambiguous intent.`,EXIT_CODE.USAGE,{code:"linked_artifact_mutation_conflict",reason:"same_path_added_and_removed",required:"Use distinct normalized paths for --add and --remove in one invocation.",why:"Conflicting batch intent cannot be applied deterministically without silently discarding metadata or a removal.",nextSteps:["Run the removal and addition as separate commands with a --message describing each intent."]})}function normalizeLinkedPath(value){return value.split(path.sep).join("/")}function anchorLinkedPath(value,workspaceRoot,invocationRoot=process.cwd()){const trimmed=value.trim();if(isRemoteLinkedArtifactReference(trimmed)){return trimmed}if(path.isAbsolute(trimmed)||/^[A-Za-z]:[\\/]/.test(trimmed)){return normalizeLinkedPath(trimmed.replaceAll("\\",path.sep))}const invocationRelativeToWorkspace=path.relative(workspaceRoot,invocationRoot);if(invocationRelativeToWorkspace.startsWith(`..${path.sep}`)||invocationRelativeToWorkspace===".."||path.isAbsolute(invocationRelativeToWorkspace)){return normalizeLinkedPath(path.normalize(trimmed))}return normalizeLinkedPath(path.relative(workspaceRoot,path.resolve(invocationRoot,trimmed)))}async function expandAddGlobEntries(entries,workspaceRoot=process.cwd(),invocationRoot=process.cwd()){const expanded=[];for(const entry of entries){if(path.resolve(invocationRoot,entry.pattern)===path.resolve(invocationRoot))continue;const absolutePattern=path.isAbsolute(entry.pattern);const matches=await glob(entry.pattern,{cwd:invocationRoot,absolute:absolutePattern,onlyFiles:true,dot:true,expandDirectories:false,followSymbolicLinks:true});const sortedMatches=[...new Set(matches.map(match=>anchorLinkedPath(match,workspaceRoot,invocationRoot)))].sort((left,right)=>left.localeCompare(right));for(const matchedPath of sortedMatches){expanded.push({path:matchedPath,scope:entry.scope,note:entry.note})}}return expanded}function applyStandaloneNote(adds,note,hasAddFlags){if(note===void 0){return adds}if(!hasAddFlags){throw new PmCliError("--note requires --add or --add-glob in the same invocation (the note annotates the links being added)",EXIT_CODE.USAGE)}const trimmed=note.trim();if(trimmed.length===0){return adds}return adds.map(entry=>entry.note===void 0?{...entry,note:trimmed}:entry)}function artifactKey(value){return`${value.path}::${value.scope}`}function sortLinkedArtifacts(artifacts){return[...artifacts].sort((left,right)=>{const byPath=left.path.localeCompare(right.path);if(byPath!==0)return byPath;return left.scope.localeCompare(right.scope)})}function dedupeLinkedArtifacts(artifacts){return[...new Map(artifacts.map(entry=>[artifactKey(entry),entry])).values()].map(entry=>({...entry,note:entry.note?.trim()||void 0}))}async function validateLinkedPaths(paths,workspaceRoot=process.cwd()){const uniquePaths=[...new Set(paths)].sort((left,right)=>left.localeCompare(right));const existingFiles=[];const missingPaths=[];const nonFilePaths=[];const remoteReferences=[];for(const relativePath of uniquePaths){if(isRemoteLinkedArtifactReference(relativePath)){remoteReferences.push(relativePath.trim());continue}const resolvedPath=path.isAbsolute(relativePath)?relativePath:path.resolve(workspaceRoot,relativePath);try{const stats=await fs.stat(resolvedPath);if(stats.isFile()){existingFiles.push(relativePath)}else{nonFilePaths.push(relativePath)}}catch(error){if(typeof error==="object"&&error!==null&&"code"in error&&isFileAbsentError(error)){missingPaths.push(relativePath);continue}nonFilePaths.push(relativePath)}}return{checked:uniquePaths.length,existing_files:existingFiles,missing_paths:missingPaths,non_file_paths:nonFilePaths,remote_references:remoteReferences}}function applyLinkedArtifactMigrations(current,adds,removes,migrations){let count=0;for(let index=0;index<current.length;index+=1){const migratedPath=applyPathMigrations(current[index].path,migrations);if(migratedPath!==current[index].path){current[index]={...current[index],path:migratedPath};count+=1}}const migratedAdds=adds.map(entry=>{const migratedPath=applyPathMigrations(entry.path,migrations);if(migratedPath!==entry.path)count+=1;return{...entry,path:migratedPath}});return{adds:migratedAdds,removes:removes.map(entry=>applyPathMigrations(entry,migrations)),count}}function mergeLinkedArtifactChanges(current,adds,removes,appendStable){const merged=dedupeLinkedArtifacts(current);for(const add of adds){const index=merged.findIndex(entry=>entry.path===add.path&&entry.scope===add.scope);if(index<0){merged.push(add)}else if(add.note!==void 0){merged[index]={...merged[index],note:add.note}}}if(removes.length>0){for(let index=merged.length-1;index>=0;index-=1){if(removes.includes(merged[index].path))merged.splice(index,1)}}return appendStable?merged:sortLinkedArtifacts(merged)}async function buildLinkedArtifactResult(params){const paths=params.artifacts.map(entry=>entry.path);return{id:params.id,artifacts:params.artifacts,changed:params.changed,count:params.artifacts.length,migrations_applied:params.migrationsApplied&&params.migrationsApplied>0?params.migrationsApplied:void 0,validation:params.options.validatePaths||params.changed?await validateLinkedPaths(paths,params.workspaceRoot):void 0}}async function runLinkedArtifacts(id,options,global2,config){const{metadataKey}=config;const stdinResolver=createStdinTokenResolver();const pmRoot=resolvePmRoot(process.cwd(),global2.path);const workspaceRoot=resolveWorkspaceRoot(pmRoot);const invocationRoot=process.cwd();await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());const resolvedAdds=await stdinResolver.resolveList(options.add,"--add");const resolvedAddGlobs=await stdinResolver.resolveList(options.addGlob,"--add-glob");const resolvedRemoves=await stdinResolver.resolveList(options.remove,"--remove");const resolvedMigrations=await stdinResolver.resolveList(options.migrate,"--migrate");const parsedAdds=parseAddEntries(resolvedAdds,config.bareNoun).map(entry=>({...entry,path:anchorLinkedPath(entry.path,workspaceRoot,invocationRoot)}));const addGlobs=parseAddGlobEntries(resolvedAddGlobs);const expandedGlobAdds=await expandAddGlobEntries(addGlobs,workspaceRoot,invocationRoot);const adds=applyStandaloneNote([...parsedAdds,...expandedGlobAdds],options.note,parsedAdds.length>0||addGlobs.length>0);const removes=parseRemoveEntries(resolvedRemoves).map(entry=>anchorLinkedPath(entry,workspaceRoot,invocationRoot));const migrations=parseMigrateEntries(resolvedMigrations);assertLinkedArtifactMutationIsUnambiguous(adds,removes,migrations);const shouldMutate=adds.length>0||removes.length>0||migrations.length>0;if(!shouldMutate){const located=await locateItem(pmRoot,id,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);if(!located){throw new PmCliError(`Item ${id} not found`,EXIT_CODE.NOT_FOUND)}const loaded=await readLocatedItem(located,{schema:settings.schema});const artifacts2=loaded.document.metadata[metadataKey]??[];return buildLinkedArtifactResult({id:located.id,artifacts:artifacts2,changed:false,options,workspaceRoot})}const author=resolveAuthor(options.author,settings.author_default);const result=await mutateItem({pmRoot,settings,id,op:config.op,author,message:options.message,force:options.force,skipNoop:true,mutate(document){const metadata=document.metadata;const current=metadata[metadataKey]??[];const next=[...current];const migrated=applyLinkedArtifactMigrations(next,adds,removes,migrations);const normalized=mergeLinkedArtifactChanges(next,migrated.adds,migrated.removes,config.supportsAppendStable&&options.appendStable===true);if(normalized.length>0){metadata[metadataKey]=normalized}else{delete metadata[metadataKey]}const changed=!stableValueEquals(current,normalized);return{changedFields:changed?[metadataKey]:[],warnings:changed&&migrated.count>0?[`path_migrations_applied:${migrated.count}`]:[]}}});const artifacts=result.item[metadataKey]??[];const migrationWarning=result.warnings.find(warning=>warning.startsWith("path_migrations_applied:"));const migrationCount=migrationWarning?Number(migrationWarning.slice("path_migrations_applied:".length)):0;return buildLinkedArtifactResult({id:result.item.id,artifacts,changed:result.changedFields.includes(metadataKey),migrationsApplied:migrationCount,options,workspaceRoot})}function renameArtifactsResultKey(result,key){const out={};for(const[field,value]of Object.entries(result)){out[field==="artifacts"?key:field]=value}return out}export{LINKED_ARTIFACT_ADD_GLOB_KEYS,LINKED_ARTIFACT_ADD_KEYS,LINKED_ARTIFACT_MIGRATE_KEYS,LINKED_ARTIFACT_REMOVE_KEYS,anchorLinkedPath,applyPathMigrations,applyStandaloneNote,artifactKey,assertLinkedArtifactMutationIsUnambiguous,dedupeLinkedArtifacts,ensureScope,expandAddGlobEntries,looksLikeStructuredPathEntry,normalizeLinkedPath,parseAddEntries,parseAddGlobEntries,parseMigrateEntries,parseRemoveEntries,renameArtifactsResultKey,runLinkedArtifacts,sortLinkedArtifacts,validateLinkedPaths};
2
2
  //# sourceMappingURL=linked-artifacts.js.map
@@ -1,2 +1,2 @@
1
- !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4b085328-0791-58f5-872a-f796f9087ab4")}catch(e2){}})();import{createHash}from"node:crypto";import{PmCliError}from"../core/shared/errors.js";import{EXIT_CODE}from"../core/shared/constants.js";import{stableStringify}from"../core/shared/serialization.js";const QUERY_CURSOR_VERSION=1;const MAX_CURSOR_LENGTH=4096;const BASE64URL_PATTERN=/^[A-Za-z0-9_-]+$/;function optionKeyForFlag(flag){return flag.replace(/^--/u,"").replace(/[-_]([a-z0-9])/gu,(_,character)=>character.toUpperCase())}function selectCursorSemanticOptions(options,contracts){const presentationKeys=new Set;for(const contract of contracts){if(contract.cursor_semantics==="presentation"){presentationKeys.add(optionKeyForFlag(contract.flag));for(const alias of contract.aliases??[]){presentationKeys.add(optionKeyForFlag(alias))}}}return Object.fromEntries(Object.entries(options).filter(([key])=>!presentationKeys.has(key)))}function createQueryFingerprint(command,contract){return createHash("sha256").update(command).update("\0").update(stableStringify(contract)).digest("hex").slice(0,24)}function encodeQueryCursor(fingerprint,afterId,afterIndex,snapshot){return Buffer.from(JSON.stringify({version:QUERY_CURSOR_VERSION,fingerprint,after_id:afterId,...afterIndex===void 0?{}:{after_index:afterIndex},...snapshot===void 0?{}:{snapshot}})).toString("base64url")}function invalidCursor(message){return new PmCliError(message,EXIT_CODE.USAGE,{code:"invalid_query_cursor",nextSteps:["Repeat the original query without --after to obtain a fresh cursor."]})}function isQueryCursorEnvelope(value){if(typeof value!=="object"||value===null||Array.isArray(value)){return false}const envelope=value;return envelope.version===QUERY_CURSOR_VERSION&&typeof envelope.fingerprint==="string"&&typeof envelope.after_id==="string"&&envelope.after_id.length>0&&(envelope.after_index===void 0||Number.isSafeInteger(envelope.after_index)&&envelope.after_index>=0)&&(envelope.snapshot===void 0||typeof envelope.snapshot==="string"&&envelope.snapshot.length>0)}function decodeQueryCursorEnvelope(cursor){if(typeof cursor!=="string"){throw invalidCursor("Query cursor is malformed.")}const normalized=cursor.trim();if(normalized.length===0||normalized.length>MAX_CURSOR_LENGTH||!BASE64URL_PATTERN.test(normalized)){throw invalidCursor("Query cursor is malformed.")}let parsed;try{parsed=JSON.parse(Buffer.from(normalized,"base64url").toString("utf8"))}catch{throw invalidCursor("Query cursor is malformed.")}if(!isQueryCursorEnvelope(parsed)){throw invalidCursor("Query cursor version or payload is unsupported.")}return parsed}function decodeQueryCursorState(cursor,expectedFingerprint){const envelope=decodeQueryCursorEnvelope(cursor);if(envelope.fingerprint!==expectedFingerprint){throw invalidCursor(`Query cursor does not match the current filters, sort, or query (${envelope.fingerprint} != ${expectedFingerprint}).`)}return{after_id:envelope.after_id,...envelope.after_index===void 0?{}:{after_index:envelope.after_index},...envelope.snapshot===void 0?{}:{snapshot:envelope.snapshot}}}function decodeQueryCursor(cursor,expectedFingerprint){return decodeQueryCursorState(cursor,expectedFingerprint).after_id}function resolveQueryCursorStart(rows,cursor,fingerprint,readId){if(cursor===void 0){return 0}const state=decodeQueryCursorState(cursor,fingerprint);const index=rows.findIndex(row=>readId(row)===state.after_id);if(index<0){if(state.after_index!==void 0){return Math.min(state.after_index,rows.length)}throw invalidCursor(`Query cursor item ${state.after_id} is no longer present in this result set.`)}return index+1}function paginateQueryRows(rows,options){if(options.cursor!==void 0&&decodeQueryCursorState(options.cursor,options.fingerprint).snapshot!==options.snapshot)throw invalidCursor("Query cursor does not match the requested snapshot.");const pageStart=resolveQueryCursorStart(rows,options.cursor,options.fingerprint,options.readId);const pageRows=rows.slice(pageStart,pageStart+options.limit);const hasMore=pageRows.length>0&&pageStart+pageRows.length<rows.length;const lastRow=pageRows.at(-1);return{rows:pageRows,has_more:hasMore,...hasMore&&lastRow!==void 0?{next_cursor:encodeQueryCursor(options.fingerprint,options.readId(lastRow),pageStart+pageRows.length-1,options.snapshot)}:{}}}const QUERY_CURSOR_CONTRACT=Object.freeze({version:QUERY_CURSOR_VERSION,max_length:MAX_CURSOR_LENGTH});export{QUERY_CURSOR_CONTRACT,createQueryFingerprint,decodeQueryCursor,decodeQueryCursorEnvelope,decodeQueryCursorState,encodeQueryCursor,paginateQueryRows,resolveQueryCursorStart,selectCursorSemanticOptions};
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="43f9050c-5daa-57e3-bc5d-529216dd0ee7")}catch(e2){}})();import{READ_OUTPUT_DIMENSION_FLAGS,READ_OUTPUT_COMPOSITION_FLAGS}from"./read-output/options.js";import{createHash}from"node:crypto";import{PmCliError}from"../core/shared/errors.js";import{EXIT_CODE}from"../core/shared/constants.js";import{stableStringify}from"../core/shared/serialization.js";const QUERY_CURSOR_VERSION=1;const MAX_CURSOR_LENGTH=4096;const BASE64URL_PATTERN=/^[A-Za-z0-9_-]+$/;function optionKeyForFlag(flag){return flag.replace(/^--/u,"").replace(/[-_]([a-z0-9])/gu,(_,character)=>character.toUpperCase())}function selectCursorSemanticOptions(options,contracts){const universalFlags=[...Object.values(READ_OUTPUT_DIMENSION_FLAGS),...READ_OUTPUT_COMPOSITION_FLAGS];const presentationKeys=new Set(universalFlags.flatMap(flag=>[optionKeyForFlag(flag),flag.slice(2).replaceAll("-","_")]));for(const contract of contracts){if(contract.cursor_semantics==="presentation"){presentationKeys.add(optionKeyForFlag(contract.flag));for(const alias of contract.aliases??[]){presentationKeys.add(optionKeyForFlag(alias))}}}return Object.fromEntries(Object.entries(options).filter(([key])=>!presentationKeys.has(key)))}function createQueryFingerprint(command,contract){return createHash("sha256").update(command).update("\0").update(stableStringify(contract)).digest("hex").slice(0,24)}function encodeQueryCursor(fingerprint,afterId,afterIndex,snapshot){return Buffer.from(JSON.stringify({version:QUERY_CURSOR_VERSION,fingerprint,after_id:afterId,...afterIndex===void 0?{}:{after_index:afterIndex},...snapshot===void 0?{}:{snapshot}})).toString("base64url")}function invalidCursor(message){return new PmCliError(message,EXIT_CODE.USAGE,{code:"invalid_query_cursor",nextSteps:["Repeat the original query without --after to obtain a fresh cursor."]})}function isQueryCursorEnvelope(value){if(typeof value!=="object"||value===null||Array.isArray(value)){return false}const envelope=value;return envelope.version===QUERY_CURSOR_VERSION&&typeof envelope.fingerprint==="string"&&typeof envelope.after_id==="string"&&envelope.after_id.length>0&&(envelope.after_index===void 0||Number.isSafeInteger(envelope.after_index)&&envelope.after_index>=0)&&(envelope.snapshot===void 0||typeof envelope.snapshot==="string"&&envelope.snapshot.length>0)}function decodeQueryCursorEnvelope(cursor){if(typeof cursor!=="string"){throw invalidCursor("Query cursor is malformed.")}const normalized=cursor.trim();if(normalized.length===0||normalized.length>MAX_CURSOR_LENGTH||!BASE64URL_PATTERN.test(normalized)){throw invalidCursor("Query cursor is malformed.")}let parsed;try{parsed=JSON.parse(Buffer.from(normalized,"base64url").toString("utf8"))}catch{throw invalidCursor("Query cursor is malformed.")}if(!isQueryCursorEnvelope(parsed)){throw invalidCursor("Query cursor version or payload is unsupported.")}return parsed}function decodeQueryCursorState(cursor,expectedFingerprint){const envelope=decodeQueryCursorEnvelope(cursor);if(envelope.fingerprint!==expectedFingerprint){throw invalidCursor(`Query cursor does not match the current filters, sort, or query (${envelope.fingerprint} != ${expectedFingerprint}).`)}return{after_id:envelope.after_id,...envelope.after_index===void 0?{}:{after_index:envelope.after_index},...envelope.snapshot===void 0?{}:{snapshot:envelope.snapshot}}}function decodeQueryCursor(cursor,expectedFingerprint){return decodeQueryCursorState(cursor,expectedFingerprint).after_id}function resolveQueryCursorStart(rows,cursor,fingerprint,readId){if(cursor===void 0){return 0}const state=decodeQueryCursorState(cursor,fingerprint);const index=rows.findIndex(row=>readId(row)===state.after_id);if(index<0){if(state.after_index!==void 0){return Math.min(state.after_index,rows.length)}throw invalidCursor(`Query cursor item ${state.after_id} is no longer present in this result set.`)}return index+1}function paginateQueryRows(rows,options){if(options.cursor!==void 0&&decodeQueryCursorState(options.cursor,options.fingerprint).snapshot!==options.snapshot)throw invalidCursor("Query cursor does not match the requested snapshot.");const pageStart=resolveQueryCursorStart(rows,options.cursor,options.fingerprint,options.readId);const pageRows=rows.slice(pageStart,pageStart+options.limit);const hasMore=pageRows.length>0&&pageStart+pageRows.length<rows.length;const lastRow=pageRows.at(-1);return{rows:pageRows,has_more:hasMore,...hasMore&&lastRow!==void 0?{next_cursor:encodeQueryCursor(options.fingerprint,options.readId(lastRow),pageStart+pageRows.length-1,options.snapshot)}:{}}}const QUERY_CURSOR_CONTRACT=Object.freeze({version:QUERY_CURSOR_VERSION,max_length:MAX_CURSOR_LENGTH});export{QUERY_CURSOR_CONTRACT,createQueryFingerprint,decodeQueryCursor,decodeQueryCursorEnvelope,decodeQueryCursorState,encodeQueryCursor,paginateQueryRows,resolveQueryCursorStart,selectCursorSemanticOptions};
2
2
  //# sourceMappingURL=pagination.js.map