@buoy-gg/env 1.7.2
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 +388 -0
- package/lib/commonjs/env/EnvVariables.js +25 -0
- package/lib/commonjs/env/components/EnvStatsOverview.js +134 -0
- package/lib/commonjs/env/components/EnvVarRow.js +170 -0
- package/lib/commonjs/env/components/EnvVarSection.js +84 -0
- package/lib/commonjs/env/components/EnvVarsModal.js +315 -0
- package/lib/commonjs/env/hooks/useDynamicEnv.js +87 -0
- package/lib/commonjs/env/index.js +16 -0
- package/lib/commonjs/env/types/index.js +27 -0
- package/lib/commonjs/env/types/types.js +1 -0
- package/lib/commonjs/env/types/userTypes.js +1 -0
- package/lib/commonjs/env/utils/envTypeDetector.js +59 -0
- package/lib/commonjs/env/utils/helpers.js +119 -0
- package/lib/commonjs/env/utils/index.js +38 -0
- package/lib/commonjs/env/utils/utils.js +121 -0
- package/lib/commonjs/index.js +54 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/preset.js +90 -0
- package/lib/module/env/EnvVariables.js +11 -0
- package/lib/module/env/components/EnvStatsOverview.js +130 -0
- package/lib/module/env/components/EnvVarRow.js +166 -0
- package/lib/module/env/components/EnvVarSection.js +80 -0
- package/lib/module/env/components/EnvVarsModal.js +311 -0
- package/lib/module/env/hooks/useDynamicEnv.js +83 -0
- package/lib/module/env/index.js +3 -0
- package/lib/module/env/types/index.js +4 -0
- package/lib/module/env/types/types.js +1 -0
- package/lib/module/env/types/userTypes.js +1 -0
- package/lib/module/env/utils/envTypeDetector.js +55 -0
- package/lib/module/env/utils/helpers.js +114 -0
- package/lib/module/env/utils/index.js +5 -0
- package/lib/module/env/utils/utils.js +116 -0
- package/lib/module/index.js +13 -0
- package/lib/module/preset.js +85 -0
- package/lib/typescript/env/EnvVariables.d.ts +8 -0
- package/lib/typescript/env/EnvVariables.d.ts.map +1 -0
- package/lib/typescript/env/components/EnvStatsOverview.d.ts +20 -0
- package/lib/typescript/env/components/EnvStatsOverview.d.ts.map +1 -0
- package/lib/typescript/env/components/EnvVarRow.d.ts +9 -0
- package/lib/typescript/env/components/EnvVarRow.d.ts.map +1 -0
- package/lib/typescript/env/components/EnvVarSection.d.ts +10 -0
- package/lib/typescript/env/components/EnvVarSection.d.ts.map +1 -0
- package/lib/typescript/env/components/EnvVarsModal.d.ts +26 -0
- package/lib/typescript/env/components/EnvVarsModal.d.ts.map +1 -0
- package/lib/typescript/env/hooks/useDynamicEnv.d.ts +39 -0
- package/lib/typescript/env/hooks/useDynamicEnv.d.ts.map +1 -0
- package/lib/typescript/env/index.d.ts +2 -0
- package/lib/typescript/env/index.d.ts.map +1 -0
- package/lib/typescript/env/types/index.d.ts +3 -0
- package/lib/typescript/env/types/index.d.ts.map +1 -0
- package/lib/typescript/env/types/types.d.ts +67 -0
- package/lib/typescript/env/types/types.d.ts.map +1 -0
- package/lib/typescript/env/types/userTypes.d.ts +3 -0
- package/lib/typescript/env/types/userTypes.d.ts.map +1 -0
- package/lib/typescript/env/utils/envTypeDetector.d.ts +10 -0
- package/lib/typescript/env/utils/envTypeDetector.d.ts.map +1 -0
- package/lib/typescript/env/utils/helpers.d.ts +70 -0
- package/lib/typescript/env/utils/helpers.d.ts.map +1 -0
- package/lib/typescript/env/utils/index.d.ts +4 -0
- package/lib/typescript/env/utils/index.d.ts.map +1 -0
- package/lib/typescript/env/utils/utils.d.ts +24 -0
- package/lib/typescript/env/utils/utils.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +5 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/preset.d.ts +86 -0
- package/lib/typescript/preset.d.ts.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.EnvVarSection = EnvVarSection;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _EnvVarRow = require("./EnvVarRow");
|
|
10
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
11
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
function EnvVarSection({
|
|
13
|
+
title,
|
|
14
|
+
count,
|
|
15
|
+
vars,
|
|
16
|
+
emptyMessage
|
|
17
|
+
}) {
|
|
18
|
+
const [expandedVar, setExpandedVar] = (0, _react.useState)(null);
|
|
19
|
+
const handleVarPress = (0, _react.useCallback)(envVar => {
|
|
20
|
+
setExpandedVar(prev => prev === envVar.key ? null : envVar.key);
|
|
21
|
+
}, []);
|
|
22
|
+
if (vars.length === 0 && title === "Required Variables") {
|
|
23
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
24
|
+
style: styles.sectionContainer,
|
|
25
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.SectionHeader, {
|
|
26
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Title, {
|
|
27
|
+
children: title
|
|
28
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Badge, {
|
|
29
|
+
count: 0,
|
|
30
|
+
color: _sharedUi.buoyColors.primary
|
|
31
|
+
})]
|
|
32
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
33
|
+
style: styles.emptySection,
|
|
34
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
35
|
+
style: styles.emptySectionText,
|
|
36
|
+
children: emptyMessage
|
|
37
|
+
})
|
|
38
|
+
})]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (vars.length === 0) return null;
|
|
42
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
43
|
+
style: styles.sectionContainer,
|
|
44
|
+
children: [title !== "" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.SectionHeader, {
|
|
45
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Title, {
|
|
46
|
+
children: title
|
|
47
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.SectionHeader.Badge, {
|
|
48
|
+
count: count,
|
|
49
|
+
color: _sharedUi.buoyColors.primary
|
|
50
|
+
})]
|
|
51
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
52
|
+
style: styles.sectionContent,
|
|
53
|
+
children: vars.map(envVar => /*#__PURE__*/(0, _jsxRuntime.jsx)(_EnvVarRow.EnvVarRow, {
|
|
54
|
+
envVar: envVar,
|
|
55
|
+
isExpanded: expandedVar === envVar.key,
|
|
56
|
+
onPress: handleVarPress
|
|
57
|
+
}, envVar.key))
|
|
58
|
+
})]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const styles = _reactNative.StyleSheet.create({
|
|
62
|
+
sectionContainer: {
|
|
63
|
+
gap: 8
|
|
64
|
+
},
|
|
65
|
+
sectionContent: {
|
|
66
|
+
// No gap needed, EnvVarRow has its own margins
|
|
67
|
+
},
|
|
68
|
+
emptySection: {
|
|
69
|
+
padding: 20,
|
|
70
|
+
backgroundColor: _sharedUi.buoyColors.primary + "08",
|
|
71
|
+
borderRadius: 8,
|
|
72
|
+
borderWidth: 1,
|
|
73
|
+
borderColor: _sharedUi.buoyColors.primary + "20",
|
|
74
|
+
alignItems: "center"
|
|
75
|
+
},
|
|
76
|
+
emptySectionText: {
|
|
77
|
+
color: _sharedUi.buoyColors.primary,
|
|
78
|
+
fontSize: 11,
|
|
79
|
+
textAlign: "center",
|
|
80
|
+
fontFamily: "monospace",
|
|
81
|
+
opacity: 0.8,
|
|
82
|
+
letterSpacing: 0.5
|
|
83
|
+
}
|
|
84
|
+
});
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.EnvVarsModal = EnvVarsModal;
|
|
7
|
+
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _reactNative = require("react-native");
|
|
10
|
+
var _EnvStatsOverview = require("./EnvStatsOverview");
|
|
11
|
+
var _useDynamicEnv = require("../hooks/useDynamicEnv");
|
|
12
|
+
var _utils = require("../utils");
|
|
13
|
+
var _EnvVarSection = require("./EnvVarSection");
|
|
14
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
|
+
/**
|
|
16
|
+
* Full-screen modal for inspecting required environment variables. Handles automatic
|
|
17
|
+
* discovery, validation, filtering, and rich search so teams can quickly spot missing
|
|
18
|
+
* or misconfigured values during development sessions.
|
|
19
|
+
*/
|
|
20
|
+
function EnvVarsModal({
|
|
21
|
+
visible,
|
|
22
|
+
onClose,
|
|
23
|
+
requiredEnvVars,
|
|
24
|
+
onBack,
|
|
25
|
+
onMinimize,
|
|
26
|
+
enableSharedModalDimensions = false
|
|
27
|
+
}) {
|
|
28
|
+
const [activeFilter, setActiveFilter] = (0, _react.useState)("all");
|
|
29
|
+
const [isSearchActive, setIsSearchActive] = (0, _react.useState)(false);
|
|
30
|
+
const [searchQuery, setSearchQuery] = (0, _react.useState)("");
|
|
31
|
+
const searchInputRef = (0, _react.useRef)(null);
|
|
32
|
+
const handleModeChange = (0, _react.useCallback)(_mode => {
|
|
33
|
+
// Mode changes handled by JsModal
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
// Focus search input when search becomes active
|
|
37
|
+
(0, _react.useEffect)(() => {
|
|
38
|
+
if (isSearchActive && searchInputRef.current) {
|
|
39
|
+
searchInputRef.current.focus();
|
|
40
|
+
}
|
|
41
|
+
}, [isSearchActive]);
|
|
42
|
+
|
|
43
|
+
// Clear search when changing filters
|
|
44
|
+
(0, _react.useEffect)(() => {
|
|
45
|
+
setSearchQuery("");
|
|
46
|
+
setIsSearchActive(false);
|
|
47
|
+
}, [activeFilter]);
|
|
48
|
+
|
|
49
|
+
// Auto-collect environment variables
|
|
50
|
+
const envResults = (0, _useDynamicEnv.useDynamicEnv)();
|
|
51
|
+
const autoCollectedEnvVars = (0, _react.useMemo)(() => {
|
|
52
|
+
const envVars = {};
|
|
53
|
+
envResults.forEach(({
|
|
54
|
+
key,
|
|
55
|
+
data
|
|
56
|
+
}) => {
|
|
57
|
+
if (data !== undefined && data !== null) {
|
|
58
|
+
envVars[key] = typeof data === "string" ? data : (0, _sharedUi.displayValue)(data);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
return envVars;
|
|
62
|
+
}, [envResults]);
|
|
63
|
+
|
|
64
|
+
// Process and categorize environment variables
|
|
65
|
+
const {
|
|
66
|
+
requiredVars,
|
|
67
|
+
optionalVars
|
|
68
|
+
} = (0, _react.useMemo)(() => {
|
|
69
|
+
return (0, _utils.processEnvVars)(autoCollectedEnvVars, requiredEnvVars);
|
|
70
|
+
}, [autoCollectedEnvVars, requiredEnvVars]);
|
|
71
|
+
|
|
72
|
+
// Calculate statistics
|
|
73
|
+
const stats = (0, _react.useMemo)(() => {
|
|
74
|
+
if (requiredEnvVars === undefined) {
|
|
75
|
+
return {
|
|
76
|
+
totalCount: 0,
|
|
77
|
+
requiredCount: 0,
|
|
78
|
+
optionalCount: 0,
|
|
79
|
+
presentRequiredCount: 0,
|
|
80
|
+
missingCount: 0,
|
|
81
|
+
wrongValueCount: 0,
|
|
82
|
+
wrongTypeCount: 0
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return (0, _utils.calculateStats)(requiredVars, optionalVars, autoCollectedEnvVars);
|
|
86
|
+
}, [requiredEnvVars, requiredVars, optionalVars, autoCollectedEnvVars]);
|
|
87
|
+
|
|
88
|
+
// Combine all vars and sort by priority (issues first)
|
|
89
|
+
const allVars = (0, _react.useMemo)(() => {
|
|
90
|
+
const combined = [...requiredVars, ...optionalVars];
|
|
91
|
+
|
|
92
|
+
// Sort by status priority: errors first, then warnings, then valid
|
|
93
|
+
return combined.sort((a, b) => {
|
|
94
|
+
const priorityMap = {
|
|
95
|
+
"required_missing": 1,
|
|
96
|
+
"required_wrong_type": 2,
|
|
97
|
+
"required_wrong_value": 3,
|
|
98
|
+
"required_present": 4,
|
|
99
|
+
"optional_present": 5
|
|
100
|
+
};
|
|
101
|
+
return (priorityMap[a.status] || 999) - (priorityMap[b.status] || 999);
|
|
102
|
+
});
|
|
103
|
+
}, [requiredVars, optionalVars]);
|
|
104
|
+
|
|
105
|
+
// Filter variables based on active filter and search
|
|
106
|
+
const filteredVars = (0, _react.useMemo)(() => {
|
|
107
|
+
let vars = [];
|
|
108
|
+
switch (activeFilter) {
|
|
109
|
+
case "all":
|
|
110
|
+
vars = allVars;
|
|
111
|
+
break;
|
|
112
|
+
case "missing":
|
|
113
|
+
vars = allVars.filter(v => v.status === "required_missing");
|
|
114
|
+
break;
|
|
115
|
+
case "issues":
|
|
116
|
+
vars = allVars.filter(v => v.status === "required_wrong_type" || v.status === "required_wrong_value");
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Apply search filter
|
|
121
|
+
if (searchQuery) {
|
|
122
|
+
const query = searchQuery.toLowerCase();
|
|
123
|
+
vars = vars.filter(v => v.key.toLowerCase().includes(query) || v.description?.toLowerCase().includes(query) || typeof v.value === 'string' && v.value.toLowerCase().includes(query));
|
|
124
|
+
}
|
|
125
|
+
return vars;
|
|
126
|
+
}, [allVars, optionalVars, activeFilter, searchQuery]);
|
|
127
|
+
|
|
128
|
+
// Calculate health percentage
|
|
129
|
+
const healthPercentage = stats.requiredCount > 0 ? Math.round(stats.presentRequiredCount / stats.requiredCount * 100) : 100;
|
|
130
|
+
const healthStatus = healthPercentage === 100 ? "HEALTHY" : healthPercentage >= 75 ? "WARNING" : healthPercentage >= 50 ? "ERROR" : "CRITICAL";
|
|
131
|
+
const healthColor = healthPercentage === 100 ? _sharedUi.buoyColors.success : healthPercentage >= 75 ? _sharedUi.buoyColors.warning : healthPercentage >= 50 ? _sharedUi.buoyColors.error : _sharedUi.buoyColors.error;
|
|
132
|
+
if (!visible) return null;
|
|
133
|
+
const storagePrefix = enableSharedModalDimensions ? _sharedUi.devToolsStorageKeys.modal.root() : _sharedUi.devToolsStorageKeys.env.modal();
|
|
134
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
|
|
135
|
+
visible: visible,
|
|
136
|
+
onClose: onClose,
|
|
137
|
+
onMinimize: onMinimize,
|
|
138
|
+
persistenceKey: storagePrefix,
|
|
139
|
+
header: {
|
|
140
|
+
customContent: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
|
|
141
|
+
children: [onBack && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
|
|
142
|
+
onBack: onBack
|
|
143
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
|
|
144
|
+
title: isSearchActive ? "" : "Environment Variables",
|
|
145
|
+
noMargin: isSearchActive,
|
|
146
|
+
children: isSearchActive && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
147
|
+
style: styles.headerSearchContainer,
|
|
148
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
|
|
149
|
+
size: 12,
|
|
150
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
151
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
|
|
152
|
+
ref: searchInputRef,
|
|
153
|
+
style: styles.headerSearchInput,
|
|
154
|
+
placeholder: "Search env keys...",
|
|
155
|
+
placeholderTextColor: _sharedUi.buoyColors.textMuted,
|
|
156
|
+
value: searchQuery,
|
|
157
|
+
onChangeText: setSearchQuery,
|
|
158
|
+
autoCorrect: false,
|
|
159
|
+
autoCapitalize: "none"
|
|
160
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
161
|
+
onPress: () => {
|
|
162
|
+
setIsSearchActive(false);
|
|
163
|
+
setSearchQuery("");
|
|
164
|
+
},
|
|
165
|
+
style: styles.clearButton,
|
|
166
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.X, {
|
|
167
|
+
size: 12,
|
|
168
|
+
color: _sharedUi.buoyColors.textSecondary
|
|
169
|
+
})
|
|
170
|
+
})]
|
|
171
|
+
})
|
|
172
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Actions, {
|
|
173
|
+
children: !isSearchActive && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.HeaderSearchButton, {
|
|
174
|
+
onPress: () => setIsSearchActive(true)
|
|
175
|
+
})
|
|
176
|
+
})]
|
|
177
|
+
}),
|
|
178
|
+
showToggleButton: true
|
|
179
|
+
},
|
|
180
|
+
onModeChange: handleModeChange,
|
|
181
|
+
enablePersistence: true,
|
|
182
|
+
initialMode: "bottomSheet",
|
|
183
|
+
enableGlitchEffects: true,
|
|
184
|
+
styles: {},
|
|
185
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
|
|
186
|
+
style: styles.scrollContainer,
|
|
187
|
+
contentContainerStyle: styles.contentContainer,
|
|
188
|
+
showsVerticalScrollIndicator: false,
|
|
189
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_EnvStatsOverview.EnvStatsOverview, {
|
|
190
|
+
stats: stats,
|
|
191
|
+
healthPercentage: healthPercentage,
|
|
192
|
+
healthStatus: healthStatus,
|
|
193
|
+
healthColor: healthColor,
|
|
194
|
+
activeFilter: activeFilter,
|
|
195
|
+
onFilterChange: setActiveFilter
|
|
196
|
+
}), filteredVars.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
197
|
+
style: styles.varsSection,
|
|
198
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
199
|
+
style: styles.sectionHeader,
|
|
200
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
201
|
+
style: styles.sectionTitle,
|
|
202
|
+
children: activeFilter === "all" ? "ALL VARIABLES" : activeFilter === "missing" ? "MISSING VARIABLES" : "ISSUES TO FIX"
|
|
203
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
204
|
+
style: styles.countBadge,
|
|
205
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
206
|
+
style: styles.countText,
|
|
207
|
+
children: filteredVars.length
|
|
208
|
+
})
|
|
209
|
+
})]
|
|
210
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_EnvVarSection.EnvVarSection, {
|
|
211
|
+
title: "",
|
|
212
|
+
count: 0,
|
|
213
|
+
vars: filteredVars,
|
|
214
|
+
emptyMessage: ""
|
|
215
|
+
})]
|
|
216
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
217
|
+
style: styles.emptyState,
|
|
218
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Search, {
|
|
219
|
+
size: 32,
|
|
220
|
+
color: _sharedUi.buoyColors.textMuted
|
|
221
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
222
|
+
style: styles.emptyTitle,
|
|
223
|
+
children: searchQuery ? "No results found" : "No variables"
|
|
224
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
225
|
+
style: styles.emptySubtitle,
|
|
226
|
+
children: searchQuery ? `No variables matching "${searchQuery}"` : `No ${activeFilter === "all" ? "" : activeFilter} variables found`
|
|
227
|
+
})]
|
|
228
|
+
})]
|
|
229
|
+
})
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const styles = _reactNative.StyleSheet.create({
|
|
233
|
+
scrollContainer: {
|
|
234
|
+
flex: 1,
|
|
235
|
+
backgroundColor: _sharedUi.buoyColors.base
|
|
236
|
+
},
|
|
237
|
+
contentContainer: {
|
|
238
|
+
padding: 8,
|
|
239
|
+
paddingBottom: 24
|
|
240
|
+
},
|
|
241
|
+
headerSearchContainer: {
|
|
242
|
+
flexDirection: "row",
|
|
243
|
+
alignItems: "center",
|
|
244
|
+
flex: 1,
|
|
245
|
+
backgroundColor: _sharedUi.buoyColors.input,
|
|
246
|
+
borderRadius: 6,
|
|
247
|
+
paddingHorizontal: 10,
|
|
248
|
+
paddingVertical: 4,
|
|
249
|
+
marginHorizontal: 12,
|
|
250
|
+
marginVertical: 4,
|
|
251
|
+
height: 32,
|
|
252
|
+
borderWidth: 1,
|
|
253
|
+
borderColor: _sharedUi.buoyColors.border
|
|
254
|
+
},
|
|
255
|
+
headerSearchInput: {
|
|
256
|
+
flex: 1,
|
|
257
|
+
marginLeft: 8,
|
|
258
|
+
fontSize: 13,
|
|
259
|
+
color: _sharedUi.buoyColors.text,
|
|
260
|
+
padding: 0,
|
|
261
|
+
height: '100%'
|
|
262
|
+
},
|
|
263
|
+
clearButton: {
|
|
264
|
+
padding: 4,
|
|
265
|
+
marginLeft: 4
|
|
266
|
+
},
|
|
267
|
+
varsSection: {
|
|
268
|
+
marginTop: 16
|
|
269
|
+
},
|
|
270
|
+
sectionHeader: {
|
|
271
|
+
flexDirection: "row",
|
|
272
|
+
justifyContent: "space-between",
|
|
273
|
+
alignItems: "center",
|
|
274
|
+
marginBottom: 8,
|
|
275
|
+
paddingHorizontal: 8
|
|
276
|
+
},
|
|
277
|
+
sectionTitle: {
|
|
278
|
+
fontSize: 10,
|
|
279
|
+
fontWeight: "700",
|
|
280
|
+
color: _sharedUi.buoyColors.textMuted,
|
|
281
|
+
letterSpacing: 1.2,
|
|
282
|
+
fontFamily: "monospace"
|
|
283
|
+
},
|
|
284
|
+
countBadge: {
|
|
285
|
+
backgroundColor: _sharedUi.buoyColors.primary + "15",
|
|
286
|
+
paddingHorizontal: 8,
|
|
287
|
+
paddingVertical: 2,
|
|
288
|
+
borderRadius: 9999,
|
|
289
|
+
borderWidth: 1,
|
|
290
|
+
borderColor: _sharedUi.buoyColors.primary + "40"
|
|
291
|
+
},
|
|
292
|
+
countText: {
|
|
293
|
+
fontSize: 10,
|
|
294
|
+
fontWeight: "500",
|
|
295
|
+
color: _sharedUi.buoyColors.primary,
|
|
296
|
+
fontFamily: "monospace"
|
|
297
|
+
},
|
|
298
|
+
emptyState: {
|
|
299
|
+
alignItems: "center",
|
|
300
|
+
justifyContent: "center",
|
|
301
|
+
paddingVertical: 48
|
|
302
|
+
},
|
|
303
|
+
emptyTitle: {
|
|
304
|
+
fontSize: 16,
|
|
305
|
+
fontWeight: "600",
|
|
306
|
+
color: _sharedUi.buoyColors.text,
|
|
307
|
+
marginTop: 12,
|
|
308
|
+
marginBottom: 8
|
|
309
|
+
},
|
|
310
|
+
emptySubtitle: {
|
|
311
|
+
fontSize: 13,
|
|
312
|
+
color: _sharedUi.buoyColors.textSecondary,
|
|
313
|
+
textAlign: "center"
|
|
314
|
+
}
|
|
315
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useDynamicEnv = useDynamicEnv;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
/**
|
|
9
|
+
* Hook that returns all available environment variables with parsed values
|
|
10
|
+
* Includes all available environment variables by default (only EXPO_PUBLIC_ prefixed vars are loaded by Expo)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Get all available environment variables (only EXPO_PUBLIC_ prefixed)
|
|
14
|
+
* const envVars = useDynamicEnv();
|
|
15
|
+
* // Returns: [
|
|
16
|
+
* // { key: 'EXPO_PUBLIC_API_URL', data: 'https://api.example.com' },
|
|
17
|
+
* // { key: 'EXPO_PUBLIC_APP_NAME', data: 'MyApp' },
|
|
18
|
+
* // ...
|
|
19
|
+
* // ]
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Filter to specific variables
|
|
23
|
+
* const envVars = useDynamicEnv({
|
|
24
|
+
* envFilter: (key) => key.includes('API') || key.includes('URL')
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Filter by value content
|
|
29
|
+
* const envVars = useDynamicEnv({
|
|
30
|
+
* envFilter: (key, value) => value !== undefined && value.length > 0
|
|
31
|
+
* });
|
|
32
|
+
*/
|
|
33
|
+
function useDynamicEnv({
|
|
34
|
+
envFilter = () => true // Default: include all available environment variables (EXPO_PUBLIC_ only)
|
|
35
|
+
} = {}) {
|
|
36
|
+
// Helper function to get a single environment variable value
|
|
37
|
+
const getEnvValue = (0, _react.useMemo)(() => {
|
|
38
|
+
return key => {
|
|
39
|
+
// @ts-ignore thhis does exist
|
|
40
|
+
const value = process.env[key];
|
|
41
|
+
if (value === undefined) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Try to parse as JSON for complex values, fall back to string
|
|
46
|
+
try {
|
|
47
|
+
// Only attempt JSON parsing if it looks like JSON (starts with { or [)
|
|
48
|
+
if (value.startsWith("{") || value.startsWith("[")) {
|
|
49
|
+
return JSON.parse(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Parse boolean-like strings
|
|
53
|
+
if (value.toLowerCase() === "true") return true;
|
|
54
|
+
if (value.toLowerCase() === "false") return false;
|
|
55
|
+
|
|
56
|
+
// Parse number-like strings
|
|
57
|
+
if (/^\d+$/.test(value)) {
|
|
58
|
+
const num = parseInt(value, 10);
|
|
59
|
+
return !isNaN(num) ? num : value;
|
|
60
|
+
}
|
|
61
|
+
if (/^\d*\.\d+$/.test(value)) {
|
|
62
|
+
const num = parseFloat(value);
|
|
63
|
+
return !isNaN(num) ? num : value;
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
} catch {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
72
|
+
// Get all environment variables and process them
|
|
73
|
+
const envResults = (0, _react.useMemo)(() => {
|
|
74
|
+
// @ts-ignore thhis does exist
|
|
75
|
+
const allEnvKeys = Object.keys(process.env);
|
|
76
|
+
const filteredKeys = allEnvKeys.filter(key => {
|
|
77
|
+
// @ts-ignore thhis does exist
|
|
78
|
+
const value = process.env[key];
|
|
79
|
+
return envFilter(key, value);
|
|
80
|
+
});
|
|
81
|
+
return filteredKeys.map(key => ({
|
|
82
|
+
key,
|
|
83
|
+
data: getEnvValue(key)
|
|
84
|
+
}));
|
|
85
|
+
}, [envFilter, getEnvValue]);
|
|
86
|
+
return envResults;
|
|
87
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _EnvVariables = require("./EnvVariables");
|
|
7
|
+
Object.keys(_EnvVariables).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _EnvVariables[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _EnvVariables[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
}
|