@detergent-software/atk 8.9.0-dev.3 → 8.9.0-dev.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/build/commands/publish.d.ts.map +1 -1
  3. package/build/commands/publish.js +17 -22
  4. package/build/commands/publish.js.map +1 -1
  5. package/build/hooks/usePublishState.d.ts +43 -8
  6. package/build/hooks/usePublishState.d.ts.map +1 -1
  7. package/build/hooks/usePublishState.js +82 -565
  8. package/build/hooks/usePublishState.js.map +1 -1
  9. package/build/lib/atk-api/generated/types.gen.d.ts +4 -4
  10. package/build/lib/checksum.d.ts +30 -14
  11. package/build/lib/checksum.d.ts.map +1 -1
  12. package/build/lib/checksum.js +93 -57
  13. package/build/lib/checksum.js.map +1 -1
  14. package/build/lib/installer.d.ts +2 -7
  15. package/build/lib/installer.d.ts.map +1 -1
  16. package/build/lib/installer.js +8 -2
  17. package/build/lib/installer.js.map +1 -1
  18. package/build/lib/owned-paths.d.ts +4 -2
  19. package/build/lib/owned-paths.d.ts.map +1 -1
  20. package/build/lib/owned-paths.js +19 -6
  21. package/build/lib/owned-paths.js.map +1 -1
  22. package/build/lib/publish-flow.d.ts +4 -9
  23. package/build/lib/publish-flow.d.ts.map +1 -1
  24. package/build/lib/publish-flow.js +505 -2
  25. package/build/lib/publish-flow.js.map +1 -1
  26. package/build/lib/publish-run.d.ts +55 -0
  27. package/build/lib/publish-run.d.ts.map +1 -0
  28. package/build/lib/publish-run.js +164 -0
  29. package/build/lib/publish-run.js.map +1 -0
  30. package/build/lib/schemas/lockfile.d.ts +3 -0
  31. package/build/lib/schemas/lockfile.d.ts.map +1 -1
  32. package/build/lib/schemas/lockfile.js +4 -0
  33. package/build/lib/schemas/lockfile.js.map +1 -1
  34. package/build/lib/sync.d.ts.map +1 -1
  35. package/build/lib/sync.js +28 -0
  36. package/build/lib/sync.js.map +1 -1
  37. package/build/lib/uninstaller.js +2 -2
  38. package/build/lib/uninstaller.js.map +1 -1
  39. package/package.json +1 -1
