@agora-sdk/social-core 0.6.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 (51) hide show
  1. package/LICENSE +202 -0
  2. package/dist/cjs/context/social-context.d.ts +65 -0
  3. package/dist/cjs/context/social-context.js +125 -0
  4. package/dist/cjs/context/social-context.js.map +1 -0
  5. package/dist/cjs/contract/index.d.ts +19 -0
  6. package/dist/cjs/contract/index.js +57 -0
  7. package/dist/cjs/contract/index.js.map +1 -0
  8. package/dist/cjs/hooks/useSocialConstellation.d.ts +29 -0
  9. package/dist/cjs/hooks/useSocialConstellation.js +70 -0
  10. package/dist/cjs/hooks/useSocialConstellation.js.map +1 -0
  11. package/dist/cjs/hooks/useSocialNeighborhood.d.ts +29 -0
  12. package/dist/cjs/hooks/useSocialNeighborhood.js +90 -0
  13. package/dist/cjs/hooks/useSocialNeighborhood.js.map +1 -0
  14. package/dist/cjs/hooks/useSocialTransparency.d.ts +25 -0
  15. package/dist/cjs/hooks/useSocialTransparency.js +28 -0
  16. package/dist/cjs/hooks/useSocialTransparency.js.map +1 -0
  17. package/dist/cjs/hooks/useSocialWeather.d.ts +28 -0
  18. package/dist/cjs/hooks/useSocialWeather.js +72 -0
  19. package/dist/cjs/hooks/useSocialWeather.js.map +1 -0
  20. package/dist/cjs/index.d.ts +14 -0
  21. package/dist/cjs/index.js +33 -0
  22. package/dist/cjs/index.js.map +1 -0
  23. package/dist/cjs/package.json +1 -0
  24. package/dist/cjs/transport/rest.d.ts +105 -0
  25. package/dist/cjs/transport/rest.js +177 -0
  26. package/dist/cjs/transport/rest.js.map +1 -0
  27. package/dist/esm/context/social-context.d.ts +65 -0
  28. package/dist/esm/context/social-context.js +120 -0
  29. package/dist/esm/context/social-context.js.map +1 -0
  30. package/dist/esm/contract/index.d.ts +19 -0
  31. package/dist/esm/contract/index.js +54 -0
  32. package/dist/esm/contract/index.js.map +1 -0
  33. package/dist/esm/hooks/useSocialConstellation.d.ts +29 -0
  34. package/dist/esm/hooks/useSocialConstellation.js +67 -0
  35. package/dist/esm/hooks/useSocialConstellation.js.map +1 -0
  36. package/dist/esm/hooks/useSocialNeighborhood.d.ts +29 -0
  37. package/dist/esm/hooks/useSocialNeighborhood.js +87 -0
  38. package/dist/esm/hooks/useSocialNeighborhood.js.map +1 -0
  39. package/dist/esm/hooks/useSocialTransparency.d.ts +25 -0
  40. package/dist/esm/hooks/useSocialTransparency.js +25 -0
  41. package/dist/esm/hooks/useSocialTransparency.js.map +1 -0
  42. package/dist/esm/hooks/useSocialWeather.d.ts +28 -0
  43. package/dist/esm/hooks/useSocialWeather.js +69 -0
  44. package/dist/esm/hooks/useSocialWeather.js.map +1 -0
  45. package/dist/esm/index.d.ts +14 -0
  46. package/dist/esm/index.js +17 -0
  47. package/dist/esm/index.js.map +1 -0
  48. package/dist/esm/transport/rest.d.ts +105 -0
  49. package/dist/esm/transport/rest.js +168 -0
  50. package/dist/esm/transport/rest.js.map +1 -0
  51. package/package.json +51 -0
