@vibelyster/depop-cli 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +18 -13
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{Impit as L}from"impit";var c="https://webapi.depop.com",v=new L({browser:"chrome"});function l(e){return{Accept:"*/*","Content-Type":"application/json",Authorization:`Bearer ${e}`,Origin:"https://www.depop.com",Referer:"https://www.depop.com/"}}async function d(e,t={}){let r=await v.fetch(e,t);if(!r.ok){let o=await r.text(),s;try{s=JSON.parse(o)}catch{s=o}throw new Error(`Depop API error ${r.status}: ${JSON.stringify(s)}`)}return r.status===204?null:r.json()}async function h(e){try{return{loggedIn:!0,user:await d(`${c}/api/v1/sellerOnboarding/sellerStatus/`,{headers:l(e)})}}catch(t){return{loggedIn:!1,error:t.message}}}async function y(e){let t=await d(`${c}/api/v1/addresses/`,{headers:l(e)});if(t?.length>0)return String(t[0].userId);throw new Error("Could not resolve userId \u2014 no addresses found on account")}async function $(e,t){let{readFile:r}=await import("node:fs/promises"),{extname:o}=await import("node:path"),s=o(e).slice(1).toLowerCase()||"jpg",n=s==="png"?"image/png":"image/jpeg",a=await d(`${c}/api/v2/pictures/`,{method:"POST",headers:l(t),body:JSON.stringify({type:"PRODUCT",extension:s})}),i=await r(e),u=await v.fetch(a.url,{method:"PUT",headers:{"Content-Type":n},body:i});if(!u.ok){let g=await u.text();throw new Error(`S3 upload failed ${u.status}: ${g}`)}return{id:a.id,url:a.url.split("?")[0]}}async function b(e,t){return d(`${c}/api/v2/drafts/`,{method:"POST",headers:l(t),body:JSON.stringify(e)})}async function I(e,t,r){return d(`${c}/api/v2/drafts/${e}/`,{method:"PUT",headers:l(r),body:JSON.stringify({id:e,...t})})}async function D(e){return d(`${c}/api/v2/drafts/`,{headers:l(e)})}async function S(e,t){return d(`${c}/api/v1/drafts/${e}/`,{method:"DELETE",headers:l(t)})}async function x(e,t,r){return d(`${c}/api/v2/products/${e}/`,{method:"PUT",headers:{...l(r),Referer:`https://www.depop.com/products/edit/${e}/`},body:JSON.stringify(t)})}async function T(e,t){return d(`${c}/api/v1/products/${e}/`,{method:"DELETE",headers:l(t)})}async function O(e,t){return d(`${c}/api/v1/product/by-slug/${e}/user/?camel_case=true`,{headers:l(t)})}async function C(e,t){return d(`${c}/api/v3/shop/${t}/products/?limit=200&force_fee_calculation=false`,{headers:l(e)})}async function E(e){return d(`${c}/api/v1/addresses/`,{headers:l(e)})}import{readFile as m,writeFile as _,mkdir as F,unlink as J}from"node:fs/promises";import{createInterface as R}from"node:readline";import{homedir as q}from"node:os";import{join as U}from"node:path";var w="https://www.depop.com",N=U(q(),".vibelyster"),f=U(N,"depop.json");function B(e){let t=R({input:process.stdin,output:process.stdout});return new Promise(r=>{t.question(e,o=>{t.close(),r(o.trim())})})}async function k(){try{let e=JSON.parse(await m(f,"utf-8"));if(e.accessToken)return e}catch{}return null}async function A(e){await F(N,{recursive:!0}),await _(f,JSON.stringify(e,null,2))}async function G(){try{await J(f)}catch{}}async function p(e){let t=K(e,"--access-token")||process.env.DEPOP_ACCESS_TOKEN;if(t)return t;let r=await k();if(r)return r.accessToken;console.error("Error: Not logged in. Run `depop login` or set DEPOP_ACCESS_TOKEN env var."),process.exit(1)}async function P(e){let t=await k();if(t?.userId)return t.userId;let r=await p(e),o=await y(r);return t&&(t.userId=o,await A(t)),o}function K(e,t){let r=e.indexOf(t);return r!==-1&&r+1<e.length?e[r+1]:null}function V(e){let t=[],r=["--access-token","--status"],o=0;for(;o<e.length;)r.includes(e[o])?o+=2:(t.push(e[o]),o++);return t}async function z(){let e=process.argv.slice(2),t=V(e),r=t[0];if(!r||r==="--help"||r==="-h"){console.log(`Depop CLI \u2014 VibeLyster
2
+ import{Impit as F}from"impit";var i="https://webapi.depop.com",v=new F({browser:"chrome"});function c(e){return{Accept:"*/*","Content-Type":"application/json",Authorization:`Bearer ${e}`,Origin:"https://www.depop.com",Referer:"https://www.depop.com/"}}async function l(e,t={}){let a=await v.fetch(e,t);if(!a.ok){let o=await a.text(),s;try{s=JSON.parse(o)}catch{s=o}throw new Error(`Depop API error ${a.status}: ${JSON.stringify(s)}`)}return a.status===204?null:a.json()}async function h(e){try{return{loggedIn:!0,user:await l(`${i}/api/v1/sellerOnboarding/sellerStatus/`,{headers:c(e)})}}catch(t){return{loggedIn:!1,error:t.message}}}async function $(e){let t=await l(`${i}/api/v1/addresses/`,{headers:c(e)});if(t?.length>0)return String(t[0].userId);throw new Error("Could not resolve userId \u2014 no addresses found on account")}async function k(e,t){let{readFile:a}=await import("node:fs/promises"),{extname:o}=await import("node:path"),s=o(e).slice(1).toLowerCase()||"jpg",n=s==="png"?"image/png":"image/jpeg",r=await l(`${i}/api/v2/pictures/`,{method:"POST",headers:c(t),body:JSON.stringify({type:"PRODUCT",extension:s})}),p=await a(e),u=await v.fetch(r.url,{method:"PUT",headers:{"Content-Type":n},body:p});if(!u.ok){let g=await u.text();throw new Error(`S3 upload failed ${u.status}: ${g}`)}return{id:r.id,url:r.url.split("?")[0]}}async function b(e,t){return l(`${i}/api/v2/drafts/`,{method:"POST",headers:c(t),body:JSON.stringify(e)})}async function I(e,t,a){return l(`${i}/api/v2/drafts/${e}/`,{method:"PUT",headers:c(a),body:JSON.stringify({id:e,...t})})}async function S(e){return l(`${i}/api/v2/drafts/`,{headers:c(e)})}async function x(e,t){return l(`${i}/api/v1/drafts/${e}/`,{method:"DELETE",headers:c(t)})}async function T(e,t,a){return l(`${i}/api/v2/products/${e}/`,{method:"PUT",headers:{...c(a),Referer:`https://www.depop.com/products/edit/${e}/`},body:JSON.stringify(t)})}async function D(e,t){return l(`${i}/api/v1/products/${e}/`,{method:"DELETE",headers:c(t)})}async function O(e,t){return l(`${i}/api/v1/product/by-slug/${e}/user/?camel_case=true`,{headers:c(t)})}async function C(e,t){return l(`${i}/api/v3/shop/${t}/products/?limit=200&force_fee_calculation=false`,{headers:c(e)})}async function P(e){return l(`${i}/api/v1/addresses/`,{headers:c(e)})}async function N(e){return l(`${i}/presentation/api/v1/attributes/groups/`,{headers:c(e)})}async function U(e){return l(`${i}/api/v2/search/filters/productAttributes/?country=en`,{headers:c(e)})}async function A(e,t="USPS"){return l(`${i}/api/v1/shipping-providers/?ids=${t}`,{headers:c(e)})}import{readFile as w,writeFile as R,mkdir as q,unlink as z}from"node:fs/promises";import{createInterface as B}from"node:readline";import{homedir as G}from"node:os";import{join as L}from"node:path";var m="https://www.depop.com",j=L(G(),".vibelyster"),f=L(j,"depop.json");function K(e){let t=B({input:process.stdin,output:process.stdout});return new Promise(a=>{t.question(e,o=>{t.close(),a(o.trim())})})}async function y(){try{let e=JSON.parse(await w(f,"utf-8"));if(e.accessToken)return e}catch{}return null}async function _(e){await q(j,{recursive:!0}),await R(f,JSON.stringify(e,null,2))}async function V(){try{await z(f)}catch{}}async function d(e){let t=H(e,"--access-token")||process.env.DEPOP_ACCESS_TOKEN;if(t)return t;let a=await y();if(a)return a.accessToken;console.error("Error: Not logged in. Run `depop login` or set DEPOP_ACCESS_TOKEN env var."),process.exit(1)}async function E(e){let t=await y();if(t?.userId)return t.userId;let a=await d(e),o=await $(a);return t&&(t.userId=o,await _(t)),o}function H(e,t){let a=e.indexOf(t);return a!==-1&&a+1<e.length?e[a+1]:null}function M(e){let t=[],a=["--access-token","--status"],o=0;for(;o<e.length;)a.includes(e[o])?o+=2:(t.push(e[o]),o++);return t}async function Q(){let e=process.argv.slice(2),t=M(e),a=t[0];if(!a||a==="--help"||a==="-h"){console.log(`Depop CLI \u2014 VibeLyster
3
3
 
4
4
  Commands:
5
5
  login Save your access token
@@ -8,6 +8,9 @@ Commands:
8
8
  listings List your products
9
9
  listing <slug> Get product details
10
10
  addresses List shipping addresses
11
+ categories List categories (group \u2192 productType)
12
+ conditions List valid condition values and colors
13
+ shipping List shipping providers and parcel sizes
11
14
  upload <image-path> Upload a square image, returns {id, url}
12
15
  create <json-file> Create a draft listing
13
16
  drafts List draft listings
@@ -22,16 +25,18 @@ Auth:
22
25
  Or set DEPOP_ACCESS_TOKEN env var.
23
26
 
24
27
  Note: Images must be square. Crop before uploading.
25
- `);return}try{switch(r){case"login":{console.log(`Depop Login
28
+ `);return}try{switch(a){case"login":{console.log(`Depop Login
26
29
  `),console.log("To get your access token:"),console.log(" 1. Log in to depop.com in your browser"),console.log(" 2. Open DevTools \u2192 Application \u2192 Cookies \u2192 depop.com"),console.log(` 3. Copy the 'access_token' cookie value
27
- `);let o=await B("access_token: ");o||(console.error("access_token is required."),process.exit(1)),console.log(`
28
- Verifying...`);let s=await h(o);s.loggedIn||(console.error("Login failed:",s.error),process.exit(1)),console.log("Resolving user ID...");let n=await y(o);await A({accessToken:o,userId:n,savedAt:new Date().toISOString()}),console.log(`
29
- Logged in! canSell: ${s.user.canSell}`),console.log(`User ID: ${n}`),console.log(`Credentials saved to ${f}`);break}case"auth":{let o=await p(e),s=await h(o);if(s.loggedIn){let n=await P(e);console.log("Logged in. User ID:",n),console.log("canSell:",s.user.canSell),console.log("stripe:",s.user.stripe?.isConnected?"connected":"not connected");let a=await k();a?(console.log(`Credentials: ${f}`),a.savedAt&&console.log("Saved at:",a.savedAt)):console.log("Credentials: environment variables")}else console.error("Not logged in:",s.error),process.exit(1);break}case"logout":{await G(),console.log("Logged out. Credentials removed from",f);break}case"listings":{let o=await p(e),s=await P(e),n=await C(o,s),a=n.products||n.objects||[];if(!a.length){console.log("No listings found.");break}for(let i of a){let u=(i.description||"(no title)").split(`
30
- `)[0].slice(0,60),g=i.slug||i.id;console.log(`[${g}] ${u} \u2014 ${i.status}`),console.log(` ${w}/products/${g}/`)}console.log(`
31
- Total: ${a.length} listings`);break}case"listing":{let o=t[1];o||(console.error("Usage: depop listing <slug>"),process.exit(1));let s=await p(e),n=await O(o,s);console.log(JSON.stringify(n,null,2));break}case"addresses":{let o=await p(e),s=await E(o);console.log(JSON.stringify(s,null,2));break}case"upload":{let o=t[1];o||(console.error("Usage: depop upload <image-path>"),console.error(`
32
- Image must be square. Depop will reject non-square images.`),process.exit(1));let s=await p(e),n=await $(o,s);console.log("Uploaded:"),console.log(" ID:",n.id),console.log(" URL:",n.url||n.imageUrl||JSON.stringify(n));break}case"create":{let o=t[1];o||(console.error("Usage: depop create <json-file>"),console.error(`
33
- See examples/draft.json for the payload format.`),process.exit(1));let s=await p(e),n=JSON.parse(await m(o,"utf-8"));console.log("Creating draft...");let a=await b(n,s);console.log("Draft created:",a.id),console.log(`
34
- To publish, open the draft in your browser:`),console.log(` ${w}/sellinghub/drafts/edit/${a.id}/`),console.log(`
35
- Or update it via: depop draft-update <draft-id> <json-file>`);break}case"drafts":{let o=await p(e),n=(await D(o)).drafts||[];if(!n.length){console.log("No drafts found.");break}for(let a of n){let i=(a.description||"(no description)").split(`
36
- `)[0].slice(0,60),u=a.priceAmount?`$${a.priceAmount}`:"?",g=a.missingFields?.length?` [missing: ${a.missingFields.join(", ")}]`:" [ready]";console.log(`[${a.id}] ${i} \u2014 ${u}${g}`)}console.log(`
37
- Total: ${n.length} drafts`);break}case"draft-update":{let o=t[1],s=t[2];(!o||!s)&&(console.error("Usage: depop draft-update <draft-id> <json-file>"),process.exit(1));let n=await p(e),a=JSON.parse(await m(s,"utf-8"));await I(o,a,n),console.log("Draft updated:",o),console.log(` ${w}/sellinghub/drafts/edit/${o}/`);break}case"draft-delete":{let o=t[1];o||(console.error("Usage: depop draft-delete <draft-id>"),process.exit(1));let s=await p(e);await S(o,s),console.log("Draft deleted:",o);break}case"edit":{let o=t[1],s=t[2];(!o||!s)&&(console.error("Usage: depop edit <product-id> <json-file>"),process.exit(1));let n=await p(e),a=JSON.parse(await m(s,"utf-8")),i=await x(o,a,n);console.log("Updated listing:"),console.log(" ID:",i.id),console.log(" URL:",`${w}/products/${i.slug||i.id}/`);break}case"delete":{let o=t[1];o||(console.error("Usage: depop delete <product-id>"),process.exit(1));let s=await p(e);await T(o,s),console.log(`Deleted product ${o}`);break}default:console.error(`Unknown command: ${r}`),console.error('Run "depop --help" for usage.'),process.exit(1)}}catch(o){console.error("Error:",o.message),process.exit(1)}}z();
30
+ `);let o=await K("access_token: ");o||(console.error("access_token is required."),process.exit(1)),console.log(`
31
+ Verifying...`);let s=await h(o);s.loggedIn||(console.error("Login failed:",s.error),process.exit(1)),console.log("Resolving user ID...");let n=await $(o);await _({accessToken:o,userId:n,savedAt:new Date().toISOString()}),console.log(`
32
+ Logged in! canSell: ${s.user.canSell}`),console.log(`User ID: ${n}`),console.log(`Credentials saved to ${f}`);break}case"auth":{let o=await d(e),s=await h(o);if(s.loggedIn){let n=await E(e);console.log("Logged in. User ID:",n),console.log("canSell:",s.user.canSell),console.log("stripe:",s.user.stripe?.isConnected?"connected":"not connected");let r=await y();r?(console.log(`Credentials: ${f}`),r.savedAt&&console.log("Saved at:",r.savedAt)):console.log("Credentials: environment variables")}else console.error("Not logged in:",s.error),process.exit(1);break}case"logout":{await V(),console.log("Logged out. Credentials removed from",f);break}case"listings":{let o=await d(e),s=await E(e),n=await C(o,s),r=n.products||n.objects||[];if(!r.length){console.log("No listings found.");break}for(let p of r){let u=(p.description||"(no title)").split(`
33
+ `)[0].slice(0,60),g=p.slug||p.id;console.log(`[${g}] ${u} \u2014 ${p.status}`),console.log(` ${m}/products/${g}/`)}console.log(`
34
+ Total: ${r.length} listings`);break}case"listing":{let o=t[1];o||(console.error("Usage: depop listing <slug>"),process.exit(1));let s=await d(e),n=await O(o,s);console.log(JSON.stringify(n,null,2));break}case"addresses":{let o=await d(e),s=await P(o);console.log(JSON.stringify(s,null,2));break}case"categories":{let o=await d(e),s=await N(o);for(let[n,r]of Object.entries(s)){if(!r.product_types?.length)continue;let p=(r.department||[]).join(", ");console.log(`
35
+ ${n} (${p}):`);for(let u of r.product_types){let g=u.name_i18n?.["en-US"]||u.name_i18n?.en||u.id;console.log(` ${u.id} \u2014 ${g}`)}}break}case"conditions":{let o=await d(e),s=await U(o);console.log("Conditions:");for(let n of s.condition||[])console.log(` ${n.id} \u2014 ${n.nameI18N} (${n.descriptionI18N})`);console.log(`
36
+ Colors (max `+(s.settings?.maxColours||2)+"):");for(let n of s.colour||[])console.log(` ${n.id} \u2014 ${n.nameI18N}`);break}case"shipping":{let o=await d(e),s=await A(o);for(let n of s){console.log(`${n.id}:`);for(let r of n.parcelSizes||[])console.log(` ${r.id} \u2014 ${r.title} (${r.subtitle}) $${r.cost?.amount}`)}break}case"upload":{let o=t[1];o||(console.error("Usage: depop upload <image-path>"),console.error(`
37
+ Image must be square. Depop will reject non-square images.`),process.exit(1));let s=await d(e),n=await k(o,s);console.log("Uploaded:"),console.log(" ID:",n.id),console.log(" URL:",n.url||n.imageUrl||JSON.stringify(n));break}case"create":{let o=t[1];o||(console.error("Usage: depop create <json-file>"),console.error(`
38
+ See examples/draft.json for the payload format.`),process.exit(1));let s=await d(e),n=JSON.parse(await w(o,"utf-8"));console.log("Creating draft...");let r=await b(n,s);console.log("Draft created:",r.id),console.log(`
39
+ To publish, open the draft in your browser:`),console.log(` ${m}/sellinghub/drafts/edit/${r.id}/`),console.log(`
40
+ Or update it via: depop draft-update <draft-id> <json-file>`);break}case"drafts":{let o=await d(e),n=(await S(o)).drafts||[];if(!n.length){console.log("No drafts found.");break}for(let r of n){let p=(r.description||"(no description)").split(`
41
+ `)[0].slice(0,60),u=r.priceAmount?`$${r.priceAmount}`:"?",g=r.missingFields?.length?` [missing: ${r.missingFields.join(", ")}]`:" [ready]";console.log(`[${r.id}] ${p} \u2014 ${u}${g}`)}console.log(`
42
+ Total: ${n.length} drafts`);break}case"draft-update":{let o=t[1],s=t[2];(!o||!s)&&(console.error("Usage: depop draft-update <draft-id> <json-file>"),process.exit(1));let n=await d(e),r=JSON.parse(await w(s,"utf-8"));await I(o,r,n),console.log("Draft updated:",o),console.log(` ${m}/sellinghub/drafts/edit/${o}/`);break}case"draft-delete":{let o=t[1];o||(console.error("Usage: depop draft-delete <draft-id>"),process.exit(1));let s=await d(e);await x(o,s),console.log("Draft deleted:",o);break}case"edit":{let o=t[1],s=t[2];(!o||!s)&&(console.error("Usage: depop edit <product-id> <json-file>"),process.exit(1));let n=await d(e),r=JSON.parse(await w(s,"utf-8")),p=await T(o,r,n);console.log("Updated listing:"),console.log(" ID:",p.id),console.log(" URL:",`${m}/products/${p.slug||p.id}/`);break}case"delete":{let o=t[1];o||(console.error("Usage: depop delete <product-id>"),process.exit(1));let s=await d(e);await D(o,s),console.log(`Deleted product ${o}`);break}default:console.error(`Unknown command: ${a}`),console.error('Run "depop --help" for usage.'),process.exit(1)}}catch(o){console.error("Error:",o.message),process.exit(1)}}Q();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibelyster/depop-cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "CLI for Depop's internal API — list, create, edit, and manage product listings",
5
5
  "type": "module",
6
6
  "bin": {