@buoy-gg/env 7.0.41 → 7.0.43

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 (51) hide show
  1. package/README.md +11 -87
  2. package/lib/commonjs/env/components/EnvStatsOverview.js +1 -159
  3. package/lib/commonjs/env/components/EnvVarRow.js +1 -189
  4. package/lib/commonjs/env/components/EnvVarSection.js +1 -84
  5. package/lib/commonjs/env/components/EnvVarsModal.js +1 -322
  6. package/lib/commonjs/env/hooks/useDynamicEnv.js +1 -92
  7. package/lib/commonjs/env/types/index.js +1 -27
  8. package/lib/commonjs/env/types/types.js +1 -1
  9. package/lib/commonjs/env/types/userTypes.js +1 -1
  10. package/lib/commonjs/env/utils/envTypeDetector.js +1 -59
  11. package/lib/commonjs/env/utils/helpers.js +1 -119
  12. package/lib/commonjs/env/utils/index.js +1 -38
  13. package/lib/commonjs/env/utils/remoteEnv.js +1 -24
  14. package/lib/commonjs/env/utils/utils.js +1 -121
  15. package/lib/commonjs/index.js +1 -77
  16. package/lib/commonjs/preset.js +1 -81
  17. package/lib/commonjs/sync/envSyncAdapter.js +1 -51
  18. package/lib/module/env/components/EnvStatsOverview.js +1 -155
  19. package/lib/module/env/components/EnvVarRow.js +1 -185
  20. package/lib/module/env/components/EnvVarSection.js +1 -80
  21. package/lib/module/env/components/EnvVarsModal.js +1 -317
  22. package/lib/module/env/hooks/useDynamicEnv.js +1 -88
  23. package/lib/module/env/types/index.js +1 -4
  24. package/lib/module/env/types/types.js +1 -1
  25. package/lib/module/env/types/userTypes.js +1 -1
  26. package/lib/module/env/utils/envTypeDetector.js +1 -55
  27. package/lib/module/env/utils/helpers.js +1 -114
  28. package/lib/module/env/utils/index.js +1 -5
  29. package/lib/module/env/utils/remoteEnv.js +1 -19
  30. package/lib/module/env/utils/utils.js +1 -116
  31. package/lib/module/index.js +1 -21
  32. package/lib/module/preset.js +1 -78
  33. package/lib/module/sync/envSyncAdapter.js +1 -46
  34. package/lib/web/index.mjs +1 -2
  35. package/package.json +4 -7
  36. package/lib/typescript/env/components/EnvStatsOverview.d.ts.map +0 -1
  37. package/lib/typescript/env/components/EnvVarRow.d.ts.map +0 -1
  38. package/lib/typescript/env/components/EnvVarSection.d.ts.map +0 -1
  39. package/lib/typescript/env/components/EnvVarsModal.d.ts.map +0 -1
  40. package/lib/typescript/env/hooks/useDynamicEnv.d.ts.map +0 -1
  41. package/lib/typescript/env/types/index.d.ts.map +0 -1
  42. package/lib/typescript/env/types/types.d.ts.map +0 -1
  43. package/lib/typescript/env/types/userTypes.d.ts.map +0 -1
  44. package/lib/typescript/env/utils/envTypeDetector.d.ts.map +0 -1
  45. package/lib/typescript/env/utils/helpers.d.ts.map +0 -1
  46. package/lib/typescript/env/utils/index.d.ts.map +0 -1
  47. package/lib/typescript/env/utils/remoteEnv.d.ts.map +0 -1
  48. package/lib/typescript/env/utils/utils.d.ts.map +0 -1
  49. package/lib/typescript/index.d.ts.map +0 -1
  50. package/lib/typescript/preset.d.ts.map +0 -1
  51. package/lib/typescript/sync/envSyncAdapter.d.ts.map +0 -1
