@use-stall/types 0.2.19 → 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.
package/index.d.ts CHANGED
@@ -25,3 +25,4 @@ export * from "./src/connectors";
25
25
  export * from "./src/pin-auth";
26
26
  export * from "./src/integrations";
27
27
  export * from "./src/promotions";
28
+ export * from "./src/core-sdk";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@use-stall/types",
3
- "version": "0.2.19",
3
+ "version": "0.3.1",
4
4
  "description": "Type declarations for Stall SDKs",
5
5
  "types": "index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,102 @@
1
+ import {
2
+ ConnectorModuleKey,
3
+ UnifiedProductType,
4
+ UnifiedOrderType,
5
+ UnifiedCustomerType,
6
+ UnifiedCollectionType,
7
+ UnifiedCategoryType,
8
+ UnifiedVariantsType,
9
+ UnifiedInventoryLevelType,
10
+ UnifiedPromotion,
11
+ UnifiedOrderNote,
12
+ UnifiedOrderRefundType,
13
+ UnifiedPaymentProviderType,
14
+ UnifiedPaymentCollectionType,
15
+ UnifiedTaxRate,
16
+ UnifiedTaxClass,
17
+ UnifiedLocationType,
18
+ UnifiedFulfillmentType,
19
+ UnifiedTagProductTag,
20
+ UnifiedFulfillmentProviderConfigType,
21
+ UnifiedFulfillmentMethodType,
22
+ } from "@use-stall/types";
23
+
24
+ export interface StallCoreConfigOptions {
25
+ connector_url: string;
26
+ version: string;
27
+ configuration: Record<string, any>;
28
+ }
29
+
30
+ export interface CoreConfig {
31
+ options: StallCoreConfigOptions;
32
+ adapter: () => Promise<AdapterModuleType>;
33
+ refreshAdapter: () => Promise<AdapterModuleType>;
34
+ }
35
+
36
+ type ModuleTypeMap = {
37
+ products: UnifiedProductType;
38
+ variants: UnifiedVariantsType;
39
+ collections: UnifiedCollectionType;
40
+ categories: UnifiedCategoryType;
41
+ tags: UnifiedTagProductTag;
42
+ inventory_levels: UnifiedInventoryLevelType;
43
+ inventory_history: UnifiedInventoryLevelType;
44
+ promotions: UnifiedPromotion;
45
+ orders: UnifiedOrderType;
46
+ order_notes: UnifiedOrderNote;
47
+ refunds: UnifiedOrderRefundType;
48
+ payment_providers: UnifiedPaymentProviderType;
49
+ payments: UnifiedPaymentCollectionType;
50
+ tax_rates: UnifiedTaxRate;
51
+ tax_classes: UnifiedTaxClass;
52
+ customers: UnifiedCustomerType;
53
+ locations: UnifiedLocationType;
54
+ fulfillment_types: UnifiedFulfillmentMethodType;
55
+ fulfillment_providers: UnifiedFulfillmentProviderConfigType;
56
+ fulfillments: UnifiedFulfillmentType;
57
+ };
58
+
59
+ // Extended module key that includes tax_classes
60
+ type ExtendedModuleKey = ConnectorModuleKey | "tax_classes";
61
+
62
+ type GetModuleType<K extends ExtendedModuleKey> = K extends keyof ModuleTypeMap
63
+ ? ModuleTypeMap[K]
64
+ : never;
65
+
66
+ export type AdapterModuleType = {
67
+ [K in ExtendedModuleKey]: {
68
+ list: (props: {
69
+ connector_config: Record<string, any>;
70
+ query?: string;
71
+ }) => Promise<GetModuleType<K>[]>;
72
+ retrieve: (props: {
73
+ connector_config: Record<string, any>;
74
+ id: string;
75
+ }) => Promise<GetModuleType<K>>;
76
+ create: (props: {
77
+ connector_config: Record<string, any>;
78
+ data: GetModuleType<K>;
79
+ }) => Promise<GetModuleType<K>>;
80
+ update: (props: {
81
+ connector_config: Record<string, any>;
82
+ id: string;
83
+ data: Partial<GetModuleType<K>>;
84
+ }) => Promise<GetModuleType<K>>;
85
+ delete: (props: {
86
+ connector_config: Record<string, any>;
87
+ id: string;
88
+ }) => Promise<void>;
89
+ bulk_create: (props: {
90
+ connector_config: Record<string, any>;
91
+ data: GetModuleType<K>[];
92
+ }) => Promise<GetModuleType<K>[]>;
93
+ bulk_update: (props: {
94
+ connector_config: Record<string, any>;
95
+ data: Array<{ id: string; data: Partial<GetModuleType<K>> }>;
96
+ }) => Promise<GetModuleType<K>[]>;
97
+ bulk_delete: (props: {
98
+ connector_config: Record<string, any>;
99
+ ids: string[];
100
+ }) => Promise<void>;
101
+ };
102
+ };
package/src/device.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
1
  import type { InstalledExtensionType } from "./extensions";
