1688-cli 0.1.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 (80) hide show
  1. package/AGENTS.md +118 -0
  2. package/README.md +48 -0
  3. package/dist/auth/cookies.js +31 -0
  4. package/dist/auth/cookies.js.map +1 -0
  5. package/dist/auth/verify.js +25 -0
  6. package/dist/auth/verify.js.map +1 -0
  7. package/dist/cli.js +373 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/cart-add.js +199 -0
  10. package/dist/commands/cart-add.js.map +1 -0
  11. package/dist/commands/cart-list.js +168 -0
  12. package/dist/commands/cart-list.js.map +1 -0
  13. package/dist/commands/cart-remove.js +119 -0
  14. package/dist/commands/cart-remove.js.map +1 -0
  15. package/dist/commands/checkout-confirm.js +407 -0
  16. package/dist/commands/checkout-confirm.js.map +1 -0
  17. package/dist/commands/checkout-prepare.js +244 -0
  18. package/dist/commands/checkout-prepare.js.map +1 -0
  19. package/dist/commands/doctor.js +246 -0
  20. package/dist/commands/doctor.js.map +1 -0
  21. package/dist/commands/image-search.js +210 -0
  22. package/dist/commands/image-search.js.map +1 -0
  23. package/dist/commands/login.js +209 -0
  24. package/dist/commands/login.js.map +1 -0
  25. package/dist/commands/logout.js +59 -0
  26. package/dist/commands/logout.js.map +1 -0
  27. package/dist/commands/offer.js +185 -0
  28. package/dist/commands/offer.js.map +1 -0
  29. package/dist/commands/order-get.js +76 -0
  30. package/dist/commands/order-get.js.map +1 -0
  31. package/dist/commands/order-list.js +176 -0
  32. package/dist/commands/order-list.js.map +1 -0
  33. package/dist/commands/order-logistics.js +152 -0
  34. package/dist/commands/order-logistics.js.map +1 -0
  35. package/dist/commands/search.js +250 -0
  36. package/dist/commands/search.js.map +1 -0
  37. package/dist/commands/seller-chat.js +213 -0
  38. package/dist/commands/seller-chat.js.map +1 -0
  39. package/dist/commands/seller-inquire.js +110 -0
  40. package/dist/commands/seller-inquire.js.map +1 -0
  41. package/dist/commands/seller-lookup-ww.js +6 -0
  42. package/dist/commands/seller-lookup-ww.js.map +1 -0
  43. package/dist/commands/seller-messages.js +181 -0
  44. package/dist/commands/seller-messages.js.map +1 -0
  45. package/dist/commands/whoami.js +53 -0
  46. package/dist/commands/whoami.js.map +1 -0
  47. package/dist/commands/workflows.js +264 -0
  48. package/dist/commands/workflows.js.map +1 -0
  49. package/dist/daemon/client.js +75 -0
  50. package/dist/daemon/client.js.map +1 -0
  51. package/dist/daemon/manager.js +128 -0
  52. package/dist/daemon/manager.js.map +1 -0
  53. package/dist/daemon/protocol.js +5 -0
  54. package/dist/daemon/protocol.js.map +1 -0
  55. package/dist/daemon/server.js +197 -0
  56. package/dist/daemon/server.js.map +1 -0
  57. package/dist/daemon/throttle.js +17 -0
  58. package/dist/daemon/throttle.js.map +1 -0
  59. package/dist/io/errors.js +10 -0
  60. package/dist/io/errors.js.map +1 -0
  61. package/dist/io/output.js +17 -0
  62. package/dist/io/output.js.map +1 -0
  63. package/dist/io/prompt.js +17 -0
  64. package/dist/io/prompt.js.map +1 -0
  65. package/dist/session/context.js +91 -0
  66. package/dist/session/context.js.map +1 -0
  67. package/dist/session/dispatch.js +50 -0
  68. package/dist/session/dispatch.js.map +1 -0
  69. package/dist/session/lock.js +23 -0
  70. package/dist/session/lock.js.map +1 -0
  71. package/dist/session/paths.js +31 -0
  72. package/dist/session/paths.js.map +1 -0
  73. package/dist/session/shared.js +104 -0
  74. package/dist/session/shared.js.map +1 -0
  75. package/dist/session/state.js +27 -0
  76. package/dist/session/state.js.map +1 -0
  77. package/dist/util/time.js +17 -0
  78. package/dist/util/time.js.map +1 -0
  79. package/package.json +44 -0
  80. package/scripts/postinstall.mjs +49 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/session/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,MAAM,UAAU,IAAI;IAClB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAI,GAAG,SAAS;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,104 @@
