@xtremax/pigeon 0.0.0-stage → 0.3.1

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 (104) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +68 -2
  3. package/bin/pigeon.mjs +92 -0
  4. package/dist/cjs/browser-stub.js +10 -0
  5. package/dist/cjs/client.js +112 -0
  6. package/dist/cjs/contract.js +5 -0
  7. package/dist/cjs/errors.js +48 -0
  8. package/dist/cjs/events.js +62 -0
  9. package/dist/cjs/idempotency.js +14 -0
  10. package/dist/cjs/inbox/browser-stub.js +10 -0
  11. package/dist/cjs/inbox/client.js +39 -0
  12. package/dist/cjs/inbox/errors.js +44 -0
  13. package/dist/cjs/inbox/handler.js +127 -0
  14. package/dist/cjs/inbox/index.js +15 -0
  15. package/dist/cjs/inbox/origin.js +22 -0
  16. package/dist/cjs/inbox/project.js +84 -0
  17. package/dist/cjs/inbox/validate.js +59 -0
  18. package/dist/cjs/inbox-react/format.js +72 -0
  19. package/dist/cjs/inbox-react/inbox-client.js +63 -0
  20. package/dist/cjs/inbox-react/inbox-context.js +13 -0
  21. package/dist/cjs/inbox-react/inbox-full-list.js +13 -0
  22. package/dist/cjs/inbox-react/inbox-list.js +37 -0
  23. package/dist/cjs/inbox-react/inbox-panel.js +13 -0
  24. package/dist/cjs/inbox-react/inbox-provider.js +157 -0
  25. package/dist/cjs/inbox-react/inbox-state.js +88 -0
  26. package/dist/cjs/inbox-react/index.js +25 -0
  27. package/dist/cjs/inbox-react/labels.js +38 -0
  28. package/dist/cjs/inbox-react/notification-bell.js +32 -0
  29. package/dist/cjs/inbox-react/notification-item.js +17 -0
  30. package/dist/cjs/inbox-react/parse.js +94 -0
  31. package/dist/cjs/inbox-react/preference-dialog.js +49 -0
  32. package/dist/cjs/inbox-react/types.js +4 -0
  33. package/dist/cjs/inbox-react/use-inbox-polling.js +94 -0
  34. package/dist/cjs/index.js +14 -0
  35. package/dist/cjs/package.json +1 -0
  36. package/dist/cjs/retry.js +14 -0
  37. package/dist/esm/browser-stub.js +6 -0
  38. package/dist/esm/client.js +107 -0
  39. package/dist/esm/contract.js +2 -0
  40. package/dist/esm/errors.js +42 -0
  41. package/dist/esm/events.js +57 -0
  42. package/dist/esm/idempotency.js +10 -0
  43. package/dist/esm/inbox/browser-stub.js +7 -0
  44. package/dist/esm/inbox/client.js +35 -0
  45. package/dist/esm/inbox/errors.js +38 -0
  46. package/dist/esm/inbox/handler.js +124 -0
  47. package/dist/esm/inbox/index.js +5 -0
  48. package/dist/esm/inbox/origin.js +19 -0
  49. package/dist/esm/inbox/project.js +76 -0
  50. package/dist/esm/inbox/validate.js +49 -0
  51. package/dist/esm/inbox-react/format.js +64 -0
  52. package/dist/esm/inbox-react/inbox-client.js +58 -0
  53. package/dist/esm/inbox-react/inbox-context.js +9 -0
  54. package/dist/esm/inbox-react/inbox-full-list.js +10 -0
  55. package/dist/esm/inbox-react/inbox-list.js +34 -0
  56. package/dist/esm/inbox-react/inbox-panel.js +10 -0
  57. package/dist/esm/inbox-react/inbox-provider.js +154 -0
  58. package/dist/esm/inbox-react/inbox-state.js +83 -0
  59. package/dist/esm/inbox-react/index.js +18 -0
  60. package/dist/esm/inbox-react/labels.js +34 -0
  61. package/dist/esm/inbox-react/notification-bell.js +29 -0
  62. package/dist/esm/inbox-react/notification-item.js +14 -0
  63. package/dist/esm/inbox-react/parse.js +85 -0
  64. package/dist/esm/inbox-react/preference-dialog.js +46 -0
  65. package/dist/esm/inbox-react/types.js +1 -0
  66. package/dist/esm/inbox-react/use-inbox-polling.js +88 -0
  67. package/dist/esm/index.js +4 -0
  68. package/dist/esm/retry.js +9 -0
  69. package/dist/inbox-react/styles.css +65 -0
  70. package/dist/types/browser-stub.d.ts +4 -0
  71. package/dist/types/client.d.ts +94 -0
  72. package/dist/types/contract.d.ts +182 -0
  73. package/dist/types/errors.d.ts +29 -0
  74. package/dist/types/events.d.ts +26 -0
  75. package/dist/types/idempotency.d.ts +4 -0
  76. package/dist/types/inbox/browser-stub.d.ts +3 -0
  77. package/dist/types/inbox/client.d.ts +34 -0
  78. package/dist/types/inbox/errors.d.ts +13 -0
  79. package/dist/types/inbox/handler.d.ts +25 -0
  80. package/dist/types/inbox/index.d.ts +6 -0
  81. package/dist/types/inbox/origin.d.ts +5 -0
  82. package/dist/types/inbox/project.d.ts +7 -0
  83. package/dist/types/inbox/validate.d.ts +25 -0
  84. package/dist/types/inbox-react/format.d.ts +13 -0
  85. package/dist/types/inbox-react/inbox-client.d.ts +24 -0
  86. package/dist/types/inbox-react/inbox-context.d.ts +29 -0
  87. package/dist/types/inbox-react/inbox-full-list.d.ts +7 -0
  88. package/dist/types/inbox-react/inbox-list.d.ts +12 -0
  89. package/dist/types/inbox-react/inbox-panel.d.ts +2 -0
  90. package/dist/types/inbox-react/inbox-provider.d.ts +18 -0
  91. package/dist/types/inbox-react/inbox-state.d.ts +70 -0
  92. package/dist/types/inbox-react/index.d.ts +19 -0
  93. package/dist/types/inbox-react/labels.d.ts +40 -0
  94. package/dist/types/inbox-react/notification-bell.d.ts +4 -0
  95. package/dist/types/inbox-react/notification-item.d.ts +9 -0
  96. package/dist/types/inbox-react/parse.d.ts +9 -0
  97. package/dist/types/inbox-react/preference-dialog.d.ts +5 -0
  98. package/dist/types/inbox-react/types.d.ts +55 -0
  99. package/dist/types/inbox-react/use-inbox-polling.d.ts +33 -0
  100. package/dist/types/index.d.ts +6 -0
  101. package/dist/types/retry.d.ts +13 -0
  102. package/package.json +34 -4
  103. package/skills/add-pigeon-notifications/SKILL.md +302 -0
  104. package/skills/add-pigeon-notifications/references/inbox-contract.instructions.md +208 -0
