( id: string, globalDataDir?: string, source: OpenSpecRootSource = 'store' )
| 134 | } |
| 135 | |
| 136 | async function resolveStoreRoot( |
| 137 | id: string, |
| 138 | globalDataDir?: string, |
| 139 | source: OpenSpecRootSource = 'store' |
| 140 | ): Promise<ResolvedOpenSpecRoot> { |
| 141 | try { |
| 142 | validateStoreId(id); |
| 143 | } catch (error) { |
| 144 | fromStoreError(error); |
| 145 | } |
| 146 | |
| 147 | let registry; |
| 148 | try { |
| 149 | registry = await readStoreRegistryState(globalDataDir ? { globalDataDir } : {}); |
| 150 | } catch (error) { |
| 151 | fromStoreError(error); |
| 152 | } |
| 153 | const entries = registry ? listStoreRegistryEntries(registry) : []; |
| 154 | const entry = entries.find((candidate) => candidate.id === id); |
| 155 | |
| 156 | if (!entry) { |
| 157 | if (entries.length === 0) { |
| 158 | throw new RootSelectionError( |
| 159 | `Unknown store '${id}'. No stores are registered.`, |
| 160 | 'no_registered_stores', |
| 161 | { |
| 162 | target: 'store.id', |
| 163 | fix: `Run openspec store setup ${id} or openspec store register <path> first.`, |
| 164 | } |
| 165 | ); |
| 166 | } |
| 167 | |
| 168 | throw new RootSelectionError( |
| 169 | `Unknown store '${id}'. Registered stores: ${entries |
| 170 | .map((candidate) => candidate.id) |
| 171 | .join(', ')}.`, |
| 172 | 'unknown_store', |
| 173 | { |
| 174 | target: 'store.id', |
| 175 | fix: 'Pass a registered store id, or run openspec store list.', |
| 176 | } |
| 177 | ); |
| 178 | } |
| 179 | |
| 180 | const storeRoot = getStoreRootForBackend(entry.backend); |
| 181 | const inspection = await inspectRegisteredStore(id, storeRoot); |
| 182 | |
| 183 | switch (inspection.kind) { |
| 184 | case 'metadata_error': |
| 185 | return fromStoreError(inspection.error); |
| 186 | case 'metadata_missing': |
| 187 | // The doctor pointer lives in the message because human-mode command |
| 188 | // wrappers print only the message, not the fix field. |
| 189 | throw new RootSelectionError( |
| 190 | `Store '${id}' is missing identity metadata at ${inspection.metadataPath}. ${doctorFix(id)}`, |
| 191 | 'store_identity_mismatch', |
| 192 | { target: 'store.metadata', fix: doctorFix(id) } |
| 193 | ); |
no test coverage detected