@flow-industries/id 0.20.0 → 0.21.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.
@@ -1,5 +1,5 @@
1
1
  export { defaultIdHost, isLocalHostname } from "../id-host";
2
- export type { AccessKeyOptions, ActionCatalogEntry, ActionCatalogResponse, ActionCurve, ActionEventRequest, ActionEventResponse, ActionSubjectRef, ActionSurface, ActionsApi, ActionTransitionKind, ActiveActionResponse, ActiveSessionConflict, AdditionalSession, Address, ConnectCapabilities, ConnectResponse, CreateFlowOptions, CreateStudySubjectInput, DialogHost, FinishActionRequest, FinishActionResponse, Flow, FlowCredential, FlowSessionState, FlowState, FlowUser, FlowWidgetHandle, FlowWidgetName, ListStudySubjectsOptions, LoginOptions, MethodName, MountFlowWidgetOptions, MountProfileOptions, OpenProfileOptions, ProfileButtonHandle, ProfilePosition, Session, StartActionInput, StartActionResponse, StartActionResult, StudyApi, StudyCatalog, StudyCategory, StudyField, StudySubject, StudySubjectList, StudySubjectRefusal, StudySubjectRemovalResponse, StudySubjectResponse, UpdateStudySubjectInput, UserActionSurface, XpEstimateContext, XpMode, } from "../types";
2
+ export type { AccessKeyOptions, ActionCatalogEntry, ActionCatalogResponse, ActionCurve, ActionEventRequest, ActionEventResponse, ActionSubjectRef, ActionSurface, ActionsApi, ActionTransitionKind, ActiveActionResponse, ActiveSessionConflict, AdditionalSession, Address, ConnectCapabilities, ConnectResponse, CreateFlowOptions, CreateStudySubjectInput, CurrentAction, DialogHost, FinishActionRequest, FinishActionResponse, Flow, FlowCredential, FlowSessionState, FlowState, FlowUser, FlowWidgetHandle, FlowWidgetName, ListStudySessionsOptions, ListStudySubjectsOptions, LoginOptions, MethodName, MountFlowWidgetOptions, MountProfileOptions, OpenProfileOptions, ProfileButtonHandle, ProfilePosition, RoomMemberEntry, Session, StartActionInput, StartActionResponse, StartActionResult, StudyApi, StudyCatalog, StudyCategory, StudyCategoryTotals, StudyField, StudyRange, StudySessionEntry, StudySessionPage, StudySubject, StudySubjectList, StudySubjectRefusal, StudySubjectRemovalResponse, StudySubjectResponse, StudySubjectTotals, StudySummary, UpdateStudySubjectInput, UserActionSurface, XpEstimateContext, XpMode, } from "../types";
3
3
  export { consistencyCurve, estimateActionXp, FLOW_SCORE_MAX, flowMultiplier, } from "../xp/curve";
4
4
  export { ActionsRequestError, createActionsApi, isActiveSessionConflict, } from "./actions";
5
5
  export { createFlow, getFlow, requireFlow, resetFlow } from "./create-flow";
@@ -8,9 +8,10 @@ export declare class StudyRequestError extends Error {
8
8
  constructor(status: number, message: string, reason?: string | undefined);
9
9
  }
10
10
  /**
11
- * Thin typed client for the study catalog and the caller's study subjects,
12
- * bound to a host and the Flow token supplier. The catalog is public and
13
- * long-cached by the browser; the subject routes attach the caller's bearer
14
- * and fail fast with a 401-shaped error when no session exists.
11
+ * Thin typed client for the study catalog, the caller's study subjects and
12
+ * their finished study time, bound to a host and the Flow token supplier. The
13
+ * catalog is public and long-cached by the browser; every other route attaches
14
+ * the caller's bearer and fails fast with a 401-shaped error when no session
15
+ * exists.
15
16
  */
16
17
  export declare function createStudyApi(host: string, getToken: () => Promise<string | null>): StudyApi;