1
+ // Long-lived shared BrowserContext for the daemon. Operations are serialized
2
+ // (one Playwright op at a time) so we look like a single, deliberate user
3
+ // rather than concurrent requests.
4
+ import fs from 'node:fs/promises';
5
+ import { chromium } from 'playwright-extra';
6
+ import stealth from 'puppeteer-extra-plugin-stealth';
7
+ import { profilePath } from './paths.js';
8
+ import { acquireLock } from './lock.js';
9
+ import { CliError } from '../io/errors.js';
10
+ import { clearStaleSingleton } from './context.js';
11
+ const stealthPlugin = stealth();
12
+ stealthPlugin.enabledEvasions.delete('iframe.contentWindow');
13
+ stealthPlugin.enabledEvasions.delete('media.codecs');
14
+ chromium.use(stealthPlugin);
15
+ const LAUNCH_OPTS = {
16
+ viewport: { width: 1440, height: 900 },
17
+ locale: 'zh-CN',
18
+ timezoneId: 'Asia/Shanghai',
19
+ };
20
+ let sharedCtx = null;
21
+ let lockRelease = null;
22
+ let opChain = Promise.resolve();
23
+ export async function getSharedContext() {
24
+ if (sharedCtx)
25
+ return sharedCtx;
26
+ lockRelease = await acquireLock();
27
+ const dir = profilePath('default');
28
+ await fs.mkdir(dir, { recursive: true });
29
+ await clearStaleSingleton(dir);
30
+ sharedCtx = await launchPreferringChrome(dir, true);
31
+ await sharedCtx.addInitScript(() => {
32
+ try {
33
+ Object.defineProperty(navigator, 'languages', {
34
+ get: () => ['zh-CN', 'zh', 'en'],
35
+ });
36
+ }
37
+ catch {
38
+ /* ignore */
39
+ }
40
+ });
41
+ return sharedCtx;
42
+ }
43
+ export async function runOnSharedCtx(fn) {
44
+ // Append to serial queue. Each op waits for the previous one to finish.
45
+ const prev = opChain;
46
+ let resolveOp;
47
+ let rejectOp;
48
+ const opPromise = new Promise((res, rej) => {
49
+ resolveOp = res;
50
+ rejectOp = rej;
51
+ });
52
+ opChain = prev.then(async () => {
53
+ try {
54
+ const ctx = await getSharedContext();
55
+ resolveOp(await fn(ctx));
56
+ }
57
+ catch (e) {
58
+ rejectOp(e);
59
+ }
60
+ });
61
+ return opPromise;
62
+ }
63
+ export async function releaseSharedContext() {
64
+ if (sharedCtx) {
65
+ await sharedCtx.close().catch(() => { });
66
+ sharedCtx = null;
67
+ }
68
+ if (lockRelease) {
69
+ await lockRelease().catch(() => { });
70
+ lockRelease = null;
71
+ }
72
+ }
73
+ async function launchPreferringChrome(dir, headless) {
74
+ const useChrome = process.env.BB1688_FORCE_CHROMIUM !== '1';
75
+ if (useChrome) {
76
+ try {
77
+ return (await chromium.launchPersistentContext(dir, {
78
+ ...LAUNCH_OPTS,
79
+ headless,
80
+ channel: 'chrome',
81
+ }));
82
+ }
83
+ catch (e) {
84
+ const msg = e.message ?? '';
85
+ if (!/Chromium\?|channel|Executable doesn't exist|chrome.*not found/i.test(msg)) {
86
+ throw e;
87
+ }
88
+ }
89
+ }
90
+ try {
91
+ return (await chromium.launchPersistentContext(dir, {
92
+ ...LAUNCH_OPTS,
93
+ headless,
94
+ }));
95
+ }
96
+ catch (e) {
97
+ const msg = e.message ?? '';
98
+ if (/Executable doesn't exist/i.test(msg)) {
99
+ throw new CliError(6, 'CHROMIUM_MISSING', 'Chromium not installed. Run: npx playwright install chromium');
100
+ }
101
+ throw e;
102
+ }
103
+ }
104
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/session/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { stateFile, ensureRoot } from './paths.js';
4
+ const EMPTY = { version: 1 };
5
+ export async function readState() {
6
+ try {
7
+ const buf = await fs.readFile(stateFile(), 'utf8');
8
+ const parsed = JSON.parse(buf);
9
+ if (parsed?.version !== 1)
10
+ return { ...EMPTY };
11
+ return { ...EMPTY, ...parsed };
12
+ }
13
+ catch (e) {
14
+ if (e.code === 'ENOENT')
15
+ return { ...EMPTY };
16
+ throw e;
17
+ }
18
+ }
19
+ export async function writeState(s) {
20
+ await ensureRoot();
21
+ await fs.mkdir(path.dirname(stateFile()), { recursive: true });
22
+ await fs.writeFile(stateFile(), JSON.stringify(s, null, 2));
23
+ }
24
+ export async function clearState() {
25
+ await writeState({ ...EMPTY });
26
+ }
27
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/session/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAUnD,MAAM,KAAK,GAAU,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;QACjD,IAAI,MAAM,EAAE,OAAO,KAAK,CAAC;YAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QAC/C,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QACxE,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,CAAQ;IACvC,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,17 @@
1
+ export function nowIso() {
2
+ return new Date().toISOString();
3
+ }
4
+ export function relative(iso) {
5
+ const diff = Date.now() - new Date(iso).getTime();
6
+ const s = Math.floor(diff / 1000);
7
+ if (s < 5)
8
+ return 'just now';
9
+ if (s < 60)
10
+ return `${s}s ago`;
11
+ if (s < 3600)
12
+ return `${Math.floor(s / 60)}m ago`;
13
+ if (s < 86400)
14
+ return `${Math.floor(s / 3600)}h ago`;
15
+ return `${Math.floor(s / 86400)}d ago`;
16
+ }
17
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/util/time.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAClD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,UAAU,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;IAClD,IAAI,CAAC,GAAG,KAAK;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;IACrD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;AACzC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "1688-cli",
3
+ "version": "0.1.0",
4
+ "description": "1688 CLI for humans, Codex, and Claude Code",
5
+ "type": "module",
6
+ "bin": {
7
+ "1688": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "scripts/postinstall.mjs",
12
+ "AGENTS.md",
13
+ "README.md"
14
+ ],
15
+ "engines": {
16
+ "node": ">=20"
17
+ },
18
+ "scripts": {
19
+ "dev": "tsx src/cli.ts",
20
+ "build": "tsc -p tsconfig.json && chmod +x dist/cli.js",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
23
+ "typecheck": "tsc --noEmit",
24
+ "prepublishOnly": "pnpm build",
25
+ "postinstall": "node scripts/postinstall.mjs"
26
+ },
27
+ "dependencies": {
28
+ "commander": "^12.1.0",
29
+ "iconv-lite": "^0.7.2",
30
+ "playwright": "^1.48.0",
31
+ "playwright-extra": "^4.3.6",
32
+ "proper-lockfile": "^4.1.2",
33
+ "puppeteer-extra-plugin-stealth": "^2.11.2",
34
+ "qrcode": "^1.5.4"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^20.14.0",
38
+ "@types/proper-lockfile": "^4.1.4",
39
+ "@types/qrcode": "^1.5.6",
40
+ "tsx": "^4.19.0",
41
+ "typescript": "^5.6.0",
42
+ "vitest": "^2.1.0"
43
+ }
44
+ }
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ // Best-effort Chromium install. Never fail the parent npm install.
3
+ import { spawnSync } from 'node:child_process';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import os from 'node:os';
7
+
8
+ if (process.env.CI || process.env.BB1688_SKIP_POSTINSTALL) {
9
+ process.exit(0);
10
+ }
11
+
12
+ function chromiumCacheDir() {
13
+ if (process.env.PLAYWRIGHT_BROWSERS_PATH) {
14
+ return process.env.PLAYWRIGHT_BROWSERS_PATH;
15
+ }
16
+ switch (process.platform) {
17
+ case 'darwin':
18
+ return path.join(os.homedir(), 'Library/Caches/ms-playwright');
19
+ case 'win32':
20
+ return path.join(
21
+ process.env.LOCALAPPDATA ?? os.homedir(),
22
+ 'ms-playwright',
23
+ );
24
+ default:
25
+ return path.join(os.homedir(), '.cache/ms-playwright');
26
+ }
27
+ }
28
+
29
+ const cache = chromiumCacheDir();
30
+ const installed =
31
+ fs.existsSync(cache) &&
32
+ fs.readdirSync(cache).some((n) => n.startsWith('chromium'));
33
+
34
+ if (installed) {
35
+ console.log('1688-cli: Chromium found, skipping download.');
36
+ process.exit(0);
37
+ }
38
+
39
+ console.log('1688-cli: Installing Chromium (~150MB)...');
40
+ const res = spawnSync('npx', ['playwright', 'install', 'chromium'], {
41
+ stdio: 'inherit',
42
+ });
43
+ if (res.status !== 0) {
44
+ console.log(
45
+ '1688-cli: Chromium install failed. Run manually before first use:\n' +
46
+ ' npx playwright install chromium',
47
+ );
48
+ }
49
+ process.exit(0);