3
2
  import type { UnifiedFulfillmentMethods } from "./fulfillment";
4
3
  import type { UnifiedMethodsType } from "./payments";
@@ -1,3 +1,180 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { UnifiedOrderType } from "./orders";
3
+ import { ComponentType } from "./utils/react";
4
+ import type { Router } from "./utils/router";
5
+ import { LookupGroupRouteType } from "./utils/lookup";
6
+ import type { CoreConfig } from "./core-sdk";
7
+
8
+ interface StallExtension {
9
+ // entrypoint: {
10
+ // id: string; // Can be lookup group or page id
11
+ // type: "lookup" | "page";
12
+ // };
13
+ pages: ExtensionPage[];
14
+ lookup: ExtensionLookupGroup[];
15
+ }
16
+
17
+ interface ExtensionPage {
18
+ index: boolean;
19
+ id: string;
20
+ title: string;
21
+ description: string;
22
+ ui: string; // Name of the component in ui.ts
23
+ }
24
+
25
+ interface ExtensionActionShortcut {
26
+ modifiers: string[];
27
+ key: string;
28
+ }
29
+
30
+ interface ExtensionLookupAction {
31
+ native: boolean;
32
+ name: string;
33
+ label: string;
34
+ static_args: Record<string, any>;
35
+ close_on_complete: boolean; // Close lookup
36
+ reopen_on_return?: boolean; // Reopen lookup on return from an external page
37
+ always_show?: boolean; // Always show the action in the lookup even if no item is selected or highlighted
38
+ shortcut?: ExtensionActionShortcut;
39
+ paths?: string[]; // You can specify a list of paths where this action should be available, when left empty it will be available everywhere
40
+ }
41
+
42
+ interface ExtensionActionFunctionProps {
43
+ static_args: Record<string, any>;
44
+ item: any;
45
+ router: Router;
46
+ active_group: LookupGroupRouteType;
47
+ action: ExtensionLookupAction;
48
+ }
49
+
50
+ enum ListDataSourceOptions {
51
+ PRODUCTS = "products",
52
+ CUSTOMERS = "customers",
53
+ ORDERS = "orders",
54
+ PARKED_ORDERS = "parked_orders",
55
+ COLLECTIONS = "collections",
56
+ CATEGORIES = "categories",
57
+ REGISTERS = "register_sessions",
58
+ TRANSACTIONS = "session_transactions",
59
+ }
60
+
61
+ type ListKeyFormat =
62
+ | "string"
63
+ | "number"
64
+ | "array"
65
+ | "date"
66
+ | "price"
67
+ | "status"
68
+ | "none";
69
+
70
+ type ListFormatKey = {
71
+ value: string;
72
+ format: ListKeyFormat;
73
+ className?: string;
74
+ };
75
+
76
+ type ListKeys = {
77
+ id: string;
78
+ image: string;
79
+ fallback?: string;
80
+ title: ListFormatKey;
81
+ description?: ListFormatKey;
82
+ right?: ListFormatKey;
83
+ };
84
+
85
+ type ListFilters = {
86
+ key: string;
87
+ type: "string" | "number" | "array";
88
+ query_value: string;
89
+ dynamic: boolean;
90
+ };
91
+
92
+ interface LocalListUIComponent {
93
+ id: string;
94
+ title: string;
95
+ description: string;
96
+ data_origin: "local";
97
+ filters: ListFilters[];
98
+ sorting: {
99
+ key: string;
100
+ order: "asc" | "desc";
101
+ };
102
+ source: ListDataSourceOptions;
103
+ keys: ListKeys;
104
+ actions: ExtensionLookupAction[];
105
+ }
106
+
107
+ interface RemoteListUIComponent {
108
+ id: string;
109
+ title: string;
110
+ description: string;
111
+ data_origin: "remote";
112
+ filters: ListFilters[];
113
+ sorting: {
114
+ key: string;
115
+ order: "asc" | "desc";
116
+ };
117
+ source: string;
118
+ keys: ListKeys;
119
+ actions: ExtensionLookupAction[];
120
+ }
121
+
122
+ type ExtensionLookupGroup = LocalListUIComponent | RemoteListUIComponent;
123
+
124
+ interface UIProps {
125
+ item: any;
126
+ search_query: Record<string, string>;
127
+ base_currency: string;
128
+ active_cart: UnifiedOrderType | null;
129
+ BackButton: ComponentType<any>;
130
+ LoaderComponent: ComponentType<any>;
131
+ router: Router;
132
+ stall: CoreConfig;
133
+ }
134
+
135
+ interface StallExtensionConfig {
136
+ $schema: string;
137
+ id: string;
138
+ name: string;
139
+ description: string;
140
+ keywords: string[];
141
+ icon: string;
142
+ version: string;
143
+ authors: string[];
144
+ repo: string;
145
+ homepage: string;
146
+ offline_ready: boolean;
147
+ entrypoint: {
148
+ id: string;
149
+ type: string; //"lookup" | "page";
150
+ };
151
+ }
152
+
153
+ enum ExtensionNativeActions {
154
+ OPEN_GROUP = "open_group",
155
+ OPEN_PAGE = "open_page",
156
+ ADD_TO_CART = "add_to_cart",
157
+ ADD_CUSTOMER_TO_ORDER = "add_customer_to_order",
158
+ }
159
+
160
+ export type {
161
+ StallExtension,
162
+ ExtensionPage,
163
+ ExtensionActionShortcut,
164
+ ExtensionLookupAction,
165
+ ExtensionActionFunctionProps,
166
+ ListFilters,
167
+ ListFormatKey,
168
+ ListKeys,
169
+ LocalListUIComponent,
170
+ RemoteListUIComponent,
171
+ ExtensionLookupGroup,
172
+ UIProps,
173
+ StallExtensionConfig,
174
+ };
175
+
176
+ export { ListDataSourceOptions, ExtensionNativeActions };
177
+
1
178
  export interface ExtensionType {
2
179
  id: string;
3
180
  version: string;
@@ -10,8 +187,7 @@ export interface ExtensionType {
10
187
  authors: string[];
11
188
  }
12
189
 
13
-
14
190
  export interface InstalledExtensionType {
15
191
  id: string;
16
192
  version: string;
17
- }
193
+ }
@@ -0,0 +1,17 @@
1
+ export interface LookupGroupRouteType {
2
+ id: string;
3
+ title: string;
4
+ extension: {
5
+ id: string;
6
+ title: string;
7
+ };
8
+ previous_route_item: Record<string, any>;
9
+ filters?: LookupListFilters[];
10
+ }
11
+
12
+ export type LookupListFilters = {
13
+ key: string;
14
+ type: "string" | "number" | "array";
15
+ query_value: string;
16
+ dynamic: boolean;
17
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A React component — either a function component or a class component —
3
+ * that accepts props of type P.
4
+ */
5
+ export type ComponentType<P = {}> =
6
+ | ((props: P & { children?: ReactNode }) => ReactNode)
7
+ | (new (props: P & { children?: ReactNode }) => { render(): ReactNode });
8
+
9
+ // Basic React node types to avoid any React import
10
+ export type ReactNode =
11
+ | string
12
+ | number
13
+ | boolean
14
+ | null
15
+ | undefined
16
+ | ReactElement
17
+ | ReactNode[];
18
+
19
+ export interface ReactElement<P = any> {
20
+ type: string | ComponentType<P>;
21
+ props: P;
22
+ key: string | number | null;
23
+ }
@@ -0,0 +1,637 @@
1
+ // ─── Primitive / shared types ────────────────────────────────────────────────
2
+
3
+ export type Primitive = string | number | boolean | null | undefined;
4
+
5
+ /** A URL-safe path made up of its three constituent parts. */
6
+ export interface Path {
7
+ /** The portion of the URL pathname before any query string. */
8
+ pathname: string;
9
+ /** The URL search string, starting with `?`. */
10
+ search: string;
11
+ /** The URL fragment identifier, starting with `#`. */
12
+ hash: string;
13
+ }
14
+
15
+ /** Accepted values for the `to` argument of `navigate`. */
16
+ export type To = string | Partial<Path>;
17
+
18
+ /** A fully-resolved browser Location, augmented with router-level state. */
19
+ export interface Location extends Path {
20
+ /**
21
+ * A value of arbitrary data associated with this location.
22
+ */
23
+ state: any;
24
+ /**
25
+ * A unique string associated with this location. May be used to safely store
26
+ * and retrieve data in some other storage API, like `localStorage`.
27
+ */
28
+ key: string;
29
+ }
30
+
31
+ // ─── History ─────────────────────────────────────────────────────────────────
32
+
33
+ export type Action = "POP" | "PUSH" | "REPLACE";
34
+
35
+ export interface Update {
36
+ action: Action;
37
+ location: Location;
38
+ delta: number | null;
39
+ }
40
+
41
+ export interface Listener {
42
+ (update: Update): void;
43
+ }
44
+
45
+ // ─── Route objects ────────────────────────────────────────────────────────────
46
+
47
+ export type AgnosticRouteMatch<
48
+ ParamsKey extends string = string,
49
+ RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject
50
+ > = {
51
+ params: Params<ParamsKey>;
52
+ pathname: string;
53
+ pathnameBase: string;
54
+ route: RouteObjectType;
55
+ };
56
+
57
+ export interface IndexRouteObject {
58
+ caseSensitive?: boolean;
59
+ path?: string;
60
+ id?: string;
61
+ loader?: LoaderFunction;
62
+ action?: ActionFunction;
63
+ hasErrorBoundary?: boolean;
64
+ shouldRevalidate?: ShouldRevalidateFunction;
65
+ handle?: RouteObject["handle"];
66
+ index: true;
67
+ children?: undefined;
68
+ element?: React.ReactNode | null;
69
+ hydrateFallbackElement?: React.ReactNode | null;
70
+ errorElement?: React.ReactNode | null;
71
+ Component?: React.ComponentType | null;
72
+ HydrateFallback?: React.ComponentType | null;
73
+ ErrorBoundary?: React.ComponentType | null;
74
+ lazy?: LazyRouteFunction<RouteObject>;
75
+ }
76
+
77
+ export interface NonIndexRouteObject {
78
+ caseSensitive?: boolean;
79
+ path?: string;
80
+ id?: string;
81
+ loader?: LoaderFunction;
82
+ action?: ActionFunction;
83
+ hasErrorBoundary?: boolean;
84
+ shouldRevalidate?: ShouldRevalidateFunction;
85
+ handle?: any;
86
+ index?: false;
87
+ children?: RouteObject[];
88
+ element?: React.ReactNode | null;
89
+ hydrateFallbackElement?: React.ReactNode | null;
90
+ errorElement?: React.ReactNode | null;
91
+ Component?: React.ComponentType | null;
92
+ HydrateFallback?: React.ComponentType | null;
93
+ ErrorBoundary?: React.ComponentType | null;
94
+ lazy?: LazyRouteFunction<RouteObject>;
95
+ }
96
+
97
+ export type RouteObject = IndexRouteObject | NonIndexRouteObject;
98
+
99
+ /**
100
+ * Framework-agnostic route object — the underlying shape the router core
101
+ * operates on (no React-specific fields).
102
+ */
103
+ export interface AgnosticRouteObject {
104
+ caseSensitive?: boolean;
105
+ children?: AgnosticRouteObject[];
106
+ element?: any;
107
+ index?: boolean;
108
+ path?: string;
109
+ id?: string;
110
+ loader?: LoaderFunction;
111
+ action?: ActionFunction;
112
+ hasErrorBoundary?: boolean;
113
+ shouldRevalidate?: ShouldRevalidateFunction;
114
+ handle?: any;
115
+ lazy?: LazyRouteFunction<AgnosticRouteObject>;
116
+ }
117
+
118
+ export interface AgnosticDataRouteObject extends AgnosticRouteObject {
119
+ children?: AgnosticDataRouteObject[];
120
+ id: string;
121
+ }
122
+
123
+ // ─── Params ──────────────────────────────────────────────────────────────────
124
+
125
+ export type Params<Key extends string = string> = {
126
+ readonly [key in Key]: string | undefined;
127
+ };
128
+
129
+ // ─── Loader / action functions ────────────────────────────────────────────────
130
+
131
+ export type LoaderFunctionArgs<Context = any> = {
132
+ request: Request;
133
+ params: Params;
134
+ context?: Context;
135
+ };
136
+
137
+ export type ActionFunctionArgs<Context = any> = {
138
+ request: Request;
139
+ params: Params;
140
+ context?: Context;
141
+ };
142
+
143
+ export interface LoaderFunction<Context = any> {
144
+ (args: LoaderFunctionArgs<Context>, handlerCtx?: unknown):
145
+ | Promise<Response>
146
+ | Response
147
+ | Promise<any>
148
+ | any;
149
+ }
150
+
151
+ export interface ActionFunction<Context = any> {
152
+ (args: ActionFunctionArgs<Context>, handlerCtx?: unknown):
153
+ | Promise<Response>
154
+ | Response
155
+ | Promise<any>
156
+ | any;
157
+ }
158
+
159
+ export interface ShouldRevalidateFunctionArgs {
160
+ currentUrl: URL;
161
+ currentParams: Params;
162
+ nextUrl: URL;
163
+ nextParams: Params;
164
+ formMethod?: string;
165
+ formAction?: string;
166
+ formEncType?: string;
167
+ text?: string;
168
+ formData?: FormData;
169
+ json?: any;
170
+ actionStatus?: number;
171
+ actionResult?: any;
172
+ defaultShouldRevalidate: boolean;
173
+ }
174
+
175
+ export interface ShouldRevalidateFunction {
176
+ (args: ShouldRevalidateFunctionArgs): boolean;
177
+ }
178
+
179
+ export type LazyRouteFunction<R extends AgnosticRouteObject> = () => Promise<
180
+ Omit<R, "lazy" | "id" | "index" | "children">
181
+ >;
182
+
183
+ // ─── Navigation ──────────────────────────────────────────────────────────────
184
+
185
+ export type FormMethod =
186
+ | "get"
187
+ | "post"
188
+ | "put"
189
+ | "patch"
190
+ | "delete"
191
+ | "GET"
192
+ | "POST"
193
+ | "PUT"
194
+ | "PATCH"
195
+ | "DELETE";
196
+
197
+ export type FormEncType =
198
+ | "application/x-www-form-urlencoded"
199
+ | "multipart/form-data"
200
+ | "application/json"
201
+ | "text/plain";
202
+
203
+ export type RelativeRoutingType = "route" | "path";
204
+
205
+ interface NavigateOptions {
206
+ replace?: boolean;
207
+ state?: any;
208
+ relative?: RelativeRoutingType;
209
+ flushSync?: boolean;
210
+ viewTransition?: boolean;
211
+ }
212
+
213
+ export interface RouterNavigateOptions extends NavigateOptions {
214
+ fromRouteId?: string;
215
+ /** Submission options */
216
+ formMethod?: FormMethod;
217
+ formAction?: string;
218
+ formEncType?: FormEncType;
219
+ body?: any;
220
+ formData?: FormData;
221
+ json?: any;
222
+ text?: string;
223
+ /** Replace / unstable flags */
224
+ preventScrollReset?: boolean;
225
+ }
226
+
227
+ export interface RouterFetchOptions {
228
+ formMethod?: FormMethod;
229
+ formAction?: string;
230
+ formEncType?: FormEncType;
231
+ body?: any;
232
+ formData?: FormData;
233
+ json?: any;
234
+ text?: string;
235
+ preventScrollReset?: boolean;
236
+ }
237
+
238
+ // ─── Navigation state ─────────────────────────────────────────────────────────
239
+
240
+ export type NavigationState =
241
+ | { state: "idle"; location?: undefined; formMethod?: undefined; formAction?: undefined; formEncType?: undefined; formData?: undefined; json?: undefined; text?: undefined }
242
+ | { state: "loading"; location: Location; formMethod?: FormMethod; formAction?: string; formEncType?: FormEncType; formData?: FormData; json?: any; text?: string }
243
+ | { state: "submitting"; location: Location; formMethod: FormMethod; formAction: string; formEncType: FormEncType; formData?: FormData; json?: any; text?: string };
244
+
245
+ export type Navigation = NavigationState;
246
+
247
+ // ─── Fetcher ─────────────────────────────────────────────────────────────────
248
+
249
+ export type FetcherState =
250
+ | { state: "idle"; data: undefined; formMethod?: undefined; formAction?: undefined; formEncType?: undefined; formData?: undefined; json?: undefined; text?: undefined }
251
+ | { state: "loading"; data: undefined; formMethod?: FormMethod; formAction?: string; formEncType?: FormEncType; formData?: FormData; json?: any; text?: string }
252
+ | { state: "submitting"; data: undefined; formMethod: FormMethod; formAction: string; formEncType: FormEncType; formData?: FormData; json?: any; text?: string };
253
+
254
+ export type Fetcher<TData = any> = (
255
+ | { state: "idle"; data: TData | undefined; formMethod?: undefined; formAction?: undefined; formEncType?: undefined; formData?: undefined; json?: undefined; text?: undefined }
256
+ | { state: "loading"; data: TData | undefined; formMethod?: FormMethod; formAction?: string; formEncType?: FormEncType; formData?: FormData; json?: any; text?: string }
257
+ | { state: "submitting"; data: TData | undefined; formMethod: FormMethod; formAction: string; formEncType: FormEncType; formData?: FormData; json?: any; text?: string }
258
+ );
259
+
260
+ // ─── Blocker ─────────────────────────────────────────────────────────────────
261
+
262
+ export type BlockerFunction = (args: {
263
+ currentLocation: Location;
264
+ nextLocation: Location;
265
+ historyAction: Action;
266
+ }) => boolean;
267
+
268
+ export type Blocker =
269
+ | { state: "unblocked"; reset: undefined; proceed: undefined; location: undefined }
270
+ | { state: "blocked"; reset: () => void; proceed: () => void; location: Location }
271
+ | { state: "proceeding"; reset: undefined; proceed: undefined; location: Location };
272
+
273
+ // ─── Revalidation ────────────────────────────────────────────────────────────
274
+
275
+ export type RevalidationState = "idle" | "loading";
276
+
277
+ // ─── Deferred data ───────────────────────────────────────────────────────────
278
+
279
+ export interface DeferredData {
280
+ readonly done: boolean;
281
+ readonly unwrappedData: Record<string, any>;
282
+ subscribe(fn: (aborted: boolean, settledKey?: string) => void): boolean;
283
+ cancel(): void;
284
+ resolveData(signal: AbortSignal): Promise<boolean>;
285
+ }
286
+
287
+ // ─── Router state ─────────────────────────────────────────────────────────────
288
+
289
+ export interface RouterState {
290
+ historyAction: Action;
291
+ location: Location;
292
+ matches: AgnosticDataRouteMatch[];
293
+ initialized: boolean;
294
+ navigation: Navigation;
295
+ restoreScrollPosition: number | false | null;
296
+ preventScrollReset: boolean;
297
+ revalidation: RevalidationState;
298
+ loaderData: RouteData;
299
+ actionData: RouteData | null;
300
+ errors: RouteData | null;
301
+ fetchers: Map<string, Fetcher>;
302
+ blockers: Map<string, Blocker>;
303
+ }
304
+
305
+ export type AgnosticDataRouteMatch = AgnosticRouteMatch<
306
+ string,
307
+ AgnosticDataRouteObject
308
+ >;
309
+
310
+ export type RouteData = {
311
+ [routeId: string]: any;
312
+ };
313
+
314
+ // ─── Scroll restoration ───────────────────────────────────────────────────────
315
+
316
+ export type GetScrollPositionFunction = () => number;
317
+
318
+ export type GetScrollRestorationKeyFunction = (
319
+ location: Location,
320
+ matches: AgnosticDataRouteMatch[]
321
+ ) => string;
322
+
323
+ // ─── Future config ────────────────────────────────────────────────────────────
324
+
325
+ export interface FutureConfig {
326
+ unstable_skipActionErrorRevalidation: boolean;
327
+ }
328
+
329
+ // ─── Router init ─────────────────────────────────────────────────────────────
330
+
331
+ export interface RouterInit {
332
+ routes: AgnosticRouteObject[];
333
+ history: {
334
+ readonly action: Action;
335
+ readonly location: Location;
336
+ listen(listener: Listener): () => void;
337
+ createHref(to: To): string;
338
+ encodeLocation(to: To): Path;
339
+ push(to: To, state?: any): void;
340
+ replace(to: To, state?: any): void;
341
+ go(delta: number): void;
342
+ back(): void;
343
+ forward(): void;
344
+ };
345
+ basename?: string;
346
+ mapRouteProperties?: (route: AgnosticRouteObject) => Partial<AgnosticRouteObject>;
347
+ future?: Partial<FutureConfig>;
348
+ hydrationData?: {
349
+ loaderData?: RouteData;
350
+ actionData?: RouteData | null;
351
+ errors?: RouteData | null;
352
+ };
353
+ window?: Window;
354
+ dataStrategy?: DataStrategyFunction;
355
+ patchRoutesOnNavigation?: PatchRoutesOnNavigationFunction;
356
+ }
357
+
358
+ // ─── Data strategy ───────────────────────────────────────────────────────────
359
+
360
+ export type DataStrategyMatch = AgnosticRouteMatch<string, AgnosticDataRouteObject> & {
361
+ shouldLoad: boolean;
362
+ resolve: (
363
+ handlerOverride?: (
364
+ handler: (ctx?: unknown) => DataFunctionReturnValue
365
+ ) => DataFunctionReturnValue
366
+ ) => Promise<DataStrategyResult>;
367
+ };
368
+
369
+ export type DataFunctionReturnValue =
370
+ | Promise<Response>
371
+ | Response
372
+ | Promise<any>
373
+ | any;
374
+
375
+ export type DataStrategyResult =
376
+ | { type: "data"; result: any }
377
+ | { type: "error"; result: any };
378
+
379
+ export interface DataStrategyFunctionArgs<Context = any> {
380
+ request: Request;
381
+ params: Params;
382
+ context?: Context;
383
+ matches: DataStrategyMatch[];
384
+ fetcherKey: string | null;
385
+ }
386
+
387
+ export interface DataStrategyFunction {
388
+ (args: DataStrategyFunctionArgs): Promise<Record<string, DataStrategyResult>>;
389
+ }
390
+
391
+ // ─── Patch routes on navigation ───────────────────────────────────────────────
392
+
393
+ export interface PatchRoutesOnNavigationFunctionArgs {
394
+ path: string;
395
+ matches: AgnosticRouteMatch[];
396
+ patch: (routeId: string | null, children: AgnosticRouteObject[]) => void;
397
+ signal: AbortSignal;
398
+ }
399
+
400
+ export interface PatchRoutesOnNavigationFunction {
401
+ (opts: PatchRoutesOnNavigationFunctionArgs): void | Promise<void>;
402
+ }
403
+
404
+ // ─── Subscriber ──────────────────────────────────────────────────────────────
405
+
406
+ export type RouterSubscriber = (
407
+ state: RouterState,
408
+ opts: { deletedFetchers: string[]; flushSync: boolean; viewTransitionOpts?: ViewTransitionOpts }
409
+ ) => void;
410
+
411
+ export interface ViewTransitionOpts {
412
+ currentLocation: Location;
413
+ nextLocation: Location;
414
+ }
415
+
416
+ // ─── Router interface (original, now fully self-contained) ────────────────────
417
+
418
+ export interface Router {
419
+ /**
420
+ * @internal
421
+ * PRIVATE - DO NOT USE
422
+ *
423
+ * Return the basename for the router
424
+ */
425
+ get basename(): RouterInit["basename"];
426
+
427
+ /**
428
+ * @internal
429
+ * PRIVATE - DO NOT USE
430
+ *
431
+ * Return the future config for the router
432
+ */
433
+ get future(): FutureConfig;
434
+
435
+ /**
436
+ * @internal
437
+ * PRIVATE - DO NOT USE
438
+ *
439
+ * Return the current state of the router
440
+ */
441
+ get state(): RouterState;
442
+
443
+ /**
444
+ * @internal
445
+ * PRIVATE - DO NOT USE
446
+ *
447
+ * Return the routes for this router instance
448
+ */
449
+ get routes(): AgnosticDataRouteObject[];
450
+
451
+ /**
452
+ * @internal
453
+ * PRIVATE - DO NOT USE
454
+ *
455
+ * Return the window associated with the router
456
+ */
457
+ get window(): RouterInit["window"];
458
+
459
+ /**
460
+ * @internal
461
+ * PRIVATE - DO NOT USE
462
+ *
463
+ * Initialize the router, including adding history listeners and kicking off
464
+ * initial data fetches. Returns a function to cleanup listeners and abort
465
+ * any in-progress loads.
466
+ */
467
+ initialize(): Router;
468
+
469
+ /**
470
+ * @internal
471
+ * PRIVATE - DO NOT USE
472
+ *
473
+ * Subscribe to router.state updates
474
+ *
475
+ * @param fn function to call with the new state
476
+ */
477
+ subscribe(fn: RouterSubscriber): () => void;
478
+
479
+ /**
480
+ * @internal
481
+ * PRIVATE - DO NOT USE
482
+ *
483
+ * Enable scroll restoration behavior in the router
484
+ *
485
+ * @param savedScrollPositions Object that will manage positions, in case
486
+ * it's being restored from sessionStorage
487
+ * @param getScrollPosition Function to get the active Y scroll position
488
+ * @param getKey Function to get the key to use for restoration
489
+ */
490
+ enableScrollRestoration(
491
+ savedScrollPositions: Record<string, number>,
492
+ getScrollPosition: GetScrollPositionFunction,
493
+ getKey?: GetScrollRestorationKeyFunction
494
+ ): () => void;
495
+
496
+ /**
497
+ * @internal
498
+ * PRIVATE - DO NOT USE
499
+ *
500
+ * Navigate forward/backward in the history stack
501
+ * @param to Delta to move in the history stack
502
+ */
503
+ navigate(to: number): Promise<void>;
504
+
505
+ /**
506
+ * Navigate to the given path
507
+ * @param to Path to navigate to
508
+ * @param opts Navigation options (method, submission, etc.)
509
+ */
510
+ navigate(to: To | null, opts?: RouterNavigateOptions): Promise<void>;
511
+
512
+ /**
513
+ * @internal
514
+ * PRIVATE - DO NOT USE
515
+ *
516
+ * Trigger a fetcher load/submission
517
+ *
518
+ * @param key Fetcher key
519
+ * @param routeId Route that owns the fetcher
520
+ * @param href href to fetch
521
+ * @param opts Fetcher options, (method, submission, etc.)
522
+ */
523
+ fetch(
524
+ key: string,
525
+ routeId: string,
526
+ href: string | null,
527
+ opts?: RouterFetchOptions
528
+ ): void;
529
+
530
+ /**
531
+ * @internal
532
+ * PRIVATE - DO NOT USE
533
+ *
534
+ * Trigger a revalidation of all current route loaders and fetcher loads
535
+ */
536
+ revalidate(): void;
537
+
538
+ /**
539
+ * @internal
540
+ * PRIVATE - DO NOT USE
541
+ *
542
+ * Utility function to create an href for the given location
543
+ * @param location
544
+ */
545
+ createHref(location: Location | URL): string;
546
+
547
+ /**
548
+ * @internal
549
+ * PRIVATE - DO NOT USE
550
+ *
551
+ * Utility function to URL encode a destination path according to the internal
552
+ * history implementation
553
+ * @param to
554
+ */
555
+ encodeLocation(to: To): Path;
556
+
557
+ /**
558
+ * @internal
559
+ * PRIVATE - DO NOT USE
560
+ *
561
+ * Get/create a fetcher for the given key
562
+ * @param key
563
+ */
564
+ getFetcher<TData = any>(key: string): Fetcher<TData>;
565
+
566
+ /**
567
+ * @internal
568
+ * PRIVATE - DO NOT USE
569
+ *
570
+ * Delete the fetcher for a given key
571
+ * @param key
572
+ */
573
+ deleteFetcher(key: string): void;
574
+
575
+ /**
576
+ * @internal
577
+ * PRIVATE - DO NOT USE
578
+ *
579
+ * Cleanup listeners and abort any in-progress loads
580
+ */
581
+ dispose(): void;
582
+
583
+ /**
584
+ * @internal
585
+ * PRIVATE - DO NOT USE
586
+ *
587
+ * Get a navigation blocker
588
+ * @param key The identifier for the blocker
589
+ * @param fn The blocker function implementation
590
+ */
591
+ getBlocker(key: string, fn: BlockerFunction): Blocker;
592
+
593
+ /**
594
+ * @internal
595
+ * PRIVATE - DO NOT USE
596
+ *
597
+ * Delete a navigation blocker
598
+ * @param key The identifier for the blocker
599
+ */
600
+ deleteBlocker(key: string): void;
601
+
602
+ /**
603
+ * @internal
604
+ * PRIVATE DO NOT USE
605
+ *
606
+ * Patch additional children routes into an existing parent route
607
+ * @param routeId The parent route id or a callback function accepting `patch`
608
+ * to perform batch patching
609
+ * @param children The additional children routes
610
+ */
611
+ patchRoutes(routeId: string | null, children: AgnosticRouteObject[]): void;
612
+
613
+ /**
614
+ * @internal
615
+ * PRIVATE - DO NOT USE
616
+ *
617
+ * HMR needs to pass in-flight route updates to React Router
618
+ * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)
619
+ */
620
+ _internalSetRoutes(routes: AgnosticRouteObject[]): void;
621
+
622
+ /**
623
+ * @internal
624
+ * PRIVATE - DO NOT USE
625
+ *
626
+ * Internal fetch AbortControllers accessed by unit tests
627
+ */
628
+ _internalFetchControllers: Map<string, AbortController>;
629
+
630
+ /**
631
+ * @internal
632
+ * PRIVATE - DO NOT USE
633
+ *
634
+ * Internal pending DeferredData instances accessed by unit tests
635
+ */
636
+ _internalActiveDeferreds: Map<string, DeferredData>;
637
+ }