{"record":{"id":"a37673893905274a","repo":"jackwener/OpenCLI","slug":"invalid-1688-store-url","errorCode":null,"errorMessage":"Invalid 1688 store URL","messagePattern":"Invalid 1688 store URL","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/1688/shared.js","lineNumber":170,"sourceCode":"        return canonicalizeStoreUrl(normalized);\n    }\n    if (normalized.endsWith('.1688.com')) {\n        return canonicalizeStoreUrl(`https://${normalized}`);\n    }\n    if (/^[a-z0-9-]+$/i.test(normalized)) {\n        return canonicalizeStoreUrl(`https://${normalized}.1688.com`);\n    }\n    throw new ArgumentError('1688 store expects a store URL or member ID', 'Example: opencli 1688 store b2b-22154705262941f196');\n}\nexport function canonicalizeStoreUrl(input) {\n    const url = parse1688Url(input);\n    const memberId = extractMemberId(url.toString());\n    if (memberId) {\n        return `${STORE_MOBILE_URL_PREFIX}${memberId}`;\n    }\n    const host = normalizeStoreHost(url.hostname);\n    if (!host) {\n        throw new ArgumentError('Invalid 1688 store URL', 'Example: opencli 1688 store https://yinuoweierfushi.1688.com/');\n    }\n    return `https://${host}`;\n}\nexport function canonicalizeItemUrl(input) {\n    const offerId = extractOfferId(input);\n    if (offerId) {\n        return `${DETAIL_URL_PREFIX}${offerId}.html`;\n    }\n    const url = parse1688UrlOrNull(input);\n    if (!url)\n        return null;\n    stripTrackingParams(url);\n    url.hash = '';\n    return url.toString();\n}\nexport function canonicalizeSellerUrl(input) {\n    const memberId = extractMemberId(input);\n    if (memberId) {","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/1688/shared.js#L152-L188","documentation":"canonicalizeStoreUrl parses an input that already looked like a URL and converts it to a canonical store URL (mobile member URL or https host). If the parsed URL's hostname does not normalize to a valid 1688 store host, it throws ArgumentError. In other words the input was a URL, but not one pointing at a 1688 store host the library understands.","triggerScenarios":"resolveStoreUrl or safeCanonicalStoreUrl receives an http(s) URL whose host is not a *.1688.com store host — e.g. https://example.com, https://detail.1688.com (offer host with no store subdomain), or a URL with an unexpected subdomain pattern.","commonSituations":"Passing an offer/detail URL to the store command; pasting a shortened or aliased domain; using a 1688 mobile app share link with a non-standard host; typos like 1688.co or 1688.comm.","solutions":["Use the store's winport URL, e.g. https://yinuoweierfushi.1688.com/ — the host must be a store subdomain of 1688.com.","If you actually have an offer URL (detail.1688.com/offer/...), use the item command instead of store.","Double-check the domain spelling; the host must normalize under normalizeStoreHost, so only standard 1688.com store hosts qualify."],"exampleFix":"// before\nopencli 1688 store https://detail.1688.com/offer/887904326744.html // offer host, not a store host\n// after\nopencli 1688 store https://yinuoweierfushi.1688.com/","handlingStrategy":"validation","validationCode":"function isStoreHostUrl(input) {\n  try {\n    const u = new URL(String(input));\n    return /(^|\\.)1688\\.com$/i.test(u.hostname)\n      && !/^detail\\./i.test(u.hostname)\n      && u.hostname.split('.')[0] !== 'www';\n  } catch { return false; }\n}\nif (!isStoreHostUrl(input)) throw new Error('Provide a store winport URL like https://shop.1688.com/');","typeGuard":"function isStoreUrlObject(input) {\n  try {\n    const u = new URL(String(input));\n    return u.hostname.endsWith('.1688.com') && u.hostname !== 'detail.1688.com';\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  const url = canonicalizeStoreUrl(input);\n} catch (e) {\n  if (e.name === 'ArgumentError') {\n    console.error(`'${input}' is not a 1688 store host. Use the shop's *.1688.com winport URL.`);\n  } else throw e;\n}","preventionTips":["Never feed offer (detail.1688.com) URLs to store flows — check the hostname first.","Beware aliased/shortened domains; resolve redirects before canonicalizing.","Keep host spelling exact: 1688.com, no typos or extra TLDs.","Write tests covering offer URLs, www URLs, and foreign domains as negative cases."],"tags":["url-parsing","argument-validation","host-validation"],"backgroundTag":"invalid-input-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}