@@ -0,0 +1,24 @@
1
+ import type { InboxMarkReadResult, InboxNotificationPage, InboxPreference, InboxReadAllResult, InboxResult, InboxSummary } from './types.js';
2
+ export declare const DEFAULT_API_BASE = "/api/communication/inbox";
3
+ /**
4
+ * The browser talks only to the host xApp's own origin (14.2). The base is a path on that origin: an absolute URL,
5
+ * a protocol-relative one or anything with a query is refused.
6
+ */
7
+ export declare function normalizeApiBase(apiBase: string | undefined): string | null;
8
+ export interface InboxBrowserClient {
9
+ summary(): Promise<InboxResult<InboxSummary>>;
10
+ list(query?: {
11
+ cursor?: string | null;
12
+ unreadOnly?: boolean;
13
+ limit?: number;
14
+ }): Promise<InboxResult<InboxNotificationPage>>;
15
+ markRead(id: string): Promise<InboxResult<InboxMarkReadResult>>;
16
+ markAllRead(upTo?: string | null): Promise<InboxResult<InboxReadAllResult>>;
17
+ getPreference(): Promise<InboxResult<InboxPreference>>;
18
+ setPreference(state: 'opted_in' | 'opted_out'): Promise<InboxResult<InboxPreference>>;
19
+ }
20
+ /**
21
+ * Every call answers a result and never throws, so an outage cannot break the host page (14.9).
22
+ * The bell shows what this xApp's own sub-tenant sent the person, and the tenant's announcements: there is nothing to choose.
23
+ */
24
+ export declare function createInboxBrowserClient(apiBase?: string, fetchImpl?: typeof fetch): InboxBrowserClient;
@@ -0,0 +1,29 @@
1
+ import { type RefObject } from 'react';
2
+ import type { InboxBrowserClient } from './inbox-client.js';
3
+ import type { InboxState } from './inbox-state.js';
4
+ import type { InboxLabels } from './labels.js';
5
+ import type { InboxNotification, InboxTab } from './types.js';
6
+ export interface InboxContextValue {
7
+ state: InboxState;
8
+ labels: InboxLabels;
9
+ locale: string | undefined;
10
+ client: InboxBrowserClient;
11
+ panelOpened: boolean;
12
+ /** The bell, so focus returns to it when the panel or a dialog closes. */
13
+ bellRef: RefObject<HTMLButtonElement | null>;
14
+ openPanel: () => void;
15
+ closePanel: () => void;
16
+ setTab: (tab: InboxTab) => void;
17
+ /** Marks the notification read and opens its link when it has a safe one. */
18
+ select: (item: InboxNotification) => void;
19
+ markAllRead: () => void;
20
+ loadMore: () => void;
21
+ viewAll: () => void;
22
+ openPreferences: () => void;
23
+ retry: () => void;
24
+ clearMessage: () => void;
25
+ /** A visible list calls this on mount and the returned function on unmount; a shown list is kept fresh by the poll. */
26
+ attachList: () => () => void;
27
+ }
28
+ export declare const InboxContext: import("react").Context<InboxContextValue | null>;
29
+ export declare function useInbox(): InboxContextValue;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Every notification, a page at a time. The provider shows it in a dialog for "View all"; a host that passes
3
+ * `onViewAll` can place it on a page of its own instead.
4
+ */
5
+ export declare function InboxFullList({ maxHeight }: {
6
+ maxHeight?: number | string;
7
+ }): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { type ReactNode } from 'react';
2
+ interface InboxListViewProps {
3
+ /** Shown beside "Mark all as read". */
4
+ heading?: ReactNode;
5
+ /** The list scrolls inside this height. */
6
+ maxHeight?: number | string;
7
+ /** Offers older notifications below the list. */
8
+ paged?: boolean;
9
+ }
10
+ /** Tabs, "Mark all as read", the list and its loading, empty and error states. Shared by the panel and the full list. */
11
+ export declare function InboxListView({ heading, maxHeight, paged }: InboxListViewProps): import("react").JSX.Element;
12
+ export {};
@@ -0,0 +1,2 @@
1
+ /** What the bell opens: the newest notifications, with the ways on to the full list and the preference. */
2
+ export declare function InboxPanel(): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type InboxLabels } from './labels.js';
3
+ export interface InboxProviderProps {
4
+ /** A path on the host's own origin. Default `/api/communication/inbox`. */
5
+ apiBase?: string;
6
+ /** Replaces any visible or accessible text. */
7
+ labels?: Partial<InboxLabels>;
8
+ /** Formats relative and exact times. Default: the browser's locale. */
9
+ locale?: string;
10
+ /** Default: opens the built-in full list in a dialog. */
11
+ onViewAll?: () => void;
12
+ /** Default: opens the built-in preference dialog. */
13
+ onOpenPreferences?: () => void;
14
+ /** Default: a new tab with `noopener,noreferrer`. */
15
+ openLink?: (url: string) => void;
16
+ children: ReactNode;
17
+ }
18
+ export declare function InboxProvider({ apiBase, labels, locale, onViewAll, onOpenPreferences, openLink, children }: InboxProviderProps): import("react").JSX.Element;
@@ -0,0 +1,70 @@
1
+ import type { InboxNotification, InboxNotificationPage, InboxSummary, InboxTab } from './types.js';
2
+ export interface InboxState {
3
+ unreadCount: number;
4
+ newestUnreadAt: string | null;
5
+ items: InboxNotification[];
6
+ nextCursor: string | null;
7
+ tab: InboxTab;
8
+ /** `error` only when nothing could be shown; a failed refresh keeps the last data. */
9
+ status: 'idle' | 'loading' | 'error' | 'refreshing';
10
+ /** The current tab has been loaded at least once. */
11
+ loaded: boolean;
12
+ loadingMore: boolean;
13
+ lastSyncedAt: string | null;
14
+ /** Items marked read before the server answered, as they were, so a failure puts them back. */
15
+ pending: Record<string, InboxNotification>;
16
+ /** The list and count as they were before "Mark all as read", until the server answers. */
17
+ markAll: {
18
+ items: InboxNotification[];
19
+ unreadCount: number;
20
+ } | null;
21
+ /** An action failed and was undone. Shown without closing the panel. */
22
+ actionFailed: boolean;
23
+ }
24
+ export declare const initialInboxState: InboxState;
25
+ /** `replace` shows a first page; `append` adds an older page; `merge` refreshes the newest page and keeps older ones already shown. */
26
+ export type PageMode = 'replace' | 'append' | 'merge';
27
+ export type InboxAction = {
28
+ type: 'summaryReceived';
29
+ summary: InboxSummary;
30
+ at: string;
31
+ } | {
32
+ type: 'loadStarted';
33
+ mode: PageMode;
34
+ } | {
35
+ type: 'pageReceived';
36
+ page: InboxNotificationPage;
37
+ mode: PageMode;
38
+ at: string;
39
+ } | {
40
+ type: 'loadFailed';
41
+ mode: PageMode;
42
+ } | {
43
+ type: 'tabChanged';
44
+ tab: InboxTab;
45
+ } | {
46
+ type: 'markReadOptimistic';
47
+ id: string;
48
+ at: string;
49
+ } | {
50
+ type: 'markReadConfirmed';
51
+ id: string;
52
+ notification: InboxNotification;
53
+ unreadCount: number;
54
+ } | {
55
+ type: 'markReadFailed';
56
+ id: string;
57
+ } | {
58
+ type: 'markAllOptimistic';
59
+ at: string;
60
+ } | {
61
+ type: 'markAllConfirmed';
62
+ unreadCount: number;
63
+ } | {
64
+ type: 'markAllFailed';
65
+ } | {
66
+ type: 'messageCleared';
67
+ };
68
+ export declare function inboxReducer(s: InboxState, a: InboxAction): InboxState;
69
+ /** "Mark all as read" is offered only when something is unread and no such request is running (12.8). */
70
+ export declare function canMarkAll(s: InboxState): boolean;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The in-app inbox for an app: a bell with an unread badge, a panel, a full list and the person's preference.
3
+ * The bell shows what this app sent the person, and the tenant's announcements.
4
+ *
5
+ * import { InboxProvider, NotificationBell } from '@xtremax/pigeon/inbox-react';
6
+ * import '@xtremax/pigeon/inbox-react/styles.css';
7
+ *
8
+ * <InboxProvider>
9
+ * <NotificationBell />
10
+ * </InboxProvider>
11
+ *
12
+ * The components call the host app's own routes (default `/api/communication/inbox`), which
13
+ * `createInboxHandler` from `@xtremax/pigeon/inbox` serves. They need React 19, Mantine 8 and Tabler icons. Nothing here holds a key or talks to another origin.
14
+ */
15
+ export { InboxProvider, type InboxProviderProps } from './inbox-provider.js';
16
+ export { NotificationBell } from './notification-bell.js';
17
+ export { InboxFullList } from './inbox-full-list.js';
18
+ export { DEFAULT_INBOX_LABELS, type InboxLabels } from './labels.js';
19
+ export type { InboxNotification, InboxPreference, InboxSummary } from './types.js';
@@ -0,0 +1,40 @@
1
+ /** Every visible and accessible text of the inbox (15.9). Pass `labels` to `InboxProvider` to replace any of them. `{n}` and `{label}` are filled in. */
2
+ export interface InboxLabels {
3
+ /** The bell's accessible name when nothing is unread. */
4
+ bell: string;
5
+ /** The bell's accessible name with a count: "{label}, {n} unread". */
6
+ bellWithCount: string;
7
+ heading: string;
8
+ tabAll: string;
9
+ tabUnread: string;
10
+ /** The Unread tab with its count: "Unread ({n})". */
11
+ tabUnreadWithCount: string;
12
+ markAllRead: string;
13
+ viewAll: string;
14
+ preferences: string;
15
+ emptyAll: string;
16
+ emptyUnread: string;
17
+ loading: string;
18
+ loadError: string;
19
+ retry: string;
20
+ actionError: string;
21
+ dismiss: string;
22
+ /** The accessible name of a dialog's close button. */
23
+ close: string;
24
+ /** Read out before an unread row, so unread is not shown by colour alone. */
25
+ unread: string;
26
+ announcement: string;
27
+ loadMore: string;
28
+ /** Announced when the count rises while the panel is closed. */
29
+ newOne: string;
30
+ newMany: string;
31
+ fullListTitle: string;
32
+ preferencesTitle: string;
33
+ preferenceToggle: string;
34
+ preferenceOn: string;
35
+ preferenceOff: string;
36
+ preferenceLoadError: string;
37
+ preferenceSaveError: string;
38
+ }
39
+ export declare const DEFAULT_INBOX_LABELS: InboxLabels;
40
+ export declare function mergeLabels(labels?: Partial<InboxLabels>): InboxLabels;
@@ -0,0 +1,4 @@
1
+ /** The bell with its unread badge. Opens the inbox panel. Place it inside `InboxProvider`. */
2
+ export declare function NotificationBell({ size }: {
3
+ size?: number;
4
+ }): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import type { InboxNotification } from './types.js';
2
+ /**
3
+ * One notification. The whole row is one button: selecting it marks the notification read and opens its link when
4
+ * it has a safe one. Title and body are text nodes, never markup (12.14).
5
+ */
6
+ export declare function NotificationItem({ item, now }: {
7
+ item: InboxNotification;
8
+ now: Date;
9
+ }): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { type InboxErrorCode, type InboxMarkReadResult, type InboxNotification, type InboxNotificationPage, type InboxPreference, type InboxReadAllResult, type InboxSummary } from './types.js';
2
+ export declare function parseNotification(v: unknown): InboxNotification | null;
3
+ export declare function parseSummary(v: unknown): InboxSummary | null;
4
+ export declare function parsePage(v: unknown): InboxNotificationPage | null;
5
+ export declare function parseMarkRead(v: unknown): InboxMarkReadResult | null;
6
+ export declare function parseReadAll(v: unknown): InboxReadAllResult | null;
7
+ export declare function parsePreference(v: unknown): InboxPreference | null;
8
+ /** The code of an error body, or the nearest one for the status. Anything unknown is `unavailable`. */
9
+ export declare function parseErrorCode(status: number, body: unknown): InboxErrorCode;
@@ -0,0 +1,5 @@
1
+ /** The person's own choice for this app's in-app notifications. Other apps are not affected. */
2
+ export declare function PreferenceDialog({ opened, onClose }: {
3
+ opened: boolean;
4
+ onClose: () => void;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The inbox formats as the component reads them (IB-2). This module imports nothing from the SDK or the Gateway:
3
+ * it talks only to the host xApp's own routes.
4
+ */
5
+ export interface InboxNotification {
6
+ id: string;
7
+ kind: 'notification' | 'announcement';
8
+ /** Plain text. Never rendered as markup. */
9
+ title: string;
10
+ body: string;
11
+ /** Absolute https, or null. */
12
+ link: string | null;
13
+ source: {
14
+ type: 'xapp' | 'tenant';
15
+ name: string;
16
+ };
17
+ createdAt: string;
18
+ read: boolean;
19
+ readAt: string | null;
20
+ }
21
+ export interface InboxSummary {
22
+ unreadCount: number;
23
+ newestUnreadAt: string | null;
24
+ pollSeconds: number;
25
+ }
26
+ export interface InboxNotificationPage {
27
+ notifications: InboxNotification[];
28
+ nextCursor: string | null;
29
+ unreadCount: number;
30
+ }
31
+ export interface InboxPreference {
32
+ state: 'opted_in' | 'opted_out' | 'not_set';
33
+ changedAt: string | null;
34
+ delivers: boolean;
35
+ }
36
+ export interface InboxMarkReadResult {
37
+ notification: InboxNotification;
38
+ unreadCount: number;
39
+ }
40
+ export interface InboxReadAllResult {
41
+ marked: number;
42
+ remaining: number;
43
+ unreadCount: number;
44
+ }
45
+ /** The six answers of the host routes (IB-8). */
46
+ export type InboxErrorCode = 'not_signed_in' | 'not_permitted' | 'not_found' | 'invalid_input' | 'rate_limited' | 'unavailable';
47
+ export declare const INBOX_ERROR_CODES: readonly InboxErrorCode[];
48
+ export type InboxResult<T> = {
49
+ ok: true;
50
+ data: T;
51
+ } | {
52
+ ok: false;
53
+ code: InboxErrorCode;
54
+ };
55
+ export type InboxTab = 'all' | 'unread';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Visibility-aware polling (13.1 to 13.9). This is the only file a push transport would replace.
3
+ * No realtime connection and no web storage are used.
4
+ */
5
+ export type PollOutcome = {
6
+ result: 'ok';
7
+ pollSeconds: number;
8
+ } | {
9
+ result: 'failed';
10
+ } | {
11
+ result: 'stop';
12
+ };
13
+ export declare const POLL_FLOOR_SECONDS = 15;
14
+ export declare const POLL_CAP_SECONDS = 300;
15
+ /**
16
+ * Seconds until the next poll. After a success: the recommended interval, at least 15. After failures:
17
+ * `min(300, base * 2^failures)` with plus or minus 20 percent jitter, still between 15 and 300.
18
+ */
19
+ export declare function nextPollDelay(failures: number, recommendedSeconds: number, random?: () => number): number;
20
+ export interface PollingEnvironment {
21
+ isVisible: () => boolean;
22
+ onVisibilityChange: (listener: () => void) => () => void;
23
+ setTimer: (fn: () => void, ms: number) => unknown;
24
+ clearTimer: (handle: unknown) => void;
25
+ random: () => number;
26
+ }
27
+ /**
28
+ * Polls now, then after each answer waits `nextPollDelay`. Pauses while the page is hidden and polls at once when it
29
+ * is visible again. `stop` (nobody is signed in) ends polling silently. Returns a function that stops it.
30
+ */
31
+ export declare function startPolling(poll: () => Promise<PollOutcome>, env: PollingEnvironment): () => void;
32
+ /** Runs `poll` for as long as the component is mounted and `enabled` is true. `poll` may change between renders. */
33
+ export declare function useInboxPolling(poll: () => Promise<PollOutcome>, enabled?: boolean): void;
@@ -0,0 +1,6 @@
1
+ export { createCommunicationClient, CommunicationError, type ClientOptions, type CommunicationClient } from './client.js';
2
+ export { createEventHandler, verifyEventSignature, type EventHandlerOptions, type VerifyResult } from './events.js';
3
+ export { deriveIdempotencyKey, newIdempotencyKey } from './idempotency.js';
4
+ export { DEFAULT_RETRY, type RetryPolicy } from './retry.js';
5
+ export type * from './contract.js';
6
+ export type { ErrorCode } from './errors.js';
@@ -0,0 +1,13 @@
1
+ export interface RetryPolicy {
2
+ maxAttempts: number;
3
+ baseDelayMs: number;
4
+ capDelayMs: number;
5
+ /** Total time across attempts and waits. */
6
+ totalTimeoutMs: number;
7
+ perAttemptTimeoutMs: number;
8
+ }
9
+ export declare const DEFAULT_RETRY: RetryPolicy;
10
+ /** Exponential backoff with full jitter, honouring Retry-After when the server sent one. */
11
+ export declare function backoffMs(attempt: number, policy: RetryPolicy, retryAfterSeconds: number | null, random?: () => number): number;
12
+ /** Only transient failures are retried: network errors, timeouts, 429 and 5xx. Client errors never are. */
13
+ export declare const isRetryableStatus: (status: number) => boolean;
package/package.json CHANGED
@@ -1,6 +1,36 @@
1
1
  {
2
2
  "name": "@xtremax/pigeon",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.3.1",
4
+ "description": "Client for Pigeon, the Buildpad Communication Gateway: send messages, verify signed events, serve an in-app inbox and show its notification bell.",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "sideEffects": ["**/*.css"],
8
+ "engines": { "node": ">=20" },
9
+ "main": "./dist/cjs/index.js",
10
+ "module": "./dist/esm/index.js",
11
+ "types": "./dist/types/index.d.ts",
12
+ "exports": {
13
+ ".": { "browser": "./dist/esm/browser-stub.js", "types": "./dist/types/index.d.ts", "import": "./dist/esm/index.js", "require": "./dist/cjs/index.js" },
14
+ "./client": { "browser": "./dist/esm/browser-stub.js", "types": "./dist/types/client.d.ts", "import": "./dist/esm/client.js", "require": "./dist/cjs/client.js" },
15
+ "./inbox": { "browser": "./dist/esm/inbox/browser-stub.js", "types": "./dist/types/inbox/index.d.ts", "import": "./dist/esm/inbox/index.js", "require": "./dist/cjs/inbox/index.js" },
16
+ "./inbox-react": { "types": "./dist/types/inbox-react/index.d.ts", "import": "./dist/esm/inbox-react/index.js", "require": "./dist/cjs/inbox-react/index.js" },
17
+ "./inbox-react/styles.css": "./dist/inbox-react/styles.css",
18
+ "./events": { "types": "./dist/types/events.d.ts", "import": "./dist/esm/events.js", "require": "./dist/cjs/events.js" },
19
+ "./contract": { "types": "./dist/types/contract.d.ts" }
20
+ },
21
+ "bin": { "pigeon": "./bin/pigeon.mjs" },
22
+ "files": ["dist", "bin", "skills", "README.md", "CHANGELOG.md"],
23
+ "scripts": {
24
+ "build": "node scripts/build.mjs",
25
+ "prepublishOnly": "node scripts/build.mjs"
26
+ },
27
+ "publishConfig": { "access": "public" },
28
+ "peerDependencies": { "@mantine/core": "^8", "@mantine/hooks": "^8", "@tabler/icons-react": "^3", "react": "^19" },
29
+ "peerDependenciesMeta": {
30
+ "@mantine/core": { "optional": true },
31
+ "@mantine/hooks": { "optional": true },
32
+ "@tabler/icons-react": { "optional": true },
33
+ "react": { "optional": true }
34
+ },
35
+ "devDependencies": { "@types/node": "^20", "typescript": "^5" }
36
+ }