@@ -10,7 +10,7 @@ import { addAssetToLockfile, findInstalledAsset, readLockfile, withLockfileLock,
10
10
  import { diffManifests, fetchExistingManifest } from './manifest-diff.js';
11
11
  import { parseOrgFromName } from './org.js';
12
12
  import { findProjectRoot } from './paths.js';
13
- import { buildPublishPlan, buildStagingArea, checkRegistryVersion, detectAssetFromPath, detectPublishType, executePublish, findSiblingDependencies, loadPublishBatch, loadPublishEntries, mapPublishError, missingDependencies, resolvePlanDependencies, unknownToolsError, updateManifestField, updateManifestVersion, validatePublishTarget, } from './publisher.js';
13
+ import { buildPublishPlan, buildStagingArea, bumpVersion, checkRegistryVersion, detectAssetFromPath, detectPublishType, executePublish, findSiblingDependencies, isOrgScopedTarget, loadPublishBatch, loadPublishEntries, mapPublishError, missingDependencies, resolvePlanDependencies, unknownToolsError, updateManifestField, updateManifestVersion, validatePublishTarget, } from './publisher.js';
14
14
  import { clearCache, fetchAssetManifest, fetchRegistry, findAsset, findBundle } from './registry.js';
15
15
  import { parseReviewersInput, validateGithubUsername } from './reviewers.js';
16
16
  import { stageInstalledFiles } from './staging.js';
@@ -63,7 +63,6 @@ export function createInitialState(flags) {
63
63
  target: undefined,
64
64
  token: undefined,
65
65
  toolAdapters: [],
66
- toolCursorIndex: 0,
67
66
  toolsDetected: [],
68
67
  validation: undefined,
69
68
  versionCheck: undefined,
@@ -799,4 +798,508 @@ const installing = {
799
798
  ctx.dispatch({ type: 'INSTALL_DONE' });
800
799
  },
801
800
  };
801
+ // ---------------------------------------------------------------------------
802
+ // Reducer
803
+ // ---------------------------------------------------------------------------
804
+ export function publishReducer(state, action) {
805
+ switch (action.type) {
806
+ case 'BUMP_DONE': {
807
+ const bumped = {
808
+ ...state,
809
+ errorMessage: action.message ? action.message : state.errorMessage,
810
+ resolvedVersion: action.version,
811
+ target: action.updatedTarget,
812
+ };
813
+ return action.message ? { ...bumped, phase: 'error' } : advanceToPlan(bumped);
814
+ }
815
+ case 'CONFIRM_PROMPT_TOOLS': {
816
+ if (action.tools.length === 0)
817
+ return state;
818
+ const updatedToolsTarget = state.target
819
+ ? {
820
+ ...state.target,
821
+ data: { ...state.target.data, tools: action.tools },
822
+ }
823
+ : undefined;
824
+ return {
825
+ ...state,
826
+ phase: phaseAfterMetadata(updatedToolsTarget),
827
+ selectedPromptTools: action.tools,
828
+ target: updatedToolsTarget,
829
+ };
830
+ }
831
+ case 'DETECT_DONE':
832
+ if (action.target.type === 'bundle' && state.entries.length > 0) {
833
+ return {
834
+ ...state,
835
+ errorMessage: 'A bundle is published on its own. Remove --with, and publish its new assets first.',
836
+ phase: 'error',
837
+ target: action.target,
838
+ };
839
+ }
840
+ return {
841
+ ...state,
842
+ phase: 'validating',
843
+ target: action.target,
844
+ };
845
+ case 'ENTRIES_CHECKED':
846
+ return advanceToPlan({ ...state, entries: action.entries });
847
+ case 'ENTRIES_LOADED':
848
+ return { ...state, entries: action.entries };
849
+ case 'ERROR':
850
+ return {
851
+ ...state,
852
+ errorCode: action.code,
853
+ errorCommand: action.command,
854
+ errorHint: action.hint,
855
+ errorMessage: action.message,
856
+ phase: 'error',
857
+ };
858
+ case 'INSTALL_DONE':
859
+ return { ...state, phase: 'done' };
860
+ case 'PLAN_DONE': {
861
+ // dry-run always shows the dry-run result; --yes / non-TTY skip the confirm prompt
862
+ // and proceed directly to publishing.
863
+ let nextPhase;
864
+ if (state.flags.dryRun) {
865
+ nextPhase = 'dry-run-result';
866
+ }
867
+ else if (state.nonInteractive) {
868
+ nextPhase = 'publishing';
869
+ }
870
+ else {
871
+ nextPhase = 'confirm-publish';
872
+ }
873
+ return {
874
+ ...state,
875
+ manifestDiff: action.manifestDiff,
876
+ phase: nextPhase,
877
+ plan: action.plan,
878
+ };
879
+ }
880
+ case 'PUBLISH_DONE': {
881
+ const nextPhase = state.isRawPublish ? 'installing' : 'done';
882
+ return {
883
+ ...state,
884
+ phase: nextPhase,
885
+ publishResult: action.result,
886
+ };
887
+ }
888
+ case 'PUBLISH_PROGRESS':
889
+ return { ...state, progressMessage: action.message };
890
+ case 'RAW_DETECT_DONE':
891
+ return {
892
+ ...state,
893
+ authorValue: action.authorValue,
894
+ isRawPublish: true,
895
+ orgValue: action.orgValue,
896
+ phase: 'gathering-metadata',
897
+ rawDetection: action.rawDetection,
898
+ toolsDetected: action.toolsDetected,
899
+ };
900
+ case 'RAW_DETECT_DONE_NON_INTERACTIVE':
901
+ return {
902
+ ...state,
903
+ isRawPublish: true,
904
+ phase: 'validating',
905
+ rawDetection: action.rawDetection,
906
+ target: action.target,
907
+ };
908
+ case 'REGISTRY_CHECK_DONE': {
909
+ const { isUpdate, resolvedVersion, token, versionCheck } = action;
910
+ let nextPhase;
911
+ let errorMessage = state.errorMessage;
912
+ let bumpedVersion = resolvedVersion;
913
+ let bumpedTarget = state.target;
914
+ if (versionCheck.status === 'new-asset') {
915
+ nextPhase = 'building-plan';
916
+ }
917
+ else if (versionCheck.status === 'version-already-bumped') {
918
+ // --yes / non-TTY implicitly confirm the update
919
+ nextPhase = state.nonInteractive ? 'building-plan' : 'confirm-update';
920
+ }
921
+ else {
922
+ // needs-bump
923
+ if (state.nonInteractive) {
924
+ if (state.flags.bump && state.target) {
925
+ // Auto-bump using the flag value; a successful publish writes it to the manifest
926
+ try {
927
+ bumpedVersion = bumpVersion(versionCheck.latestVersion, state.flags.bump);
928
+ bumpedTarget = {
929
+ ...state.target,
930
+ data: { ...state.target.data, version: bumpedVersion },
931
+ };
932
+ nextPhase = 'building-plan';
933
+ }
934
+ catch {
935
+ errorMessage = 'Failed to compute bumped version.';
936
+ nextPhase = 'error';
937
+ }
938
+ }
939
+ else if (isBatch(state.flags)) {
940
+ // advanceToPlan lists every asset of the batch that needs --bump, once the entries are checked.
941
+ nextPhase = 'building-plan';
942
+ }
943
+ else {
944
+ errorMessage = `--bump <patch|minor|major> required: registry has v${versionCheck.latestVersion} but manifest is not newer`;
945
+ nextPhase = 'error';
946
+ }
947
+ }
948
+ else {
949
+ nextPhase = 'bump-prompt';
950
+ }
951
+ }
952
+ const checked = {
953
+ ...state,
954
+ errorMessage,
955
+ isUpdate,
956
+ phase: nextPhase,
957
+ resolvedVersion: bumpedVersion,
958
+ target: bumpedTarget,
959
+ token,
960
+ versionCheck,
961
+ };
962
+ return nextPhase === 'building-plan' ? advanceToPlan(checked) : checked;
963
+ }
964
+ case 'RESOLVE_TOOLS_NONINTERACTIVE': {
965
+ const updatedTarget = state.target
966
+ ? {
967
+ ...state.target,
968
+ data: { ...state.target.data, tools: action.tools },
969
+ }
970
+ : undefined;
971
+ return {
972
+ ...state,
973
+ phase: 'checking-registry',
974
+ target: updatedTarget,
975
+ };
976
+ }
977
+ case 'RESOLVED_INSTALLED':
978
+ return {
979
+ ...state,
980
+ phase: 'detecting',
981
+ resolvedPath: action.resolvedPath,
982
+ };
983
+ case 'RESOLVED_UPDATE':
984
+ return {
985
+ ...state,
986
+ phase: 'detecting',
987
+ resolvedPath: action.resolvedPath,
988
+ };
989
+ case 'SET_BUMP_SELECTION':
990
+ return { ...state, bumpSelection: action.value };
991
+ case 'SET_CONFIRM_VALUE':
992
+ return { ...state, confirmValue: action.value };
993
+ case 'SET_DESCRIPTION':
994
+ return { ...state, descriptionValue: action.value };
995
+ case 'SET_PROMPT_TAGS':
996
+ return { ...state, promptTagsValue: action.value };
997
+ case 'SET_PUBLISH_CONFIRM_VALUE':
998
+ return { ...state, publishConfirmValue: action.value };
999
+ case 'SET_REVIEWER':
1000
+ return { ...state, reviewerValue: action.value };
1001
+ case 'SET_TAGS':
1002
+ return { ...state, tagsValue: action.value };
1003
+ case 'SET_WITH_CONFIRM_VALUE':
1004
+ return { ...state, withConfirmValue: action.value };
1005
+ case 'STAGING_DONE':
1006
+ return {
1007
+ ...state,
1008
+ phase: 'validating',
1009
+ target: action.target,
1010
+ };
1011
+ case 'SUBMIT_BUMP': {
1012
+ const trimmed = state.bumpSelection.trim().toLowerCase();
1013
+ if (trimmed !== 'patch' && trimmed !== 'minor' && trimmed !== 'major') {
1014
+ return state; // Ignore invalid input
1015
+ }
1016
+ // The prompt is for an entry: bump it, then on to the next pending bump or the plan.
1017
+ if (state.bumpEntry !== undefined) {
1018
+ const entry = state.entries[state.bumpEntry];
1019
+ if (entry?.versionCheck?.status !== 'needs-bump')
1020
+ return state;
1021
+ return bumpEntryAt({ ...state, bumpSelection: '' }, state.bumpEntry, trimmed);
1022
+ }
1023
+ if (!state.target || !state.versionCheck || state.versionCheck.status !== 'needs-bump') {
1024
+ return state;
1025
+ }
1026
+ // Compute the bumped version in the reducer (pure, synchronous)
1027
+ const bumpType = trimmed;
1028
+ try {
1029
+ const newVersion = bumpVersion(state.versionCheck.latestVersion, bumpType);
1030
+ // The bump is only on the target until the publish succeeds, which writes it to
1031
+ // the manifest; entries still to check or bump come first.
1032
+ return advanceToPlan({
1033
+ ...state,
1034
+ bumpSelection: '',
1035
+ resolvedVersion: newVersion,
1036
+ target: { ...state.target, data: { ...state.target.data, version: newVersion } },
1037
+ });
1038
+ }
1039
+ catch {
1040
+ return {
1041
+ ...state,
1042
+ errorMessage: 'Failed to compute bumped version.',
1043
+ phase: 'error',
1044
+ };
1045
+ }
1046
+ }
1047
+ case 'SUBMIT_CONFIRM': {
1048
+ const trimmed = state.confirmValue.trim().toLowerCase();
1049
+ if (trimmed === 'y' || trimmed === 'yes') {
1050
+ return advanceToPlan(state);
1051
+ }
1052
+ else if (trimmed === 'n' || trimmed === 'no') {
1053
+ return { ...state, errorMessage: 'Publish cancelled.', phase: 'error' };
1054
+ }
1055
+ // Otherwise ignore (wait for valid input)
1056
+ return state;
1057
+ }
1058
+ case 'SUBMIT_DESCRIPTION': {
1059
+ const trimmed = state.descriptionValue.trim();
1060
+ if (!trimmed)
1061
+ return state; // Don't allow empty description
1062
+ return {
1063
+ ...state,
1064
+ descriptionValue: trimmed,
1065
+ metadataSubPhase: 'tags',
1066
+ };
1067
+ }
1068
+ case 'SUBMIT_PROMPT_TAGS': {
1069
+ const parsedTags = splitList(state.promptTagsValue);
1070
+ // Update the target's data with the new tags
1071
+ const updatedTagsTarget = state.target
1072
+ ? {
1073
+ ...state.target,
1074
+ data: { ...state.target.data, tags: parsedTags.length > 0 ? parsedTags : undefined },
1075
+ }
1076
+ : undefined;
1077
+ // Check if tools are also missing (only for assets)
1078
+ const needsToolsPrompt = updatedTagsTarget?.type === 'asset' &&
1079
+ (!('tools' in updatedTagsTarget.data) ||
1080
+ !Array.isArray(updatedTagsTarget.data.tools) ||
1081
+ (updatedTagsTarget.data.tools?.length ?? 0) === 0);
1082
+ const nextTagsPhase = needsToolsPrompt ? 'loading-tools' : phaseAfterMetadata(updatedTagsTarget);
1083
+ return {
1084
+ ...state,
1085
+ phase: nextTagsPhase,
1086
+ target: updatedTagsTarget,
1087
+ };
1088
+ }
1089
+ case 'SUBMIT_PUBLISH_CONFIRM': {
1090
+ const trimmed = state.publishConfirmValue.trim().toLowerCase();
1091
+ if (trimmed === 'y' || trimmed === 'yes') {
1092
+ return { ...state, phase: 'publishing' };
1093
+ }
1094
+ else if (trimmed === 'n' || trimmed === 'no') {
1095
+ return { ...state, errorMessage: 'Publish cancelled.', phase: 'error' };
1096
+ }
1097
+ // Otherwise ignore (wait for valid input)
1098
+ return state;
1099
+ }
1100
+ case 'SUBMIT_REVIEWER':
1101
+ return { ...state, phase: 'checking-registry' };
1102
+ case 'SUBMIT_TAGS':
1103
+ return {
1104
+ ...state,
1105
+ metadataSubPhase: 'building-staging',
1106
+ };
1107
+ case 'SUBMIT_WITH_CONFIRM': {
1108
+ const trimmed = state.withConfirmValue.trim().toLowerCase();
1109
+ if (trimmed === 'y' || trimmed === 'yes') {
1110
+ return advanceToPlan({
1111
+ ...state,
1112
+ entries: [...state.entries, ...state.suggestedEntries],
1113
+ missingDependencies: [],
1114
+ pendingError: undefined,
1115
+ suggestedEntries: [],
1116
+ withConfirmValue: '',
1117
+ });
1118
+ }
1119
+ if ((trimmed === 'n' || trimmed === 'no') && state.pendingError) {
1120
+ return publishReducer({ ...state, suggestedEntries: [], withConfirmValue: '' }, state.pendingError);
1121
+ }
1122
+ return state;
1123
+ }
1124
+ case 'SUGGEST_ENTRIES':
1125
+ return {
1126
+ ...state,
1127
+ missingDependencies: action.missing,
1128
+ pendingError: action.error,
1129
+ phase: 'confirm-with',
1130
+ suggestedEntries: action.suggested,
1131
+ withConfirmValue: '',
1132
+ };
1133
+ case 'TOOLS_LOADED':
1134
+ return {
1135
+ ...state,
1136
+ phase: 'prompting-tools',
1137
+ toolAdapters: action.adapters,
1138
+ };
1139
+ case 'VALIDATE_DONE': {
1140
+ if (!action.validation.valid) {
1141
+ return {
1142
+ ...state,
1143
+ errorMessage: `Validation failed:\n${action.validation.errors.map((e) => ` - ${e}`).join('\n')}`,
1144
+ phase: 'error',
1145
+ validation: action.validation,
1146
+ };
1147
+ }
1148
+ // Seed the reviewers field: the --reviewer flag wins over the project's
1149
+ // lockfile-configured default (org.ts's CLI-flag > lockfile priority chain).
1150
+ const reviewerValue = state.flags.reviewerFlag ?? (action.lockfileOrgReviewers ?? []).join(', ');
1151
+ // Determine next phase based on missing tags/tools. A batch asks for neither: as for
1152
+ // a --with entry, a missing one is only a warning.
1153
+ const batch = isBatch(state.flags);
1154
+ const manifest = state.target?.data;
1155
+ const hasTags = batch || (manifest && 'tags' in manifest && Array.isArray(manifest.tags) && manifest.tags.length > 0);
1156
+ const hasTools = batch ||
1157
+ // Only assets have tools; bundles skip the tools prompt
1158
+ state.target?.type !== 'asset' ||
1159
+ (manifest && 'tools' in manifest && Array.isArray(manifest.tools) && manifest.tools.length > 0);
1160
+ const isOrgScoped = batch
1161
+ ? [state.target, ...state.entries.map((entry) => entry.target)].some((t) => t && isOrgScopedTarget(t))
1162
+ : Boolean(state.target && isOrgScopedTarget(state.target));
1163
+ // Reviewers only apply to org-scoped assets (non-org PRs always go to the registry
1164
+ // maintainer) — fail fast rather than silently ignoring the flag.
1165
+ if (!isOrgScoped && state.flags.reviewerFlag && parseReviewersInput(state.flags.reviewerFlag).length > 0) {
1166
+ return {
1167
+ ...state,
1168
+ errorMessage: 'The --reviewer flag only applies to org-scoped assets. Remove the flag to publish this asset.',
1169
+ phase: 'error',
1170
+ validation: action.validation,
1171
+ };
1172
+ }
1173
+ // Non-interactive path: resolve tags from --tags flag (or empty) right here, then
1174
+ // either route to loading-tools (effect resolves tools async) or directly to
1175
+ // checking-registry. Manifest tags always win when present. The reviewer prompt
1176
+ // never applies here — non-interactive mode always skips it.
1177
+ if (state.nonInteractive) {
1178
+ let nextTarget = state.target;
1179
+ if (!hasTags && nextTarget) {
1180
+ const flagTags = splitList(state.flags.tagsFlag);
1181
+ nextTarget = {
1182
+ ...nextTarget,
1183
+ data: { ...nextTarget.data, tags: flagTags.length > 0 ? flagTags : undefined },
1184
+ };
1185
+ }
1186
+ let nextPhase;
1187
+ if (!hasTools) {
1188
+ // The loading-tools effect detects whether we're non-interactive and
1189
+ // either resolves tools from the manifest/flag/inference or errors out.
1190
+ nextPhase = 'loading-tools';
1191
+ }
1192
+ else {
1193
+ nextPhase = 'checking-registry';
1194
+ }
1195
+ return {
1196
+ ...state,
1197
+ phase: nextPhase,
1198
+ reviewerValue,
1199
+ target: nextTarget,
1200
+ validation: action.validation,
1201
+ };
1202
+ }
1203
+ let nextPhase;
1204
+ if (!hasTags) {
1205
+ nextPhase = 'prompting-tags';
1206
+ }
1207
+ else if (!hasTools) {
1208
+ nextPhase = 'loading-tools';
1209
+ }
1210
+ else {
1211
+ nextPhase = isOrgScoped ? 'prompting-reviewer' : 'checking-registry';
1212
+ }
1213
+ return {
1214
+ ...state,
1215
+ phase: nextPhase,
1216
+ reviewerValue,
1217
+ validation: action.validation,
1218
+ };
1219
+ }
1220
+ default:
1221
+ return state;
1222
+ }
1223
+ }
1224
+ /**
1225
+ * The step before `building-plan`, once the root asset's own checks are done:
1226
+ * check the entries not yet checked, then settle each entry that needs a bump
1227
+ * (the bump prompt; `--bump` or an error when non-interactive), then plan.
1228
+ */
1229
+ function advanceToPlan(state) {
1230
+ if (state.entries.some((entry) => !entry.versionCheck)) {
1231
+ return { ...state, bumpEntry: undefined, phase: 'checking-entries' };
1232
+ }
1233
+ // A batch without --bump names every asset that needs one, not just the first.
1234
+ if (isBatch(state.flags) && state.nonInteractive && !state.flags.bump) {
1235
+ const pending = [
1236
+ ...(state.target && state.versionCheck?.status === 'needs-bump' && !state.resolvedVersion
1237
+ ? [{ label: state.flags.rawPath, latestVersion: state.versionCheck.latestVersion, target: state.target }]
1238
+ : []),
1239
+ ...state.entries.flatMap((entry) => entry.versionCheck?.status === 'needs-bump' && entry.resolvedVersion === undefined
1240
+ ? [{ label: entry.label, latestVersion: entry.versionCheck.latestVersion, target: entry.target }]
1241
+ : []),
1242
+ ];
1243
+ if (pending.length > 0) {
1244
+ const lines = pending.map((p) => ` ${p.label}: ${p.target.assetType}:${p.target.data.name} v${p.target.data.version}, registry has v${p.latestVersion}`);
1245
+ return {
1246
+ ...state,
1247
+ errorMessage: `--bump <patch|minor|major> required: these manifests are not newer than the registry:\n${lines.join('\n')}`,
1248
+ phase: 'error',
1249
+ };
1250
+ }
1251
+ }
1252
+ const index = state.entries.findIndex((entry) => entry.versionCheck?.status === 'needs-bump' && entry.resolvedVersion === undefined);
1253
+ const entry = state.entries[index];
1254
+ if (entry?.versionCheck?.status !== 'needs-bump') {
1255
+ return { ...state, bumpEntry: undefined, phase: 'building-plan' };
1256
+ }
1257
+ if (!state.nonInteractive) {
1258
+ return { ...state, bumpEntry: index, bumpSelection: '', phase: 'bump-prompt' };
1259
+ }
1260
+ const { latestVersion } = entry.versionCheck;
1261
+ if (!state.flags.bump) {
1262
+ return {
1263
+ ...state,
1264
+ errorMessage: `--bump <patch|minor|major> required: registry has v${latestVersion} of ${entry.target.assetType}:${entry.target.data.name} (from ${entry.label}) but its manifest is not newer`,
1265
+ phase: 'error',
1266
+ };
1267
+ }
1268
+ return bumpEntryAt(state, index, state.flags.bump);
1269
+ }
1270
+ /**
1271
+ * Bump the entry at `index` from its registry version, then go on toward the
1272
+ * plan; an error state, as for the root, when the version can't be bumped.
1273
+ */
1274
+ function bumpEntryAt(state, index, bump) {
1275
+ const entry = state.entries[index];
1276
+ if (entry?.versionCheck?.status !== 'needs-bump')
1277
+ return state;
1278
+ let version;
1279
+ try {
1280
+ version = bumpVersion(entry.versionCheck.latestVersion, bump);
1281
+ }
1282
+ catch {
1283
+ return { ...state, errorMessage: `Failed to compute bumped version for ${entry.label}.`, phase: 'error' };
1284
+ }
1285
+ return advanceToPlan({ ...state, entries: replaceEntry(state.entries, index, withVersion(entry, version)) });
1286
+ }
1287
+ /**
1288
+ * Phase to enter once the tags/tools metadata prompts are resolved: org-scoped
1289
+ * targets get the reviewer prompt, everything else proceeds to the registry check.
1290
+ */
1291
+ function phaseAfterMetadata(target) {
1292
+ return target && isOrgScopedTarget(target) ? 'prompting-reviewer' : 'checking-registry';
1293
+ }
1294
+ function replaceEntry(entries, index, entry) {
1295
+ return entries.map((current, i) => (i === index ? entry : current));
1296
+ }
1297
+ /** The entry published at `version`; a successful publish writes it to the entry's manifest. */
1298
+ function withVersion(entry, version) {
1299
+ return {
1300
+ ...entry,
1301
+ resolvedVersion: version,
1302
+ target: { ...entry.target, data: { ...entry.target.data, version } },
1303
+ };
1304
+ }
802
1305
  //# sourceMappingURL=publish-flow.js.map