@geoly-ai/social-hub-cli 0.3.44 → 0.3.46

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 (60) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cli-error-channels.test.js +40 -0
  3. package/dist/cli-error-channels.test.js.map +1 -1
  4. package/dist/client.d.ts +7 -1
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/client.js +19 -2
  7. package/dist/client.js.map +1 -1
  8. package/dist/cmd-manifest.json +15 -2
  9. package/dist/cmd-manifest.test.js +13 -0
  10. package/dist/cmd-manifest.test.js.map +1 -1
  11. package/dist/index.d.ts +39 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +238 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/output.d.ts +12 -0
  16. package/dist/output.d.ts.map +1 -1
  17. package/dist/output.js +42 -0
  18. package/dist/output.js.map +1 -1
  19. package/dist/permissions-gates-restrictions.d.ts +10 -0
  20. package/dist/permissions-gates-restrictions.d.ts.map +1 -0
  21. package/dist/permissions-gates-restrictions.js +53 -0
  22. package/dist/permissions-gates-restrictions.js.map +1 -0
  23. package/dist/permissions-gates-restrictions.test.d.ts +2 -0
  24. package/dist/permissions-gates-restrictions.test.d.ts.map +1 -0
  25. package/dist/permissions-gates-restrictions.test.js +37 -0
  26. package/dist/permissions-gates-restrictions.test.js.map +1 -0
  27. package/dist/permissions.d.ts.map +1 -1
  28. package/dist/permissions.js +2 -0
  29. package/dist/permissions.js.map +1 -1
  30. package/dist/public-reddit.test.d.ts +2 -0
  31. package/dist/public-reddit.test.d.ts.map +1 -0
  32. package/dist/public-reddit.test.js +339 -0
  33. package/dist/public-reddit.test.js.map +1 -0
  34. package/dist/reddit-account-type-filter.test.d.ts +2 -0
  35. package/dist/reddit-account-type-filter.test.d.ts.map +1 -0
  36. package/dist/reddit-account-type-filter.test.js +92 -0
  37. package/dist/reddit-account-type-filter.test.js.map +1 -0
  38. package/dist/register-extensions.d.ts.map +1 -1
  39. package/dist/register-extensions.js +2 -0
  40. package/dist/register-extensions.js.map +1 -1
  41. package/dist/register-restrictions.d.ts +64 -0
  42. package/dist/register-restrictions.d.ts.map +1 -0
  43. package/dist/register-restrictions.js +431 -0
  44. package/dist/register-restrictions.js.map +1 -0
  45. package/dist/register-restrictions.test.d.ts +2 -0
  46. package/dist/register-restrictions.test.d.ts.map +1 -0
  47. package/dist/register-restrictions.test.js +315 -0
  48. package/dist/register-restrictions.test.js.map +1 -0
  49. package/package.json +3 -3
  50. package/skills/integrity.json +10 -10
  51. package/skills/manifest.json +1 -1
  52. package/skills/social-hub-admin/SKILL.md +39 -0
  53. package/skills/social-hub-calendar-directives/SKILL.md +14 -1
  54. package/skills/social-hub-calendar-jobs/SKILL.md +14 -0
  55. package/skills/social-hub-cli/SKILL.md +2 -0
  56. package/skills/social-hub-graph-compliance/SKILL.md +42 -0
  57. package/skills/social-hub-intelligence/SKILL.md +111 -0
  58. package/skills/social-hub-ops-runtime/SKILL.md +44 -0
  59. package/skills/social-hub-posts/SKILL.md +4 -0
  60. package/skills/social-hub-publishing/SKILL.md +12 -0
package/dist/output.d.ts CHANGED
@@ -4,6 +4,18 @@ export declare function resolveOutputFormat(opts: {
4
4
  }): OutputFormat;
5
5
  export declare function printResult(data: unknown, format?: OutputFormat): void;
6
6
  export declare function parseJsonOption(raw: string | undefined): Record<string, unknown>;
7
+ /**
8
+ * 错误是不是「板块受限拦截」(HTTP 409 且 `details.code ∈ {TARGET_BLOCKED, JOB_BLOCKED}`
9
+ * 或 `details.reason === "target_blocked"`)。与 SDK `getSubredditRestrictionBlock` 同一判据;
10
+ * 这里本地实现而不 import,是因为多处 CLI 测试整包 mock 了 SDK。
11
+ * 鸭子类型:SDK 的 SocialHubHttpError 与本包 HubHttpError 都带 status/code/details。
12
+ */
13
+ export declare function restrictionBlockFromError(e: unknown): {
14
+ status: number;
15
+ code?: string;
16
+ message: string;
17
+ details: Record<string, unknown>;
18
+ } | null;
7
19
  export declare function formatCliError(e: unknown): string;