@@ -13,10 +13,11 @@ export class StudyRequestError extends Error {
13
13
  }
14
14
  }
15
15
  /**
16
- * Thin typed client for the study catalog and the caller's study subjects,
17
- * bound to a host and the Flow token supplier. The catalog is public and
18
- * long-cached by the browser; the subject routes attach the caller's bearer
19
- * and fail fast with a 401-shaped error when no session exists.
16
+ * Thin typed client for the study catalog, the caller's study subjects and
17
+ * their finished study time, bound to a host and the Flow token supplier. The
18
+ * catalog is public and long-cached by the browser; every other route attaches
19
+ * the caller's bearer and fails fast with a 401-shaped error when no session
20
+ * exists.
20
21
  */
21
22
  export function createStudyApi(host, getToken) {
22
23
  const api = createJsonApi(host, "/api/study", getToken, (status, message, reason) => new StudyRequestError(status, message, reason));
@@ -38,5 +39,17 @@ export function createStudyApi(host, getToken) {
38
39
  method: "DELETE",
39
40
  authRequired: true,
40
41
  }),
42
+ summary: (range) => api.request(`/summary?${new URLSearchParams({ range: range ?? "today" })}`, { authRequired: true }),
43
+ sessions: (options) => {
44
+ const params = new URLSearchParams({ subject: options.subject });
45
+ if (options.before !== undefined)
46
+ params.set("before", options.before);
47
+ if (options.limit !== undefined) {
48
+ params.set("limit", String(options.limit));
49
+ }
50
+ return api.request(`/sessions?${params}`, {
51
+ authRequired: true,
52
+ });
53
+ },
41
54
  };
42
55
  }
@@ -2,7 +2,7 @@
2
2
  * `createStudyApi` and `useActiveAction` take and return. The wire shapes
3
3
  * themselves live in `./xp` and `./study`; this file only names the client
4
4
  * inputs and the composed results a consumer app programs against. */
5
- import type { CreateStudySubjectInput, StudyCatalog, StudySubject, StudySubjectList, StudySubjectRemovalResponse, UpdateStudySubjectInput } from "./study";
5
+ import type { CreateStudySubjectInput, StudyCatalog, StudyRange, StudySessionPage, StudySubject, StudySubjectList, StudySubjectRemovalResponse, StudySummary, UpdateStudySubjectInput } from "./study";
6
6
  import type { ActionCatalogEntry, ActionCatalogResponse, ActionTransitionKind, ActiveActionResponse, ActiveSessionConflict, FinishActionResponse, StartActionResponse, UserActionSurface } from "./xp";
7
7
  /** The curve parameters `estimateActionXp` reads. A catalog entry satisfies
8
8
  * it, and so does the server's own registry descriptor, so the widget and a
@@ -61,6 +61,17 @@ export interface ListStudySubjectsOptions {
61
61
  /** Include archived subjects after the live ones. */
62
62
  archived?: boolean;
63
63
  }
64
+ /** Query of GET /api/study/sessions as the SDK takes it: one subject's
65
+ * finished sessions, newest first. Feed a page's `nextBefore` back as
66
+ * `before` until it is null. */
67
+ export interface ListStudySessionsOptions {
68
+ /** The subject's id; an archived subject is readable too. */
69
+ subject: string;
70
+ /** ISO instant; only sessions started strictly before it are listed. */
71
+ before?: string;
72
+ /** 1..100; the server defaults to 50. */
73
+ limit?: number;
74
+ }
64
75
  /** Envelope of every single-subject study route. */
