Summary
The prefix used for region/base-URL resolution is computed two different ways in two
different places, and the two disagree whenever the API key does not start with sk-.
This is reachable today because getApiKey() returns process.env.TUYA_API_KEY verbatim,
bypassing the sk- validation that tuya init enforces.
The two implementations
resolveBaseUrl / resolveWsUri in src/config.js:36-58 strip sk- only if it is
present, then take the first two characters:
let key = apiKey;
if (key.startsWith('sk-')) {
key = key.slice(3);
}
const prefix = key.slice(0, 2).toUpperCase();
But doctor and init hard-code a fixed offset of 3, assuming sk- is always there:
src/commands/doctor.js:37 — const prefix = apiKey.slice(3, 5).toUpperCase();
src/commands/init.js:46 — const prefix = apiKey.slice(3, 5).toUpperCase();
src/commands/init.js:65 — const prefix = apiKey.slice(3, 5).toUpperCase();
What goes wrong
Set a perfectly valid raw key (no sk-), e.g. export TUYA_API_KEY=AYabc123...:
resolveBaseUrl strips nothing, reads slice(0,2) = AY → correctly returns the China base URL.
doctor reads slice(3,5) = c1 → getRegionName('C1') returns 'Unknown'.
So tuya doctor happily connects to the right data center but reports
Base URL: https://openapi.tuyacn.com (Unknown), which looks like a misconfiguration to
the user. The init path has the same skew if a key is pasted without the prefix.
Suggested fix
Export the prefix-extraction logic from config.js (it already exists inside
resolveBaseUrl) and reuse it everywhere instead of re-deriving the offset by hand. A single
getKeyPrefix(apiKey) helper removes the slice(3,5) vs slice(0,2)-after-strip divergence.
Summary
The prefix used for region/base-URL resolution is computed two different ways in two
different places, and the two disagree whenever the API key does not start with
sk-.This is reachable today because
getApiKey()returnsprocess.env.TUYA_API_KEYverbatim,bypassing the
sk-validation thattuya initenforces.The two implementations
resolveBaseUrl/resolveWsUriinsrc/config.js:36-58stripsk-only if it ispresent, then take the first two characters:
But
doctorandinithard-code a fixed offset of 3, assumingsk-is always there:src/commands/doctor.js:37—const prefix = apiKey.slice(3, 5).toUpperCase();src/commands/init.js:46—const prefix = apiKey.slice(3, 5).toUpperCase();src/commands/init.js:65—const prefix = apiKey.slice(3, 5).toUpperCase();What goes wrong
Set a perfectly valid raw key (no
sk-), e.g.export TUYA_API_KEY=AYabc123...:resolveBaseUrlstrips nothing, readsslice(0,2)=AY→ correctly returns the China base URL.doctorreadsslice(3,5)=c1→getRegionName('C1')returns'Unknown'.So
tuya doctorhappily connects to the right data center but reportsBase URL: https://openapi.tuyacn.com (Unknown), which looks like a misconfiguration tothe user. The
initpath has the same skew if a key is pasted without the prefix.Suggested fix
Export the prefix-extraction logic from
config.js(it already exists insideresolveBaseUrl) and reuse it everywhere instead of re-deriving the offset by hand. A singlegetKeyPrefix(apiKey)helper removes theslice(3,5)vsslice(0,2)-after-strip divergence.