@luckystack/core 0.10.2 → 0.12.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 (134) hide show
  1. package/AGENTS.md +11 -0
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +2 -88
  4. package/dist/apiInterceptors.d.ts +36 -0
  5. package/dist/apiMethodMapRegistry.d.ts +5 -0
  6. package/dist/apiRequest.d.ts +71 -0
  7. package/dist/apiTypeStubs.d.ts +3 -5
  8. package/dist/avatarConfig.d.ts +22 -0
  9. package/dist/bindAddress.d.ts +15 -0
  10. package/dist/bootUuid.d.ts +24 -0
  11. package/dist/cancelRegistry.d.ts +7 -0
  12. package/dist/checkOrigin.d.ts +6 -0
  13. package/dist/{chunk-IJYNVM2W.js → chunk-P3SSLA3E.js} +2 -2
  14. package/dist/chunk-P3SSLA3E.js.map +1 -0
  15. package/dist/{chunk-5FXBTGYL.js → chunk-XDX5MV54.js} +2 -2
  16. package/dist/chunk-XDX5MV54.js.map +1 -0
  17. package/dist/client.d.ts +46 -335
  18. package/dist/client.js +5 -5
  19. package/dist/client.js.map +1 -1
  20. package/dist/clientHookBus.d.ts +62 -0
  21. package/dist/clients.d.ts +16 -0
  22. package/dist/config.d.ts +8 -2
  23. package/dist/configUtils.d.ts +16 -0
  24. package/dist/consoleLog.d.ts +1 -0
  25. package/dist/cookies.d.ts +28 -0
  26. package/dist/createRegistry.d.ts +39 -0
  27. package/dist/csrf.d.ts +30 -0
  28. package/dist/csrfConfig.d.ts +32 -0
  29. package/dist/db.d.ts +12 -0
  30. package/dist/dbHealthCheck.d.ts +6 -0
  31. package/dist/{config-CwW3KY9r.d.ts → deployConfigRegistry.d.ts} +8 -43
  32. package/dist/emailRegistry.d.ts +139 -0
  33. package/dist/env.d.ts +38 -0
  34. package/dist/errorFormatterRegistry.d.ts +54 -0
  35. package/dist/errorTrackerIdentity.d.ts +14 -0
  36. package/dist/errorTrackerRegistry.d.ts +85 -0
  37. package/dist/escapeHtml.d.ts +6 -0
  38. package/dist/eslint/index.d.ts +5 -8
  39. package/dist/eslint/index.js +125 -8
  40. package/dist/eslint/index.js.map +1 -1
  41. package/dist/eslint/internal/hasPackage.d.ts +1 -0
  42. package/dist/eslint/internal/ruleTypes.d.ts +4 -0
  43. package/dist/eslint/rules/no-arbitrary-tailwind-color.d.ts +3 -0
  44. package/dist/eslint/rules/no-direct-prisma-import-in-components.d.ts +3 -0
  45. package/dist/eslint/rules/no-local-socket-enumeration.d.ts +3 -0
  46. package/dist/eslint/rules/no-raw-fetch-in-src.d.ts +3 -0
  47. package/dist/eslint/rules/no-raw-try-catch.d.ts +3 -0
  48. package/dist/eslint/rules/no-unsafe-api-wrappers.d.ts +3 -0
  49. package/dist/eslint/rules/no-unsafe-sync-wrappers.d.ts +3 -0
  50. package/dist/eslint/rules/no-untranslated-jsx-text.d.ts +4 -0
  51. package/dist/eslint/rules/prefer-luckystack-confirm.d.ts +3 -0
  52. package/dist/eslint/rules/prefer-luckystack-dropdown.d.ts +3 -0
  53. package/dist/eslint/rules/prefer-luckystack-notify.d.ts +3 -0
  54. package/dist/extractToken.d.ts +12 -0
  55. package/dist/extractTokenFromRequest.d.ts +12 -0
  56. package/dist/getParams.d.ts +9 -0
  57. package/dist/hooks/registry.d.ts +12 -0
  58. package/dist/hooks/types.d.ts +446 -0
  59. package/dist/httpApiUtils.d.ts +54 -0
  60. package/dist/index.d.ts +110 -1892
  61. package/dist/index.js +2 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/lease.d.ts +18 -0
  64. package/dist/localSocketEnumerationGuard.d.ts +22 -0
  65. package/dist/localeReloader.d.ts +3 -0
  66. package/dist/localesRegistry.d.ts +8 -0
  67. package/dist/localizedNormalizer.d.ts +50 -0
  68. package/dist/loggerRegistry.d.ts +12 -0
  69. package/dist/middlewareRegistry.d.ts +45 -0
  70. package/dist/notifier.d.ts +17 -0
  71. package/dist/offlineQueue.d.ts +48 -0
  72. package/dist/oneTimeToken.d.ts +43 -0
  73. package/dist/pageRouteValidation.d.ts +37 -0
  74. package/dist/paths.d.ts +35 -0
  75. package/dist/peerDeps.d.ts +23 -0
  76. package/dist/portOverrideRegistry.d.ts +3 -0
  77. package/dist/processUpload.d.ts +44 -0
  78. package/dist/{sessionTypes-DanjuPaE.d.ts → projectConfig.d.ts} +32 -129
  79. package/dist/rateLimiter.d.ts +90 -0
  80. package/dist/react/AvatarProvider.d.ts +11 -0
  81. package/dist/react/Middleware.d.ts +10 -0
  82. package/dist/react/Router.d.ts +1 -0
  83. package/dist/react/TranslationProvider.d.ts +22 -0
  84. package/dist/react/notify.d.ts +12 -0
  85. package/dist/react/sessionContext.d.ts +31 -0
  86. package/dist/react/useTheme.d.ts +5 -0
  87. package/dist/redactedLogKeys.d.ts +22 -0
  88. package/dist/redis.d.ts +15 -0
  89. package/dist/redisKeyFormatter.d.ts +7 -0
  90. package/dist/resolveClientIp.d.ts +51 -0
  91. package/dist/responseNormalizer.d.ts +33 -0
  92. package/dist/roomNameFormatterRegistry.d.ts +36 -0
  93. package/dist/roomSockets.d.ts +23 -0
  94. package/dist/routedDataQuery.d.ts +7 -0
  95. package/dist/routedHttpInvocation.d.ts +20 -0
  96. package/dist/runtimeMapsRegistry.d.ts +18 -0
  97. package/dist/runtimeTypeValidation.d.ts +13 -0
  98. package/dist/secretsResolved.d.ts +3 -0
  99. package/dist/{sentrySetup-HNIURVUZ.js → sentrySetup-OLZ4BO7Q.js} +2 -2
  100. package/dist/sentrySetup.d.ts +21 -0
  101. package/dist/serveAvatars.d.ts +5 -0
  102. package/dist/serviceRoute.d.ts +27 -0
  103. package/dist/servicesConfigRegistry.d.ts +22 -0
  104. package/dist/sessionProviderRegistry.d.ts +46 -0
  105. package/dist/sessionTypes.d.ts +79 -0
  106. package/dist/sleep.d.ts +1 -0
  107. package/dist/socketEvents.d.ts +37 -0
  108. package/dist/socketMiddlewareRegistry.d.ts +20 -0
  109. package/dist/socketRedisAdapter.d.ts +21 -0
  110. package/dist/socketState.d.ts +5 -0
  111. package/dist/socketStatusTypes.d.ts +6 -0
  112. package/dist/socketTypes.d.ts +34 -0
  113. package/dist/synchronizedEnvHashes.d.ts +66 -0
  114. package/dist/testFileConvention.d.ts +11 -0
  115. package/dist/testResetTargets.d.ts +5 -0
  116. package/dist/tryCatch.d.ts +1 -0
  117. package/dist/tryCatchClient.d.ts +1 -0
  118. package/dist/tryCatchSync.d.ts +1 -0
  119. package/dist/validateRequest.d.ts +50 -0
  120. package/docs/app-bootstrap.md +4 -449
  121. package/docs/config-registry.md +3 -346
  122. package/docs/csrf-config.md +3 -86
  123. package/docs/error-tracker-registry.md +3 -192
  124. package/docs/hooks.md +2 -295
  125. package/docs/rate-limit-strategy.md +3 -168
  126. package/docs/redis-adapter.md +5 -110
  127. package/docs/session-types.md +3 -178
  128. package/docs/socket-bootstrap.md +5 -385
  129. package/package.json +4 -4
  130. package/CLAUDE.md +0 -256
  131. package/dist/chunk-5FXBTGYL.js.map +0 -1
  132. package/dist/chunk-IJYNVM2W.js.map +0 -1
  133. package/dist/pageRouteValidation-B4Cmtfjv.d.ts +0 -280
  134. /package/dist/{sentrySetup-HNIURVUZ.js.map → sentrySetup-OLZ4BO7Q.js.map} +0 -0
