(storeRoot: string, id: string)
| 870 | } |
| 871 | |
| 872 | async function assertSafeToDeleteStoreRoot(storeRoot: string, id: string): Promise<{ |
| 873 | exists: boolean; |
| 874 | }> { |
| 875 | const kind = await pathKind(storeRoot); |
| 876 | |
| 877 | if (kind === 'missing') { |
| 878 | return { exists: false }; |
| 879 | } |
| 880 | |
| 881 | if (kind !== 'directory') { |
| 882 | throw new StoreError( |
| 883 | `Store path is not a directory: ${storeRoot}`, |
| 884 | 'store_remove_path_not_directory', |
| 885 | { |
| 886 | target: 'store.root', |
| 887 | fix: 'Run "openspec store unregister <id>" if you only want to forget this local registry entry.', |
| 888 | } |
| 889 | ); |
| 890 | } |
| 891 | |
| 892 | const metadata = await readStoreMetadataForOperation(storeRoot); |
| 893 | if (!metadata) { |
| 894 | throw new StoreError( |
| 895 | 'Store remove refuses to delete a folder without store metadata.', |
| 896 | 'store_remove_metadata_missing', |
| 897 | { |
| 898 | target: 'store.metadata', |
| 899 | fix: 'Run "openspec store unregister <id>" if you only want to forget this local registry entry.', |
| 900 | } |
| 901 | ); |
| 902 | } |
| 903 | |
| 904 | if (metadata.id !== id) { |
| 905 | throw new StoreError( |
| 906 | `Store metadata id '${metadata.id}' does not match requested id '${id}'.`, |
| 907 | 'store_metadata_id_mismatch', |
| 908 | { |
| 909 | target: 'store.metadata', |
| 910 | fix: 'Repair the registry or run store unregister instead of deleting this folder.', |
| 911 | } |
| 912 | ); |
| 913 | } |
| 914 | |
| 915 | return { exists: true }; |
| 916 | } |
| 917 | |
| 918 | export async function removeStore( |
| 919 | target: PreparedStoreCleanup |
no test coverage detected