@unbrained/pm-cli 2026.9.30 → 2026.10.2
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +20 -0
- package/dist/cli/error-guidance.d.ts +5 -0
- package/dist/cli/error-guidance.js +1 -1
- package/dist/cli/main.js +2 -2
- package/dist/cli/register-list-query.d.ts +8 -5
- package/dist/cli/register-list-query.js +2 -2
- package/dist/cli/register-structured-mutation.d.ts +2 -0
- package/dist/cli/register-structured-mutation.js +1 -1
- package/dist/cli/runtime/projection-retry.d.ts +9 -0
- package/dist/cli/runtime/projection-retry.js +2 -0
- package/dist/cli/runtime/selection.d.ts +5 -1
- package/dist/cli/runtime/selection.js +1 -1
- package/dist/cli-bundle/bundle-manifest.json +157 -157
- package/dist/cli-bundle/chunks/{chunk-EGAIIWI3.js → chunk-7FUEQOYG.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-7NL3A2BY.js +2 -0
- package/dist/cli-bundle/chunks/chunk-CZLAWXDR.js +8 -0
- package/dist/cli-bundle/chunks/chunk-HY6M34B4.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-O23CQ5T4.js → chunk-MTJMOI4I.js} +14 -14
- package/dist/cli-bundle/chunks/chunk-R4TUD355.js +6 -0
- package/dist/cli-bundle/chunks/chunk-R7ULWMBG.js +238 -0
- package/dist/cli-bundle/chunks/chunk-SV7CZEVV.js +20 -0
- package/dist/cli-bundle/chunks/chunk-TRYXVQ7W.js +3 -0
- package/dist/cli-bundle/chunks/{chunk-BTCE36JS.js → chunk-WP6NRH72.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-XRN3JYNN.js → chunk-XOUBIF6Z.js} +38 -38
- package/dist/cli-bundle/chunks/chunk-Z2GYDSAO.js +3 -0
- package/dist/cli-bundle/chunks/{chunk-6YEET7XI.js → chunk-ZI7F3FVE.js} +47 -47
- package/dist/cli-bundle/chunks/{register-list-query-SYNBVMNG.js → register-list-query-R4PHNB7W.js} +6 -6
- package/dist/cli-bundle/chunks/register-mutation-PDDAUDYV.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-7FCJUC4Z.js → register-operations-A5HJT46K.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-YTWW2KL5.js → register-setup-EZ2F25JI.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-MOUCTR72.js → chunk-3BIYG72P.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-T4PZJQG4.js → chunk-4FFPGNCJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-AKB3JN57.js → chunk-BLCTBSGT.js} +45 -45
- package/dist/cli-bundle/focused-chunks/{chunk-XUCXRZZZ.js → chunk-DBD4W4QP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-KZULQIAG.js → chunk-E754JDLY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-4AORVUT4.js → chunk-EJN7DY3B.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-OMBDUJWZ.js → chunk-FKK2HI3S.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-GBD4EN6S.js +12 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ZJ3CLTV4.js → chunk-GMYUNHST.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-IR4UXLRP.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-RIJQQOEZ.js → chunk-UTRSM3ZK.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-EVMH4SKN.js → chunk-VVWYI2X7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-WCY6HRZO.js +30 -0
- package/dist/cli-bundle/focused-chunks/{chunk-XB5Q2P7Z.js → chunk-XRSCIYHR.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-YC32ZSLS.js +165 -0
- package/dist/cli-bundle/focused-chunks/{chunk-IQBFYQF2.js → chunk-ZIXFMIUL.js} +2 -2
- package/dist/cli-bundle/main.js +22 -22
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +2 -2
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +48 -48
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +7 -7
- package/dist/core/fs/fs-utils.d.ts +11 -0
- package/dist/core/fs/fs-utils.js +2 -2
- package/dist/core/shared/errors.d.ts +9 -0
- package/dist/core/shared/errors.js +1 -1
- package/dist/core/store/settings.d.ts +15 -5
- package/dist/core/store/settings.js +3 -3
- package/dist/core/telemetry/runtime.js +3 -3
- package/dist/mcp/server.js +1 -1
- package/dist/sdk/agent/closed-domain-contracts.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
- package/dist/sdk/item-transaction.d.ts +11 -0
- package/dist/sdk/item-transaction.js +1 -1
- package/dist/sdk/merge/install.d.ts +2 -2
- package/dist/sdk/merge/install.js +1 -1
- package/dist/sdk/pagination.js +1 -1
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/context.d.ts +2 -0
- package/dist/sdk/query/context.js +1 -1
- package/dist/sdk/query/get.d.ts +19 -15
- package/dist/sdk/query/get.js +1 -1
- package/dist/sdk/query/list.js +1 -1
- package/dist/sdk/query/search-contracts.js +1 -1
- package/dist/sdk/query/search-pagination.d.ts +4 -0
- package/dist/sdk/query/search-pagination.js +1 -1
- package/dist/sdk/query/search.js +1 -1
- package/dist/sdk/read-output/options.d.ts +14 -0
- package/dist/sdk/read-output/options.js +2 -0
- package/dist/sdk/read-output-budget.js +1 -1
- package/dist/sdk/read-output-contracts.js +1 -1
- package/dist/sdk/read-output-rows.d.ts +4 -0
- package/dist/sdk/read-output-rows.js +1 -1
- package/dist/sdk/runtime-primitives.d.ts +2 -2
- package/dist/sdk/runtime-primitives.js +1 -1
- package/dist/sdk/runtime.js +1 -1
- package/dist/sdk/workspace-transaction.d.ts +2 -0
- package/dist/sdk/workspace-transaction.js +2 -2
- package/docs/BOUNDED_CONTEXT_READS.md +10 -7
- package/docs/COMMANDS.md +1 -1
- package/docs/MERGE_SAFETY.md +12 -6
- package/docs/OUTPUT_PROJECTION_CONTRACTS.md +27 -0
- package/docs/SDK.md +98 -0
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +6 -3
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-claude/package.json +2 -2
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/pm-codex/package.json +2 -2
- package/plugins/pm-codex/plugin.json +1 -1
- package/dist/cli-bundle/chunks/chunk-6XTJLOKW.js +0 -3
- package/dist/cli-bundle/chunks/chunk-A6NDNRCK.js +0 -6
- package/dist/cli-bundle/chunks/chunk-BNAT4EYR.js +0 -20
- package/dist/cli-bundle/chunks/chunk-BX4LEJX4.js +0 -8
- package/dist/cli-bundle/chunks/chunk-FYTXVVZG.js +0 -2
- package/dist/cli-bundle/chunks/chunk-UIAH7UFK.js +0 -238
- package/dist/cli-bundle/chunks/chunk-USTAFHIM.js +0 -2
- package/dist/cli-bundle/chunks/chunk-YM342ELM.js +0 -3
- package/dist/cli-bundle/chunks/register-mutation-4GSUK23D.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-3CAZ7Z4R.js +0 -30
- package/dist/cli-bundle/focused-chunks/chunk-EFD4ATS7.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-IDB6E3ZV.js +0 -165
- package/dist/cli-bundle/focused-chunks/chunk-UPOMLSW7.js +0 -20
|
@@ -1,4 +1,4 @@
|
|
|
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]="2a195145-3f40-5d1d-943e-fddfb05d9881")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isFileMissingError,readFileIfExists,writeFileAtomic}from"../../core/fs/fs-utils.js";import{access,readFile,realpath}from"node:fs/promises";import{constants}from"node:fs";import{execFile}from"node:child_process";import path from"node:path";import{promisify}from"node:util";import{pathExists}from"../../core/fs/fs-utils.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{acquireLock}from"../../core/lock/lock.js";import{resolvePmPackageRootFromModule}from"../../core/packages/root.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolveAuthor}from"../../core/shared/author.js";import{nowIso}from"../../core/shared/time.js";import{resolvePmRoot}from"../../core/store/paths.js";import{readSettings,resolveGovernanceKnobs}from"../../core/store/settings.js";import{isPathOutsideRoot}from"../workspace.js";import{resolveSourceContextWritePolicy}from"../environment/source-context.js";import{gitWorkspaceEnvironment,resolveMergeDriverConfigScope}from"./worktree-config.js";import{discoverProjectRuntimeVersionPins}from"../environment/project-runtime-compatibility.js";const execFileAsync=promisify(execFile);const PM_GITATTRIBUTES_START="# pm-cli:merge-drivers:start";const PM_GITATTRIBUTES_END="# pm-cli:merge-drivers:end";const PM_GITATTRIBUTES_V2_START="# pm-cli:merge-drivers:v2:start";const PM_GITATTRIBUTES_V2_END="# pm-cli:merge-drivers:v2:end";const MERGE_FENCE_LOCK_ID="merge-fence";const MERGE_ATTRIBUTES_LOCK_ID="merge-attributes";function quoteMergeDriverArgument(value){return`'${value.replaceAll("'",`'"'"'`)}'`}async function resolveMergeDriverCliCommand(){const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);let executable=process.execPath;const runtimeIdentity=await realpath(process.execPath);const bunVersion=process.versions.bun;for(const directory of(process.env.PATH??"").split(path.delimiter)){if(!path.isAbsolute(directory))continue;const candidate=path.join(directory,bunVersion===void 0?path.basename(process.execPath):"bun");try{await access(candidate,constants.X_OK);if(bunVersion!==void 0){const{stdout}=await execFileAsync(candidate,["--version"],{encoding:"utf8",windowsHide:true,timeout:1e4});if(stdout.trim()===bunVersion){executable=await realpath(candidate);break}continue}if(candidate!==runtimeIdentity&&await realpath(candidate)===runtimeIdentity){executable=candidate;break}}catch{}}return`${quoteMergeDriverArgument(executable)} ${quoteMergeDriverArgument(path.join(packageRoot,"dist","cli.js"))}`}const MERGE_DRIVER_DEFINITIONS=[{key:"pm-item-toon",name:"pm field-aware TOON item document merge",artifact:"item",itemPath:"%P"},{key:"pm-item-markdown",name:"pm field-aware JSON-markdown item document merge",artifact:"item",itemPath:"%P"},{key:"pm-history",name:"pm append-only history stream merge",artifact:"history",itemPath:void 0},{key:"pm-relationship",name:"pm append-only relationship event store merge",artifact:"relationship",itemPath:void 0},{key:"pm-json",name:"pm key-level JSON config merge",artifact:"json",itemPath:void 0}];function resolveMergeInstallContext(options){const explicitPath=options.explicitPath?.trim();const sourceWorkspaceRoot=options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim();const sourcePmRoot=options.environment.PM_SOURCE_PM_PATH?.trim();const sourcePolicy=resolveSourceContextWritePolicy(options.environment);const sourceCoordinatesAvailable=Boolean(sourceWorkspaceRoot&&sourcePmRoot);const sourceContextSelected=explicitPath===void 0&&sourceCoordinatesAvailable&&(options.dryRun||sourcePolicy.source_writes_allowed);if(explicitPath!==void 0){const pmRoot=resolvePmRoot(options.cwd,explicitPath);return{pm_root:pmRoot,workspace_start:pmRoot,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}if(sourceContextSelected){return{pm_root:path.resolve(sourcePmRoot),workspace_start:path.resolve(sourceWorkspaceRoot),source_coordinates_available:true,source_context_selected:true,source_policy:sourcePolicy}}return{pm_root:sourceCoordinatesAvailable?resolvePmRoot(options.cwd,".agents/pm"):resolvePmRoot(options.cwd),workspace_start:options.cwd,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}async function findGitWorkspaceRoot(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--show-toplevel"],{cwd,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,timeout:1e4});return await realpath(stdout.trim())}catch{return null}}async function resolveGitWorkspaceRoot(cwd){const workspaceRoot=await findGitWorkspaceRoot(cwd);if(workspaceRoot===null){throw new PmCliError("pm merge install requires a git repository (merge drivers are git configuration).",EXIT_CODE.USAGE)}return workspaceRoot}function toPosixRelative(fromPath,toPath){return path.relative(fromPath,toPath).replaceAll("\\","/")}function quoteGitAttributePattern(value){return`"${value.replaceAll("\\","\\\\").replaceAll('"','\\"')}"`}function readSingleQuotedArgument(command,offset){if(command[offset]!=="'"){return null}let value="";for(let index=offset+1;index<command.length;index+=1){if(command.startsWith(`'"'"'`,index)){value+="'";index+=4;continue}if(command[index]==="'"){return{value,nextOffset:index+1}}value+=command[index]}return null}async function isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,version){const exactPins=discoverProjectRuntimeVersionPins(workspaceRoot).filter(pin=>pin.constraint==="exact");if(exactPins.some(pin=>pin.version!==version))return false;const driverWorkspace=await findGitWorkspaceRoot(packageRoot);if(driverWorkspace!==null&&driverWorkspace!==await realpath(workspaceRoot)){const commonDirectories=await Promise.all([driverWorkspace,workspaceRoot].map(async cwd=>{const result=await execFileAsync("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd,env:gitWorkspaceEnvironment(),timeout:1e4});return realpath(result.stdout.trim())}));if(commonDirectories[0]===commonDirectories[1])return false}return true}async function isPortableMergeDriverCommand(configured,expectedSuffix,workspaceRoot){const nodeArgument=readSingleQuotedArgument(configured,0);if(nodeArgument===null||configured[nodeArgument.nextOffset]!==" "){return false}const cliArgument=readSingleQuotedArgument(configured,nodeArgument.nextOffset+1);if(cliArgument===null||configured.slice(cliArgument.nextOffset)!==expectedSuffix||!/^(?:node|bun)(?:\.exe)?$/iu.test(path.basename(nodeArgument.value))||path.basename(cliArgument.value)!=="cli.js"||path.basename(path.dirname(cliArgument.value))!=="dist"){return false}if(!await pathExists(nodeArgument.value)||!await pathExists(cliArgument.value)){return false}try{const packageRoot=path.dirname(path.dirname(cliArgument.value));const manifest=JSON.parse(await readFile(path.join(packageRoot,"package.json"),"utf8"));const pmBin=typeof manifest.bin==="string"?manifest.bin:manifest.bin?.pm;if(!await isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,manifest.version))return false;return manifest.name==="@unbrained/pm-cli"&&pmBin==="dist/cli.js"}catch{return false}}function buildMergeAttributePatterns(trackerRelativeRoot,typeFolders){const prefix=trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"";const patterns=[`${quoteGitAttributePattern(`${prefix}**/*.toon`)} merge=pm-item-toon`,`${quoteGitAttributePattern(`${prefix}**/*.md`)} merge=pm-item-markdown`];for(const folder of typeFolders){patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.toon`)} merge=pm-item-toon`);patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.md`)} merge=pm-item-markdown`)}patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.jsonl`)} merge=pm-relationship`);patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`);patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`);patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.json`)} merge=pm-json`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/**`)} -merge`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);return patterns}function managedMergeBlocks(content){const blocks=[];let cursor=0;while(cursor<content.length){const legacyStart=content.indexOf(PM_GITATTRIBUTES_START,cursor);const versionedStart=content.indexOf(PM_GITATTRIBUTES_V2_START,cursor);const start=legacyStart===-1?versionedStart:versionedStart===-1?legacyStart:Math.min(legacyStart,versionedStart);if(start===-1)break;const versioned=start===versionedStart;const startMarker=versioned?PM_GITATTRIBUTES_V2_START:PM_GITATTRIBUTES_START;const endMarker=versioned?PM_GITATTRIBUTES_V2_END:PM_GITATTRIBUTES_END;const closing=content.indexOf(endMarker,start+startMarker.length);const end=closing===-1?content.length:closing+endMarker.length;blocks.push({start,end,closed:closing!==-1,lines:content.slice(start+startMarker.length,closing===-1?end:closing).split("\n").map(line=>line.trim()).filter(Boolean)});cursor=end}return blocks}function blockBelongsToTracker(lines,patterns,trackerRelativeRoot){const ownedPatterns=new Set(patterns);const prefix=quoteGitAttributePattern(trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"").slice(0,-1);return lines.some(line=>ownedPatterns.has(line)||line.startsWith(prefix)&&/^[^/]+\/\*\.(?:toon|md)" merge=pm-item-(?:toon|markdown)$/u.test(line.slice(prefix.length)))}async function reconcileGitattributesBlock(workspaceRoot,trackerRelativeRoot,patterns,dryRun){const gitattributesPath=path.join(workspaceRoot,".gitattributes");const gitDirectory=dryRun?null:(await execFileAsync("git",["rev-parse","--absolute-git-dir"],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,timeout:1e4})).stdout.trim();const releaseLock=gitDirectory===null?null:await acquireLock(gitDirectory,MERGE_ATTRIBUTES_LOCK_ID,120,"merge-fence",false,true,5e3);try{const current=await readFileIfExists(gitattributesPath)??"";const block=[PM_GITATTRIBUTES_V2_START,...patterns,PM_GITATTRIBUTES_V2_END].join("\n");const blocks=managedMergeBlocks(current);const owned=blocks.filter(candidate=>blockBelongsToTracker(candidate.lines,patterns,trackerRelativeRoot));if(owned.length===0&&trackerRelativeRoot===".agents/pm"&&blocks.length===1&&blocks[0].lines.every(line=>!line.includes(".agents/pm/"))){owned.push(blocks[0])}let next;if(owned.length>0){const first=owned[0];next=current;for(const duplicate of owned.slice(1).reverse()){next=`${next.slice(0,duplicate.start)}${next.slice(duplicate.end)}`}next=`${next.slice(0,first.start)}${block}${next.slice(first.end)}`}else{const prefix=current.trimEnd();next=`${prefix.length>0?`${prefix}
|
|
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]="22d0a3bd-dd65-5d9a-86bd-e8116d53d94f")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{isFileMissingError,readFileIfExists,writeFileAtomic}from"../../core/fs/fs-utils.js";import{access,readFile,realpath}from"node:fs/promises";import{constants}from"node:fs";import{execFile}from"node:child_process";import path from"node:path";import{promisify}from"node:util";import{pathExists}from"../../core/fs/fs-utils.js";import{resolveItemTypeRegistry}from"../../core/item/type-registry.js";import{acquireLock}from"../../core/lock/lock.js";import{resolvePmPackageRootFromModule}from"../../core/packages/root.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolveAuthor}from"../../core/shared/author.js";import{nowIso}from"../../core/shared/time.js";import{resolvePmRoot}from"../../core/store/paths.js";import{readSettings,resolveGovernanceKnobs}from"../../core/store/settings.js";import{isPathOutsideRoot}from"../workspace.js";import{resolveSourceContextWritePolicy}from"../environment/source-context.js";import{gitWorkspaceEnvironment,resolveMergeDriverConfigScope}from"./worktree-config.js";import{discoverProjectRuntimeVersionPins}from"../environment/project-runtime-compatibility.js";const execFileAsync=promisify(execFile);const PM_GITATTRIBUTES_START="# pm-cli:merge-drivers:start";const PM_GITATTRIBUTES_END="# pm-cli:merge-drivers:end";const PM_GITATTRIBUTES_V2_START="# pm-cli:merge-drivers:v2:start";const PM_GITATTRIBUTES_V2_END="# pm-cli:merge-drivers:v2:end";const MERGE_FENCE_LOCK_ID="merge-fence";const MERGE_ATTRIBUTES_LOCK_ID="merge-attributes";function quoteMergeDriverArgument(value){return`'${value.replaceAll("'",`'"'"'`)}'`}async function resolveMatchingBunLauncher(candidate,version){const resolvedCandidate=await realpath(candidate);if(/(?:^|[\\/])bun-node-[^\\/]+[\\/]bun(?:\.exe)?$/iu.test(resolvedCandidate)){return void 0}const{stdout}=await execFileAsync(candidate,["--version"],{encoding:"utf8",windowsHide:true,timeout:1e4});return stdout.trim()===version?resolvedCandidate:void 0}async function resolveMergeDriverCliCommand(){const packageRoot=resolvePmPackageRootFromModule(import.meta.url,["../../.."]);let executable=process.execPath;let bunLauncherFound=false;const runtimeIdentity=await realpath(process.execPath);const bunVersion=process.versions.bun;const pathCandidates=(process.env.PATH??"").split(path.delimiter).filter(directory=>path.isAbsolute(directory)).map(directory=>path.join(directory,bunVersion===void 0?path.basename(process.execPath):process.platform==="win32"?"bun.exe":"bun"));const candidates=bunVersion===void 0?pathCandidates:[process.env.npm_execpath??"",...pathCandidates,runtimeIdentity].filter(candidate=>path.isAbsolute(candidate)&&/^(?:bun|bun\.exe)$/iu.test(path.basename(candidate)));for(const candidate of candidates){try{await access(candidate,constants.X_OK);if(bunVersion!==void 0){const launcher=await resolveMatchingBunLauncher(candidate,bunVersion);if(launcher!==void 0){executable=launcher;bunLauncherFound=true;break}continue}if(candidate!==runtimeIdentity&&await realpath(candidate)===runtimeIdentity){executable=candidate;break}}catch{}}if(bunVersion!==void 0&&!bunLauncherFound){throw new PmCliError("Cannot install Bun merge drivers without a durable executable matching the current Bun version.",EXIT_CODE.DEPENDENCY_FAILED,{code:"merge_bun_launcher_unavailable",why:"The current Bun process may be a temporary bunx launcher that Git cannot reuse after this command exits.",nextSteps:["Run with a durable version-matched Bun executable, expose one on an absolute PATH entry, or invoke pm through a Bun runner that publishes an absolute npm_execpath.","Retry pm merge install, then check pm health --strict-exit before merging branches."]})}return`${quoteMergeDriverArgument(executable)} ${quoteMergeDriverArgument(path.join(packageRoot,"dist","cli.js"))}`}const MERGE_DRIVER_DEFINITIONS=[{key:"pm-item-toon",name:"pm field-aware TOON item document merge",artifact:"item",itemPath:"%P"},{key:"pm-item-markdown",name:"pm field-aware JSON-markdown item document merge",artifact:"item",itemPath:"%P"},{key:"pm-history",name:"pm append-only history stream merge",artifact:"history",itemPath:void 0},{key:"pm-relationship",name:"pm append-only relationship event store merge",artifact:"relationship",itemPath:void 0},{key:"pm-json",name:"pm key-level JSON config merge",artifact:"json",itemPath:void 0}];function resolveMergeInstallContext(options){const explicitPath=options.explicitPath?.trim();const sourceWorkspaceRoot=options.environment.PM_SOURCE_WORKSPACE_ROOT?.trim();const sourcePmRoot=options.environment.PM_SOURCE_PM_PATH?.trim();const sourcePolicy=resolveSourceContextWritePolicy(options.environment);const sourceCoordinatesAvailable=Boolean(sourceWorkspaceRoot&&sourcePmRoot);const sourceContextSelected=explicitPath===void 0&&sourceCoordinatesAvailable&&(options.dryRun||sourcePolicy.source_writes_allowed);if(explicitPath!==void 0){const pmRoot=resolvePmRoot(options.cwd,explicitPath);return{pm_root:pmRoot,workspace_start:pmRoot,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}if(sourceContextSelected){return{pm_root:path.resolve(sourcePmRoot),workspace_start:path.resolve(sourceWorkspaceRoot),source_coordinates_available:true,source_context_selected:true,source_policy:sourcePolicy}}return{pm_root:sourceCoordinatesAvailable?resolvePmRoot(options.cwd,".agents/pm"):resolvePmRoot(options.cwd),workspace_start:options.cwd,source_coordinates_available:sourceCoordinatesAvailable,source_context_selected:false,source_policy:sourcePolicy}}async function findGitWorkspaceRoot(cwd){try{const{stdout}=await execFileAsync("git",["rev-parse","--show-toplevel"],{cwd,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,timeout:1e4});return await realpath(stdout.trim())}catch{return null}}async function resolveGitWorkspaceRoot(cwd){const workspaceRoot=await findGitWorkspaceRoot(cwd);if(workspaceRoot===null){throw new PmCliError("pm merge install requires a git repository (merge drivers are git configuration).",EXIT_CODE.USAGE)}return workspaceRoot}function toPosixRelative(fromPath,toPath){return path.relative(fromPath,toPath).replaceAll("\\","/")}function quoteGitAttributePattern(value){return`"${value.replaceAll("\\","\\\\").replaceAll('"','\\"')}"`}function readSingleQuotedArgument(command,offset){if(command[offset]!=="'"){return null}let value="";for(let index=offset+1;index<command.length;index+=1){if(command.startsWith(`'"'"'`,index)){value+="'";index+=4;continue}if(command[index]==="'"){return{value,nextOffset:index+1}}value+=command[index]}return null}async function isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,version){const exactPins=discoverProjectRuntimeVersionPins(workspaceRoot).filter(pin=>pin.constraint==="exact");if(exactPins.some(pin=>pin.version!==version))return false;const driverWorkspace=await findGitWorkspaceRoot(packageRoot);if(driverWorkspace!==null&&driverWorkspace!==await realpath(workspaceRoot)){const commonDirectories=await Promise.all([driverWorkspace,workspaceRoot].map(async cwd=>{const result=await execFileAsync("git",["rev-parse","--path-format=absolute","--git-common-dir"],{cwd,env:gitWorkspaceEnvironment(),timeout:1e4});return realpath(result.stdout.trim())}));if(commonDirectories[0]===commonDirectories[1])return false}return true}async function isPortableMergeDriverCommand(configured,expectedSuffix,workspaceRoot){const nodeArgument=readSingleQuotedArgument(configured,0);if(nodeArgument===null||configured[nodeArgument.nextOffset]!==" "){return false}const cliArgument=readSingleQuotedArgument(configured,nodeArgument.nextOffset+1);if(cliArgument===null||configured.slice(cliArgument.nextOffset)!==expectedSuffix||!/^(?:node|bun)(?:\.exe)?$/iu.test(path.basename(nodeArgument.value))||path.basename(cliArgument.value)!=="cli.js"||path.basename(path.dirname(cliArgument.value))!=="dist"){return false}if(!await pathExists(nodeArgument.value)||!await pathExists(cliArgument.value)){return false}try{const packageRoot=path.dirname(path.dirname(cliArgument.value));const manifest=JSON.parse(await readFile(path.join(packageRoot,"package.json"),"utf8"));const pmBin=typeof manifest.bin==="string"?manifest.bin:manifest.bin?.pm;if(!await isMergeDriverWorkspaceCompatible(packageRoot,workspaceRoot,manifest.version))return false;return manifest.name==="@unbrained/pm-cli"&&pmBin==="dist/cli.js"}catch{return false}}function buildMergeAttributePatterns(trackerRelativeRoot,typeFolders){const prefix=trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"";const patterns=[`${quoteGitAttributePattern(`${prefix}**/*.toon`)} merge=pm-item-toon`,`${quoteGitAttributePattern(`${prefix}**/*.md`)} merge=pm-item-markdown`];for(const folder of typeFolders){patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.toon`)} merge=pm-item-toon`);patterns.push(`${quoteGitAttributePattern(`${prefix}${folder}/*.md`)} merge=pm-item-markdown`)}patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.jsonl`)} merge=pm-relationship`);patterns.push(`${quoteGitAttributePattern(`${prefix}history/*.jsonl`)} merge=pm-history`);patterns.push(`${quoteGitAttributePattern(`${prefix}settings.json`)} merge=pm-json`);patterns.push(`${quoteGitAttributePattern(`${prefix}**/*.json`)} merge=pm-json`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/**`)} -merge`);patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);return patterns}function managedMergeBlocks(content){const blocks=[];let cursor=0;while(cursor<content.length){const legacyStart=content.indexOf(PM_GITATTRIBUTES_START,cursor);const versionedStart=content.indexOf(PM_GITATTRIBUTES_V2_START,cursor);const start=legacyStart===-1?versionedStart:versionedStart===-1?legacyStart:Math.min(legacyStart,versionedStart);if(start===-1)break;const versioned=start===versionedStart;const startMarker=versioned?PM_GITATTRIBUTES_V2_START:PM_GITATTRIBUTES_START;const endMarker=versioned?PM_GITATTRIBUTES_V2_END:PM_GITATTRIBUTES_END;const closing=content.indexOf(endMarker,start+startMarker.length);const end=closing===-1?content.length:closing+endMarker.length;blocks.push({start,end,closed:closing!==-1,lines:content.slice(start+startMarker.length,closing===-1?end:closing).split("\n").map(line=>line.trim()).filter(Boolean)});cursor=end}return blocks}function blockBelongsToTracker(lines,patterns,trackerRelativeRoot){const ownedPatterns=new Set(patterns);const prefix=quoteGitAttributePattern(trackerRelativeRoot.length>0?`${trackerRelativeRoot}/`:"").slice(0,-1);return lines.some(line=>ownedPatterns.has(line)||line.startsWith(prefix)&&/^[^/]+\/\*\.(?:toon|md)" merge=pm-item-(?:toon|markdown)$/u.test(line.slice(prefix.length)))}async function reconcileGitattributesBlock(workspaceRoot,trackerRelativeRoot,patterns,dryRun){const gitattributesPath=path.join(workspaceRoot,".gitattributes");const gitDirectory=dryRun?null:(await execFileAsync("git",["rev-parse","--absolute-git-dir"],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,timeout:1e4})).stdout.trim();const releaseLock=gitDirectory===null?null:await acquireLock(gitDirectory,MERGE_ATTRIBUTES_LOCK_ID,120,"merge-fence",false,true,5e3);try{const current=await readFileIfExists(gitattributesPath)??"";const block=[PM_GITATTRIBUTES_V2_START,...patterns,PM_GITATTRIBUTES_V2_END].join("\n");const blocks=managedMergeBlocks(current);const owned=blocks.filter(candidate=>blockBelongsToTracker(candidate.lines,patterns,trackerRelativeRoot));if(owned.length===0&&trackerRelativeRoot===".agents/pm"&&blocks.length===1&&blocks[0].lines.every(line=>!line.includes(".agents/pm/"))){owned.push(blocks[0])}let next;if(owned.length>0){const first=owned[0];next=current;for(const duplicate of owned.slice(1).reverse()){next=`${next.slice(0,duplicate.start)}${next.slice(duplicate.end)}`}next=`${next.slice(0,first.start)}${block}${next.slice(first.end)}`}else{const prefix=current.trimEnd();next=`${prefix.length>0?`${prefix}
|
|
2
2
|
|
|
3
3
|
`:""}${block}
|
|
4
4
|
`}if(next===current){return{path:gitattributesPath,changed:false}}if(!dryRun){await writeFileAtomic(gitattributesPath,next)}return{path:gitattributesPath,changed:true}}finally{await releaseLock?.()}}function resolveProjectMergeTypeFolders(settings){const registry=resolveItemTypeRegistry(settings,null);return[...new Set(Object.values(registry.type_to_folder))].sort((left,right)=>left.localeCompare(right))}async function auditMergeAttributeFence(pmRoot,typeFolders){const resolvedRoot=path.resolve(pmRoot);let fenceDirectory=null;let fenceContent="";let directory=resolvedRoot;for(let depth=0;depth<8;depth+=1){const candidate=path.join(directory,".gitattributes");try{const raw=await readFile(candidate,"utf8");if(raw.includes(PM_GITATTRIBUTES_V2_START)||raw.includes(PM_GITATTRIBUTES_START)){fenceDirectory=directory;fenceContent=raw;break}}catch{}const parent=path.dirname(directory);if(parent===directory){break}directory=parent}if(fenceDirectory===null){return{status:"not_installed",missing_patterns:[],stale_patterns:[],schema_scope:"project"}}const fencePath=path.join(fenceDirectory,".gitattributes");const relativeRoot=toPosixRelative(fenceDirectory,resolvedRoot);const blocks=managedMergeBlocks(fenceContent);const expected=buildMergeAttributePatterns(relativeRoot,typeFolders);const owned=blocks.filter(block=>blockBelongsToTracker(block.lines,expected,relativeRoot));const committed=owned.flatMap(block=>block.closed?block.lines:[]);const committedSet=new Set(committed);const expectedSet=new Set(expected);const missing=expected.filter(line=>!committedSet.has(line));const stale=committed.filter(line=>!expectedSet.has(line));return{status:owned.length!==1||!owned[0].closed||missing.length>0||stale.length>0?"drift":"ok",path:fencePath,missing_patterns:missing,stale_patterns:stale,schema_scope:"project"}}async function auditMergeDriverConfiguration(workspaceRoot){const missingKeys=[];const driftedKeys=[];for(const definition of MERGE_DRIVER_DEFINITIONS){const key=`merge.${definition.key}.driver`;const expectedSuffix=` merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`;try{const{stdout}=await execFileAsync("git",["config","--get",key],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,timeout:1e4});const configured=stdout.trim();if(!await isPortableMergeDriverCommand(configured,expectedSuffix,workspaceRoot)){driftedKeys.push(key)}}catch{missingKeys.push(key)}}return{status:missingKeys.length>0?"missing":driftedKeys.length>0?"drift":"ok",missing_keys:missingKeys,drifted_keys:driftedKeys}}async function refreshMergeAttributeFenceIfInstalled(pmRoot){let workspaceRoot;try{workspaceRoot=await resolveGitWorkspaceRoot(path.resolve(pmRoot))}catch{return{status:"no_git"}}const trackerRelativeRoot=toPosixRelative(workspaceRoot,path.resolve(pmRoot));const lockSettings=await readSettings(pmRoot);const owner=resolveAuthor(void 0,lockSettings.author_default);const releaseLock=await acquireLock(pmRoot,MERGE_FENCE_LOCK_ID,lockSettings.locks.ttl_seconds,owner,false,resolveGovernanceKnobs(lockSettings).force_required_for_stale_lock,lockSettings.locks.wait_ms);try{const gitattributesPath=path.join(workspaceRoot,".gitattributes");let current;try{current=await readFile(gitattributesPath,"utf8")}catch(error){if(error instanceof Error&&"code"in error&&isFileMissingError(error)){return{status:"not_installed",path:gitattributesPath}}throw error}if(!current.includes(PM_GITATTRIBUTES_V2_START)&&!current.includes(PM_GITATTRIBUTES_START)){return{status:"not_installed",path:gitattributesPath}}const settings=await readSettings(pmRoot);const typeFolders=resolveProjectMergeTypeFolders(settings);const outcome=await reconcileGitattributesBlock(workspaceRoot,trackerRelativeRoot,buildMergeAttributePatterns(trackerRelativeRoot,typeFolders),false);return{status:outcome.changed?"refreshed":"unchanged",path:outcome.path}}finally{await releaseLock()}}async function runMergeInstall(options,global2){const context=resolveMergeInstallContext({cwd:process.cwd(),explicitPath:global2.path,dryRun:options.dryRun===true,environment:process.env});const pmRoot=context.pm_root;await assertInitializedTracker(pmRoot);const workspaceRoot=await resolveGitWorkspaceRoot(context.workspace_start);return installMergeFence({pmRoot,workspaceRoot,dryRun:options.dryRun===true})}async function installMergeFence(options){const pmRoot=path.resolve(options.pmRoot);const workspaceRoot=path.resolve(options.workspaceRoot);const dryRun=options.dryRun===true;let canonicalPmRoot;let canonicalWorkspaceRoot;try{[canonicalPmRoot,canonicalWorkspaceRoot]=await Promise.all([realpath(pmRoot),realpath(workspaceRoot)])}catch(error){throw new PmCliError(`Cannot resolve tracker root ${pmRoot} or workspace root ${workspaceRoot}: ${String(error)}`,EXIT_CODE.NOT_FOUND,{code:"merge_root_not_found",nextSteps:["Initialize the tracker and ensure both paths are accessible.",'Retry "pm merge install" from the repository workspace.']})}const trackerRelativeRoot=toPosixRelative(canonicalWorkspaceRoot,canonicalPmRoot);if(isPathOutsideRoot(trackerRelativeRoot)){throw new PmCliError(`Tracker root ${pmRoot} is outside the git repository ${workspaceRoot}; there is nothing to configure for this repository.`,EXIT_CODE.USAGE)}const settings=await readSettings(canonicalPmRoot);const typeFolders=resolveProjectMergeTypeFolders(settings);const patterns=buildMergeAttributePatterns(trackerRelativeRoot,typeFolders);const gitConfigEntries=[];const cliCommand=await resolveMergeDriverCliCommand();for(const definition of MERGE_DRIVER_DEFINITIONS){gitConfigEntries.push({key:`merge.${definition.key}.name`,value:definition.name});gitConfigEntries.push({key:`merge.${definition.key}.driver`,value:`${cliCommand} merge driver ${definition.artifact} "%O" "%A" "%B"${definition.itemPath===void 0?"":` --item-path ${definition.itemPath}`}`})}if(!dryRun){try{const configScope=await resolveMergeDriverConfigScope(canonicalWorkspaceRoot);for(const entry of gitConfigEntries){await execFileAsync("git",["config",configScope,entry.key,entry.value],{cwd:canonicalWorkspaceRoot,env:gitWorkspaceEnvironment(),encoding:"utf8",windowsHide:true,timeout:1e4})}}catch{throw new PmCliError(`Cannot install repository-local merge drivers in ${canonicalWorkspaceRoot}. Ensure the repository Git config is writable and no other Git process holds its lock, then retry.`,EXIT_CODE.DEPENDENCY_FAILED,{code:"merge_git_config_unwritable",why:"pm merge install must persist clone-local driver commands before publishing their shared .gitattributes mappings.",nextSteps:["Make the repository Git config writable or wait for the process holding its lock to finish.",'Retry "pm merge install"; the operation is idempotent.','Use "pm merge install --dry-run --json" when the workspace is intentionally read-only.']})}}const gitattributes=await reconcileGitattributesBlock(canonicalWorkspaceRoot,trackerRelativeRoot,patterns,dryRun);return{ok:true,dry_run:dryRun,workspace_root:canonicalWorkspaceRoot,pm_root:canonicalPmRoot,gitattributes:{path:gitattributes.path,changed:gitattributes.changed,patterns,schema_scope:"project"},git_config:gitConfigEntries,guidance:["Commit .gitattributes so every branch and collaborator shares the merge mapping.",'git config is per-clone: each collaborator (and each fresh worktree/clone) runs "pm merge install" once.','After merging branches, run "pm merge reconcile --dry-run" to inspect the complete receipt and history repair, then apply "pm merge reconcile"; use --force only after explicitly accepting any discarded values.',"Custom item types registered later refresh this fence automatically (pm schema add-type/remove-type); rerun pm merge install only after out-of-band type-folder edits."],generated_at:nowIso()}}export{PM_GITATTRIBUTES_END,PM_GITATTRIBUTES_START,PM_GITATTRIBUTES_V2_END,PM_GITATTRIBUTES_V2_START,auditMergeAttributeFence,auditMergeDriverConfiguration,buildMergeAttributePatterns,findGitWorkspaceRoot,installMergeFence,refreshMergeAttributeFenceIfInstalled,resolveMergeInstallContext,resolveProjectMergeTypeFolders,runMergeInstall};
|
package/dist/sdk/pagination.js
CHANGED
|
@@ -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]="
|
|
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
|