@sublay/js 7.8.0 → 7.9.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.
package/dist/index.js CHANGED
@@ -1978,6 +1978,49 @@ async function fetchModeratedReports(client, data) {
1978
1978
  return response.data;
1979
1979
  }
1980
1980
 
1981
+ // src/modules/reputation/index.ts
1982
+ var reputation_exports = {};
1983
+ __export(reputation_exports, {
1984
+ createGrant: () => createGrant,
1985
+ listGrants: () => listGrants
1986
+ });
1987
+
1988
+ // src/modules/reputation/createGrant.ts
1989
+ async function createGrant(client, data) {
1990
+ const response = await client.projectInstance.post(
1991
+ "/reputation-grants",
1992
+ data
1993
+ );
1994
+ return response.data;
1995
+ }
1996
+
1997
+ // src/modules/reputation/listGrants.ts
1998
+ async function listGrants(client, data) {
1999
+ const {
2000
+ spaceReputation,
2001
+ spaceReputationId,
2002
+ spaceReputationDescendants,
2003
+ ...rest
2004
+ } = data;
2005
+ const response = await client.projectInstance.get(
2006
+ "/reputation-grants",
2007
+ {
2008
+ params: {
2009
+ ...rest,
2010
+ // `spaceReputationId=context` scores each hydrated user against THAT
2011
+ // GRANT'S own bucket. Normalized rather than spread raw — axios would
2012
+ // bracket-encode the object and the server would ignore it.
2013
+ ...buildSpaceReputationParams({
2014
+ spaceReputation,
2015
+ spaceReputationId,
2016
+ spaceReputationDescendants
2017
+ })
2018
+ }
2019
+ }
2020
+ );
2021
+ return response.data;
2022
+ }
2023
+
1981
2024
  // src/modules/search/index.ts
1982
2025
  var search_exports = {};