@@ -1,280 +0,0 @@
1
- import { Socket } from 'socket.io-client';
2
-
3
- declare function sleep(ms: number): Promise<void>;
4
-
5
- declare function tryCatchSync<T, P = void>(func: (values: P) => T, params?: P): [Error | null, T | null];
6
-
7
- interface NotifyParam {
8
- key: string;
9
- value: string | number | boolean;
10
- }
11
- interface NotifyInput {
12
- key: string;
13
- params?: NotifyParam[];
14
- }
15
- interface Notifier {
16
- success: (input: NotifyInput) => void;
17
- error: (input: NotifyInput) => void;
18
- info: (input: NotifyInput) => void;
19
- warning: (input: NotifyInput) => void;
20
- }
21
- declare const registerNotifier: (notifier: Notifier) => void;
22
- declare const getNotifier: () => Notifier;
23
- declare const notify: Notifier;
24
-
25
- declare let socket: Socket | null;
26
- declare const setSocket: (next: Socket | null) => void;
27
- declare const incrementResponseIndex: () => number;
28
- declare const waitForSocket: () => Promise<Socket | null>;
29
-
30
- /** Why a queued item was dropped (handed to its `onDrop` callback). */
31
- type QueueDropReason = 'expired' | 'queue-full';
32
- interface ApiQueueItem {
33
- id: string;
34
- key: string;
35
- run: (socketInstance: Socket) => void;
36
- createdAt: number;
37
- /**
38
- * Per-request override of `projectConfig.offlineQueue.dropPolicy`. See
39
- * `SyncQueueItem.dropPolicy` for details.
40
- */
41
- dropPolicy?: 'drop-oldest' | 'drop-newest' | 'reject';
42
- /**
43
- * Optional callback invoked when THIS item is dropped (evicted for age or
44
- * because the queue was full / rejected) instead of ever running (SYNC-09).
45
- * The transport wires this to settle the pending `syncRequest`/`apiRequest`
46
- * promise with an error envelope, so an evicted offline request resolves
47
- * rather than hanging forever. Invoked at most once; failures are swallowed.
48
- */
49
- onDrop?: (reason: QueueDropReason) => void;
50
- }
51
- interface SyncQueueItem {
52
- id: string;
53
- key: string;
54
- run: (socketInstance: Socket) => void;
55
- createdAt: number;
56
- /**
57
- * Per-request override of `projectConfig.offlineQueue.dropPolicy`. Lets a
58
- * specific sync ("editor cursor move") pick `'drop-oldest'` while the app
59
- * default stays `'reject'` for safer sends. When omitted, falls back to
60
- * the global config.
61
- */
62
- dropPolicy?: 'drop-oldest' | 'drop-newest' | 'reject';
63
- /** See {@link ApiQueueItem.onDrop} (SYNC-09). */
64
- onDrop?: (reason: QueueDropReason) => void;
65
- }
66
- declare const isOnline: () => boolean;
67
- declare const enqueueApiRequest: (item: ApiQueueItem) => boolean;
68
- declare const enqueueSyncRequest: (item: SyncQueueItem) => boolean;
69
- declare const removeApiQueueItem: (id: string) => void;
70
- declare const removeSyncQueueItem: (id: string) => void;
71
- declare const removeApiQueueItemsByKey: (key: string) => void;
72
- declare const flushApiQueue: (canRun: () => boolean, socketInstance: Socket) => void;
73
- declare const flushSyncQueue: (canRun: () => boolean, socketInstance: Socket) => void;
74
- declare const getApiQueueSize: () => number;
75
- declare const getSyncQueueSize: () => number;
76
-
77
- interface ErrorParam {
78
- key: string;
79
- value: string | number | boolean;
80
- }
81
- interface ErrorResponseInput {
82
- status?: unknown;
83
- errorCode?: unknown;
84
- errorParams?: unknown;
85
- httpStatus?: unknown;
86
- }
87
- interface NormalizedErrorResponse {
88
- status: 'error';
89
- message: string;
90
- errorCode: string;
91
- errorParams?: ErrorParam[];
92
- httpStatus?: number;
93
- }
94
- declare const INVALID_ERROR_RESPONSE_CODE = "error.invalidResponse";
95
- declare const isErrorParamArray: (value: unknown) => value is ErrorParam[];
96
- declare const normalizeErrorResponseCore: ({ response, fallbackHttpStatus, fallbackErrorCode, resolveMessage, }: {
97
- response: ErrorResponseInput;
98
- fallbackHttpStatus?: number;
99
- fallbackErrorCode?: string;
100
- resolveMessage?: (args: {
101
- errorCode: string;
102
- errorParams?: ErrorParam[];
103
- }) => string;
104
- }) => NormalizedErrorResponse;
105
- declare const defaultHttpStatusForResponse: ({ status, explicitHttpStatus, fallbackErrorStatus, }: {
106
- status: "success" | "error";
107
- explicitHttpStatus?: number;
108
- fallbackErrorStatus?: number;
109
- }) => number;
110
-
111
- /**
112
- * Fetch (or return the cached) CSRF token for the active session. Returns
113
- * null in token mode or when no session exists. Callers should attach the
114
- * returned value as the `X-CSRF-Token` request header.
115
- */
116
- declare const getCsrfToken: (origin?: string) => Promise<string | null>;
117
- /** Drop the cached token. Call this on logout or when a 403 csrfMismatch is seen. */
118
- declare const clearCsrfToken: () => void;
119
- /**
120
- * Drop-in replacement for `fetch` that automatically attaches the framework's
121
- * `X-CSRF-Token` and `X-Request-Id` headers to state-changing requests in
122
- * cookie mode. Use this for any project-side HTTP call that hits a
123
- * LuckyStack `/api/*`, `/sync/*`, or `/auth/api/*` endpoint.
124
- *
125
- * Behavior:
126
- * - GET / OPTIONS / HEAD: passes through without CSRF (read-only).
127
- * - Token mode: passes through without CSRF (immune by design).
128
- * - Cookie mode + state-changing method: lazily fetches `/auth/csrf` once,
129
- * caches, attaches as `x-csrf-token`. On a 403 `auth.csrfMismatch`
130
- * response, clears the cache and retries once.
131
- * - `credentials: 'include'` is forced unless the caller overrode it.
132
- *
133
- * @example
134
- * import { httpFetch } from '@luckystack/core/client';
135
- * const res = await httpFetch('/api/system/myRoute/v1', {
136
- * method: 'POST',
137
- * body: JSON.stringify({ ... }),
138
- * });
139
- */
140
- declare const httpFetch: typeof fetch;
141
-
142
- type HttpMethodLiteral = 'GET' | 'POST' | 'PUT' | 'DELETE';
143
- type ApiMethodMap = Record<string, Record<string, Record<string, HttpMethodLiteral>>>;
144
- declare const registerApiMethodMap: (map: ApiMethodMap) => void;
145
- declare const getRegisteredApiMethod: (pagePath: string, apiName: string, version: string) => HttpMethodLiteral | undefined;
146
- declare const isApiMethodMapRegistered: () => boolean;
147
-
148
- declare const ROUTED_DATA_QUERY_KEY = "__luckystack_data";
149
- /**
150
- * Append `data` to `path` as the reserved `__luckystack_data` query value
151
- * (JSON-encoded), plus any `extraParams`. Tolerates a `path` that already
152
- * carries a query string.
153
- */
154
- declare const buildRoutedGetUrl: (path: string, data: unknown, extraParams?: Record<string, string>) => string;
155
-
156
- interface ServiceRouteParseSuccess {
157
- status: 'success';
158
- normalizedRouteName: string;
159
- service: string;
160
- routeName: string;
161
- }
162
- interface ServiceRouteParseError {
163
- status: 'error';
164
- reason: string;
165
- }
166
- type ServiceRouteParseResult = ServiceRouteParseSuccess | ServiceRouteParseError;
167
- interface TransportRouteParseSuccess {
168
- status: 'success';
169
- normalizedFullName: string;
170
- version: string;
171
- serviceRoute: ServiceRouteParseSuccess;
172
- }
173
- interface TransportRouteParseError {
174
- status: 'error';
175
- reason: string;
176
- }
177
- type TransportRouteParseResult = TransportRouteParseSuccess | TransportRouteParseError;
178
- declare const parseServiceRouteName: (value: string) => ServiceRouteParseResult;
179
- declare const parseTransportRouteName: ({ value, prefix, }: {
180
- value: string;
181
- prefix: "api" | "sync";
182
- }) => TransportRouteParseResult;
183
-
184
- declare const socketEventNames: {
185
- readonly apiRequest: "apiRequest";
186
- readonly apiCancel: "apiCancel";
187
- readonly sync: "sync";
188
- readonly syncCancel: "syncCancel";
189
- readonly joinRoom: "joinRoom";
190
- readonly leaveRoom: "leaveRoom";
191
- readonly getJoinedRooms: "getJoinedRooms";
192
- readonly updateLocation: "updateLocation";
193
- readonly updateSession: "updateSession";
194
- readonly sessionReplaced: "sessionReplaced";
195
- readonly logout: "logout";
196
- readonly intentionalDisconnect: "intentionalDisconnect";
197
- readonly intentionalReconnect: "intentionalReconnect";
198
- readonly activity: "activity";
199
- readonly userAfk: "userAfk";
200
- readonly userBack: "userBack";
201
- readonly userLeft: "userLeft";
202
- readonly connect: "connect";
203
- readonly disconnect: "disconnect";
204
- readonly reconnectAttempt: "reconnect_attempt";
205
- readonly connectError: "connect_error";
206
- readonly apiResponsePrefix: "apiResponse-";
207
- readonly apiStreamPrefix: "apiStream-";
208
- readonly syncResponsePrefix: "sync-";
209
- readonly syncProgressPrefix: "sync-progress-";
210
- readonly joinRoomResponsePrefix: "joinRoom-";
211
- readonly leaveRoomResponsePrefix: "leaveRoom-";
212
- readonly getJoinedRoomsResponsePrefix: "getJoinedRooms-";
213
- };
214
- declare const buildApiResponseEventName: (responseIndex: number | string) => string;
215
- declare const buildApiStreamEventName: (responseIndex: number | string) => string;
216
- declare const buildSyncResponseEventName: (responseIndex: number | string) => string;
217
- declare const buildSyncProgressEventName: (responseIndex: number | string) => string;
218
- declare const buildJoinRoomResponseEventName: (responseIndex: number | string) => string;
219
- declare const buildLeaveRoomResponseEventName: (responseIndex: number | string) => string;
220
- declare const buildGetJoinedRoomsResponseEventName: (responseIndex: number | string) => string;
221
-
222
- type SOCKETSTATUS = "CONNECTED" | "DISCONNECTED" | "AFK" | "RECONNECTING" | "STARTUP";
223
- interface statusContent {
224
- status: SOCKETSTATUS;
225
- reconnectAttempt?: number;
226
- endTime?: number;
227
- }
228
-
229
- type LoggerContext = Record<string, unknown>;
230
- interface Logger {
231
- debug: (message: string, context?: LoggerContext) => void;
232
- info: (message: string, context?: LoggerContext) => void;
233
- warn: (message: string, context?: LoggerContext) => void;
234
- error: (message: string, error?: unknown, context?: LoggerContext) => void;
235
- }
236
- declare const createDevLogger: () => Logger;
237
- declare const registerLogger: (logger: Logger) => void;
238
- declare const getLogger: () => Logger;
239
- declare const isLoggerRegistered: () => boolean;
240
- declare const resetLoggerForTests: () => void;
241
-
242
- interface PageRouteRules {
243
- /**
244
- * Single-character prefix that marks a folder as **invisible-parent** for
245
- * page routing. Default: `'_'`.
246
- */
247
- privateFolderPrefix: string;
248
- /**
249
- * Folder names that are reserved for framework-internal use and may NEVER
250
- * host a `page.tsx`, nested or otherwise. Scaffold + page-discovery emit
251
- * a hard error when a page is placed inside one.
252
- */
253
- scaffoldIgnoredFolders: readonly string[];
254
- }
255
- declare const DEFAULT_PAGE_ROUTE_RULES: PageRouteRules;
256
- interface PagePathValidationResult {
257
- /** `true` when the page file produces a routeable URL. */
258
- valid: boolean;
259
- /** Computed URL when `valid`. Always begins with `/`. `/` for root page. */
260
- route?: string;
261
- /** Human-readable explanation when `!valid`. */
262
- reason?: string;
263
- }
264
- /**
265
- * Validate a `page.tsx` file path relative to `src/`. Accepts both
266
- * forward and back slashes, with or without a leading `./` or `/`.
267
- * The filename **must** be `page.tsx` (or `page.jsx`); other filenames
268
- * return `valid: false`.
269
- *
270
- * Examples (defaults):
271
- * admin/page.tsx -> { valid: true, route: '/admin' }
272
- * _housing/renting/page.tsx -> { valid: true, route: '/renting' }
273
- * _housing/page.tsx -> { valid: false, reason: 'no URL segment left after stripping underscore folders' }
274
- * _api/something/page.tsx -> { valid: false, reason: 'page.tsx cannot live inside reserved folder _api' }
275
- * page.tsx -> { valid: true, route: '/' }
276
- * some/route.tsx -> { valid: false, reason: 'not a page file (expected page.tsx)' }
277
- */
278
- declare const validatePagePath: (srcRelativePath: string, rules?: PageRouteRules) => PagePathValidationResult;
279
-
280
- export { type ErrorResponseInput as $, type ApiMethodMap as A, isOnline as B, normalizeErrorResponseCore as C, DEFAULT_PAGE_ROUTE_RULES as D, notify as E, parseServiceRouteName as F, registerApiMethodMap as G, type HttpMethodLiteral as H, registerLogger as I, registerNotifier as J, removeApiQueueItem as K, type Logger as L, removeApiQueueItemsByKey as M, type Notifier as N, removeSyncQueueItem as O, type PagePathValidationResult as P, setSocket as Q, ROUTED_DATA_QUERY_KEY as R, type SOCKETSTATUS as S, sleep as T, socket as U, socketEventNames as V, type statusContent as W, tryCatchSync as X, validatePagePath as Y, waitForSocket as Z, type ErrorParam as _, type LoggerContext as a, type NormalizedErrorResponse as a0, INVALID_ERROR_RESPONSE_CODE as a1, type QueueDropReason as a2, type ServiceRouteParseError as a3, type ServiceRouteParseResult as a4, type ServiceRouteParseSuccess as a5, type TransportRouteParseError as a6, type TransportRouteParseResult as a7, type TransportRouteParseSuccess as a8, createDevLogger as a9, defaultHttpStatusForResponse as aa, isErrorParamArray as ab, isLoggerRegistered as ac, parseTransportRouteName as ad, resetLoggerForTests as ae, type NotifyInput as b, type NotifyParam as c, type PageRouteRules as d, buildApiResponseEventName as e, buildApiStreamEventName as f, buildGetJoinedRoomsResponseEventName as g, buildJoinRoomResponseEventName as h, buildLeaveRoomResponseEventName as i, buildRoutedGetUrl as j, buildSyncProgressEventName as k, buildSyncResponseEventName as l, clearCsrfToken as m, enqueueApiRequest as n, enqueueSyncRequest as o, flushApiQueue as p, flushSyncQueue as q, getApiQueueSize as r, getCsrfToken as s, getLogger as t, getNotifier as u, getRegisteredApiMethod as v, getSyncQueueSize as w, httpFetch as x, incrementResponseIndex as y, isApiMethodMapRegistered as z };