@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.
- package/README.md +11 -87
- package/lib/commonjs/env/components/EnvStatsOverview.js +1 -159
- package/lib/commonjs/env/components/EnvVarRow.js +1 -189
- package/lib/commonjs/env/components/EnvVarSection.js +1 -84
- package/lib/commonjs/env/components/EnvVarsModal.js +1 -322
- package/lib/commonjs/env/hooks/useDynamicEnv.js +1 -92
- package/lib/commonjs/env/types/index.js +1 -27
- package/lib/commonjs/env/types/types.js +1 -1
- package/lib/commonjs/env/types/userTypes.js +1 -1
- package/lib/commonjs/env/utils/envTypeDetector.js +1 -59
- package/lib/commonjs/env/utils/helpers.js +1 -119
- package/lib/commonjs/env/utils/index.js +1 -38
- package/lib/commonjs/env/utils/remoteEnv.js +1 -24
- package/lib/commonjs/env/utils/utils.js +1 -121
- package/lib/commonjs/index.js +1 -77
- package/lib/commonjs/preset.js +1 -81
- package/lib/commonjs/sync/envSyncAdapter.js +1 -51
- package/lib/module/env/components/EnvStatsOverview.js +1 -155
- package/lib/module/env/components/EnvVarRow.js +1 -185
- package/lib/module/env/components/EnvVarSection.js +1 -80
- package/lib/module/env/components/EnvVarsModal.js +1 -317
- package/lib/module/env/hooks/useDynamicEnv.js +1 -88
- package/lib/module/env/types/index.js +1 -4
- package/lib/module/env/types/types.js +1 -1
- package/lib/module/env/types/userTypes.js +1 -1
- package/lib/module/env/utils/envTypeDetector.js +1 -55
- package/lib/module/env/utils/helpers.js +1 -114
- package/lib/module/env/utils/index.js +1 -5
- package/lib/module/env/utils/remoteEnv.js +1 -19
- package/lib/module/env/utils/utils.js +1 -116
- package/lib/module/index.js +1 -21
- package/lib/module/preset.js +1 -78
- package/lib/module/sync/envSyncAdapter.js +1 -46
- package/lib/web/index.mjs +1 -2
- package/package.json +4 -7
- package/lib/typescript/env/components/EnvStatsOverview.d.ts.map +0 -1
- package/lib/typescript/env/components/EnvVarRow.d.ts.map +0 -1
- package/lib/typescript/env/components/EnvVarSection.d.ts.map +0 -1
- package/lib/typescript/env/components/EnvVarsModal.d.ts.map +0 -1
- package/lib/typescript/env/hooks/useDynamicEnv.d.ts.map +0 -1
- package/lib/typescript/env/types/index.d.ts.map +0 -1
- package/lib/typescript/env/types/types.d.ts.map +0 -1
- package/lib/typescript/env/types/userTypes.d.ts.map +0 -1
- package/lib/typescript/env/utils/envTypeDetector.d.ts.map +0 -1
- package/lib/typescript/env/utils/helpers.d.ts.map +0 -1
- package/lib/typescript/env/utils/index.d.ts.map +0 -1
- package/lib/typescript/env/utils/remoteEnv.d.ts.map +0 -1
- package/lib/typescript/env/utils/utils.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- 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}
|