1983
2026
  __export(search_exports, {
@@ -2598,11 +2641,9 @@ __export(workspaces_exports, {
2598
2641
 
2599
2642
  // src/modules/workspaces/createWorkspace.ts
2600
2643
  async function createWorkspace(client, data) {
2601
- const body = { ...data };
2602
- delete body.userId;
2603
2644
  const response = await client.projectInstance.post(
2604
2645
  "/workspaces",
2605
- body
2646
+ data
2606
2647
  );
2607
2648
  return response.data;
2608
2649
  }
@@ -2619,17 +2660,13 @@ async function fetchWorkspace(client, data) {
2619
2660
 
2620
2661
  // src/modules/workspaces/fetchManyWorkspaces.ts
2621
2662
  async function fetchManyWorkspaces(client, data = {}) {
2622
- const params = { ...data };
2623
- delete params.userId;
2624
- const response = await client.projectInstance.get("/workspaces", { params });
2663
+ const response = await client.projectInstance.get("/workspaces", { params: data });
2625
2664
  return response.data;
2626
2665
  }
2627
2666
 
2628
2667
  // src/modules/workspaces/updateWorkspace.ts
2629
2668
  async function updateWorkspace(client, data) {
2630
- const { workspaceId, ...rest } = data;
2631
- const body = { ...rest };
2632
- delete body.userId;
2669
+ const { workspaceId, ...body } = data;
2633
2670
  const response = await client.projectInstance.patch(
2634
2671
  `/workspaces/${workspaceId}`,
2635
2672
  body
@@ -2658,9 +2695,7 @@ async function deleteWorkspace(client, data) {
2658
2695
 
2659
2696
  // src/modules/workspaces/transferWorkspaceOwnership.ts
2660
2697
  async function transferWorkspaceOwnership(client, data) {
2661
- const { workspaceId, ...rest } = data;
2662
- const body = { ...rest };
2663
- delete body.userId;
2698
+ const { workspaceId, ...body } = data;
2664
2699
  const response = await client.projectInstance.post(
2665
2700
  `/workspaces/${workspaceId}/transfer-ownership`,
2666
2701
  body
@@ -2670,9 +2705,7 @@ async function transferWorkspaceOwnership(client, data) {
2670
2705
 
2671
2706
  // src/modules/workspaces/fetchWorkspaceMembers.ts
2672
2707
  async function fetchWorkspaceMembers(client, data) {
2673
- const { workspaceId, ...rest } = data;
2674
- const params = { ...rest };
2675
- delete params.userId;
2708
+ const { workspaceId, ...params } = data;
2676
2709
  const response = await client.projectInstance.get(`/workspaces/${workspaceId}/members`, { params });
2677
2710
  return response.data;
2678
2711
  }
@@ -2688,9 +2721,7 @@ async function fetchWorkspaceMemberStanding(client, data) {
2688
2721
 
2689
2722
  // src/modules/workspaces/updateWorkspaceMember.ts
2690
2723
  async function updateWorkspaceMember(client, data) {
2691
- const { workspaceId, targetUserId, ...rest } = data;
2692
- const body = { ...rest };
2693
- delete body.userId;
2724
+ const { workspaceId, targetUserId, ...body } = data;
2694
2725
  const response = await client.projectInstance.patch(
2695
2726
  `/workspaces/${workspaceId}/members/${targetUserId}`,
2696
2727
  body
@@ -2908,6 +2939,7 @@ var PUSH_EVENT_TYPES = [
2908
2939
  "event-invite",
2909
2940
  "event-updated",
2910
2941
  "event-cancelled",
2942
+ "reputation-grant",
2911
2943
  "message"
2912
2944
  ];
2913
2945
  var MUTE_DURATIONS = ["8h", "24h", "1w", "forever"];
@@ -2926,6 +2958,7 @@ var SublayClient = class _SublayClient {
2926
2958
  connections;
2927
2959
  appNotifications;
2928
2960
  reports;
2961
+ reputation;
2929
2962
  search;
2930
2963
  storage;
2931
2964
  oauth;
@@ -2945,6 +2978,7 @@ var SublayClient = class _SublayClient {
2945
2978
  this.connections = bindModule(connections_exports, this.http);
2946
2979
  this.appNotifications = bindModule(app_notifications_exports, this.http);
2947
2980
  this.reports = bindModule(reports_exports, this.http);
2981
+ this.reputation = bindModule(reputation_exports, this.http);
2948
2982
  this.search = bindModule(search_exports, this.http);
2949
2983
  this.storage = bindModule(storage_exports, this.http);
2950
2984
  this.oauth = bindModule(oauth_exports, this.http);
package/dist/index.mjs CHANGED
@@ -1946,6 +1946,49 @@ async function fetchModeratedReports(client, data) {
1946
1946
  return response.data;
1947
1947
  }
1948
1948
 
1949
+ // src/modules/reputation/index.ts
1950
+ var reputation_exports = {};
1951
+ __export(reputation_exports, {
1952
+ createGrant: () => createGrant,
1953
+ listGrants: () => listGrants
1954
+ });
1955
+
1956
+ // src/modules/reputation/createGrant.ts
1957
+ async function createGrant(client, data) {
1958
+ const response = await client.projectInstance.post(
1959
+ "/reputation-grants",
1960
+ data
1961
+ );
1962
+ return response.data;
1963
+ }
1964
+
1965
+ // src/modules/reputation/listGrants.ts
1966
+ async function listGrants(client, data) {
1967
+ const {
1968
+ spaceReputation,
1969
+ spaceReputationId,
1970
+ spaceReputationDescendants,
1971
+ ...rest
1972
+ } = data;
1973
+ const response = await client.projectInstance.get(
1974
+ "/reputation-grants",
1975
+ {
1976
+ params: {
1977
+ ...rest,
1978
+ // `spaceReputationId=context` scores each hydrated user against THAT
1979
+ // GRANT'S own bucket. Normalized rather than spread raw — axios would
1980
+ // bracket-encode the object and the server would ignore it.
1981
+ ...buildSpaceReputationParams({
1982
+ spaceReputation,
1983
+ spaceReputationId,
1984
+ spaceReputationDescendants
1985
+ })
1986
+ }
1987
+ }
1988
+ );
1989
+ return response.data;
1990
+ }
1991
+
1949
1992
  // src/modules/search/index.ts
1950
1993
  var search_exports = {};
1951
1994
  __export(search_exports, {
@@ -2566,11 +2609,9 @@ __export(workspaces_exports, {
2566
2609
 
2567
2610
  // src/modules/workspaces/createWorkspace.ts
2568
2611
  async function createWorkspace(client, data) {
2569
- const body = { ...data };
2570
- delete body.userId;
2571
2612
  const response = await client.projectInstance.post(
2572
2613
  "/workspaces",
2573
- body
2614
+ data
2574
2615
  );
2575
2616
  return response.data;
2576
2617
  }
@@ -2587,17 +2628,13 @@ async function fetchWorkspace(client, data) {
2587
2628
 
2588
2629
  // src/modules/workspaces/fetchManyWorkspaces.ts
2589
2630
  async function fetchManyWorkspaces(client, data = {}) {
2590
- const params = { ...data };
2591
- delete params.userId;
2592
- const response = await client.projectInstance.get("/workspaces", { params });
2631
+ const response = await client.projectInstance.get("/workspaces", { params: data });
2593
2632
  return response.data;
2594
2633
  }
2595
2634
 
2596
2635
  // src/modules/workspaces/updateWorkspace.ts
2597
2636
  async function updateWorkspace(client, data) {
2598
- const { workspaceId, ...rest } = data;
2599
- const body = { ...rest };
2600
- delete body.userId;
2637
+ const { workspaceId, ...body } = data;
2601
2638
  const response = await client.projectInstance.patch(
2602
2639
  `/workspaces/${workspaceId}`,
2603
2640
  body
@@ -2626,9 +2663,7 @@ async function deleteWorkspace(client, data) {
2626
2663
 
2627
2664
  // src/modules/workspaces/transferWorkspaceOwnership.ts
2628
2665
  async function transferWorkspaceOwnership(client, data) {
2629
- const { workspaceId, ...rest } = data;
2630
- const body = { ...rest };
2631
- delete body.userId;
2666
+ const { workspaceId, ...body } = data;
2632
2667
  const response = await client.projectInstance.post(
2633
2668
  `/workspaces/${workspaceId}/transfer-ownership`,
2634
2669
  body
@@ -2638,9 +2673,7 @@ async function transferWorkspaceOwnership(client, data) {
2638
2673
 
2639
2674
  // src/modules/workspaces/fetchWorkspaceMembers.ts
2640
2675
  async function fetchWorkspaceMembers(client, data) {
2641
- const { workspaceId, ...rest } = data;
2642
- const params = { ...rest };
2643
- delete params.userId;
2676
+ const { workspaceId, ...params } = data;
2644
2677
  const response = await client.projectInstance.get(`/workspaces/${workspaceId}/members`, { params });
2645
2678
  return response.data;
2646
2679
  }
@@ -2656,9 +2689,7 @@ async function fetchWorkspaceMemberStanding(client, data) {
2656
2689
 
2657
2690
  // src/modules/workspaces/updateWorkspaceMember.ts
2658
2691
  async function updateWorkspaceMember(client, data) {
2659
- const { workspaceId, targetUserId, ...rest } = data;
2660
- const body = { ...rest };
2661
- delete body.userId;
2692
+ const { workspaceId, targetUserId, ...body } = data;
2662
2693
  const response = await client.projectInstance.patch(
2663
2694
  `/workspaces/${workspaceId}/members/${targetUserId}`,
2664
2695
  body
@@ -2876,6 +2907,7 @@ var PUSH_EVENT_TYPES = [
2876
2907
  "event-invite",
2877
2908
  "event-updated",
2878
2909
  "event-cancelled",
2910
+ "reputation-grant",
2879
2911
  "message"
2880
2912
  ];
2881
2913
  var MUTE_DURATIONS = ["8h", "24h", "1w", "forever"];
@@ -2894,6 +2926,7 @@ var SublayClient = class _SublayClient {
2894
2926
  connections;
2895
2927
  appNotifications;
2896
2928
  reports;
2929
+ reputation;
2897
2930
  search;
2898
2931
  storage;
2899
2932
  oauth;
@@ -2913,6 +2946,7 @@ var SublayClient = class _SublayClient {
2913
2946
  this.connections = bindModule(connections_exports, this.http);
2914
2947
  this.appNotifications = bindModule(app_notifications_exports, this.http);
2915
2948
  this.reports = bindModule(reports_exports, this.http);
2949
+ this.reputation = bindModule(reputation_exports, this.http);
2916
2950
  this.search = bindModule(search_exports, this.http);
2917
2951
  this.storage = bindModule(storage_exports, this.http);
2918
2952
  this.oauth = bindModule(oauth_exports, this.http);
@@ -1,3 +1,4 @@
1
+ import { GrantSummary } from "./ReputationGrant";
1
2
  import { GifData } from "./Comment";
2
3
  import { File } from "./File";
3
4
  import { Mention } from "./Mention";
@@ -17,6 +18,13 @@ export interface ChatMessage {
17
18
  threadReplyCount: number;
18
19
  reactionCounts: Record<string, number>;
19
20
  userReactions: string[];
21
+ /**
22
+ * Reputation-grant summary. Opt-in — present exactly when the read requested
23
+ * `include=grants`. Once requested the server always returns the object,
24
+ * zero-filled rather than omitted, on projects with no grants and on projects
25
+ * without the reputation bundle alike.
26
+ */
27
+ grants?: GrantSummary;
20
28
  editedAt: string | null;
21
29
  userDeletedAt: string | null;
22
30
  moderationStatus: "approved" | "removed" | null;
@@ -1,3 +1,4 @@
1
+ import { GrantSummary } from "./ReputationGrant";
1
2
  import { Entity } from "./Entity";
2
3
  import { Mention } from "./Mention";
3
4
  import { User } from "./User";
@@ -28,6 +29,13 @@ export interface Comment {
28
29
  reactionCounts: ReactionCounts;
29
30
  userReaction?: ReactionType | null;
30
31
  repliesCount: number;
32
+ /**
33
+ * Reputation-grant summary. Opt-in — present exactly when the read requested
34
+ * `include=grants`. Once requested the server always returns the object,
35
+ * zero-filled rather than omitted, on projects with no grants and on projects
36
+ * without the reputation bundle alike.
37
+ */
38
+ grants?: GrantSummary;
31
39
  metadata: Record<string, any>;
32
40
  createdAt: string;
33
41
  updatedAt: string;
@@ -1,3 +1,4 @@
1
+ import { GrantSummary } from "./ReputationGrant";
1
2
  import { Mention } from "./Mention";
2
3
  import { User } from "./User";
3
4
  import { Space } from "./Space";
@@ -43,6 +44,13 @@ export interface Entity {
43
44
  nsfwEffective: boolean;
44
45
  topComment: TopComment | null;
45
46
  isSaved?: boolean;
47
+ /**
48
+ * Reputation-grant summary. Opt-in — present exactly when the read requested
49
+ * `include=grants`. Once requested the server always returns the object,
50
+ * zero-filled rather than omitted, on projects with no grants and on projects
51
+ * without the reputation bundle alike.
52
+ */
53
+ grants?: GrantSummary;
46
54
  isDraft: boolean | null;
47
55
  moderationStatus: "approved" | "removed" | null;
48
56
  moderatedAt: string | null;
@@ -4,7 +4,7 @@
4
4
  * (server `src/constants/push/pushEvents.ts`); these are the only names a
5
5
  * `disabledTypes` set may contain.
6
6
  */
7
- export declare const PUSH_EVENT_TYPES: readonly ["entity-comment", "comment-reply", "entity-mention", "comment-mention", "entity-reaction", "comment-reaction", "entity-reaction-milestone-specific", "entity-reaction-milestone-total", "comment-reaction-milestone-specific", "comment-reaction-milestone-total", "new-follow", "connection-request", "connection-accepted", "space-membership-approved", "event-invite", "event-updated", "event-cancelled", "message"];
7
+ export declare const PUSH_EVENT_TYPES: readonly ["entity-comment", "comment-reply", "entity-mention", "comment-mention", "entity-reaction", "comment-reaction", "entity-reaction-milestone-specific", "entity-reaction-milestone-total", "comment-reaction-milestone-specific", "comment-reaction-milestone-total", "new-follow", "connection-request", "connection-accepted", "space-membership-approved", "event-invite", "event-updated", "event-cancelled", "reputation-grant", "message"];
8
8
  export type PushEventType = (typeof PUSH_EVENT_TYPES)[number];
9
9
  /**
10
10
  * The four conversation-mute duration choices. Send the CHOICE, never a raw
@@ -0,0 +1,85 @@
1
+ import { User } from "./User";
2
+ /** The three grantable target kinds. Polymorphic — `targetId` carries no FK. */
3
+ export type ReputationGrantTargetType = "entity" | "comment" | "chat-message";
4
+ /**
5
+ * Who created the grant. `"user"` is a debited transfer (reputation moved out
6
+ * of `senderId`'s bucket); `"app"` is a mint issued by the project itself with
7
+ * a null `senderId`. Persisted rather than inferred from `senderId`, which is
8
+ * also null for a transfer whose sender was later deleted.
9
+ */
10
+ export type ReputationGrantSourceType = "user" | "app";
11
+ /**
12
+ * The "which item was rewarded" pair, as a both-or-neither union.
13
+ *
14
+ * Modelled as a two-branch union rather than two independent optional fields so
15
+ * a half-filled target — `{ targetType }` with no `targetId`, or the reverse —
16
+ * does not compile. The server answers that shape with
17
+ * `400 reputation-grant/invalid-body` on the write (a shared
18
+ * `bothOrNeitherTarget` refinement) and
19
+ * `400 reputation-grant/invalid-filter` on the list, so the union turns a
20
+ * guaranteed round trip into a red squiggle.
21
+ *
22
+ * The empty branch is `?: undefined`, NOT `?: null` — deliberately, and for the
23
+ * same reason `metadata` is not nullable: `grantBodyFields.targetType` is
24
+ * `.optional()` with no `.nullable()`, so an explicit `targetType: null` is
25
+ * rejected. Omit both keys to mean "no target".
26
+ *
27
+ * Building the pair conditionally needs one accommodation: an inline
28
+ * conditional spread of just these two keys widens both to `T | undefined` and
29
+ * then matches neither branch. Either branch the whole argument, or name this
30
+ * type on a helper and spread that:
31
+ *
32
+ * ```ts
33
+ * const target: ReputationGrantTargetFilter = item
34
+ * ? { targetType: "entity", targetId: item.id }
35
+ * : {};
36
+ * await listGrants(client, { ...base, ...target });
37
+ * ```
38
+ */
39
+ export type ReputationGrantTargetFilter = {
40
+ /** The kind of item rewarded. Requires `targetId` alongside it. */
41
+ targetType: ReputationGrantTargetType;
42
+ /** The rewarded item's id. Requires `targetType` alongside it. */
43
+ targetId: string;
44
+ } | {
45
+ targetType?: undefined;
46
+ targetId?: undefined;
47
+ };
48
+ /**
49
+ * Per-item reputation-grant summary. Covers positive grants only — negative
50
+ * grants (app deductions) are invisible on every public read surface.
51
+ */
52
+ export interface GrantSummary {
53
+ /** Sum of positive grant amounts on the item. */
54
+ total: number;
55
+ /** Number of positive grants on the item. */
56
+ count: number;
57
+ /** The calling user's own summed positive grants on the item. */
58
+ viewerTotal: number;
59
+ }
60
+ /**
61
+ * A single reputation movement. Rows are append-only — nothing updates or
62
+ * soft-deletes them — so the table is the audit log behind every balance.
63
+ */
64
+ export interface ReputationGrant {
65
+ id: string;
66
+ sourceType: ReputationGrantSourceType;
67
+ /** Null for an app mint, and for a transfer whose sender was deleted. */
68
+ senderId: string | null;
69
+ /** Populated when the list is called with `include: "user"`. */
70
+ sender?: User | null;
71
+ recipientId: string;
72
+ /** Populated when the list is called with `include: "user"`. */
73
+ recipient?: User | null;
74
+ /** Non-zero. Negative only when `sourceType` is `"app"`. */
75
+ amount: number;
76
+ /** The bucket both legs moved in; null = the project-general bucket. */
77
+ spaceId: string | null;
78
+ /** Both null or both non-null. */
79
+ targetType: ReputationGrantTargetType | null;
80
+ targetId: string | null;
81
+ note: string | null;
82
+ metadata: Record<string, any> | null;
83
+ createdAt: string;
84
+ updatedAt: string;
85
+ }
@@ -60,6 +60,29 @@ export interface WorkspaceInvitation {
60
60
  export interface WorkspaceRosterReason {
61
61
  type: "owner" | "member" | "ancestor-owner" | "reach-holder" | "descendant-member";
62
62
  rank?: number;
63
+ /**
64
+ * The SAME ladder position, expressed as an offset from the CALLER: `1` = one
65
+ * rung below you, `0` = your peer, `-3` = three rungs above you. The caller's
66
+ * own anchor is their member row on this workspace if they hold one, and apex
67
+ * (one step above rank 0) if they do not — so a rank-0 member reads back as
68
+ * `relativeRank: 1` for an owner.
69
+ *
70
+ * Authority-bearing and fenced WITH `rank`, never beside it: it is `rank`
71
+ * minus a number the caller already knows, so leaking it leaks `rank` exactly.
72
+ *
73
+ * Present on same-node `member` reasons only. `descendant-member` entries
74
+ * carry `rank` but NEVER `relativeRank` — rank is per-workspace, so an offset
75
+ * measured against your standing on THIS node would be arithmetic across two
76
+ * different ladders. Use their absolute `rank` there.
77
+ *
78
+ * Note the deliberate asymmetry with the fence described above: the FENCE is
79
+ * per node (a descendant row may or may not carry `rank` depending on your
80
+ * standing there), but PRESENCE of `relativeRank` is not — it is absent on
81
+ * every `descendant-member` row, unconditionally, however much authority you
82
+ * hold. A field that appears and disappears by who is asking is worse to
83
+ * consume than one that is uniformly absent.
84
+ */
85
+ relativeRank?: number;
63
86
  capabilities?: WorkspaceCapability[];
64
87
  permissions?: string[];
65
88
  title?: string | null;
@@ -99,6 +122,13 @@ export interface WorkspaceMemberStanding {
99
122
  capabilities?: WorkspaceCapability[];
100
123
  permissions?: string[];
101
124
  rank?: number | null;
125
+ /**
126
+ * `rank` expressed as an offset from the CALLER (negative = senior to you).
127
+ * `null` exactly when `rank` is `null` — a target with no direct member row
128
+ * here sits outside the ladder and has no position to measure. Fenced with
129
+ * `rank`: absent (not null) for a caller who may not see it.
130
+ */
131
+ relativeRank?: number | null;
102
132
  title: string | null;
103
133
  metadata: Record<string, any>;
104
134
  }
@@ -4,5 +4,10 @@ import { SpaceReputationContextParams } from "../../interfaces/SpaceReputation";
4
4
  export interface GetMessageProps extends SpaceReputationContextParams {
5
5
  conversationId: string;
6
6
  messageId: string;
7
+ /**
8
+ * Comma-separated associations to populate. Only `"grants"` is supported
9
+ * here — it attaches the message's reputation-grant summary.
10
+ */
11
+ include?: string;
7
12
  }
8
13
  export declare function getMessage(client: SublayHttpClient, data: GetMessageProps): Promise<ChatMessage>;
@@ -20,7 +20,11 @@ export interface ListMessagesProps extends SpaceReputationContextParams {
20
20
  /** Page size (default 50, max 100). */
21
21
  limit?: number;
22
22
  sort?: "asc" | "desc";
23
- /** Comma-separated associations to populate, e.g. "files". */
23
+ /**
24
+ * Comma-separated associations to populate: `"files"` (message
25
+ * attachments) and `"grants"` (the reputation-grant summary). Combine
26
+ * them as `"files,grants"` — the server splits and trims this itself.
27
+ */
24
28
  include?: string;
25
29
  /** Optional filters, e.g. `{ hasReplies: true }`. */
26
30
  filters?: MessageFilters;
@@ -0,0 +1,45 @@
1
+ import { SublayHttpClient } from "../../core/client";
2
+ import { ReputationGrant, ReputationGrantTargetFilter } from "../../interfaces/ReputationGrant";
3
+ interface CreateGrantBaseProps {
4
+ /** The user receiving the reputation. Cannot be the logged-in user. */
5
+ recipientId: string;
6
+ /**
7
+ * Positive integer. A user transfer can never mint (negatives) nor be a
8
+ * no-op (zero) — minting is service-key-only and lives in `@sublay/node`.
9
+ */
10
+ amount: number;
11
+ /** The bucket both legs move in. Omitted/null = the project-general bucket. */
12
+ spaceId?: string | null;
13
+ /**
14
+ * Free-text reason. Trimmed and capped at 2000 characters server-side.
15
+ * Genuinely nullable — an explicit `null` is accepted and means "no note".
16
+ */
17
+ note?: string | null;
18
+ /**
19
+ * Arbitrary JSON, capped at 1 MB server-side.
20
+ *
21
+ * NOT nullable — deliberately asymmetric with `note` directly above, not a
22
+ * typo. The server's shared `metadataSchema` is `z.record(...).optional()`
23
+ * with no `.nullable()`, so an explicit `metadata: null` is rejected with
24
+ * `400 reputation-grant/invalid-body`. Omit the key to mean "no metadata".
25
+ */
26
+ metadata?: Record<string, any>;
27
+ }
28
+ /**
29
+ * `targetType` and `targetId` are supplied together or not at all — the
30
+ * both-or-neither pair is carried by {@link ReputationGrantTargetFilter}, which
31
+ * makes the half-filled shape a compile error instead of a
32
+ * `400 reputation-grant/invalid-body`.
33
+ */
34
+ export type CreateGrantProps = CreateGrantBaseProps & ReputationGrantTargetFilter;
35
+ /**
36
+ * Transfers reputation from the logged-in user to another user — a **debited
37
+ * transfer**: the amount leaves the sender's bucket and lands in the
38
+ * recipient's bucket in the same space. Nothing is created.
39
+ *
40
+ * There is no actor field: the sender is always the user the token belongs to.
41
+ * Naming somebody else as the sender requires a service key, which this SDK
42
+ * never holds.
43
+ */
44
+ export declare function createGrant(client: SublayHttpClient, data: CreateGrantProps): Promise<ReputationGrant>;
45
+ export {};
@@ -0,0 +1,2 @@
1
+ export { createGrant } from "./createGrant";
2
+ export { listGrants } from "./listGrants";
@@ -0,0 +1,45 @@
1
+ import { SublayHttpClient } from "../../core/client";
2
+ import { GrantSummary, ReputationGrant, ReputationGrantTargetFilter } from "../../interfaces/ReputationGrant";
3
+ import { PaginatedResponse } from "../../interfaces/IPaginatedResponse";
4
+ import { SpaceReputationContextParams } from "../../interfaces/SpaceReputation";
5
+ interface ListGrantsBaseProps extends SpaceReputationContextParams {
6
+ page?: number;
7
+ limit?: number;
8
+ /** What this user received. */
9
+ recipientId?: string;
10
+ /** What this user sent. */
11
+ senderId?: string;
12
+ /** Associations to expand. Only `"user"` is supported (hydrates both parties). */
13
+ include?: string;
14
+ }
15
+ /**
16
+ * The third filter shape — "who rewarded this item" — is the
17
+ * {@link ReputationGrantTargetFilter} pair, so a half-filled target is a
18
+ * compile error rather than a `400 reputation-grant/invalid-filter`.
19
+ *
20
+ * Mutual exclusivity between the three shapes is NOT expressed in the type: a
21
+ * three-way exclusive union would multiply out across every pagination and
22
+ * space-reputation field and make the props unreadable, for a rule the server
23
+ * reports clearly. Only the both-or-neither pairing is typed.
24
+ */
25
+ export type ListGrantsProps = ListGrantsBaseProps & ReputationGrantTargetFilter;
26
+ /**
27
+ * The `summary` block rides alongside the page envelope, and only on the
28
+ * target filter shape.
29
+ */
30
+ export interface ListGrantsResponse extends PaginatedResponse<ReputationGrant> {
31
+ summary?: GrantSummary;
32
+ }
33
+ /**
34
+ * Lists reputation grants.
35
+ *
36
+ * Exactly one filter shape per request — `recipientId`, `senderId`, or
37
+ * `targetType` + `targetId`. Supplying none or combining two is a `400`; the
38
+ * shapes are not AND-ed, which is what keeps the `summary` block reconcilable
39
+ * with the rows beneath it.
40
+ *
41
+ * Only positive grants are ever returned. Negative grants are app moderation
42
+ * deductions and are unreadable from every public surface.
43
+ */
44
+ export declare function listGrants(client: SublayHttpClient, data: ListGrantsProps): Promise<ListGrantsResponse>;
45
+ export {};
@@ -7,11 +7,60 @@ export interface CreateWorkspaceInviteProps {
7
7
  username?: string;
8
8
  capabilities?: WorkspaceCapability[];
9
9
  permissions?: string[];
10
- rank: number;
10
+ /**
11
+ * The invited rank, ABSOLUTE — a position on this workspace's ladder (smaller
12
+ * = more senior). The escape hatch, and what tier-constant apps want, since
13
+ * they compute the number anyway.
14
+ *
15
+ * Optional, and mutually exclusive with `relativeRank` — sending both is a
16
+ * 400. Sending NEITHER defaults to `relativeRank: 1`, one rung below the
17
+ * inviter, which is well defined for every actor and can never fail the rank
18
+ * floor.
19
+ *
20
+ * ⚠️ That default is for a NEW invitation. Re-inviting a target who already
21
+ * has a live pending invite updates it in place, and there omitting both rank
22
+ * fields PRESERVES the stored rank instead of re-defaulting it. See the
23
+ * function doc below.
24
+ */
25
+ rank?: number;
26
+ /**
27
+ * The invited rank, RELATIVE to the inviter: `1` = one rung below me, `2` =
28
+ * two rungs below, and so on. The documented happy path — every governance
29
+ * rule about rank is relative, so this is what callers usually mean.
30
+ *
31
+ * Must be `>= 1` on a write. `0` would mean "a peer", which the assign rule
32
+ * forbids (you cannot clone your own authority), and a negative offset would
33
+ * mint someone senior to you; both are a 400. Both rank fields are also capped at `2147483647` (int4), and the RESOLVED sum is bounded too — an in-range anchor plus an in-range offset can still overflow, which is a 400 rather than a 500.
34
+ *
35
+ * The anchor is the inviter's OWN rank if they hold a member row on this
36
+ * workspace, and apex (one step above rank 0) if they do not — so an owner's
37
+ * `relativeRank: 1` lands on rank 0, while a rank-3 member's lands on rank 4.
38
+ *
39
+ * ⚠️ A SNAPSHOT, not a live link: the offset is resolved to an absolute rank
40
+ * once, at invite time, and frozen. It does not track the inviter's later
41
+ * promotions or demotions.
42
+ */
43
+ relativeRank?: number;
11
44
  title?: string | null;
12
45
  }
13
46
  /**
14
47
  * Create an invitation (requires the `invite` capability on the workspace). The
15
48
  * inviter is the bearer-token user.
49
+ *
50
+ * The invited rank comes in either coordinate — `rank` (absolute) or
51
+ * `relativeRank` (an offset from the inviter) — never both. Omitting both
52
+ * defaults to `relativeRank: 1`, one rung below the inviter, which is the
53
+ * documented happy path and can never fail the rank floor.
54
+ *
55
+ * ⚠️ This route doubles as an UPSERT, and the default above applies only to a
56
+ * NEW invitation. Re-inviting a target who already holds a live pending invite
57
+ * refreshes THAT invitation in place — same id, expiry reset — and on that
58
+ * branch an omitted grant field is PRESERVED, not re-defaulted or blanked:
59
+ * `rank`, `capabilities`, `permissions` and `title` all keep their stored
60
+ * values. A "Resend invitation" button that posts only the address therefore
61
+ * cannot silently re-rank the invitee to one below whoever clicked it. An
62
+ * explicit value still overwrites, and an explicit `relativeRank` re-resolves
63
+ * against the CURRENT caller. Full semantics:
64
+ * https://docs.sublay.io/api-reference/workspaces/invitations/create-invite
16
65
  */
17
66
  export declare function createWorkspaceInvite(client: SublayHttpClient, data: CreateWorkspaceInviteProps): Promise<WorkspaceInvitation>;
@@ -7,7 +7,7 @@ export interface DeleteWorkspaceResponse {
7
7
  }
8
8
  /**
9
9
  * Owner-only delete (own owner or an ancestor owner). Cascades the whole
10
- * subtree transactionally. The actor is the bearer-token user — no `userId`
11
- * body is sent.
10
+ * subtree transactionally. The actor is the bearer-token user — no actor
11
+ * field is sent.
12
12
  */
13
13
  export declare function deleteWorkspace(client: SublayHttpClient, data: DeleteWorkspaceProps): Promise<DeleteWorkspaceResponse>;