@appilots/sdk 0.7.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -4
- package/dist/.build-meta.json +5 -0
- package/dist/{chunk-KYFAXT6V.js → chunk-2GCWCPSD.js} +19 -16
- package/dist/{chunk-R4D34FEW.mjs → chunk-AHHDOUVX.mjs} +2151 -333
- package/dist/{chunk-DR75QTYK.mjs → chunk-IHPLS5FE.mjs} +16 -13
- package/dist/{chunk-HFRIB4YN.js → chunk-VX7AL4SA.js} +1049 -1162
- package/dist/{chunk-KUFWRJC4.mjs → chunk-XHR65V2W.mjs} +831 -949
- package/dist/{chunk-DZ7QRFHD.js → chunk-YB77RYCC.js} +2178 -332
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +11 -11
- package/dist/hooks/index.mjs +2 -2
- package/dist/{index-nI-s3Exg.d.mts → index-BPZ0j71S.d.mts} +315 -15
- package/dist/{index-nI-s3Exg.d.ts → index-BPZ0j71S.d.ts} +315 -15
- package/dist/index.d.mts +325 -22
- package/dist/index.d.ts +325 -22
- package/dist/index.js +340 -227
- package/dist/index.mjs +274 -173
- package/dist/navigation/index.d.mts +171 -3
- package/dist/navigation/index.d.ts +171 -3
- package/dist/navigation/index.js +13 -13
- package/dist/navigation/index.mjs +2 -2
- package/metro.d.ts +16 -1
- package/metro.js +104 -10
- package/package.json +16 -6
- package/dist/registerScreen-D1oGm28T.d.mts +0 -159
- package/dist/registerScreen-D1oGm28T.d.ts +0 -159
|
@@ -1,5 +1,160 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
interface AppilotsNavigationContainerProps {
|
|
4
|
+
children: React__default.ReactElement;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Wraps your NavigationContainer from the outside and automatically
|
|
8
|
+
* injects `ref` and `onStateChange` to track the current screen.
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { NavigationContainer } from '@react-navigation/native';
|
|
12
|
+
* import { AppilotsNavigationContainer } from '@appilots/sdk';
|
|
13
|
+
*
|
|
14
|
+
* <AppilotsProvider>
|
|
15
|
+
* <AppilotsNavigationContainer>
|
|
16
|
+
* <NavigationContainer>
|
|
17
|
+
* <Stack.Navigator>...</Stack.Navigator>
|
|
18
|
+
* </NavigationContainer>
|
|
19
|
+
* </AppilotsNavigationContainer>
|
|
20
|
+
* <AppilotsChat />
|
|
21
|
+
* </AppilotsProvider>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function AppilotsNavigationContainer({ children }: AppilotsNavigationContainerProps): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Navigation-related types for the Appilots SDK.
|
|
28
|
+
*/
|
|
29
|
+
interface ScreenFieldMetadata {
|
|
30
|
+
/** Field identifier (used by AI model to reference this field) */
|
|
31
|
+
id: string;
|
|
32
|
+
/** Human-readable label (must match the UI component's label) */
|
|
33
|
+
label: string;
|
|
34
|
+
/** Field type */
|
|
35
|
+
type: 'text' | 'number' | 'select' | 'toggle' | 'date' | string;
|
|
36
|
+
/** Whether the field is required */
|
|
37
|
+
required?: boolean;
|
|
38
|
+
/** Options for select fields */
|
|
39
|
+
options?: {
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}[];
|
|
43
|
+
}
|
|
44
|
+
interface ScreenActionMetadata {
|
|
45
|
+
/** Action identifier (used by AI model to reference this action) */
|
|
46
|
+
id: string;
|
|
47
|
+
/** Human-readable label (must match the UI component's label) */
|
|
48
|
+
label: string;
|
|
49
|
+
/** Action type */
|
|
50
|
+
type: 'submit' | 'button' | 'link' | string;
|
|
51
|
+
/** Target screen for navigation/link actions, when known. */
|
|
52
|
+
targetScreen?: string;
|
|
53
|
+
/**
|
|
54
|
+
* When true, the agent MUST present a confirmation card to the user
|
|
55
|
+
* before executing this action. Set at registerScreen time for
|
|
56
|
+
* high-risk or destructive operations.
|
|
57
|
+
*
|
|
58
|
+
* The server's permission policy honours this flag when present in
|
|
59
|
+
* the MCP doc, but a stale MCP can miss it. As defense-in-depth,
|
|
60
|
+
* the SDK also gates such actions locally: when a `ui_interaction`
|
|
61
|
+
* targets an action with `requiresConfirmation: true` and there is
|
|
62
|
+
* NO already-pending confirm action in the queue, the executor
|
|
63
|
+
* synthesises one and waits for user input before pressing.
|
|
64
|
+
*/
|
|
65
|
+
requiresConfirmation?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Structured risk/effect metadata. Prefer these fields over label
|
|
68
|
+
* heuristics for multilingual apps: the runtime can gate the action
|
|
69
|
+
* without trying to infer intent from Portuguese/English/etc. text.
|
|
70
|
+
*/
|
|
71
|
+
effect?: 'read' | 'write' | 'destructive' | string;
|
|
72
|
+
riskLevel?: 'low' | 'medium' | 'high' | string;
|
|
73
|
+
destructive?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Static-analysis hints produced by the MCP generator (Camada B).
|
|
76
|
+
* Present only when the generator could statically prove the
|
|
77
|
+
* handler's async shape — otherwise undefined and the SDK falls
|
|
78
|
+
* back to agnostic runtime signals (ActivityIndicator,
|
|
79
|
+
* pressed-button-still-disabled, fingerprint quiescence).
|
|
80
|
+
*
|
|
81
|
+
* Mirrors `AppilotsInferredAction` from `@appilots/mcp-generator`.
|
|
82
|
+
* Kept as a structural type here to avoid a runtime dependency
|
|
83
|
+
* between sdk and mcp-generator packages.
|
|
84
|
+
*/
|
|
85
|
+
appilotsInferred?: AppilotsInferredAction;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Inferred metadata about an action's expected async behavior.
|
|
89
|
+
* See `packages/mcp-generator/docs/INFERRED_ACTION_FIELDS.md` for
|
|
90
|
+
* the full schema and detection rules.
|
|
91
|
+
*/
|
|
92
|
+
interface AppilotsInferredAction {
|
|
93
|
+
isAsyncTrigger?: boolean;
|
|
94
|
+
expectedOutcome?: 'navigation' | 'inline-feedback' | 'data-arrival' | 'mixed' | 'none';
|
|
95
|
+
loadingStateBindings?: string[];
|
|
96
|
+
}
|
|
97
|
+
interface ScreenMetadata {
|
|
98
|
+
/** Unique screen identifier */
|
|
99
|
+
name: string;
|
|
100
|
+
/** Human-readable title */
|
|
101
|
+
title?: string;
|
|
102
|
+
/** Description of what this screen does */
|
|
103
|
+
description?: string;
|
|
104
|
+
/** Available actions on this screen (legacy: string[], new: ScreenActionMetadata[]) */
|
|
105
|
+
actions?: (string | ScreenActionMetadata)[];
|
|
106
|
+
/** Form fields available on this screen (legacy: string[], new: ScreenFieldMetadata[]) */
|
|
107
|
+
fields?: ScreenFieldMetadata[];
|
|
108
|
+
/** Legacy: simple list of form field names */
|
|
109
|
+
formFields?: string[];
|
|
110
|
+
/** Tags for categorisation */
|
|
111
|
+
tags?: string[];
|
|
112
|
+
/**
|
|
113
|
+
* Dev-defined prompts to surface as chips when the chat opens on this
|
|
114
|
+
* screen. Highest priority — these win over screen-action and global
|
|
115
|
+
* popular prompts. Keep them short and specific to the screen ("Adicionar
|
|
116
|
+
* cliente" beats "Me ajude").
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* registerScreen({
|
|
120
|
+
* name: 'Customers',
|
|
121
|
+
* suggestedPrompts: ['Adicionar cliente', 'Buscar por nome'],
|
|
122
|
+
* });
|
|
123
|
+
*/
|
|
124
|
+
suggestedPrompts?: string[];
|
|
125
|
+
}
|
|
126
|
+
interface NavigationConfig {
|
|
127
|
+
/** Root navigator name */
|
|
128
|
+
rootNavigator?: string;
|
|
129
|
+
/** Map of screen names to metadata */
|
|
130
|
+
screens?: Record<string, ScreenMetadata>;
|
|
131
|
+
/** Navigation linking config */
|
|
132
|
+
linking?: {
|
|
133
|
+
prefixes?: string[];
|
|
134
|
+
config?: Record<string, unknown>;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Register a screen with metadata so the AI agent can understand it.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* registerScreen({
|
|
144
|
+
* name: 'ItemList',
|
|
145
|
+
* title: 'Items',
|
|
146
|
+
* description: 'Lists items available in this app',
|
|
147
|
+
* actions: ['viewDetails', 'addItem'],
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function registerScreen(metadata: ScreenMetadata): void;
|
|
152
|
+
/** Get metadata for a specific screen */
|
|
153
|
+
declare function getScreenMetadata(name: string): ScreenMetadata | undefined;
|
|
154
|
+
/** Get all registered screens */
|
|
155
|
+
declare function getAllScreens(): ScreenMetadata[];
|
|
156
|
+
/** Clear the screen registry (useful for testing) */
|
|
157
|
+
declare function clearScreenRegistry(): void;
|
|
3
158
|
|
|
4
159
|
/**
|
|
5
160
|
* Global navigation state — lightweight singleton so any part of the SDK
|
|
@@ -7,6 +162,19 @@ import 'react';
|
|
|
7
162
|
*
|
|
8
163
|
* Updated by AppilotsNavigationContainer and read by useAppilotsChat().
|
|
9
164
|
*/
|
|
165
|
+
/**
|
|
166
|
+
* Tell the SDK which screen the user is on.
|
|
167
|
+
*
|
|
168
|
+
* `AppilotsNavigationContainer` calls this for you on every React
|
|
169
|
+
* Navigation state change. It is public API for the apps that have no
|
|
170
|
+
* `NavigationContainer` to wrap — Expo Router and other file-based
|
|
171
|
+
* routers — where manifest mode declares the screens but nothing tracks
|
|
172
|
+
* which one is live. Without it `currentScreen` stays null and the agent
|
|
173
|
+
* does not know where it is, even with a perfect application map.
|
|
174
|
+
*
|
|
175
|
+
* The name must match the screen's name in the map, or the agent will
|
|
176
|
+
* look up metadata for a screen that does not exist.
|
|
177
|
+
*/
|
|
10
178
|
declare function setCurrentScreen(screen: string): void;
|
|
11
179
|
/**
|
|
12
180
|
* Get the current screen name. Prefers a LIVE reading from the navigation
|
|
@@ -40,4 +208,4 @@ interface RuntimeNavigationStateSnapshot {
|
|
|
40
208
|
*/
|
|
41
209
|
declare function getNavigationStateSnapshot(): RuntimeNavigationStateSnapshot | null;
|
|
42
210
|
|
|
43
|
-
export { type RuntimeNavigationStateSnapshot, getActiveRouteNames, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, setCurrentScreen, setNavigationRef };
|
|
211
|
+
export { AppilotsNavigationContainer, type NavigationConfig, type RuntimeNavigationStateSnapshot, type ScreenActionMetadata, type ScreenFieldMetadata, type ScreenMetadata, clearScreenRegistry, getActiveRouteNames, getAllScreens, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, getScreenMetadata, registerScreen, setCurrentScreen, setNavigationRef };
|
|
@@ -1,5 +1,160 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
interface AppilotsNavigationContainerProps {
|
|
4
|
+
children: React__default.ReactElement;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Wraps your NavigationContainer from the outside and automatically
|
|
8
|
+
* injects `ref` and `onStateChange` to track the current screen.
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { NavigationContainer } from '@react-navigation/native';
|
|
12
|
+
* import { AppilotsNavigationContainer } from '@appilots/sdk';
|
|
13
|
+
*
|
|
14
|
+
* <AppilotsProvider>
|
|
15
|
+
* <AppilotsNavigationContainer>
|
|
16
|
+
* <NavigationContainer>
|
|
17
|
+
* <Stack.Navigator>...</Stack.Navigator>
|
|
18
|
+
* </NavigationContainer>
|
|
19
|
+
* </AppilotsNavigationContainer>
|
|
20
|
+
* <AppilotsChat />
|
|
21
|
+
* </AppilotsProvider>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function AppilotsNavigationContainer({ children }: AppilotsNavigationContainerProps): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Navigation-related types for the Appilots SDK.
|
|
28
|
+
*/
|
|
29
|
+
interface ScreenFieldMetadata {
|
|
30
|
+
/** Field identifier (used by AI model to reference this field) */
|
|
31
|
+
id: string;
|
|
32
|
+
/** Human-readable label (must match the UI component's label) */
|
|
33
|
+
label: string;
|
|
34
|
+
/** Field type */
|
|
35
|
+
type: 'text' | 'number' | 'select' | 'toggle' | 'date' | string;
|
|
36
|
+
/** Whether the field is required */
|
|
37
|
+
required?: boolean;
|
|
38
|
+
/** Options for select fields */
|
|
39
|
+
options?: {
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}[];
|
|
43
|
+
}
|
|
44
|
+
interface ScreenActionMetadata {
|
|
45
|
+
/** Action identifier (used by AI model to reference this action) */
|
|
46
|
+
id: string;
|
|
47
|
+
/** Human-readable label (must match the UI component's label) */
|
|
48
|
+
label: string;
|
|
49
|
+
/** Action type */
|
|
50
|
+
type: 'submit' | 'button' | 'link' | string;
|
|
51
|
+
/** Target screen for navigation/link actions, when known. */
|
|
52
|
+
targetScreen?: string;
|
|
53
|
+
/**
|
|
54
|
+
* When true, the agent MUST present a confirmation card to the user
|
|
55
|
+
* before executing this action. Set at registerScreen time for
|
|
56
|
+
* high-risk or destructive operations.
|
|
57
|
+
*
|
|
58
|
+
* The server's permission policy honours this flag when present in
|
|
59
|
+
* the MCP doc, but a stale MCP can miss it. As defense-in-depth,
|
|
60
|
+
* the SDK also gates such actions locally: when a `ui_interaction`
|
|
61
|
+
* targets an action with `requiresConfirmation: true` and there is
|
|
62
|
+
* NO already-pending confirm action in the queue, the executor
|
|
63
|
+
* synthesises one and waits for user input before pressing.
|
|
64
|
+
*/
|
|
65
|
+
requiresConfirmation?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Structured risk/effect metadata. Prefer these fields over label
|
|
68
|
+
* heuristics for multilingual apps: the runtime can gate the action
|
|
69
|
+
* without trying to infer intent from Portuguese/English/etc. text.
|
|
70
|
+
*/
|
|
71
|
+
effect?: 'read' | 'write' | 'destructive' | string;
|
|
72
|
+
riskLevel?: 'low' | 'medium' | 'high' | string;
|
|
73
|
+
destructive?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Static-analysis hints produced by the MCP generator (Camada B).
|
|
76
|
+
* Present only when the generator could statically prove the
|
|
77
|
+
* handler's async shape — otherwise undefined and the SDK falls
|
|
78
|
+
* back to agnostic runtime signals (ActivityIndicator,
|
|
79
|
+
* pressed-button-still-disabled, fingerprint quiescence).
|
|
80
|
+
*
|
|
81
|
+
* Mirrors `AppilotsInferredAction` from `@appilots/mcp-generator`.
|
|
82
|
+
* Kept as a structural type here to avoid a runtime dependency
|
|
83
|
+
* between sdk and mcp-generator packages.
|
|
84
|
+
*/
|
|
85
|
+
appilotsInferred?: AppilotsInferredAction;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Inferred metadata about an action's expected async behavior.
|
|
89
|
+
* See `packages/mcp-generator/docs/INFERRED_ACTION_FIELDS.md` for
|
|
90
|
+
* the full schema and detection rules.
|
|
91
|
+
*/
|
|
92
|
+
interface AppilotsInferredAction {
|
|
93
|
+
isAsyncTrigger?: boolean;
|
|
94
|
+
expectedOutcome?: 'navigation' | 'inline-feedback' | 'data-arrival' | 'mixed' | 'none';
|
|
95
|
+
loadingStateBindings?: string[];
|
|
96
|
+
}
|
|
97
|
+
interface ScreenMetadata {
|
|
98
|
+
/** Unique screen identifier */
|
|
99
|
+
name: string;
|
|
100
|
+
/** Human-readable title */
|
|
101
|
+
title?: string;
|
|
102
|
+
/** Description of what this screen does */
|
|
103
|
+
description?: string;
|
|
104
|
+
/** Available actions on this screen (legacy: string[], new: ScreenActionMetadata[]) */
|
|
105
|
+
actions?: (string | ScreenActionMetadata)[];
|
|
106
|
+
/** Form fields available on this screen (legacy: string[], new: ScreenFieldMetadata[]) */
|
|
107
|
+
fields?: ScreenFieldMetadata[];
|
|
108
|
+
/** Legacy: simple list of form field names */
|
|
109
|
+
formFields?: string[];
|
|
110
|
+
/** Tags for categorisation */
|
|
111
|
+
tags?: string[];
|
|
112
|
+
/**
|
|
113
|
+
* Dev-defined prompts to surface as chips when the chat opens on this
|
|
114
|
+
* screen. Highest priority — these win over screen-action and global
|
|
115
|
+
* popular prompts. Keep them short and specific to the screen ("Adicionar
|
|
116
|
+
* cliente" beats "Me ajude").
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* registerScreen({
|
|
120
|
+
* name: 'Customers',
|
|
121
|
+
* suggestedPrompts: ['Adicionar cliente', 'Buscar por nome'],
|
|
122
|
+
* });
|
|
123
|
+
*/
|
|
124
|
+
suggestedPrompts?: string[];
|
|
125
|
+
}
|
|
126
|
+
interface NavigationConfig {
|
|
127
|
+
/** Root navigator name */
|
|
128
|
+
rootNavigator?: string;
|
|
129
|
+
/** Map of screen names to metadata */
|
|
130
|
+
screens?: Record<string, ScreenMetadata>;
|
|
131
|
+
/** Navigation linking config */
|
|
132
|
+
linking?: {
|
|
133
|
+
prefixes?: string[];
|
|
134
|
+
config?: Record<string, unknown>;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Register a screen with metadata so the AI agent can understand it.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* registerScreen({
|
|
144
|
+
* name: 'ItemList',
|
|
145
|
+
* title: 'Items',
|
|
146
|
+
* description: 'Lists items available in this app',
|
|
147
|
+
* actions: ['viewDetails', 'addItem'],
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function registerScreen(metadata: ScreenMetadata): void;
|
|
152
|
+
/** Get metadata for a specific screen */
|
|
153
|
+
declare function getScreenMetadata(name: string): ScreenMetadata | undefined;
|
|
154
|
+
/** Get all registered screens */
|
|
155
|
+
declare function getAllScreens(): ScreenMetadata[];
|
|
156
|
+
/** Clear the screen registry (useful for testing) */
|
|
157
|
+
declare function clearScreenRegistry(): void;
|
|
3
158
|
|
|
4
159
|
/**
|
|
5
160
|
* Global navigation state — lightweight singleton so any part of the SDK
|
|
@@ -7,6 +162,19 @@ import 'react';
|
|
|
7
162
|
*
|
|
8
163
|
* Updated by AppilotsNavigationContainer and read by useAppilotsChat().
|
|
9
164
|
*/
|
|
165
|
+
/**
|
|
166
|
+
* Tell the SDK which screen the user is on.
|
|
167
|
+
*
|
|
168
|
+
* `AppilotsNavigationContainer` calls this for you on every React
|
|
169
|
+
* Navigation state change. It is public API for the apps that have no
|
|
170
|
+
* `NavigationContainer` to wrap — Expo Router and other file-based
|
|
171
|
+
* routers — where manifest mode declares the screens but nothing tracks
|
|
172
|
+
* which one is live. Without it `currentScreen` stays null and the agent
|
|
173
|
+
* does not know where it is, even with a perfect application map.
|
|
174
|
+
*
|
|
175
|
+
* The name must match the screen's name in the map, or the agent will
|
|
176
|
+
* look up metadata for a screen that does not exist.
|
|
177
|
+
*/
|
|
10
178
|
declare function setCurrentScreen(screen: string): void;
|
|
11
179
|
/**
|
|
12
180
|
* Get the current screen name. Prefers a LIVE reading from the navigation
|
|
@@ -40,4 +208,4 @@ interface RuntimeNavigationStateSnapshot {
|
|
|
40
208
|
*/
|
|
41
209
|
declare function getNavigationStateSnapshot(): RuntimeNavigationStateSnapshot | null;
|
|
42
210
|
|
|
43
|
-
export { type RuntimeNavigationStateSnapshot, getActiveRouteNames, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, setCurrentScreen, setNavigationRef };
|
|
211
|
+
export { AppilotsNavigationContainer, type NavigationConfig, type RuntimeNavigationStateSnapshot, type ScreenActionMetadata, type ScreenFieldMetadata, type ScreenMetadata, clearScreenRegistry, getActiveRouteNames, getAllScreens, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, getScreenMetadata, registerScreen, setCurrentScreen, setNavigationRef };
|
package/dist/navigation/index.js
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunk2GCWCPSD_js = require('../chunk-2GCWCPSD.js');
|
|
4
|
+
var chunkYB77RYCC_js = require('../chunk-YB77RYCC.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "AppilotsNavigationContainer", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunk2GCWCPSD_js.AppilotsNavigationContainer; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "clearScreenRegistry", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkYB77RYCC_js.clearScreenRegistry; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "getActiveRouteNames", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkYB77RYCC_js.getActiveRouteNames; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "getAllScreens", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkYB77RYCC_js.getAllScreens; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "getCurrentScreen", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkYB77RYCC_js.getCurrentScreen; }
|
|
27
27
|
});
|
|
28
28
|
Object.defineProperty(exports, "getNavigationRef", {
|
|
29
29
|
enumerable: true,
|
|
30
|
-
get: function () { return
|
|
30
|
+
get: function () { return chunkYB77RYCC_js.getNavigationRef; }
|
|
31
31
|
});
|
|
32
32
|
Object.defineProperty(exports, "getNavigationStateSnapshot", {
|
|
33
33
|
enumerable: true,
|
|
34
|
-
get: function () { return
|
|
34
|
+
get: function () { return chunkYB77RYCC_js.getNavigationStateSnapshot; }
|
|
35
35
|
});
|
|
36
36
|
Object.defineProperty(exports, "getScreenMetadata", {
|
|
37
37
|
enumerable: true,
|
|
38
|
-
get: function () { return
|
|
38
|
+
get: function () { return chunkYB77RYCC_js.getScreenMetadata; }
|
|
39
39
|
});
|
|
40
40
|
Object.defineProperty(exports, "registerScreen", {
|
|
41
41
|
enumerable: true,
|
|
42
|
-
get: function () { return
|
|
42
|
+
get: function () { return chunkYB77RYCC_js.registerScreen; }
|
|
43
43
|
});
|
|
44
44
|
Object.defineProperty(exports, "setCurrentScreen", {
|
|
45
45
|
enumerable: true,
|
|
46
|
-
get: function () { return
|
|
46
|
+
get: function () { return chunkYB77RYCC_js.setCurrentScreen; }
|
|
47
47
|
});
|
|
48
48
|
Object.defineProperty(exports, "setNavigationRef", {
|
|
49
49
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
50
|
+
get: function () { return chunkYB77RYCC_js.setNavigationRef; }
|
|
51
51
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { AppilotsNavigationContainer } from '../chunk-
|
|
2
|
-
export { clearScreenRegistry, getActiveRouteNames, getAllScreens, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, getScreenMetadata, registerScreen, setCurrentScreen, setNavigationRef } from '../chunk-
|
|
1
|
+
export { AppilotsNavigationContainer } from '../chunk-IHPLS5FE.mjs';
|
|
2
|
+
export { clearScreenRegistry, getActiveRouteNames, getAllScreens, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, getScreenMetadata, registerScreen, setCurrentScreen, setNavigationRef } from '../chunk-AHHDOUVX.mjs';
|
package/metro.d.ts
CHANGED
|
@@ -30,12 +30,27 @@ export interface WithAppilotsOptions {
|
|
|
30
30
|
* @default `<projectRoot>/.appilotsrc`
|
|
31
31
|
*/
|
|
32
32
|
configPath?: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Treat a missing `.appilotsrc` as "no auto-init wanted" and return the
|
|
36
|
+
* Metro config untouched, instead of throwing.
|
|
37
|
+
*
|
|
38
|
+
* Only set this if you also drop `import '@appilots/auto-init'` from your
|
|
39
|
+
* entry file and pass the config to `<AppilotsProvider config={…}>`
|
|
40
|
+
* yourself — otherwise the import has nothing to resolve to and Metro
|
|
41
|
+
* fails later with a message that does not mention `.appilotsrc` at all.
|
|
42
|
+
*
|
|
43
|
+
* A malformed `.appilotsrc` always throws, `optional` or not.
|
|
44
|
+
*
|
|
45
|
+
* @default false
|
|
46
|
+
*/
|
|
47
|
+
optional?: boolean;
|
|
33
48
|
}
|
|
34
49
|
|
|
35
50
|
/**
|
|
36
51
|
* Wraps a Metro config so `AppilotsProvider` auto-loads `.appilotsrc`.
|
|
37
52
|
*
|
|
38
|
-
*
|
|
53
|
+
* Throws when no `.appilotsrc` is found, unless `options.optional` is set.
|
|
39
54
|
*
|
|
40
55
|
* @example
|
|
41
56
|
* ```js
|
package/metro.js
CHANGED
|
@@ -31,11 +31,47 @@ function parseConfigJSON(raw) {
|
|
|
31
31
|
return JSON.stringify(parsed, null, 2);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* The error for "there is no .appilotsrc".
|
|
36
|
+
*
|
|
37
|
+
* This used to be a `console.warn` followed by `return metroConfig`, which
|
|
38
|
+
* made the plugin a no-op — and then the `import '@appilots/auto-init'` line
|
|
39
|
+
* in the app's index.js had nothing to resolve to. What the developer saw was
|
|
40
|
+
* a Metro resolution failure (or, once the shim had been written and the file
|
|
41
|
+
* later removed, a bare `ENOENT: no such file or directory, open
|
|
42
|
+
* '…/.appilotsrc'` red screen) with no mention of the missing config or of
|
|
43
|
+
* how to create it. A warning that is only visible in Metro's scrollback,
|
|
44
|
+
* seconds before an unrelated-looking error, is not a warning.
|
|
45
|
+
*
|
|
46
|
+
* Failing here instead stops the build at the actual cause and names the fix.
|
|
47
|
+
*/
|
|
48
|
+
function missingConfigError(configPath) {
|
|
49
|
+
return new Error(
|
|
50
|
+
'[Appilots] .appilotsrc not found at ' +
|
|
51
|
+
configPath +
|
|
52
|
+
'\n' +
|
|
53
|
+
'\n' +
|
|
54
|
+
'withAppilots() reads it to generate the module that\n' +
|
|
55
|
+
' import "@appilots/auto-init";\n' +
|
|
56
|
+
'resolves to, so the bundle cannot be built without it.\n' +
|
|
57
|
+
'\n' +
|
|
58
|
+
'Fix, whichever fits:\n' +
|
|
59
|
+
' • cp .appilotsrc.example .appilotsrc (if your project ships one)\n' +
|
|
60
|
+
' • npx @appilots/cli init (creates one for this project)\n' +
|
|
61
|
+
' • withAppilots(config, { optional: true })\n' +
|
|
62
|
+
' to make the file optional. Then also drop the\n' +
|
|
63
|
+
' `import "@appilots/auto-init"` line and pass the config\n' +
|
|
64
|
+
' yourself: <AppilotsProvider config={{ projectId, apiKey }}>.',
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
34
68
|
function createShimSource(configJSON) {
|
|
35
69
|
return (
|
|
36
70
|
'// Auto-generated by @appilots/sdk/metro — do not edit\n' +
|
|
37
71
|
'var _g = typeof globalThis !== "undefined" ? globalThis : global;\n' +
|
|
38
|
-
'var _config = ' +
|
|
72
|
+
'var _config = ' +
|
|
73
|
+
configJSON +
|
|
74
|
+
';\n' +
|
|
39
75
|
'_g.__APPILOTS_RC__ = _config;\n' +
|
|
40
76
|
'\n' +
|
|
41
77
|
'// Call initAppilots immediately so auto-tracking patches React.createElement\n' +
|
|
@@ -73,8 +109,8 @@ function withAppilots(metroConfig, options = {}) {
|
|
|
73
109
|
const configPath = options.configPath || path.resolve(projectRoot, '.appilotsrc');
|
|
74
110
|
|
|
75
111
|
if (!fs.existsSync(configPath)) {
|
|
76
|
-
|
|
77
|
-
|
|
112
|
+
if (options.optional) return metroConfig;
|
|
113
|
+
throw missingConfigError(configPath);
|
|
78
114
|
}
|
|
79
115
|
|
|
80
116
|
const shimDir = path.resolve(projectRoot, 'node_modules', '.cache', 'appilots');
|
|
@@ -82,20 +118,29 @@ function withAppilots(metroConfig, options = {}) {
|
|
|
82
118
|
let lastConfigSource = null;
|
|
83
119
|
|
|
84
120
|
const ensureShimFresh = () => {
|
|
85
|
-
|
|
121
|
+
let source;
|
|
122
|
+
try {
|
|
123
|
+
source = fs.readFileSync(configPath, 'utf8').trim();
|
|
124
|
+
} catch (error) {
|
|
125
|
+
// Reached when the file existed at config load and is gone by the time
|
|
126
|
+
// Metro resolves the import — deleted, renamed, or a checkout switched
|
|
127
|
+
// underneath a running bundler. Raw, this is the `ENOENT … open
|
|
128
|
+
// '.appilotsrc'` red screen; the point of catching it is that the
|
|
129
|
+
// message names the file's role and how to restore it.
|
|
130
|
+
if (error && error.code === 'ENOENT') throw missingConfigError(configPath);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
86
133
|
if (source === lastConfigSource && fs.existsSync(shimPath)) {
|
|
87
134
|
return;
|
|
88
135
|
}
|
|
136
|
+
// A malformed .appilotsrc throws from JSON.parse and is NOT downgraded to
|
|
137
|
+
// a warning either: the shim would be stale or absent, and the failure
|
|
138
|
+
// would resurface later as an unresolvable module.
|
|
89
139
|
writeShim(parseConfigJSON(source), shimPath);
|
|
90
140
|
lastConfigSource = source;
|
|
91
141
|
};
|
|
92
142
|
|
|
93
|
-
|
|
94
|
-
ensureShimFresh();
|
|
95
|
-
} catch (error) {
|
|
96
|
-
const message = error && error.message ? error.message : String(error);
|
|
97
|
-
console.warn('[Appilots] failed to generate auto-init shim from ' + configPath + ': ' + message);
|
|
98
|
-
}
|
|
143
|
+
ensureShimFresh();
|
|
99
144
|
|
|
100
145
|
// Resolve `@appilots/auto-init` to the shim
|
|
101
146
|
const existingResolveRequest = metroConfig.resolver?.resolveRequest;
|
|
@@ -115,6 +160,55 @@ function withAppilots(metroConfig, options = {}) {
|
|
|
115
160
|
return context.resolveRequest(context, moduleName, platform);
|
|
116
161
|
},
|
|
117
162
|
},
|
|
163
|
+
transformer: withPreservedNames(metroConfig.transformer),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Keep function and class names through minification (#386).
|
|
169
|
+
*
|
|
170
|
+
* The introspection matches several React Native components by name,
|
|
171
|
+
* and the ones with no `displayName` — `Switch`, `Modal`, `FlatList`,
|
|
172
|
+
* `SectionList`, `VirtualizedList` — fall through to the function or
|
|
173
|
+
* class name, which is exactly what a minifier rewrites. Bundling
|
|
174
|
+
* `apps/example-app` with `--minify true` (Metro 0.81.5 / RN 0.76.9)
|
|
175
|
+
* drops every one of those names to zero occurrences.
|
|
176
|
+
*
|
|
177
|
+
* Metro's default minifier config sets neither flag
|
|
178
|
+
* (`metro-config/src/defaults/index.js`), and its `toplevel: false`
|
|
179
|
+
* does not help: Metro wraps each module in `__d(function (…) {`, so
|
|
180
|
+
* these are local names, not top-level ones.
|
|
181
|
+
*
|
|
182
|
+
* This is a SAFETY NET, not the fix. The React Native CLI's release
|
|
183
|
+
* build does not minify at all when Hermes is on (the default since
|
|
184
|
+
* 0.70), and `withAppilots()` cannot reach an app that builds its Metro
|
|
185
|
+
* config by hand or uses Re.Pack. The detection itself is what must
|
|
186
|
+
* survive without names, which is why the walker falls back to
|
|
187
|
+
* accessibility roles, the native modal host, and the list props
|
|
188
|
+
* signature.
|
|
189
|
+
*
|
|
190
|
+
* The app's own `minifierConfig` wins on every key it sets, including
|
|
191
|
+
* these two — a project that deliberately mangles names keeps doing so.
|
|
192
|
+
*/
|
|
193
|
+
function withPreservedNames(transformer) {
|
|
194
|
+
const existing = transformer || {};
|
|
195
|
+
const minifierConfig = existing.minifierConfig || {};
|
|
196
|
+
const mangle = minifierConfig.mangle;
|
|
197
|
+
return {
|
|
198
|
+
...existing,
|
|
199
|
+
minifierConfig: {
|
|
200
|
+
keep_fnames: true,
|
|
201
|
+
keep_classnames: true,
|
|
202
|
+
...minifierConfig,
|
|
203
|
+
// Terser reads `keep_fnames` inside `mangle` as well as at the
|
|
204
|
+
// top level, and the nested one is what actually governs
|
|
205
|
+
// renaming. Only added when the app already configures `mangle`
|
|
206
|
+
// as an object — `mangle: false` means "do not mangle at all",
|
|
207
|
+
// and turning that into an object would switch mangling ON.
|
|
208
|
+
...(mangle && typeof mangle === 'object'
|
|
209
|
+
? { mangle: { keep_fnames: true, keep_classnames: true, ...mangle } }
|
|
210
|
+
: {}),
|
|
211
|
+
},
|
|
118
212
|
};
|
|
119
213
|
}
|
|
120
214
|
|