@@ -1,322 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.EnvToolView = EnvToolView;
7
- exports.EnvVarsModal = EnvVarsModal;
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _react = require("react");
10
- var _reactNative = require("react-native");
11
- var _EnvStatsOverview = require("./EnvStatsOverview");
12
- var _useDynamicEnv = require("../hooks/useDynamicEnv");
13
- var _utils = require("../utils");
14
- var _EnvVarSection = require("./EnvVarSection");
15
- var _jsxRuntime = require("react/jsx-runtime");
16
- /**
17
- * Full-screen modal for inspecting required environment variables. Handles automatic
18
- * discovery, validation, filtering, and rich search so teams can quickly spot missing
19
- * or misconfigured values during development sessions.
20
- */
21
- function EnvVarsModal({
22
- visible,
23
- onClose,
24
- requiredEnvVars,
25
- onBack,
26
- onMinimize,
27
- enableSharedModalDimensions = false,
28
- inline = false
29
- }) {
30
- const [activeFilter, setActiveFilter] = (0, _react.useState)("all");
31
- const [isSearchActive, setIsSearchActive] = (0, _react.useState)(false);
32
- const [searchQuery, setSearchQuery] = (0, _react.useState)("");
33
- const searchInputRef = (0, _react.useRef)(null);
34
- const handleModeChange = (0, _react.useCallback)(_mode => {
35
- // Mode changes handled by JsModal
36
- }, []);
37
-
38
- // Focus search input when search becomes active
39
- (0, _react.useEffect)(() => {
40
- if (isSearchActive && searchInputRef.current) {
41
- searchInputRef.current.focus();
42
- }
43
- }, [isSearchActive]);
44
-
45
- // Clear search when changing filters
46
- (0, _react.useEffect)(() => {
47
- setSearchQuery("");
48
- setIsSearchActive(false);
49
- }, [activeFilter]);
50
-
51
- // Auto-collect environment variables
52
- const envResults = (0, _useDynamicEnv.useDynamicEnv)();
53
- const autoCollectedEnvVars = (0, _react.useMemo)(() => {
54
- const envVars = {};
55
- envResults.forEach(({
56
- key,
57
- data
58
- }) => {
59
- if (data !== undefined && data !== null) {
60
- envVars[key] = typeof data === "string" ? data : (0, _sharedUi.displayValue)(data);
61
- }
62
- });
63
- return envVars;
64
- }, [envResults]);
65
-
66
- // Process and categorize environment variables
67
- const {
68
- requiredVars,
69
- optionalVars
70
- } = (0, _react.useMemo)(() => {
71
- return (0, _utils.processEnvVars)(autoCollectedEnvVars, requiredEnvVars);
72
- }, [autoCollectedEnvVars, requiredEnvVars]);
73
-
74
- // Calculate statistics
75
- const stats = (0, _react.useMemo)(() => {
76
- if (requiredEnvVars === undefined) {
77
- return {
78
- totalCount: 0,
79
- requiredCount: 0,
80
- optionalCount: 0,
81
- presentRequiredCount: 0,
82
- missingCount: 0,
83
- wrongValueCount: 0,
84
- wrongTypeCount: 0
85
- };
86
- }
87
- return (0, _utils.calculateStats)(requiredVars, optionalVars, autoCollectedEnvVars);
88
- }, [requiredEnvVars, requiredVars, optionalVars, autoCollectedEnvVars]);
89
-
90
- // Combine all vars and sort by priority (issues first)
91
- const allVars = (0, _react.useMemo)(() => {
92
- const combined = [...requiredVars, ...optionalVars];
93
-
94
- // Sort by status priority: errors first, then warnings, then valid
95
- return combined.sort((a, b) => {
96
- const priorityMap = {
97
- "required_missing": 1,
98
- "required_wrong_type": 2,
99
- "required_wrong_value": 3,
100
- "required_present": 4,
101
- "optional_present": 5
102
- };
103
- return (priorityMap[a.status] || 999) - (priorityMap[b.status] || 999);
104
- });
105
- }, [requiredVars, optionalVars]);
106
-
107
- // Filter variables based on active filter and search
108
- const filteredVars = (0, _react.useMemo)(() => {
109
- let vars = [];
110
- switch (activeFilter) {
111
- case "all":
112
- vars = allVars;
113
- break;
114
- case "missing":
115
- vars = allVars.filter(v => v.status === "required_missing");
116
- break;
117
- case "issues":
118
- vars = allVars.filter(v => v.status === "required_wrong_type" || v.status === "required_wrong_value");
119
- break;
120
- }
121
-
122
- // Apply search filter
123
- if (searchQuery) {
124
- const query = searchQuery.toLowerCase();
125
- vars = vars.filter(v => v.key.toLowerCase().includes(query) || v.description?.toLowerCase().includes(query) || typeof v.value === 'string' && v.value.toLowerCase().includes(query));
126
- }
127
- return vars;
128
- }, [allVars, optionalVars, activeFilter, searchQuery]);
129
-
130
- // Calculate health percentage
131
- const healthPercentage = stats.requiredCount > 0 ? Math.round(stats.presentRequiredCount / stats.requiredCount * 100) : 100;
132
- const healthStatus = healthPercentage === 100 ? "HEALTHY" : healthPercentage >= 75 ? "WARNING" : healthPercentage >= 50 ? "ERROR" : "CRITICAL";
133
- const healthColor = healthPercentage === 100 ? _sharedUi.buoyColors.success : healthPercentage >= 75 ? _sharedUi.buoyColors.warning : healthPercentage >= 50 ? _sharedUi.buoyColors.error : _sharedUi.buoyColors.error;
134
- if (!visible) return null;
135
- const storagePrefix = enableSharedModalDimensions ? _sharedUi.devToolsStorageKeys.modal.root() : _sharedUi.devToolsStorageKeys.env.modal();
136
- const header = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
137
- children: [onBack && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
138
- onBack: onBack
139
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
140
- title: isSearchActive ? "" : "Environment Variables",
141
- noMargin: isSearchActive,
142
- children: isSearchActive && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Search, {
143
- value: searchQuery,
144
- onChangeText: setSearchQuery,
145
- onCancel: () => {
146
- setIsSearchActive(false);
147
- setSearchQuery("");
148
- },
149
- placeholder: "Search env keys...",
150
- accessibilityLabel: "Search env keys",
151
- testID: "buoy-env-search"
152
- // The field itself is a handle Detox can use but XCUITest
153
- // cannot: on this RN version a TextInput's testID never
154
- // reaches the XCUITest element tree — iOS folds the input
155
- // into the header's accessibility container. This wrapper
156
- // handle is the one the a11y lane can actually see.
157
- ,
158
- containerTestID: "buoy-env-search-field",
159
- clearTestID: "buoy-env-search-clear"
160
- })
161
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Actions, {
162
- children: !isSearchActive && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.HeaderSearchButton, {
163
- onPress: () => setIsSearchActive(true),
164
- testID: "buoy-env-search-open",
165
- accessibilityLabel: "Search env keys"
166
- })
167
- })]
168
- });
169
- const body = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
170
- style: styles.scrollContainer,
171
- contentContainerStyle: styles.contentContainer,
172
- showsVerticalScrollIndicator: false,
173
- testID: "buoy-env-scroll",
174
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_EnvStatsOverview.EnvStatsOverview, {
175
- stats: stats,
176
- healthPercentage: healthPercentage,
177
- healthStatus: healthStatus,
178
- healthColor: healthColor,
179
- activeFilter: activeFilter,
180
- onFilterChange: setActiveFilter
181
- }), filteredVars.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
182
- style: styles.varsSection,
183
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
184
- style: styles.sectionHeader,
185
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
186
- style: styles.sectionTitle,
187
- testID: "buoy-env-section-title",
188
- children: activeFilter === "all" ? "ALL VARIABLES" : activeFilter === "missing" ? "MISSING VARIABLES" : "ISSUES TO FIX"
189
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
190
- style: styles.countBadge,
191
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
192
- style: styles.countText,
193
- testID: "buoy-env-section-count",
194
- children: filteredVars.length
195
- })
196
- })]
197
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_EnvVarSection.EnvVarSection, {
198
- title: "",
199
- count: 0,
200
- vars: filteredVars,
201
- emptyMessage: ""
202
- })]
203
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
204
- testID: "buoy-env-empty",
205
- ...(0, _sharedUi.resolveListEmptyState)({
206
- subject: "variables",
207
- verb: "declared",
208
- search: searchQuery,
209
- total: allVars.length,
210
- waiting: {
211
- // A missing .env is a config problem, not a stream that has
212
- // not started — `keys` is the env-and-secrets state.
213
- otto: "keys",
214
- title: "No variables",
215
- message: `No ${activeFilter === "all" ? "" : activeFilter} variables found`
216
- }
217
- })
218
- })]
219
- });
220
-
221
- // The ONLY difference between the phone and the desktop dashboard is which
222
- // shell the header and body go in. Everything above this line is shared.
223
- if (inline) {
224
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
225
- style: styles.inlineRoot,
226
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
227
- style: styles.inlineHeader,
228
- ..._sharedUi.windowDragProps,
229
- children: header
230
- }), body]
231
- });
232
- }
233
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
234
- visible: visible,
235
- onClose: onClose,
236
- onMinimize: onMinimize,
237
- persistenceKey: storagePrefix,
238
- header: {
239
- customContent: header,
240
- showToggleButton: true
241
- },
242
- onModeChange: handleModeChange,
243
- enablePersistence: true,
244
- initialMode: "bottomSheet",
245
- enableGlitchEffects: true,
246
- styles: {},
247
- children: body
248
- });
249
- }
250
-
251
- /**
252
- * The same env tool as `EnvVarsModal`, rendered INLINE for hosts that place
253
- * tools in a panel. Exists so there is exactly one implementation — the desktop
254
- * dashboard used to ship its own copy of this component's internals.
255
- */
256
- function EnvToolView({
257
- requiredEnvVars
258
- }) {
259
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(EnvVarsModal, {
260
- inline: true,
261
- visible: true,
262
- requiredEnvVars: requiredEnvVars,
263
- onClose: () => {}
264
- });
265
- }
266
- const styles = _reactNative.StyleSheet.create({
267
- inlineRoot: {
268
- flex: 1,
269
- minHeight: 0,
270
- // Transparent so the desktop workbench's hoisted sky (one field spanning
271
- // sidebar + panel) shows through — the shell paints its base beneath it.
272
- backgroundColor: "transparent"
273
- },
274
- inlineHeader: {
275
- paddingHorizontal: 12,
276
- paddingVertical: 8,
277
- borderBottomWidth: 1,
278
- borderBottomColor: _sharedUi.buoyColors.border,
279
- // Clear, like Bench — the host's hoisted sky shows through the header.
280
- backgroundColor: "transparent"
281
- },
282
- scrollContainer: {
283
- flex: 1,
284
- // Transparent so JsModal's ToolBackground shows through (the modal paints opaque base beneath it).
285
- backgroundColor: "transparent"
286
- },
287
- contentContainer: {
288
- padding: 8,
289
- paddingBottom: 24
290
- },
291
- varsSection: {
292
- marginTop: 16
293
- },
294
- sectionHeader: {
295
- flexDirection: "row",
296
- justifyContent: "space-between",
297
- alignItems: "center",
298
- marginBottom: 8,
299
- paddingHorizontal: 8
300
- },
301
- sectionTitle: {
302
- fontSize: 10,
303
- fontWeight: "700",
304
- color: _sharedUi.night.color.textTertiary,
305
- letterSpacing: 1.2,
306
- fontFamily: _sharedUi.monoFont
307
- },
308
- countBadge: {
309
- backgroundColor: _sharedUi.night.color.accent + "15",
310
- paddingHorizontal: 8,
311
- paddingVertical: 2,
312
- borderRadius: 9999,
313
- borderWidth: 1,
314
- borderColor: _sharedUi.night.color.accent + "40"
315
- },
316
- countText: {
317
- fontSize: 10,
318
- fontWeight: "500",
319
- color: _sharedUi.night.color.accent,
320
- fontFamily: _sharedUi.monoFont
321
- }
322
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.EnvToolView=EnvToolView;exports.EnvVarsModal=EnvVarsModal;var _sharedUi=require("@buoy-gg/shared-ui");var _react=require("react");var _reactNative=require("react-native");var _EnvStatsOverview=require("./EnvStatsOverview");var _useDynamicEnv=require("../hooks/useDynamicEnv");var _utils=require("../utils");var _EnvVarSection=require("./EnvVarSection");var _jsxRuntime=require("react/jsx-runtime");function EnvVarsModal({visible:c,onClose:w,requiredEnvVars:u,onBack:f,onMinimize:V,enableSharedModalDimensions:E=false,inline:j=false}){const[o,M]=(0,_react.useState)("all");const[s,g]=(0,_react.useState)(false);const[a,y]=(0,_react.useState)("");const C=(0,_react.useRef)(null);const _=(0,_react.useCallback)(e=>{},[]);(0,_react.useEffect)(()=>{if(s&&C.current){C.current.focus()}},[s]);(0,_react.useEffect)(()=>{y("");g(false)},[o]);const p=(0,_useDynamicEnv.useDynamicEnv)();const d=(0,_react.useMemo)(()=>{const e={};p.forEach(({key:t,data:r})=>{if(r!==void 0&&r!==null){e[t]=typeof r==="string"?r:(0,_sharedUi.displayValue)(r)}});return e},[p]);const{requiredVars:h,optionalVars:i}=(0,_react.useMemo)(()=>{return(0,_utils.processEnvVars)(d,u)},[d,u]);const v=(0,_react.useMemo)(()=>{if(u===void 0){return{totalCount:0,requiredCount:0,optionalCount:0,presentRequiredCount:0,missingCount:0,wrongValueCount:0,wrongTypeCount:0}}return(0,_utils.calculateStats)(h,i,d)},[u,h,i,d]);const l=(0,_react.useMemo)(()=>{const e=[...h,...i];return e.sort((t,r)=>{const x={"required_missing":1,"required_wrong_type":2,"required_wrong_value":3,"required_present":4,"optional_present":5};return(x[t.status]||999)-(x[r.status]||999)})},[h,i]);const b=(0,_react.useMemo)(()=>{let e=[];switch(o){case"all":e=l;break;case"missing":e=l.filter(t=>t.status==="required_missing");break;case"issues":e=l.filter(t=>t.status==="required_wrong_type"||t.status==="required_wrong_value");break}if(a){const t=a.toLowerCase();e=e.filter(r=>r.key.toLowerCase().includes(t)||r.description?.toLowerCase().includes(t)||typeof r.value==="string"&&r.value.toLowerCase().includes(t))}return e},[l,i,o,a]);const n=v.requiredCount>0?Math.round(v.presentRequiredCount/v.requiredCount*100):100;const I=n===100?"HEALTHY":n>=75?"WARNING":n>=50?"ERROR":"CRITICAL";const T=n===100?_sharedUi.buoyColors.success:n>=75?_sharedUi.buoyColors.warning:n>=50?_sharedUi.buoyColors.error:_sharedUi.buoyColors.error;if(!c)return null;const q=E?_sharedUi.devToolsStorageKeys.modal.root():_sharedUi.devToolsStorageKeys.env.modal();const S=(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[f&&(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation,{onBack:f}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:s?"":"Environment Variables",noMargin:s,children:s&&(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Search,{value:a,onChangeText:y,onCancel:()=>{g(false);y("")},placeholder:"Search env keys...",accessibilityLabel:"Search env keys",testID:"buoy-env-search",containerTestID:"buoy-env-search-field",clearTestID:"buoy-env-search-clear"})}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Actions,{children:!s&&(0,_jsxRuntime.jsx)(_sharedUi.HeaderSearchButton,{onPress:()=>g(true),testID:"buoy-env-search-open",accessibilityLabel:"Search env keys"})})]});const m=(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.scrollContainer,contentContainerStyle:styles.contentContainer,showsVerticalScrollIndicator:false,testID:"buoy-env-scroll",children:[(0,_jsxRuntime.jsx)(_EnvStatsOverview.EnvStatsOverview,{stats:v,healthPercentage:n,healthStatus:I,healthColor:T,activeFilter:o,onFilterChange:M}),b.length>0?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.varsSection,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.sectionHeader,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.sectionTitle,testID:"buoy-env-section-title",children:o==="all"?"ALL VARIABLES":o==="missing"?"MISSING VARIABLES":"ISSUES TO FIX"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.countBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.countText,testID:"buoy-env-section-count",children:b.length})})]}),(0,_jsxRuntime.jsx)(_EnvVarSection.EnvVarSection,{title:"",count:0,vars:b,emptyMessage:""})]}):(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:"buoy-env-empty",...(0,_sharedUi.resolveListEmptyState)({subject:"variables",verb:"declared",search:a,total:l.length,waiting:{otto:"keys",title:"No variables",message:`No ${o==="all"?"":o} variables found`}})})]});if(j){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.inlineRoot,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.inlineHeader,..._sharedUi.windowDragProps,children:S}),m]})}return(0,_jsxRuntime.jsx)(_sharedUi.JsModal,{visible:c,onClose:w,onMinimize:V,persistenceKey:q,header:{customContent:S,showToggleButton:true},onModeChange:_,enablePersistence:true,initialMode:"bottomSheet",enableGlitchEffects:true,styles:{},children:m})}function EnvToolView({requiredEnvVars:c}){return(0,_jsxRuntime.jsx)(EnvVarsModal,{inline:true,visible:true,requiredEnvVars:c,onClose:()=>{}})}const styles=_reactNative.StyleSheet.create({inlineRoot:{flex:1,minHeight:0,backgroundColor:"transparent"},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:_sharedUi.buoyColors.border,backgroundColor:"transparent"},scrollContainer:{flex:1,backgroundColor:"transparent"},contentContainer:{padding:8,paddingBottom:24},varsSection:{marginTop:16},sectionHeader:{flexDirection:"row",justifyContent:"space-between",alignItems:"center",marginBottom:8,paddingHorizontal:8},sectionTitle:{fontSize:10,fontWeight:"700",color:_sharedUi.night.color.textTertiary,letterSpacing:1.2,fontFamily:_sharedUi.monoFont},countBadge:{backgroundColor:_sharedUi.night.color.accent+"15",paddingHorizontal:8,paddingVertical:2,borderRadius:9999,borderWidth:1,borderColor:_sharedUi.night.color.accent+"40"},countText:{fontSize:10,fontWeight:"500",color:_sharedUi.night.color.accent,fontFamily:_sharedUi.monoFont}});
@@ -1,92 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useDynamicEnv = useDynamicEnv;
7
- var _react = require("react");
8
- var _remoteEnv = require("../utils/remoteEnv");
9
- /**
10
- * Hook that returns all available environment variables with parsed values
11
- * Includes all available environment variables by default (only EXPO_PUBLIC_ prefixed vars are loaded by Expo)
12
- *
13
- * @example
14
- * // Get all available environment variables (only EXPO_PUBLIC_ prefixed)
15
- * const envVars = useDynamicEnv();
16
- * // Returns: [
17
- * // { key: 'EXPO_PUBLIC_API_URL', data: 'https://api.example.com' },
18
- * // { key: 'EXPO_PUBLIC_APP_NAME', data: 'MyApp' },
19
- * // ...
20
- * // ]
21
- *
22
- * @example
23
- * // Filter to specific variables
24
- * const envVars = useDynamicEnv({
25
- * envFilter: (key) => key.includes('API') || key.includes('URL')
26
- * });
27
- *
28
- * @example
29
- * // Filter by value content
30
- * const envVars = useDynamicEnv({
31
- * envFilter: (key, value) => value !== undefined && value.length > 0
32
- * });
33
- */
34
- function useDynamicEnv({
35
- envFilter = () => true // Default: include all available environment variables (EXPO_PUBLIC_ only)
36
- } = {}) {
37
- // In remote mirror mode (desktop dashboard) env values come from the
38
- // synced device instead of the local process.env
39
- const envSource =
40
- // @ts-ignore process.env does exist
41
- (0, _remoteEnv.getRemoteEnv)() ?? (typeof process === "undefined" ? {} : process.env);
42
-
43
- // Helper function to get a single environment variable value
44
- const getEnvValue = (0, _react.useMemo)(() => {
45
- return key => {
46
- const value = envSource[key];
47
- if (value === undefined) {
48
- return null;
49
- }
50
-
51
- // Try to parse as JSON for complex values, fall back to string
52
- try {
53
- // Only attempt JSON parsing if it looks like JSON (starts with { or [)
54
- if (value.startsWith("{") || value.startsWith("[")) {
55
- return JSON.parse(value);
56
- }
57
-
58
- // Parse boolean-like strings
59
- if (value.toLowerCase() === "true") return true;
60
- if (value.toLowerCase() === "false") return false;
61
-
62
- // Parse number-like strings
63
- if (/^\d+$/.test(value)) {
64
- const num = parseInt(value, 10);
65
- return !isNaN(num) ? num : value;
66
- }
67
- if (/^\d*\.\d+$/.test(value)) {
68
- const num = parseFloat(value);
69
- return !isNaN(num) ? num : value;
70
- }
71
- return value;
72
- } catch {
73
- return value;
74
- }
75
- };
76
- }, [envSource]);
77
-
78
- // Get all environment variables and process them
79
- const envResults = (0, _react.useMemo)(() => {
80
- const allEnvKeys = Object.keys(envSource);
81
- const filteredKeys = allEnvKeys.filter(key => {
82
- const value = envSource[key];
83
- return envFilter(key, value);
84
- });
85
- return filteredKeys.map(key => ({
86
- key,
87
- data: getEnvValue(key)
88
- }));
89
- // eslint-disable-next-line react-hooks/exhaustive-deps
90
- }, [envFilter, getEnvValue, envSource]);
91
- return envResults;
92
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.useDynamicEnv=useDynamicEnv;var _react=require("react");var _remoteEnv=require("../utils/remoteEnv");function useDynamicEnv({envFilter:s=()=>true}={}){const r=(0,_remoteEnv.getRemoteEnv)()??(typeof process==="undefined"?{}:process.env);const u=(0,_react.useMemo)(()=>{return n=>{const e=r[n];if(e===void 0){return null}try{if(e.startsWith("{")||e.startsWith("[")){return JSON.parse(e)}if(e.toLowerCase()==="true")return true;if(e.toLowerCase()==="false")return false;if(/^\d+$/.test(e)){const t=parseInt(e,10);return!isNaN(t)?t:e}if(/^\d*\.\d+$/.test(e)){const t=parseFloat(e);return!isNaN(t)?t:e}return e}catch{return e}}},[r]);const o=(0,_react.useMemo)(()=>{const n=Object.keys(r);const e=n.filter(t=>{const a=r[t];return s(t,a)});return e.map(t=>({key:t,data:u(t)}))},[s,u,r]);return o}
@@ -1,27 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- var _types = require("./types");
7
- Object.keys(_types).forEach(function (key) {
8
- if (key === "default" || key === "__esModule") return;
9
- if (key in exports && exports[key] === _types[key]) return;
10
- Object.defineProperty(exports, key, {
11
- enumerable: true,
12
- get: function () {
13
- return _types[key];
14
- }
15
- });
16
- });
17
- var _userTypes = require("./userTypes");
18
- Object.keys(_userTypes).forEach(function (key) {
19
- if (key === "default" || key === "__esModule") return;
20
- if (key in exports && exports[key] === _userTypes[key]) return;
21
- Object.defineProperty(exports, key, {
22
- enumerable: true,
23
- get: function () {
24
- return _userTypes[key];
25
- }
26
- });
27
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});var _types=require("./types");Object.keys(_types).forEach(function(e){if(e==="default"||e==="__esModule")return;if(e in exports&&exports[e]===_types[e])return;Object.defineProperty(exports,e,{enumerable:true,get:function(){return _types[e]}})});var _userTypes=require("./userTypes");Object.keys(_userTypes).forEach(function(e){if(e==="default"||e==="__esModule")return;if(e in exports&&exports[e]===_userTypes[e])return;Object.defineProperty(exports,e,{enumerable:true,get:function(){return _userTypes[e]}})});
@@ -1 +1 @@
1
- "use strict";
1
+ "use strict";
@@ -1 +1 @@
1
- "use strict";
1
+ "use strict";
@@ -1,59 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getEnvVarType = getEnvVarType;
7
- /**
8
- * Detects the type of an environment variable value
9
- * First checks if useDynamicEnv already parsed it to the correct type,
10
- * then analyzes string content to detect what type it represents
11
- *
12
- * @returns One of: "string", "number", "boolean", "array", "object"
13
- */
14
- function getEnvVarType(value) {
15
- // Check the actual parsed value type from useDynamicEnv
16
- const type = typeof value;
17
- if (type === "boolean") return "boolean";
18
- if (type === "number") return "number";
19
- if (Array.isArray(value)) return "array";
20
- if (type === "object" && value !== null) return "object";
21
-
22
- // For strings, check if they look like other types
23
- if (type === "string") {
24
- const strValue = value;
25
-
26
- // Check if it looks like JSON
27
- if (strValue.startsWith("{") && strValue.endsWith("}") || strValue.startsWith("[") && strValue.endsWith("]")) {
28
- try {
29
- const parsed = JSON.parse(strValue);
30
- return Array.isArray(parsed) ? "array" : "object";
31
- } catch {
32
- return "string";
33
- }
34
- }
35
-
36
- // Check if it's a boolean string
37
- const lowerStr = strValue.toLowerCase();
38
- if (lowerStr === "true" || lowerStr === "false" || lowerStr === "enabled" || lowerStr === "disabled" || lowerStr === "yes" || lowerStr === "no" || lowerStr === "on" || lowerStr === "off") {
39
- return "boolean";
40
- }
41
-
42
- // Check if it's a number string (including 1 and 0 as numbers, not booleans)
43
- if (!isNaN(Number(strValue)) && strValue.trim() !== "") {
44
- return "number";
45
- }
46
-
47
- // Check if it's a URL
48
- if (strValue.startsWith("http://") || strValue.startsWith("https://")) {
49
- return "url";
50
- }
51
-
52
- // Check if it's a comma-separated array
53
- if (strValue.includes(",")) {
54
- return "array";
55
- }
56
- return "string";
57
- }
58
- return "unknown";
59
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getEnvVarType=getEnvVarType;function getEnvVarType(e){const n=typeof e;if(n==="boolean")return"boolean";if(n==="number")return"number";if(Array.isArray(e))return"array";if(n==="object"&&e!==null)return"object";if(n==="string"){const r=e;if(r.startsWith("{")&&r.endsWith("}")||r.startsWith("[")&&r.endsWith("]")){try{const s=JSON.parse(r);return Array.isArray(s)?"array":"object"}catch{return"string"}}const t=r.toLowerCase();if(t==="true"||t==="false"||t==="enabled"||t==="disabled"||t==="yes"||t==="no"||t==="on"||t==="off"){return"boolean"}if(!isNaN(Number(r))&&r.trim()!==""){return"number"}if(r.startsWith("http://")||r.startsWith("https://")){return"url"}if(r.includes(",")){return"array"}return"string"}return"unknown"}
@@ -1,119 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.createEnvVarConfig = createEnvVarConfig;
7
- exports.envVar = envVar;
8
- /**
9
- * Helper to create a required env var configuration with type checking
10
- *
11
- * @example
12
- * const config = envVar("EXPO_PUBLIC_API_URL")
13
- * .withType("string")
14
- * .withDescription("Backend API endpoint")
15
- * .build();
16
- *
17
- * @example
18
- * const config = envVar("EXPO_PUBLIC_DEBUG_MODE")
19
- * .withDescription("Enable debug logging")
20
- * .withType("boolean")
21
- * .build();
22
- */
23
- class EnvVarBuilder {
24
- constructor(key) {
25
- this.key = key;
26
- }
27
- /** Just check if the variable exists */
28
- exists() {
29
- return this.key;
30
- }
31
-
32
- /** Check for a specific value */
33
- withValue(value) {
34
- this.expectedValue = value;
35
- delete this.expectedType; // Can't have both type and value
36
- return this;
37
- }
38
-
39
- /** Check for a specific type */
40
- withType(type) {
41
- this.expectedType = type;
42
- delete this.expectedValue; // Can't have both type and value
43
- return this;
44
- }
45
-
46
- /** Add a description for documentation */
47
- withDescription(desc) {
48
- this.description = desc;
49
- return this;
50
- }
51
-
52
- /** Build the final configuration */
53
- build() {
54
- if (this.expectedValue !== undefined) {
55
- return this.description ? {
56
- key: this.key,
57
- expectedValue: this.expectedValue,
58
- description: this.description
59
- } : {
60
- key: this.key,
61
- expectedValue: this.expectedValue
62
- };
63
- }
64
- if (this.expectedType !== undefined) {
65
- return this.description ? {
66
- key: this.key,
67
- expectedType: this.expectedType,
68
- description: this.description
69
- } : {
70
- key: this.key,
71
- expectedType: this.expectedType
72
- };
73
- }
74
-
75
- // If neither type nor value is specified, just check existence
76
- return this.key;
77
- }
78
- }
79
-
80
- /**
81
- * Fluent builder for defining expected environment variables. Helps teams author readable
82
- * `requiredEnvVars` arrays by chaining type/value/description requirements while keeping the
83
- * final shape compatible with `EnvVarsModal` and related helpers.
84
- *
85
- * @param key - Environment variable name to validate.
86
- * @returns Builder with convenience methods like `.withType()` and `.withValue()`.
87
- */
88
- function envVar(key) {
89
- return new EnvVarBuilder(key);
90
- }
91
-
92
- /**
93
- * Normalizes `requiredEnvVars` definitions while documenting intent in code. The helper simply
94
- * returns the provided array, but allows teams to co-locate examples and benefit from IDE hovers.
95
- *
96
- * @param vars - Collection of required environment variable definitions created manually or via `envVar()`.
97
- * @returns The original array, unchanged, for ergonomic chaining and inference.
98
- *
99
- * @example
100
- * const requiredEnvVars = createEnvVarConfig([
101
- * // Simple existence check
102
- * "EXPO_PUBLIC_API_URL",
103
- *
104
- * // Type checking
105
- * { key: "EXPO_PUBLIC_DEBUG_MODE", expectedType: "boolean" },
106
- *
107
- * // Value checking
108
- * { key: "EXPO_PUBLIC_ENVIRONMENT", expectedValue: "development" },
109
- *
110
- * // With descriptions
111
- * envVar("EXPO_PUBLIC_MAX_RETRIES")
112
- * .withType("number")
113
- * .withDescription("Maximum number of API retry attempts")
114
- * .build(),
115
- * ]);
116
- */
117
- function createEnvVarConfig(vars) {
118
- return vars;
119
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.createEnvVarConfig=createEnvVarConfig;exports.envVar=envVar;class EnvVarBuilder{constructor(e){this.key=e}exists(){return this.key}withValue(e){this.expectedValue=e;delete this.expectedType;return this}withType(e){this.expectedType=e;delete this.expectedValue;return this}withDescription(e){this.description=e;return this}build(){if(this.expectedValue!==void 0){return this.description?{key:this.key,expectedValue:this.expectedValue,description:this.description}:{key:this.key,expectedValue:this.expectedValue}}if(this.expectedType!==void 0){return this.description?{key:this.key,expectedType:this.expectedType,description:this.description}:{key:this.key,expectedType:this.expectedType}}return this.key}}function envVar(t){return new EnvVarBuilder(t)}function createEnvVarConfig(t){return t}