65
76
  export interface StudySubjectResponse {
66
77
  subject: StudySubject;
@@ -72,6 +83,10 @@ export interface StudyApi {
72
83
  createSubject(input: CreateStudySubjectInput): Promise<StudySubjectResponse>;
73
84
  updateSubject(id: string, patch: UpdateStudySubjectInput): Promise<StudySubjectResponse>;
74
85
  deleteSubject(id: string): Promise<StudySubjectRemovalResponse>;
86
+ /** Finished study time per subject and category; `range` defaults to
87
+ * `today`. The running session is absent: add `/api/actions/me` live. */
88
+ summary(range?: StudyRange): Promise<StudySummary>;
89
+ sessions(options: ListStudySessionsOptions): Promise<StudySessionPage>;
75
90
  }
76
91
  export type UseActiveActionOptions = {
77
92
  /** Override the Flow ID origin; defaults to the resolved Flow's `host`. */
@@ -1,4 +1,4 @@
1
- export type { ActionCurve, ActionEventRequest, ActionEventResponse, ActionsApi, ActiveActionState, FinishActionRequest, ListStudySubjectsOptions, StartActionInput, StartActionResult, StudyApi, StudySubjectResponse, UseActiveActionOptions, XpEstimateContext, } from "./actions";
1
+ export type { ActionCurve, ActionEventRequest, ActionEventResponse, ActionsApi, ActiveActionState, FinishActionRequest, ListStudySessionsOptions, ListStudySubjectsOptions, StartActionInput, StartActionResult, StudyApi, StudySubjectResponse, UseActiveActionOptions, XpEstimateContext, } from "./actions";
2
2
  export type { AccountSession, AccountSessionsResponse, AdditionalSession, AuthConfig, AuthResponse, AuthResponseWithWebAuthn, BioNormalization, BioRejection, BioWriteRefusal, BioWriteResult, FlowCredential, FlowUser, PasskeyPluginOptions, RevokeAllSessionsResponse, RevokeSessionResponse, SecurityActivityEntry, SecurityActivityResponse, SessionUser, VerifiedFlowJWT, VerifyOptions, WebAuthnSignature, } from "./auth";
3
3
  export type { BodyRegion, CosmeticItem, CosmeticMaterial, CosmeticPaint, CosmeticSlot, EquipConflict, EquippedCosmetic, EquippedCosmetics, EquipRegion, PaintSlot, SettingsConflict, } from "./cosmetics";
4
4
  export { BODY_REGIONS, COSMETIC_MATERIALS } from "./cosmetics";
@@ -13,6 +13,6 @@ export type { CreateRoomEventInput, RoomEventArchive, RoomEventAttendance, RoomE
13
13
  export type { CreateRoomInput, GlobalRole, ModerationSubject, MyRooms, PlayerPositionReport, RoleChangeVerdict, RoomCapabilities, RoomCapability, RoomChannel, RoomDetail, RoomList, RoomMemberEntry, RoomMembers, RoomOccupancy, RoomOwner, RoomPlayerPosition, RoomPresenceEntry, RoomPresenceSnapshot, RoomRestrictionKind, RoomRole, RoomSummary, RoomSurfaceSettings, RoomsApi, RoomVisibility, StaffEntry, UpdateRoomInput, VerifyRoomContext, Viewer, VoiceDecisionReason, VoiceDecisionSubject, VoiceRoomDecision, } from "./rooms";
14
14
  export type { AccessKeyOptions, AccessKeyPreparation, Address, ColorScheme, CreateDialogHostOptions, CreateFlowOptions, DialogHost, DialogOpenOptions, FinalizeAccessKeyParams, Flow, FlowConnectorParameters, FlowCookieNames, FlowIdProviderProps, FlowSessionState, FlowState, FlowWidgetHandle, FlowWidgetName, FlowWidgetProps, Listener, LoginOptions, MountFlowWidgetOptions, MountProfileOptions, OpenProfileOptions, PrepareArgsWithAuth, PrepareTransactionRequestPhase, ProfileButtonHandle, ProfileButtonProps, ProfilePosition, ResolveAccountParams, ResolvedAccessKeyOptions, RootCredential, RunLoginParams, RunLoginResult, SendCallsArgs, SendTransactionArgs, Session, SigningContext, SignMessageArgs, SignTypedDataArgs, Store, StoredAccessKey, UseOpenProfileOptions, WagmiConnectCapabilities, WagmiConnectParams, } from "./sdk";
15
15
  export type { GracefulShutdownCleanup, GracefulShutdownOptions, GracefulShutdownServer, GracefulShutdownSignal, ResolvedFlowSession, ResolveSessionOptions, SessionRouteOptions, SessionRouteResponse, SessionRouteSession, } from "./server";
16
- export type { CreateStudySubjectInput, StudyCatalog, StudyCategory, StudyField, StudySubject, StudySubjectCreation, StudySubjectList, StudySubjectRefusal, StudySubjectRemoval, StudySubjectRemovalResponse, StudySubjectUpdate, UpdateStudySubjectInput, } from "./study";
16
+ export type { CreateStudySubjectInput, ListStudySessionsInput, StudyCatalog, StudyCategory, StudyCategoryTotals, StudyField, StudyRange, StudySessionEntry, StudySessionPage, StudySessionsResult, StudySubject, StudySubjectCreation, StudySubjectList, StudySubjectRefusal, StudySubjectRemoval, StudySubjectRemovalResponse, StudySubjectTotals, StudySubjectUpdate, StudySummary, UpdateStudySubjectInput, } from "./study";
17
17
  export type { CoinAsset, IdentifiedTx, TxApprove, TxConvert, TxSend, TxSwap, } from "./tx";
18
- export type { ActionCatalogEntry, ActionCatalogResponse, ActionDayContext, ActionEventKind, ActionSessionState, ActionSubjectRef, ActionSurface, ActionTransitionKind, ActiveActionResponse, ActiveSessionConflict, FinishActionResponse, LevelProgress, PublicProfile, PublicProfileRefusal, PublicProfileResult, PublicProfileSignal, PublicUserProfile, StartActionResponse, StartUserSessionResult, UserActionSurface, XpGrantResult, XpMode, XpRecentGrant, XpSummary, } from "./xp";
18
+ export type { ActionCatalogEntry, ActionCatalogResponse, ActionDayContext, ActionEventKind, ActionSessionState, ActionSubjectRef, ActionSurface, ActionTransitionKind, ActiveActionResponse, ActiveSessionConflict, CurrentAction, FinishActionResponse, LevelProgress, PublicProfile, PublicProfileRefusal, PublicProfileResult, PublicProfileSignal, PublicUserProfile, StartActionResponse, StartUserSessionResult, UserActionSurface, XpGrantResult, XpMode, XpRecentGrant, XpSummary, } from "./xp";
@@ -1,4 +1,5 @@
1
1
  import type { RawRecord } from "../json";
2
+ import type { CurrentAction } from "./xp";
2
3
  /** Room registry types shared by the server routes and the client SDK. */
3
4
  export type RoomVisibility = "public" | "unlisted" | "private";
4
5
  /**
@@ -93,6 +94,16 @@ export interface RoomMemberEntry {
93
94
  * producers omit it; this one because a whole deployment might.
94
95
  */
95
96
  isGuest?: boolean;
97
+ /**
98
+ * The member's active action session as the roster may show it — "Studying",
99
+ * "Meditating" — or `null` when they have none. The subject rides inside
100
+ * only when that member shares it (`study.share_subject`).
101
+ *
102
+ * Optional for the reason `isGuest` is: this server always sends it, but a
103
+ * server older than the field omits it, and `undefined` must read as
104
+ * "unknown" rather than as "idle".
105
+ */
106
+ currentAction?: CurrentAction | null;
96
107
  role: RoomRole;
97
108
  joinedAt: string;
98
109
  }
@@ -1,4 +1,5 @@
1
1
  /** Study catalog and study-subject shapes that cross the server/SDK boundary. */
2
+ import type { ActionSubjectRef, ActionSurface } from "./xp";
2
3
  /**
3
4
  * One predefined thing a person can study. `slug` is `category/field`,
4
5
  * lowercase ASCII and stable forever — it is what a subject row stores and
@@ -86,3 +87,68 @@ export type StudySubjectRemoval = {
86
87
  export type StudySubjectRemovalResponse = Extract<StudySubjectRemoval, {
87
88
  ok: true;
88
89
  }>;
90
+ /** The window GET /api/study/summary totals over. Days are UTC calendar days,
91
+ * like the XP curve's: `today` is since UTC midnight, `7d` and `30d` are the
92
+ * 7 and 30 UTC days ending today, `all` is unbounded. */
93
+ export type StudyRange = "today" | "7d" | "30d" | "all";
94
+ /** One subject's finished study time in a range. `lastAt` is the start of
95
+ * the most recent session counted. The subject resolves whether or not it has
96
+ * since been archived, so history keeps its name. */
97
+ export interface StudySubjectTotals {
98
+ subject: ActionSubjectRef;
99
+ seconds: number;
100
+ focusedSeconds: number;
101
+ sessions: number;
102
+ lastAt: string;
103
+ }
104
+ /** One catalog category's finished study time in a range: the sum over every
105
+ * subject whose `field` is that category or one of its fields. */
106
+ export interface StudyCategoryTotals {
107
+ slug: string;
108
+ label: string;
109
+ seconds: number;
110
+ }
111
+ /**
112
+ * Response of GET /api/study/summary: finished `action.study` sessions only,
113
+ * summed from the durations materialized at finish. `subjects` and
114
+ * `categories` are ordered by seconds descending. Sessions without a subject
115
+ * (a game Study started while the user had none) count in `total` only.
116
+ */
117
+ export interface StudySummary {
118
+ range: StudyRange;
119
+ subjects: StudySubjectTotals[];
120
+ categories: StudyCategoryTotals[];
121
+ total: {
122
+ seconds: number;
123
+ sessions: number;
124
+ };
125
+ }
126
+ /** One finished study session as GET /api/study/sessions lists it. */
127
+ export interface StudySessionEntry {
128
+ sessionId: string;
129
+ startedAt: string;
130
+ finishedAt: string;
131
+ seconds: number;
132
+ focusedSeconds: number;
133
+ xpGranted: number;
134
+ surface: ActionSurface;
135
+ }
136
+ /** Response of GET /api/study/sessions: newest first, `nextBefore` is the
137
+ * `before` of the next page or null on the last one. */
138
+ export interface StudySessionPage {
139
+ sessions: StudySessionEntry[];
140
+ nextBefore: string | null;
141
+ }
142
+ export interface ListStudySessionsInput {
143
+ subjectId: string;
144
+ /** Exclusive upper bound on `startedAt`; omit for the newest page. */
145
+ before?: Date;
146
+ limit: number;
147
+ }
148
+ export type StudySessionsResult = {
149
+ ok: true;
150
+ page: StudySessionPage;
151
+ } | {
152
+ ok: false;
153
+ reason: "not_found";
154
+ };
@@ -195,3 +195,20 @@ export type PublicProfileResult = {
195
195
  reason: PublicProfileRefusal;
196
196
  signal: PublicProfileSignal;
197
197
  };
198
+ /**
199
+ * What a user is doing right now, as OTHER users see it — the room roster's
200
+ * view of an active `action_session`, not the owner's own
201
+ * {@link ActiveActionResponse}. Deliberately narrower: no clock, no XP
202
+ * context, no session id, because a reader has no session to drive. `label`
203
+ * is `null` for a source the registry no longer names, exactly as the owner's
204
+ * view reports it. `subject` is the study subject's name and is present only
205
+ * while the owner's `study.share_subject` setting is on — the subject is their
206
+ * own words ("Bar exam prep"), so its absence is the default, not a gap.
207
+ */
208
+ export interface CurrentAction {
209
+ source: string;
210
+ label: string | null;
211
+ /** ISO timestamp of the session's start. */
212
+ since: string;
213
+ subject?: string;
214
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flow-industries/id",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",