@@ -0,0 +1,65 @@
1
+ import React from "react";
2
+ import { SocialRestClient } from "../transport/rest.js";
3
+ import { ResolvedSocialConfig } from "../contract/index.js";
4
+ /**
5
+ * The resolved-config sentinel used when the social graph is unavailable (`503
6
+ * social/graph-unavailable`) — every lens and analytics flag disabled, so hooks/components render
7
+ * nothing rather than erroring. Tier is the safe `"community"` default and numeric tuning fields are
8
+ * zeroed; none of these are read while the lenses are disabled.
9
+ */
10
+ export declare const ALL_DISABLED_SOCIAL_CONFIG: ResolvedSocialConfig;
11
+ /**
12
+ * The value exposed by {@link useSocial}: the shared REST client, the auto-fetched feature config and
13
+ * its load state, and the active project id.
14
+ */
15
+ export interface SocialContextValue {
16
+ /** REST client for the social endpoints. */
17
+ rest: SocialRestClient;
18
+ /**
19
+ * The project's resolved social config, or `null` until the transparency fetch resolves. When the
20
+ * graph is unavailable this is the {@link ALL_DISABLED_SOCIAL_CONFIG} sentinel (not `null`).
21
+ */
22
+ config: ResolvedSocialConfig | null;
23
+ /** True while the initial transparency fetch is in flight. */
24
+ configLoading: boolean;
25
+ /** A non-degradation error from the transparency fetch (the `503` graph-off case is not an error). */
26
+ configError: unknown;
27
+ /** The Agora project id these clients are scoped to. */
28
+ projectId: string;
29
+ }
30
+ /** Props for {@link SocialProvider}. */
31
+ export interface SocialProviderProps {
32
+ /** Agora project id (path-scoped on every endpoint — a privacy boundary). */
33
+ projectId: string;
34
+ /** Current access token. Re-pass on refresh; read lazily per request. */
35
+ accessToken?: string;
36
+ /** Override token resolution (takes precedence over `accessToken`). */
37
+ getAccessToken?: () => string | undefined;
38
+ /** Override the API base URL. Defaults to @agora-sdk/core `getApiBaseUrl()`. */
39
+ baseUrl?: string;
40
+ children: React.ReactNode;
41
+ }
42
+ /**
43
+ * Provides the social REST client + the project's resolved feature config to the `useSocial*` hooks
44
+ * and components. Render inside a `ReplykeProvider`. Auto-fetches `GET /social/transparency` once on
45
+ * mount; treats `503 social/graph-unavailable` as "all lenses disabled" rather than an error.
46
+ *
47
+ * @param props - {@link SocialProviderProps}.
48
+ * @returns A context provider wrapping `children`.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * <SocialProvider projectId={projectId} accessToken={token}>
53
+ * <CommunityWeather />
54
+ * <Constellation />
55
+ * </SocialProvider>
56
+ * ```
57
+ */
58
+ export declare function SocialProvider({ projectId, accessToken, getAccessToken, baseUrl, children, }: SocialProviderProps): React.JSX.Element;
59
+ /**
60
+ * Access the nearest {@link SocialContextValue}.
61
+ *
62
+ * @returns The shared rest client, resolved feature config + load state, and project id.
63
+ * @throws {Error} When called outside a `<SocialProvider>`.
64
+ */
65
+ export declare function useSocial(): SocialContextValue;
@@ -0,0 +1,120 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // SocialProvider — wires the social REST transport and auto-resolves the project's feature config.
3
+ //
4
+ // Sits INSIDE a ReplykeProvider: by default it resolves the API base URL from @agora-sdk/core's
5
+ // runtime singleton (getApiBaseUrl). On mount it fetches `GET /social/transparency` once and stores
6
+ // the resolved config so every hook/component can self-gate on the per-project feature flags WITHOUT
7
+ // each issuing its own probe (SOCIAL.md §7 — "check transparency at app init"). There is no crypto and
8
+ // no persistence here: social data is public/server-side and slow-moving, so the provider holds
9
+ // fetched config in React state only.
10
+ //
11
+ // Graceful degradation: a `503 social/graph-unavailable` is treated as "the whole graph is off" — we
12
+ // store an ALL-DISABLED sentinel rather than an error, so surfaces hide silently instead of throwing
13
+ // at members. Any other failure is surfaced via `configError` for the host app to decide on.
14
+ import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
15
+ import { getApiBaseUrl } from "@agora-sdk/core";
16
+ import { SocialRestClient } from "../transport/rest.js";
17
+ import { SocialApiError } from "../transport/rest.js";
18
+ /**
19
+ * The resolved-config sentinel used when the social graph is unavailable (`503
20
+ * social/graph-unavailable`) — every lens and analytics flag disabled, so hooks/components render
21
+ * nothing rather than erroring. Tier is the safe `"community"` default and numeric tuning fields are
22
+ * zeroed; none of these are read while the lenses are disabled.
23
+ */
24
+ export const ALL_DISABLED_SOCIAL_CONFIG = {
25
+ privacyTier: "community",
26
+ graphEnabled: false,
27
+ weatherEnabled: false,
28
+ constellationEnabled: false,
29
+ constellationKFloor: 0,
30
+ neighborhoodEnabled: false,
31
+ neighborhoodIncludeInteractions: false,
32
+ influenceScoresEnabled: false,
33
+ siloDetectionEnabled: false,
34
+ engagementScoresEnabled: false,
35
+ frictionVisibleToStewards: false,
36
+ frictionAnalyticsEnabled: false,
37
+ readAffinityEnabled: false,
38
+ readReceiptsAllowed: false,
39
+ warmthHalfLifeDays: 0,
40
+ frictionHalfLifeDays: 0,
41
+ };
42
+ const SocialContext = createContext(null);
43
+ /**
44
+ * Provides the social REST client + the project's resolved feature config to the `useSocial*` hooks
45
+ * and components. Render inside a `ReplykeProvider`. Auto-fetches `GET /social/transparency` once on
46
+ * mount; treats `503 social/graph-unavailable` as "all lenses disabled" rather than an error.
47
+ *
48
+ * @param props - {@link SocialProviderProps}.
49
+ * @returns A context provider wrapping `children`.
50
+ *
51
+ * @example
52
+ * ```tsx
53
+ * <SocialProvider projectId={projectId} accessToken={token}>
54
+ * <CommunityWeather />
55
+ * <Constellation />
56
+ * </SocialProvider>
57
+ * ```
58
+ */
59
+ export function SocialProvider({ projectId, accessToken, getAccessToken, baseUrl, children, }) {
60
+ const tokenRef = useRef(accessToken);
61
+ tokenRef.current = accessToken;
62
+ const resolveToken = useMemo(() => getAccessToken ?? (() => tokenRef.current), [getAccessToken]);
63
+ const rest = useMemo(() => new SocialRestClient({
64
+ projectId,
65
+ getAccessToken: resolveToken,
66
+ getBaseUrl: () => baseUrl ?? getApiBaseUrl(),
67
+ }), [projectId, resolveToken, baseUrl]);
68
+ const [config, setConfig] = useState(null);
69
+ const [configLoading, setConfigLoading] = useState(true);
70
+ const [configError, setConfigError] = useState(null);
71
+ // Auto-resolve the per-project feature config once on mount (and whenever the client identity
72
+ // changes). A `503 social/graph-unavailable` is degradation, not an error: store the all-disabled
73
+ // sentinel so every surface hides silently (SOCIAL.md §7). A stale-guard prevents a slow first fetch
74
+ // from clobbering a newer one after a projectId/token swap.
75
+ useEffect(() => {
76
+ let active = true;
77
+ setConfigLoading(true);
78
+ setConfigError(null);
79
+ rest
80
+ .getTransparency()
81
+ .then((resolved) => {
82
+ if (!active)
83
+ return;
84
+ setConfig(resolved);
85
+ })
86
+ .catch((err) => {
87
+ if (!active)
88
+ return;
89
+ if (err instanceof SocialApiError && err.code === "social/graph-unavailable") {
90
+ setConfig(ALL_DISABLED_SOCIAL_CONFIG);
91
+ }
92
+ else {
93
+ setConfigError(err);
94
+ }
95
+ })
96
+ .finally(() => {
97
+ if (active)
98
+ setConfigLoading(false);
99
+ });
100
+ return () => {
101
+ active = false;
102
+ };
103
+ }, [rest]);
104
+ const value = useMemo(() => ({ rest, config, configLoading, configError, projectId }), [rest, config, configLoading, configError, projectId]);
105
+ return _jsx(SocialContext.Provider, { value: value, children: children });
106
+ }
107
+ /**
108
+ * Access the nearest {@link SocialContextValue}.
109
+ *
110
+ * @returns The shared rest client, resolved feature config + load state, and project id.
111
+ * @throws {Error} When called outside a `<SocialProvider>`.
112
+ */
113
+ export function useSocial() {
114
+ const ctx = useContext(SocialContext);
115
+ if (!ctx) {
116
+ throw new Error("useSocial must be used within a <SocialProvider>.");
117
+ }
118
+ return ctx;
119
+ }
120
+ //# sourceMappingURL=social-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"social-context.js","sourceRoot":"","sources":["../../../src/context/social-context.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export type { SocialWeather, WeatherBand, SocialConstellation, ConstellationBlob, BlobSizeBucket, SocialNeighborhood, NeighborhoodTie, NeighborhoodTieKind, ResolvedSocialConfig, SocialPrivacyTier, } from "@agora-server/contract";
2
+ import type { WeatherBand, BlobSizeBucket, NeighborhoodTieKind } from "@agora-server/contract";
3
+ /**
4
+ * Runtime list of {@link WeatherBand} values, low → high (for iteration / validation). Mirrors the
5
+ * contract's `WEATHER_BANDS`; re-declared locally so core's CJS build need not `require()` the
6
+ * ESM-only contract. Typed against the contract union, so any drift is a compile error.
7
+ */
8
+ export declare const WEATHER_BANDS: readonly WeatherBand[];
9
+ /**
10
+ * Runtime list of {@link BlobSizeBucket} values, small → large (for iteration / validation). Mirrors
11
+ * the contract's `BLOB_SIZE_BUCKETS` (en-dash strings); re-declared locally for the CJS-build reason
12
+ * above.
13
+ */
14
+ export declare const BLOB_SIZE_BUCKETS: readonly BlobSizeBucket[];
15
+ /**
16
+ * Runtime list of {@link NeighborhoodTieKind} values (for iteration / validation). Mirrors the
17
+ * contract's `NEIGHBORHOOD_TIE_KINDS`; re-declared locally for the CJS-build reason above.
18
+ */
19
+ export declare const NEIGHBORHOOD_TIE_KINDS: readonly NeighborhoodTieKind[];
@@ -0,0 +1,54 @@
1
+ // Social-graph wire types — re-exported from the published `@agora-server/contract` (Apache-2.0).
2
+ //
3
+ // The dependency arrow is **SDK → contract**: agora-server owns the social wire contract, this SDK
4
+ // depends on it. As of `@agora-server/contract@0.12.1` the social surface is published, so this module
5
+ // is a thin **type-only re-export** (one source of truth, zero drift) — it replaces the earlier local
6
+ // byte-faithful stand-in that stood in until the contract shipped these types.
7
+ //
8
+ // Type-only on purpose: `@agora-server/contract` is ESM-only, but `export type` re-exports are erased
9
+ // from the emitted JS, so core's dual ESM/CJS build never `require()`s it at runtime (mirrors
10
+ // `secure-chat-core/src/contract`). For the SAME reason the three runtime const arrays are re-declared
11
+ // **locally** rather than value-re-exported — a value re-export would force the CJS build to
12
+ // `require()` the ESM-only contract. They are typed against the contract's unions, so any drift in the
13
+ // bands/buckets/tie-kinds becomes a compile error here.
14
+ //
15
+ // Scope: only the three member-facing lenses (Weather, Constellation, Neighborhood) + the resolved
16
+ // config the SDK consumes. The contract's corporate-analytics surface (influence / silos / engagement,
17
+ // read-receipts) is intentionally NOT re-exported — it is outside this package's scope.
18
+ //
19
+ // Wire conventions (owned by the contract): timestamps are ISO 8601 strings; `value`/`trend`/
20
+ // `brightness` are JSON numbers; size buckets are en-dash strings ("5–9", U+2013).
21
+ /**
22
+ * Runtime list of {@link WeatherBand} values, low → high (for iteration / validation). Mirrors the
23
+ * contract's `WEATHER_BANDS`; re-declared locally so core's CJS build need not `require()` the
24
+ * ESM-only contract. Typed against the contract union, so any drift is a compile error.
25
+ */
26
+ export const WEATHER_BANDS = [
27
+ "quiet",
28
+ "stormy",
29
+ "overcast",
30
+ "fine",
31
+ "sunny",
32
+ ];
33
+ /**
34
+ * Runtime list of {@link BlobSizeBucket} values, small → large (for iteration / validation). Mirrors
35
+ * the contract's `BLOB_SIZE_BUCKETS` (en-dash strings); re-declared locally for the CJS-build reason
36
+ * above.
37
+ */
38
+ export const BLOB_SIZE_BUCKETS = [
39
+ "5–9",
40
+ "10–19",
41
+ "20–49",
42
+ "50–99",
43
+ "100+",
44
+ ];
45
+ /**
46
+ * Runtime list of {@link NeighborhoodTieKind} values (for iteration / validation). Mirrors the
47
+ * contract's `NEIGHBORHOOD_TIE_KINDS`; re-declared locally for the CJS-build reason above.
48
+ */
49
+ export const NEIGHBORHOOD_TIE_KINDS = [
50
+ "follow",
51
+ "connection",
52
+ "interaction",
53
+ ];
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/contract/index.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,EAAE;AACF,mGAAmG;AACnG,uGAAuG;AACvG,sGAAsG;AACtG,+EAA+E;AAC/E,EAAE;AACF,sGAAsG;AACtG,8FAA8F;AAC9F,uGAAuG;AACvG,6FAA6F;AAC7F,uGAAuG;AACvG,wDAAwD;AACxD,EAAE;AACF,mGAAmG;AACnG,uGAAuG;AACvG,wFAAwF;AACxF,EAAE;AACF,8FAA8F;AAC9F,mFAAmF;AAiBnF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,OAAO;IACP,QAAQ;IACR,UAAU;IACV,MAAM;IACN,OAAO;CACR,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA8B;IAC1D,KAAK;IACL,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;CACP,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAmC;IACpE,QAAQ;IACR,YAAY;IACZ,aAAa;CACd,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { SocialConstellation } from "../contract/index.js";
2
+ /** The state and actions returned by {@link useSocialConstellation}. */
3
+ export interface UseSocialConstellationValues {
4
+ /** The current snapshot, or `null` while loading, when disabled, or on error. `asOf: null` = still forming. */
5
+ constellation: SocialConstellation | null;
6
+ /** True while a fetch is in flight (always `false` when the lens is disabled). */
7
+ loading: boolean;
8
+ /** The last error thrown by the fetch, or `null`. */
9
+ error: unknown;
10
+ /** Re-fetch the snapshot. No-op when the lens is disabled. */
11
+ refresh: () => Promise<void>;
12
+ }
13
+ /**
14
+ * Load the Constellation snapshot (anonymous cluster blobs) for the current project.
15
+ *
16
+ * Waits for the provider's transparency config, then fetches `GET /social/constellation` only when
17
+ * `constellationEnabled` is true. A snapshot with `asOf === null` is the valid "still forming" state,
18
+ * not an error — render a nebula.
19
+ *
20
+ * @returns {@link UseSocialConstellationValues} — the snapshot, load state, and a `refresh` action.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * const { constellation } = useSocialConstellation();
25
+ * if (!constellation) return null; // disabled or loading
26
+ * if (constellation.asOf === null) return <Nebula />; // still forming
27
+ * ```
28
+ */
29
+ export declare function useSocialConstellation(): UseSocialConstellationValues;
@@ -0,0 +1,67 @@
1
+ // useSocialConstellation — load the anonymous Constellation snapshot, gated on the feature config.
2
+ //
3
+ // Self-gates on `config.constellationEnabled`. The Constellation is a slow seasonal snapshot
4
+ // (materialized ~every 6 weeks), so one fetch on enable is plenty; `refresh()` is exposed only for
5
+ // completeness. The returned `blobs` carry no stable identity — re-randomizing their LAYOUT on every
6
+ // render is the rendering layer's job (SOCIAL.md §6), not this hook's.
7
+ import { useCallback, useEffect, useState } from "react";
8
+ import { isSocialDegradation } from "../transport/rest.js";
9
+ import { useSocial } from "../context/social-context.js";
10
+ /**
11
+ * Load the Constellation snapshot (anonymous cluster blobs) for the current project.
12
+ *
13
+ * Waits for the provider's transparency config, then fetches `GET /social/constellation` only when
14
+ * `constellationEnabled` is true. A snapshot with `asOf === null` is the valid "still forming" state,
15
+ * not an error — render a nebula.
16
+ *
17
+ * @returns {@link UseSocialConstellationValues} — the snapshot, load state, and a `refresh` action.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * const { constellation } = useSocialConstellation();
22
+ * if (!constellation) return null; // disabled or loading
23
+ * if (constellation.asOf === null) return <Nebula />; // still forming
24
+ * ```
25
+ */
26
+ export function useSocialConstellation() {
27
+ const { rest, config, configLoading } = useSocial();
28
+ const enabled = config?.constellationEnabled ?? false;
29
+ const [constellation, setConstellation] = useState(null);
30
+ const [loading, setLoading] = useState(false);
31
+ const [error, setError] = useState(null);
32
+ const refresh = useCallback(async () => {
33
+ if (!enabled)
34
+ return;
35
+ setLoading(true);
36
+ setError(null);
37
+ try {
38
+ setConstellation(await rest.getConstellation());
39
+ }
40
+ catch (err) {
41
+ // Fail soft on degradation (graph off, or the lens disabled mid-session): hide the surface —
42
+ // clear the snapshot and swallow the error rather than surface it to members (SOCIAL.md §7). Real
43
+ // errors still propagate via `error`.
44
+ if (isSocialDegradation(err)) {
45
+ setConstellation(null);
46
+ setError(null);
47
+ }
48
+ else {
49
+ setError(err);
50
+ }
51
+ }
52
+ finally {
53
+ setLoading(false);
54
+ }
55
+ }, [enabled, rest]);
56
+ useEffect(() => {
57
+ if (configLoading)
58
+ return;
59
+ if (!enabled) {
60
+ setConstellation(null);
61
+ return;
62
+ }
63
+ void refresh();
64
+ }, [configLoading, enabled, refresh]);
65
+ return { constellation, loading, error, refresh };
66
+ }
67
+ //# sourceMappingURL=useSocialConstellation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSocialConstellation.js","sourceRoot":"","sources":["../../../src/hooks/useSocialConstellation.tsx"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,EAAE;AACF,6FAA6F;AAC7F,mGAAmG;AACnG,qGAAqG;AACrG,uEAAuE;AAEvE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAczD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,CAAC;IACpD,MAAM,OAAO,GAAG,MAAM,EAAE,oBAAoB,IAAI,KAAK,CAAC;IAEtD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAA6B,IAAI,CAAC,CAAC;IACrF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAU,IAAI,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACrC,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,gBAAgB,CAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,6FAA6F;YAC7F,kGAAkG;YAClG,sCAAsC;YACtC,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAEpB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,aAAa;YAAE,OAAO;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,gBAAgB,CAAC,IAAI,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QACD,KAAK,OAAO,EAAE,CAAC;IACjB,CAAC,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACpD,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { SocialNeighborhood } from "../contract/index.js";
2
+ /** The state and actions returned by {@link useSocialNeighborhood}. */
3
+ export interface UseSocialNeighborhoodValues {
4
+ /** The caller's ties (brightest-first), or `null` while loading, when disabled, or on error. */
5
+ neighborhood: SocialNeighborhood | null;
6
+ /** True while a fetch is in flight (always `false` when the lens is disabled). */
7
+ loading: boolean;
8
+ /** The last error thrown by the fetch, or `null`. */
9
+ error: unknown;
10
+ /** The effective `includeInteractions` value currently in effect. */
11
+ includeInteractions: boolean;
12
+ /** Flip whether interaction-only ties are included; triggers a re-fetch. */
13
+ setIncludeInteractions: (value: boolean) => void;
14
+ }
15
+ /**
16
+ * Load the caller's Neighborhood — their own named ties with dyadic brightness. Self-view only.
17
+ *
18
+ * Waits for the provider's transparency config, seeds the `includeInteractions` toggle from the
19
+ * project default, then fetches `GET /social/neighborhood` only when `neighborhoodEnabled` is true.
20
+ * Flipping the toggle re-fetches; the hook syncs to the server's echoed effective value.
21
+ *
22
+ * @returns {@link UseSocialNeighborhoodValues} — the ties, load state, and the interactions toggle.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const { neighborhood, includeInteractions, setIncludeInteractions } = useSocialNeighborhood();
27
+ * ```
28
+ */
29
+ export declare function useSocialNeighborhood(): UseSocialNeighborhoodValues;
@@ -0,0 +1,87 @@
1
+ // useSocialNeighborhood — load the caller's own named ties (self-view), gated on the feature config.
2
+ //
3
+ // Self-gates on `config.neighborhoodEnabled`. Owns the `includeInteractions` toggle: it seeds from the
4
+ // project default (`config.neighborhoodIncludeInteractions`) once config resolves, then re-fetches
5
+ // whenever the caller flips it. The server always echoes the EFFECTIVE value, so we sync local state to
6
+ // the response (`includesInteractions`) rather than trusting the request optimistically.
7
+ //
8
+ // Privacy (SOCIAL.md §6): the Neighborhood is self-view only and must not persist across sign-outs or
9
+ // user switches. This hook keeps ties in component state only (no cache) and clears them when the lens
10
+ // disables or the provider's client identity changes — so a project/token swap cannot leak a prior
11
+ // user's ties.
12
+ import { useCallback, useEffect, useRef, useState } from "react";
13
+ import { isSocialDegradation } from "../transport/rest.js";
14
+ import { useSocial } from "../context/social-context.js";
15
+ /**
16
+ * Load the caller's Neighborhood — their own named ties with dyadic brightness. Self-view only.
17
+ *
18
+ * Waits for the provider's transparency config, seeds the `includeInteractions` toggle from the
19
+ * project default, then fetches `GET /social/neighborhood` only when `neighborhoodEnabled` is true.
20
+ * Flipping the toggle re-fetches; the hook syncs to the server's echoed effective value.
21
+ *
22
+ * @returns {@link UseSocialNeighborhoodValues} — the ties, load state, and the interactions toggle.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const { neighborhood, includeInteractions, setIncludeInteractions } = useSocialNeighborhood();
27
+ * ```
28
+ */
29
+ export function useSocialNeighborhood() {
30
+ const { rest, config, configLoading } = useSocial();
31
+ const enabled = config?.neighborhoodEnabled ?? false;
32
+ const projectDefault = config?.neighborhoodIncludeInteractions ?? false;
33
+ const [neighborhood, setNeighborhood] = useState(null);
34
+ const [loading, setLoading] = useState(false);
35
+ const [error, setError] = useState(null);
36
+ const [includeInteractions, setIncludeInteractions] = useState(false);
37
+ // Seed the toggle from the project default exactly once, when config first resolves. After that the
38
+ // caller owns it. A ref guards against re-seeding (which would clobber a user's choice on re-render).
39
+ const seeded = useRef(false);
40
+ useEffect(() => {
41
+ if (configLoading || seeded.current)
42
+ return;
43
+ setIncludeInteractions(projectDefault);
44
+ seeded.current = true;
45
+ }, [configLoading, projectDefault]);
46
+ const fetchFor = useCallback(async (include) => {
47
+ if (!enabled)
48
+ return;
49
+ setLoading(true);
50
+ setError(null);
51
+ try {
52
+ const result = await rest.getNeighborhood({ includeInteractions: include });
53
+ setNeighborhood(result);
54
+ // Sync to the server's effective value (it may override the request, e.g. project policy).
55
+ setIncludeInteractions(result.includesInteractions);
56
+ }
57
+ catch (err) {
58
+ // Fail soft on degradation (graph off, or the lens disabled mid-session): hide the surface —
59
+ // clear ties and swallow the error rather than surface it to members (SOCIAL.md §7). Real
60
+ // errors still propagate via `error`.
61
+ if (isSocialDegradation(err)) {
62
+ setNeighborhood(null);
63
+ setError(null);
64
+ }
65
+ else {
66
+ setError(err);
67
+ }
68
+ }
69
+ finally {
70
+ setLoading(false);
71
+ }
72
+ }, [enabled, rest]);
73
+ // Fetch on enable and whenever the toggle changes. Clear ties when disabled or before re-fetch under
74
+ // a new identity — the self-view must never linger across a user switch (SOCIAL.md §6).
75
+ useEffect(() => {
76
+ if (configLoading || !seeded.current)
77
+ return;
78
+ if (!enabled) {
79
+ setNeighborhood(null);
80
+ return;
81
+ }
82
+ void fetchFor(includeInteractions);
83
+ // eslint-disable-next-line react-hooks/exhaustive-deps
84
+ }, [configLoading, enabled, includeInteractions, fetchFor]);
85
+ return { neighborhood, loading, error, includeInteractions, setIncludeInteractions };
86
+ }
87
+ //# sourceMappingURL=useSocialNeighborhood.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSocialNeighborhood.js","sourceRoot":"","sources":["../../../src/hooks/useSocialNeighborhood.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { ResolvedSocialConfig } from "../contract/index.js";
2
+ /** The state returned by {@link useSocialTransparency}. */
3
+ export interface UseSocialTransparencyValues {
4
+ /** The resolved config, or `null` until the provider's transparency fetch resolves. */
5
+ config: ResolvedSocialConfig | null;
6
+ /** True while the provider's initial transparency fetch is in flight. */
7
+ loading: boolean;
8
+ /** A non-degradation error from the transparency fetch, or `null`. */
9
+ error: unknown;
10
+ }
11
+ /**
12
+ * Read the project's resolved social config (which lenses are enabled, decay half-lives, k-floor).
13
+ *
14
+ * Reads straight from the provider — no extra request. Returns `config: null` until the provider's
15
+ * mount-time transparency fetch resolves.
16
+ *
17
+ * @returns {@link UseSocialTransparencyValues} — the resolved config and its load state.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * const { config } = useSocialTransparency();
22
+ * if (config?.weatherEnabled) renderWeatherNavEntry();
23
+ * ```
24
+ */
25
+ export declare function useSocialTransparency(): UseSocialTransparencyValues;
@@ -0,0 +1,25 @@
1
+ // useSocialTransparency — read the project's resolved social config from the provider.
2
+ //
3
+ // The provider already fetches `GET /social/transparency` once on mount, so this hook issues no
4
+ // request of its own — it just surfaces the cached config + load state. Use it to render a how-it-works
5
+ // panel (which lenses are on, decay half-lives, k-floor) or to drive nav-entry visibility.
6
+ import { useSocial } from "../context/social-context.js";
7
+ /**
8
+ * Read the project's resolved social config (which lenses are enabled, decay half-lives, k-floor).
9
+ *
10
+ * Reads straight from the provider — no extra request. Returns `config: null` until the provider's
11
+ * mount-time transparency fetch resolves.
12
+ *
13
+ * @returns {@link UseSocialTransparencyValues} — the resolved config and its load state.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * const { config } = useSocialTransparency();
18
+ * if (config?.weatherEnabled) renderWeatherNavEntry();
19
+ * ```
20
+ */
21
+ export function useSocialTransparency() {
22
+ const { config, configLoading, configError } = useSocial();
23
+ return { config, loading: configLoading, error: configError };
24
+ }
25
+ //# sourceMappingURL=useSocialTransparency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSocialTransparency.js","sourceRoot":"","sources":["../../../src/hooks/useSocialTransparency.tsx"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,EAAE;AACF,gGAAgG;AAChG,wGAAwG;AACxG,2FAA2F;AAG3F,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAYzD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE,CAAC;IAC3D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AAChE,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { SocialWeather } from "../contract/index.js";
2
+ /** The state and actions returned by {@link useSocialWeather}. */
3
+ export interface UseSocialWeatherValues {
4
+ /** The current Weather reading, or `null` while loading, when disabled, or on error. */
5
+ weather: SocialWeather | null;
6
+ /** True while a fetch is in flight (always `false` when the lens is disabled). */
7
+ loading: boolean;
8
+ /** The last error thrown by the fetch, or `null`. */
9
+ error: unknown;
10
+ /** Re-fetch the Weather reading. No-op when the lens is disabled. */
11
+ refresh: () => Promise<void>;
12
+ }
13
+ /**
14
+ * Load the Community Weather scalar for the current project.
15
+ *
16
+ * Waits for the provider's transparency config, then fetches `GET /social/weather` only when
17
+ * `weatherEnabled` is true. When the lens is disabled it returns `{ weather: null, loading: false }`
18
+ * and issues no request.
19
+ *
20
+ * @returns {@link UseSocialWeatherValues} — the reading, load state, and a `refresh` action.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * const { weather, loading } = useSocialWeather();
25
+ * if (!weather) return null; // disabled or still loading
26
+ * ```
27
+ */
28
+ export declare function useSocialWeather(): UseSocialWeatherValues;
@@ -0,0 +1,69 @@
1
+ // useSocialWeather — load the Community Weather scalar, gated on the project's feature config.
2
+ //
3
+ // Self-gates on `config.weatherEnabled` from the provider: when the lens is disabled (or the graph is
4
+ // unavailable) the hook returns `weather: null` and never issues a request, so a host app can render
5
+ // `<CommunityWeather />` unconditionally and have it disappear when off (SOCIAL.md §7). Weather is a
6
+ // ~1h server-cached aggregate, so a single fetch on enable is enough; `refresh()` is exposed for
7
+ // manual refetch (e.g. pull-to-refresh).
8
+ import { useCallback, useEffect, useState } from "react";
9
+ import { isSocialDegradation } from "../transport/rest.js";
10
+ import { useSocial } from "../context/social-context.js";
11
+ /**
12
+ * Load the Community Weather scalar for the current project.
13
+ *
14
+ * Waits for the provider's transparency config, then fetches `GET /social/weather` only when
15
+ * `weatherEnabled` is true. When the lens is disabled it returns `{ weather: null, loading: false }`
16
+ * and issues no request.
17
+ *
18
+ * @returns {@link UseSocialWeatherValues} — the reading, load state, and a `refresh` action.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * const { weather, loading } = useSocialWeather();
23
+ * if (!weather) return null; // disabled or still loading
24
+ * ```
25
+ */
26
+ export function useSocialWeather() {
27
+ const { rest, config, configLoading } = useSocial();
28
+ const enabled = config?.weatherEnabled ?? false;
29
+ const [weather, setWeather] = useState(null);
30
+ const [loading, setLoading] = useState(false);
31
+ const [error, setError] = useState(null);
32
+ const refresh = useCallback(async () => {
33
+ if (!enabled)
34
+ return;
35
+ setLoading(true);
36
+ setError(null);
37
+ try {
38
+ setWeather(await rest.getWeather());
39
+ }
40
+ catch (err) {
41
+ // Fail soft on degradation (graph off, or the lens disabled mid-session): hide the surface —
42
+ // clear the reading and swallow the error rather than surface it to members (SOCIAL.md §7). Real
43
+ // errors still propagate via `error`.
44
+ if (isSocialDegradation(err)) {
45
+ setWeather(null);
46
+ setError(null);
47
+ }
48
+ else {
49
+ setError(err);
50
+ }
51
+ }
52
+ finally {
53
+ setLoading(false);
54
+ }
55
+ }, [enabled, rest]);
56
+ // Fetch once the config has resolved and the lens is enabled. When disabled, clear any stale reading
57
+ // so a config flip to off (or a project switch) doesn't leave the previous community's weather on screen.
58
+ useEffect(() => {
59
+ if (configLoading)
60
+ return;
61
+ if (!enabled) {
62
+ setWeather(null);
63
+ return;
64
+ }
65
+ void refresh();
66
+ }, [configLoading, enabled, refresh]);
67
+ return { weather, loading, error, refresh };
68
+ }
69
+ //# sourceMappingURL=useSocialWeather.js.map