8
20
  /**
9
21
  * 把一行文本**同步**写进 stderr,写完再返回(D-06)。
@@ -1 +1 @@
1
- {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAM/D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAI3E;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,MAAM,GAAE,YAAqB,GAC5B,IAAI,CA0BN;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CA0CjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAsBlD;AAOD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC,CAqBf"}
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAM/D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAI3E;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,MAAM,GAAE,YAAqB,GAC5B,IAAI,CA0BN;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAKD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,OAAO,GAAG;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,GAAG,IAAI,CAmBP;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CA8DjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAsBlD;AAOD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAChC,OAAO,CAAC,IAAI,CAAC,CAqBf"}
package/dist/output.js CHANGED
@@ -48,7 +48,49 @@ export function parseJsonOption(raw) {
48
48
  process.exit(1);
49
49
  }
50
50
  }
51
+ /** 板块受限拦截的两个 `details.code`(与 contracts / SDK 同值)。 */
52
+ const RESTRICTION_BLOCK_CODES = new Set(["TARGET_BLOCKED", "JOB_BLOCKED"]);
53
+ /**
54
+ * 错误是不是「板块受限拦截」(HTTP 409 且 `details.code ∈ {TARGET_BLOCKED, JOB_BLOCKED}`
55
+ * 或 `details.reason === "target_blocked"`)。与 SDK `getSubredditRestrictionBlock` 同一判据;
56
+ * 这里本地实现而不 import,是因为多处 CLI 测试整包 mock 了 SDK。
57
+ * 鸭子类型:SDK 的 SocialHubHttpError 与本包 HubHttpError 都带 status/code/details。
58
+ */
59
+ export function restrictionBlockFromError(e) {
60
+ if (!(e instanceof Error))
61
+ return null;
62
+ const { status, code, details } = e;
63
+ if (status !== 409 || !details || typeof details !== "object")
64
+ return null;
65
+ const d = details;
66
+ const hit = RESTRICTION_BLOCK_CODES.has(d["code"]) ||
67
+ d["reason"] === "target_blocked";
68
+ if (!hit)
69
+ return null;
70
+ return {
71
+ status,
72
+ code: typeof code === "string" ? code : undefined,
73
+ message: e.message.replace(/^HTTP 409:\s*/, ""),
74
+ details: d,
75
+ };
76
+ }
51
77
  export function formatCliError(e) {
78
+ // 板块受限拦截:stderr 输出**结构化 JSON**(含 details)。其余错误的文案一概不变 ——
79
+ // 只在这一类上改格式,不影响既有错误通道的断言与消费者。
80
+ // agent 按 `error.details.code` 识别,**不要匹配 message**;命中即本轮跳过该目标、不重试。
81
+ const block = restrictionBlockFromError(e);
82
+ if (block) {
83
+ return JSON.stringify({
84
+ error: {
85
+ status: block.status,
86
+ code: block.code ?? "CONFLICT",
87
+ message: block.message,
88
+ details: block.details,
89
+ retryable: false,
90
+ hint: "Subreddit restricted: skip this target for this round; do not retry, fail or skip-report it. Only an admin revoke lifts the restriction.",
91
+ },
92
+ }, null, 2);
93
+ }
52
94
  if (e instanceof Error) {
53
95
  try {
54
96
  const parsed = JSON.parse(e.message);
@@ -1 +1 @@
1
- {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { CliPermissionGate } from "./permissions.js";
2
+ /**
3
+ * 板块限制(阶段 A4)CLI gates。
4
+ * - list / fanout 默认走 team 路由(`compliance:read`);`--system` 时本地另按系统级资源预检。
5
+ * - 系统级(get/create/confirm/revoke):独立资源 `systemSubredditRestriction`,
6
+ * **仅 admin**;API 另拒 API key 与受限(绑定 job/account、带动作白名单)的 CLI token。
7
+ * - team 级 runner 面:report = `compliance:create`,check = `compliance:read`。
8
+ */
9
+ export declare const RESTRICTION_PERMISSION_GATES: CliPermissionGate[];
10
+ //# sourceMappingURL=permissions-gates-restrictions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-gates-restrictions.d.ts","sourceRoot":"","sources":["../src/permissions-gates-restrictions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,iBAAiB,EA4C3D,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 板块限制(阶段 A4)CLI gates。
3
+ * - list / fanout 默认走 team 路由(`compliance:read`);`--system` 时本地另按系统级资源预检。
4
+ * - 系统级(get/create/confirm/revoke):独立资源 `systemSubredditRestriction`,
5
+ * **仅 admin**;API 另拒 API key 与受限(绑定 job/account、带动作白名单)的 CLI token。
6
+ * - team 级 runner 面:report = `compliance:create`,check = `compliance:read`。
7
+ */
8
+ export const RESTRICTION_PERMISSION_GATES = [
9
+ {
10
+ command: "restrictions list",
11
+ resource: "compliance",
12
+ action: "read",
13
+ note: "默认 team 路由;--system 走系统级 admin 面(systemSubredditRestriction:list,仅不受限登录的 admin)",
14
+ },
15
+ {
16
+ command: "restrictions get",
17
+ resource: "systemSubredditRestriction",
18
+ action: "read",
19
+ note: "admin only; unrestricted login only",
20
+ },
21
+ {
22
+ command: "restrictions fanout",
23
+ resource: "compliance",
24
+ action: "read",
25
+ note: "默认 team 路由(只含本 team 回执);--system 走系统级 admin 面(systemSubredditRestriction:read)",
26
+ },
27
+ {
28
+ command: "restrictions create",
29
+ resource: "systemSubredditRestriction",
30
+ action: "create",
31
+ note: "admin only; user only(API 拒 API Key / 服务 token / 受限 token)",
32
+ },
33
+ {
34
+ command: "restrictions confirm",
35
+ resource: "systemSubredditRestriction",
36
+ action: "update",
37
+ note: "admin only; user only",
38
+ },
39
+ {
40
+ command: "restrictions revoke",
41
+ resource: "systemSubredditRestriction",
42
+ action: "update",
43
+ note: "admin only; user only",
44
+ },
45
+ {
46
+ command: "restrictions report",
47
+ resource: "compliance",
48
+ action: "create",
49
+ note: "--scope system(且 strong)另需 manager/admin",
50
+ },
51
+ { command: "restrictions check", resource: "compliance", action: "read" },
52
+ ];
53
+ //# sourceMappingURL=permissions-gates-restrictions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-gates-restrictions.js","sourceRoot":"","sources":["../src/permissions-gates-restrictions.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAwB;IAC/D;QACE,OAAO,EAAE,mBAAmB;QAC5B,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,iFAAiF;KACxF;IACD;QACE,OAAO,EAAE,kBAAkB;QAC3B,QAAQ,EAAE,4BAA4B;QACtC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,qCAAqC;KAC5C;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,gFAAgF;KACvF;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,QAAQ,EAAE,4BAA4B;QACtC,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,4DAA4D;KACnE;IACD;QACE,OAAO,EAAE,sBAAsB;QAC/B,QAAQ,EAAE,4BAA4B;QACtC,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,uBAAuB;KAC9B;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,QAAQ,EAAE,4BAA4B;QACtC,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,uBAAuB;KAC9B;IACD;QACE,OAAO,EAAE,qBAAqB;QAC9B,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,0CAA0C;KACjD;IACD,EAAE,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE;CAC1E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=permissions-gates-restrictions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-gates-restrictions.test.d.ts","sourceRoot":"","sources":["../src/permissions-gates-restrictions.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { beforeAll, describe, expect, it, vi } from "vitest";
2
+ import { canPerformAction } from "@geoly-ai/social-hub-authz";
3
+ import { listAllCommandPaths } from "./cmd-manifest.js";
4
+ import { RESTRICTION_PERMISSION_GATES } from "./permissions-gates-restrictions.js";
5
+ import { CLI_PERMISSION_GATES, findGateForCommand } from "./permissions.js";
6
+ vi.mock("@geoly-ai/social-hub-sdk", () => ({
7
+ SocialHubClient: vi.fn().mockImplementation(() => ({})),
8
+ getSocialHubHealth: vi.fn(),
9
+ }));
10
+ let program;
11
+ beforeAll(async () => {
12
+ program = (await import("./index.js")).program;
13
+ });
14
+ describe("restrictions CLI permission gates", () => {
15
+ it("全部登记进 CLI_PERMISSION_GATES(auth explain 能看到)且路径唯一", () => {
16
+ for (const gate of RESTRICTION_PERMISSION_GATES) {
17
+ expect(findGateForCommand(gate.command)).toEqual(gate);
18
+ }
19
+ const commands = CLI_PERMISSION_GATES.map((g) => g.command);
20
+ expect(commands.length).toBe(new Set(commands).size);
21
+ });
22
+ /** 期望值取自实际命令树:新增 restrictions 子命令却忘了配 gate,这里当场变红。 */
23
+ it("覆盖 restrictions 树的全部叶子命令", () => {
24
+ const leaves = listAllCommandPaths(program).filter((path) => path.startsWith("restrictions "));
25
+ expect(leaves.length).toBe(8);
26
+ expect(RESTRICTION_PERMISSION_GATES.map((g) => g.command).sort()).toEqual(leaves.sort());
27
+ });
28
+ it("系统级命令:manager 本地预检就被拒,admin 放行(与服务端矩阵同源)", () => {
29
+ const system = RESTRICTION_PERMISSION_GATES.filter((g) => g.resource === "systemSubredditRestriction");
30
+ expect(system).toHaveLength(4);
31
+ for (const gate of system) {
32
+ expect(canPerformAction({ role: "manager", ...gate })).toBe(false);
33
+ expect(canPerformAction({ role: "admin", ...gate })).toBe(true);
34
+ }
35
+ });
36
+ });
37
+ //# sourceMappingURL=permissions-gates-restrictions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-gates-restrictions.test.js","sourceRoot":"","sources":["../src/permissions-gates-restrictions.test.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IACzC,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACvD,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC5B,CAAC,CAAC,CAAC;AAEJ,IAAI,OAAgB,CAAC;AAErB,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,OAA6B,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,KAAK,MAAM,IAAI,IAAI,4BAA4B,EAAE,CAAC;YAChD,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC5D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,sDAAsD;IACtD,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAC1D,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CACjC,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,4BAA4B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CACvE,MAAM,CAAC,IAAI,EAAE,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,MAAM,GAAG,4BAA4B,CAAC,MAAM,CAChD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,4BAA4B,CACnD,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC1B,MAAM,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnE,MAAM,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,IAAI,EACT,qBAAqB,EAEtB,MAAM,4BAA4B,CAAC;AAMpC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,EAAE,iBAAiB,EAkHnD,CAAC;AAEF,wBAAgB,UAAU,CACxB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAET;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB;oDACgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CAST;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG;IACjD,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;IACjD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;2CACuC;IACvC,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACnD,CAgBA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAIP;AAED,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,GAClB,iBAAiB,GAAG,SAAS,CAE/B"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,IAAI,EACT,qBAAqB,EAEtB,MAAM,4BAA4B,CAAC;AAOpC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,EAAE,iBAAiB,EAmHnD,CAAC;AAEF,wBAAgB,UAAU,CACxB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAET;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB;oDACgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CAST;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG;IACjD,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;IACjD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;2CACuC;IACvC,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACnD,CAgBA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAIP;AAED,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,GAClB,iBAAiB,GAAG,SAAS,CAE/B"}
@@ -3,6 +3,7 @@ import { ADMIN_PERMISSION_GATES } from "./permissions-gates-admin.js";
3
3
  import { SUBREDDIT_STYLE_PERMISSION_GATES } from "./permissions-gates-subreddit-style.js";
4
4
  import { CONTENT_CLASSIFICATION_PERMISSION_GATES } from "./permissions-gates-content-classification.js";
5
5
  import { NOTIFY_PERMISSION_GATES } from "./permissions-gates-notify.js";
6
+ import { RESTRICTION_PERMISSION_GATES } from "./permissions-gates-restrictions.js";
6
7
  /** Representative write/high-risk commands mapped to authz resources. */
7
8
  export const CLI_PERMISSION_GATES = [
8
9
  { command: "accounts list", resource: "socialAccount", action: "list" },
@@ -118,6 +119,7 @@ export const CLI_PERMISSION_GATES = [
118
119
  ...SUBREDDIT_STYLE_PERMISSION_GATES,
119
120
  ...CONTENT_CLASSIFICATION_PERMISSION_GATES,
120
121
  ...NOTIFY_PERMISSION_GATES,
122
+ ...RESTRICTION_PERMISSION_GATES,
121
123
  ];
122
124
  export function roleAllows(role, resource, action) {
123
125
  return canPerformAction({ role, resource, action });
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=public-reddit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public-reddit.test.d.ts","sourceRoot":"","sources":["../src/public-reddit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,339 @@
1
+ /**
2
+ * B5:`intelligence public-*` 四条命令。
3
+ *
4
+ * 核心纪律(方案 §5 B5 / §6):
5
+ * - DISABLED / POLICY_DENIED 等错误码 **必须** 报成「不是没有数据」+ 非 0 退出,绝不能被当成空结果;
6
+ * 正向对照:真正的空页(HTTP 200、items=[])打印「无结果」且退出码为 0。
7
+ * - count 必须带 query(requiredOption + 本地二次拦截)与窗口,且不允许把错误吞成 0 / 空。
8
+ */
9
+ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi, } from "vitest";
10
+ import { listAllCommandPaths } from "./cmd-manifest.js";
11
+ vi.mock("@geoly-ai/social-hub-sdk", () => ({
12
+ SocialHubClient: vi.fn(),
13
+ getSocialHubHealth: vi.fn(),
14
+ }));
15
+ const stderr = vi.fn();
16
+ vi.mock("./output.js", async (orig) => ({
17
+ ...(await orig()),
18
+ writeStderrSync: (t) => stderr(t),
19
+ }));
20
+ const fake = {
21
+ listPublicRedditCommunities: vi.fn(),
22
+ searchPublicRedditPosts: vi.fn(),
23
+ countPublicRedditPosts: vi.fn(),
24
+ getPublicRedditStatus: vi.fn(),
25
+ };
26
+ vi.mock("./client.js", () => ({
27
+ requireClient: () => fake,
28
+ resolveTeamId: (t) => t ?? "team-1",
29
+ getBaseUrl: () => "http://localhost",
30
+ }));
31
+ let mod;
32
+ let logSpy;
33
+ class ExitError extends Error {
34
+ code;
35
+ constructor(code) {
36
+ super(`EXIT:${code}`);
37
+ this.code = code;
38
+ }
39
+ }
40
+ beforeAll(async () => {
41
+ mod = await import("./index.js");
42
+ }, 30000);
43
+ beforeEach(() => {
44
+ logSpy = vi.spyOn(console, "log").mockImplementation(() => { });
45
+ vi.spyOn(process, "exit").mockImplementation(((code) => {
46
+ throw new ExitError(code ?? 0);
47
+ }));
48
+ });
49
+ afterEach(() => {
50
+ vi.restoreAllMocks();
51
+ stderr.mockReset();
52
+ for (const f of Object.values(fake))
53
+ f.mockReset();
54
+ });
55
+ const emptyPage = (excluded = []) => ({
56
+ items: [],
57
+ nextCursor: null,
58
+ source: { excludedCommunities: excluded, warnings: [] },
59
+ });
60
+ function httpError(status, code, message = "boom") {
61
+ return Object.assign(new Error(`HTTP ${status}: ${message}`), {
62
+ name: "SocialHubHttpError",
63
+ status,
64
+ code,
65
+ });
66
+ }
67
+ const stderrText = () => stderr.mock.calls.map((c) => String(c[0])).join("\n");
68
+ const stdoutText = () => logSpy.mock.calls.map((c) => String(c[0])).join("\n");
69
+ describe("命令注册", () => {
70
+ it("manifest 含 4 条新命令", () => {
71
+ const paths = listAllCommandPaths(mod.program);
72
+ for (const p of [
73
+ "intelligence public-communities",
74
+ "intelligence public-posts",
75
+ "intelligence public-post-count",
76
+ "intelligence public-status",
77
+ ]) {
78
+ expect(paths).toContain(p);
79
+ }
80
+ });
81
+ it("public-post-count 帮助文案写明昂贵读/禁止轮询/必须带 query/query 外发", () => {
82
+ const intel = mod.program.commands.find((c) => c.name() === "intelligence");
83
+ const desc = intel.commands
84
+ .find((c) => c.name() === "public-post-count")
85
+ .description();
86
+ expect(desc).toContain("昂贵读");
87
+ expect(desc).toContain("禁止轮询");
88
+ expect(desc).toContain("必须带 query");
89
+ expect(desc).toContain("query 会发往外部数据服务");
90
+ });
91
+ it("public-post-count 的 --query 是 requiredOption(commander 层必填)", () => {
92
+ const intel = mod.program.commands.find((c) => c.name() === "intelligence");
93
+ const cmd = intel.commands.find((c) => c.name() === "public-post-count");
94
+ expect(cmd.options.find((o) => o.long === "--query")?.mandatory).toBe(true);
95
+ expect(cmd.options.find((o) => o.long === "--subreddit")?.mandatory).toBe(true);
96
+ });
97
+ });
98
+ describe("--subreddit 解析", () => {
99
+ it("a,b -> 列表;trim、去空项、去重保序", () => {
100
+ expect(mod.parsePublicRedditSubreddits("a,b")).toEqual(["a", "b"]);
101
+ expect(mod.parsePublicRedditSubreddits(" a , ,b,a ,")).toEqual(["a", "b"]);
102
+ expect(mod.parsePublicRedditSubreddits(",,")).toEqual([]);
103
+ });
104
+ it("public-posts:列表传给 SDK(命令行接线,非仅纯函数)", async () => {
105
+ fake.searchPublicRedditPosts.mockResolvedValue(emptyPage());
106
+ await mod.program.parseAsync([
107
+ "node",
108
+ "social-hub",
109
+ "intelligence",
110
+ "public-posts",
111
+ "--subreddit",
112
+ "abc,def",
113
+ "--query",
114
+ "crm",
115
+ "--window",
116
+ "week",
117
+ ]);
118
+ expect(fake.searchPublicRedditPosts).toHaveBeenCalledTimes(1);
119
+ expect(fake.searchPublicRedditPosts.mock.calls[0]?.[0]).toMatchObject({
120
+ subreddit: ["abc", "def"],
121
+ query: "crm",
122
+ window: "week",
123
+ });
124
+ });
125
+ it("空列表 / 超过 20 个:本地拒绝、退出码 1、SDK 零调用", async () => {
126
+ await expect(mod.runPublicPosts(fake, { subreddit: " , " })).rejects.toMatchObject({ code: 1 });
127
+ const many = Array.from({ length: 21 }, (_, i) => `sub${String(i).padStart(2, "0")}`).join(",");
128
+ await expect(mod.runPublicPosts(fake, { subreddit: many })).rejects.toMatchObject({ code: 1 });
129
+ expect(fake.searchPublicRedditPosts).not.toHaveBeenCalled();
130
+ expect(stderrText()).toContain("最多 20");
131
+ // 正向对照:恰好 20 个放行
132
+ fake.searchPublicRedditPosts.mockResolvedValue(emptyPage());
133
+ await mod.runPublicPosts(fake, {
134
+ subreddit: many.split(",").slice(0, 20).join(","),
135
+ });
136
+ expect(fake.searchPublicRedditPosts).toHaveBeenCalledTimes(1);
137
+ });
138
+ });
139
+ describe("错误码透传:读取失败 ≠ 没有数据", () => {
140
+ it.each([
141
+ ["PUBLIC_REDDIT_DISABLED", 503],
142
+ ["PUBLIC_REDDIT_POLICY_DENIED", 503],
143
+ ["PUBLIC_REDDIT_AUTH_FAILED", 503],
144
+ ])("%s:stderr 明确文案 + 退出码 1,stdout 零字节,且没有「无结果」", async (code, status) => {
145
+ fake.searchPublicRedditPosts.mockRejectedValue(httpError(status, code));
146
+ await expect(mod.runPublicPosts(fake, { subreddit: "abc" })).rejects.toMatchObject({ code: 1 });
147
+ const err = stderrText();
148
+ expect(err).toContain(`[${code}]`);
149
+ expect(err).toContain("这不是「没有数据」");
150
+ expect(err).not.toContain("无结果");
151
+ expect(logSpy).not.toHaveBeenCalled();
152
+ });
153
+ it("DISABLED / POLICY_DENIED 文案互不相同,各自点名原因", async () => {
154
+ fake.searchPublicRedditPosts.mockRejectedValueOnce(httpError(503, "PUBLIC_REDDIT_DISABLED"));
155
+ await expect(mod.runPublicPosts(fake, { subreddit: "abc" })).rejects.toBeDefined();
156
+ const disabled = stderrText();
157
+ stderr.mockReset();
158
+ fake.searchPublicRedditPosts.mockRejectedValueOnce(httpError(503, "PUBLIC_REDDIT_POLICY_DENIED"));
159
+ await expect(mod.runPublicPosts(fake, { subreddit: "abc" })).rejects.toBeDefined();
160
+ const denied = stderrText();
161
+ expect(disabled).toContain("未启用");
162
+ expect(denied).toContain("拒绝");
163
+ expect(disabled).not.toBe(denied);
164
+ });
165
+ it("四条命令都走同一外壳(DISABLED 对 communities/count/status 同样非 0 退出)", async () => {
166
+ const e = httpError(503, "PUBLIC_REDDIT_DISABLED");
167
+ fake.listPublicRedditCommunities.mockRejectedValue(e);
168
+ fake.countPublicRedditPosts.mockRejectedValue(e);
169
+ fake.getPublicRedditStatus.mockRejectedValue(e);
170
+ await expect(mod.runPublicCommunities(fake, {})).rejects.toMatchObject({
171
+ code: 1,
172
+ });
173
+ await expect(mod.runPublicPostCount(fake, {
174
+ subreddit: "abc",
175
+ query: "q",
176
+ window: "day",
177
+ })).rejects.toMatchObject({ code: 1 });
178
+ await expect(mod.runPublicStatus(fake)).rejects.toMatchObject({ code: 1 });
179
+ expect(logSpy).not.toHaveBeenCalled();
180
+ });
181
+ it("未知 PUBLIC_REDDIT_* 码也走兜底(不是空结果);Retry-After 被带出", async () => {
182
+ fake.searchPublicRedditPosts.mockRejectedValue(Object.assign(httpError(503, "PUBLIC_REDDIT_SOMETHING_NEW"), {
183
+ retryAfterSeconds: 30,
184
+ }));
185
+ await expect(mod.runPublicPosts(fake, { subreddit: "abc" })).rejects.toMatchObject({ code: 1 });
186
+ expect(stderrText()).toContain("[PUBLIC_REDDIT_SOMETHING_NEW]");
187
+ expect(stderrText()).toContain("Retry-After: 30s");
188
+ });
189
+ it("非公开库错误原样重抛给默认边界(不吞、不改写)", async () => {
190
+ const other = httpError(500, "INTERNAL");
191
+ fake.searchPublicRedditPosts.mockRejectedValue(other);
192
+ await expect(mod.runPublicPosts(fake, { subreddit: "abc" })).rejects.toBe(other);
193
+ expect(stderr).not.toHaveBeenCalled();
194
+ });
195
+ });
196
+ describe("正向对照:正常空页打印「无结果」且退出码 0", () => {
197
+ it("items=[] -> stdout 完整 JSON,stderr「无结果」,未退出", async () => {
198
+ fake.searchPublicRedditPosts.mockResolvedValue(emptyPage());
199
+ await mod.runPublicPosts(fake, { subreddit: "abc" });
200
+ expect(stderrText()).toContain("无结果");
201
+ expect(stderrText()).not.toContain("这不是「没有数据」");
202
+ expect(JSON.parse(stdoutText())).toMatchObject({
203
+ items: [],
204
+ nextCursor: null,
205
+ });
206
+ expect(process.exit).not.toHaveBeenCalled();
207
+ });
208
+ it("空页但有被排除的板块:提示空结果不代表这些板块没数据", async () => {
209
+ fake.searchPublicRedditPosts.mockResolvedValue(emptyPage([{ communityId: "zzz", reason: "not_in_upstream_catalog" }]));
210
+ await mod.runPublicPosts(fake, { subreddit: "zzz" });
211
+ expect(stderrText()).toContain("被排除");
212
+ expect(stderrText()).toContain("zzz");
213
+ expect(stderrText()).toContain("不代表");
214
+ });
215
+ it("有数据时不打印「无结果」", async () => {
216
+ fake.searchPublicRedditPosts.mockResolvedValue({
217
+ items: [{ upstreamId: "1" }],
218
+ nextCursor: "n",
219
+ source: { excludedCommunities: [], warnings: [] },
220
+ });
221
+ await mod.runPublicPosts(fake, { subreddit: "abc" });
222
+ expect(stderr).not.toHaveBeenCalled();
223
+ expect(JSON.parse(stdoutText()).items).toHaveLength(1);
224
+ });
225
+ });
226
+ describe("public-post-count 本地拦截", () => {
227
+ it("缺 query(空白)/缺窗口 -> 退出码 1,SDK 零调用", async () => {
228
+ await expect(mod.runPublicPostCount(fake, {
229
+ subreddit: "abc",
230
+ query: " ",
231
+ window: "day",
232
+ })).rejects.toMatchObject({ code: 1 });
233
+ await expect(mod.runPublicPostCount(fake, { subreddit: "abc", query: "q" })).rejects.toMatchObject({ code: 1 });
234
+ expect(fake.countPublicRedditPosts).not.toHaveBeenCalled();
235
+ });
236
+ it("命令行不带 --query:commander 拒绝,SDK 零调用", async () => {
237
+ await expect(mod.program.parseAsync([
238
+ "node",
239
+ "social-hub",
240
+ "intelligence",
241
+ "public-post-count",
242
+ "--subreddit",
243
+ "abc",
244
+ "--window",
245
+ "day",
246
+ ])).rejects.toBeInstanceOf(ExitError);
247
+ expect(fake.countPublicRedditPosts).not.toHaveBeenCalled();
248
+ });
249
+ it("正向对照:query + 窗口齐全 -> SDK 恰好一次,body 形状正确;50 个放行、51 个拒绝", async () => {
250
+ fake.countPublicRedditPosts.mockResolvedValue({ exact: true, total: 3 });
251
+ await mod.runPublicPostCount(fake, {
252
+ subreddit: "abc,def",
253
+ query: " crm ",
254
+ window: "month",
255
+ });
256
+ expect(fake.countPublicRedditPosts).toHaveBeenCalledTimes(1);
257
+ expect(fake.countPublicRedditPosts.mock.calls[0]?.[0]).toMatchObject({
258
+ subreddits: ["abc", "def"],
259
+ query: "crm",
260
+ window: "month",
261
+ });
262
+ const names = (n) => Array.from({ length: n }, (_, i) => `sub${String(i).padStart(3, "0")}`).join(",");
263
+ await mod.runPublicPostCount(fake, {
264
+ subreddit: names(50),
265
+ query: "q",
266
+ window: "day",
267
+ });
268
+ await expect(mod.runPublicPostCount(fake, {
269
+ subreddit: names(51),
270
+ query: "q",
271
+ window: "day",
272
+ })).rejects.toMatchObject({ code: 1 });
273
+ expect(fake.countPublicRedditPosts).toHaveBeenCalledTimes(2);
274
+ });
275
+ it("exact=false 时 total=null 原样输出(不补 0、不当空)", async () => {
276
+ fake.countPublicRedditPosts.mockResolvedValue({
277
+ exact: false,
278
+ total: null,
279
+ communities: [],
280
+ });
281
+ await mod.runPublicPostCount(fake, {
282
+ subreddit: "abc",
283
+ query: "q",
284
+ window: "day",
285
+ });
286
+ expect(JSON.parse(stdoutText())).toMatchObject({
287
+ exact: false,
288
+ total: null,
289
+ });
290
+ });
291
+ });
292
+ describe("命令行接线(parseAsync 正向路径)", () => {
293
+ it("public-post-count / public-communities / public-status 各自把参数送到对应 SDK 方法", async () => {
294
+ fake.countPublicRedditPosts.mockResolvedValue({
295
+ exact: true,
296
+ total: 1,
297
+ communities: [],
298
+ });
299
+ fake.listPublicRedditCommunities.mockResolvedValue(emptyPage());
300
+ fake.getPublicRedditStatus.mockResolvedValue({ mode: "on" });
301
+ const run = (...a) => mod.program.parseAsync(["node", "social-hub", "intelligence", ...a]);
302
+ await run("public-post-count", "--subreddit", "abc,def", "--query", "crm", "--window", "day");
303
+ expect(fake.countPublicRedditPosts.mock.calls[0]?.[0]).toMatchObject({
304
+ subreddits: ["abc", "def"],
305
+ query: "crm",
306
+ window: "day",
307
+ });
308
+ await run("public-communities", "--pool-kinds", "primary", "--has-profile", "true");
309
+ expect(fake.listPublicRedditCommunities.mock.calls[0]?.[0]).toMatchObject({
310
+ poolKind: "primary",
311
+ hasProfile: true,
312
+ });
313
+ await run("public-status");
314
+ expect(fake.getPublicRedditStatus).toHaveBeenCalledTimes(1);
315
+ });
316
+ it("新增错误码文案:SCOPE_TOO_LARGE 点名缩小范围", async () => {
317
+ fake.searchPublicRedditPosts.mockRejectedValue(httpError(422, "PUBLIC_REDDIT_SCOPE_TOO_LARGE"));
318
+ await expect(mod.runPublicPosts(fake, { subreddit: "abc" })).rejects.toMatchObject({ code: 1 });
319
+ expect(stderrText()).toContain("按月切分");
320
+ });
321
+ });
322
+ describe("public-communities", () => {
323
+ it("--has-profile 非 true/false 本地拒绝;合法值转成布尔", async () => {
324
+ await expect(mod.runPublicCommunities(fake, { hasProfile: "yes" })).rejects.toMatchObject({ code: 1 });
325
+ expect(fake.listPublicRedditCommunities).not.toHaveBeenCalled();
326
+ fake.listPublicRedditCommunities.mockResolvedValue(emptyPage());
327
+ await mod.runPublicCommunities(fake, {
328
+ hasProfile: "false",
329
+ limit: "5",
330
+ industryKeys: "a,b",
331
+ });
332
+ expect(fake.listPublicRedditCommunities.mock.calls[0]?.[0]).toMatchObject({
333
+ hasProfile: false,
334
+ limit: 5,
335
+ industryKey: "a,b",
336
+ });
337
+ });
338
+ });
339
+ //# sourceMappingURL=public-reddit.test.js.map