(text: string)
| 231 | } |
| 232 | |
| 233 | function parseJsonStore(text: string): Credentials { |
| 234 | const obj = parseJsonObject(text, "credential file root"); |
| 235 | const out: Credentials = {}; |
| 236 | const apiKey = pickRequiredStringOrAbsent(obj, "api_key", "api_key"); |
| 237 | if (apiKey !== undefined) { |
| 238 | if (!isHeaderSafe(apiKey)) { |
| 239 | throw ErrInvalidStore("api_key must not contain control characters"); |
| 240 | } |
| 241 | out.api_key = apiKey; |
| 242 | } |
| 243 | if (obj["oauth"] !== undefined && obj["oauth"] !== null) { |
| 244 | out.oauth = parseOAuth(obj["oauth"]); |
| 245 | } |
| 246 | if (obj["user"] !== undefined && obj["user"] !== null) { |
| 247 | out.user = parseUser(obj["user"]); |
| 248 | } |
| 249 | // Capture any top-level keys this CLI version doesn't model so the |
| 250 | // next write round-trips them instead of dropping another CLI's data. |
| 251 | const unknownRoot = collectUnknown(obj, KNOWN_ROOT_KEYS); |
| 252 | if (unknownRoot) out[UNKNOWN] = unknownRoot; |
| 253 | return out; |
| 254 | } |
| 255 | |
| 256 | /** Optional-field picker variants used by the data-driven parsers. */ |
| 257 | type FieldPicker = "header_safe" | "non_empty"; |
no test coverage detected