@optique/env 1.0.0-dev.1616 → 1.0.0-dev.1658

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/dist/index.cjs CHANGED
@@ -24,9 +24,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  const __optique_core_annotations = __toESM(require("@optique/core/annotations"));
25
25
  const __optique_core_message = __toESM(require("@optique/core/message"));
26
26
  const __optique_core_mode_dispatch = __toESM(require("@optique/core/mode-dispatch"));
27
+ const __optique_core_parser = __toESM(require("@optique/core/parser"));
27
28
  const __optique_core_valueparser = __toESM(require("@optique/core/valueparser"));
28
29
 
29
30
  //#region src/index.ts
31
+ const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
30
32
  const activeEnvSourceRegistry = /* @__PURE__ */ new Map();
31
33
  /**
32
34
  * Sets active environment source data for a context.
@@ -127,6 +129,7 @@ function bindEnv(parser, options) {
127
129
  $valueType: parser.$valueType,
128
130
  $stateType: parser.$stateType,
129
131
  priority: parser.priority,
132
+ [__optique_core_parser.unmatchedNonCliDependencySourceStateMarker]: true,
130
133
  usage: options.default !== void 0 ? [{
131
134
  type: "optional",
132
135
  terms: parser.usage
@@ -134,6 +137,15 @@ function bindEnv(parser, options) {
134
137
  leadingNames: parser.leadingNames,
135
138
  acceptingAnyToken: parser.acceptingAnyToken,
136
139
  initialState: parser.initialState,
140
+ getSuggestRuntimeNodes(state, path) {
141
+ const innerState = isEnvBindState(state) ? state.cliState === void 0 ? parser.initialState : state.cliState : state;
142
+ const innerNodes = parser.getSuggestRuntimeNodes?.(innerState, path) ?? [];
143
+ return boundParser.dependencyMetadata?.source != null ? [...innerNodes, {
144
+ path,
145
+ parser: boundParser,
146
+ state
147
+ }] : innerNodes;
148
+ },
137
149
  parse: (context) => {
138
150
  const annotations = (0, __optique_core_annotations.getAnnotations)(context.state);
139
151
  const innerState = isEnvBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
@@ -178,7 +190,7 @@ function bindEnv(parser, options) {
178
190
  },
179
191
  complete: (state, exec) => {
180
192
  if (isEnvBindState(state) && state.hasCliValue) return parser.complete(state.cliState, exec);
181
- return getEnvOrDefault(state, options, parser.$mode, parser, isEnvBindState(state) ? state.cliState : void 0, exec);
193
+ return getEnvOrDefault(state, options, parser.$mode, parser, isEnvBindState(state) ? state.cliState : (0, __optique_core_annotations.isInjectedAnnotationWrapper)(state) ? void 0 : state, exec);
182
194
  },
183
195
  suggest: parser.suggest,
184
196
  ...typeof deferPromptUntilConfigResolves === "function" ? { shouldDeferCompletion: (state, exec) => deferPromptUntilConfigResolves.call(parser, state, exec) } : {},
@@ -187,6 +199,10 @@ function bindEnv(parser, options) {
187
199
  return parser.getDocFragments(state, defaultValue);
188
200
  }
189
201
  };
202
+ Object.defineProperty(boundParser, inheritParentAnnotationsKey, {
203
+ value: true,
204
+ configurable: true
205
+ });
190
206
  if ("placeholder" in parser) Object.defineProperty(boundParser, "placeholder", {
191
207
  get() {
192
208
  return parser.placeholder;
@@ -199,6 +215,30 @@ function bindEnv(parser, options) {
199
215
  configurable: true,
200
216
  enumerable: false
201
217
  });
218
+ const dependencyMetadata = parser.dependencyMetadata;
219
+ if (dependencyMetadata != null) {
220
+ const sourceMetadata = dependencyMetadata.source;
221
+ Object.defineProperty(boundParser, "dependencyMetadata", {
222
+ value: sourceMetadata == null ? dependencyMetadata : {
223
+ ...dependencyMetadata,
224
+ source: {
225
+ ...sourceMetadata,
226
+ extractSourceValue: (state) => {
227
+ if (!isEnvBindState(state)) {
228
+ if (sourceMetadata.preservesSourceValue) return getEnvSourceValue(state, options, state, sourceMetadata.extractSourceValue);
229
+ return sourceMetadata.extractSourceValue(state);
230
+ }
231
+ if (state.hasCliValue) return sourceMetadata.extractSourceValue(state.cliState);
232
+ const innerState = state.cliState ?? state;
233
+ if (!sourceMetadata.preservesSourceValue) return sourceMetadata.extractSourceValue(innerState);
234
+ return getEnvSourceValue(state, options, innerState, sourceMetadata.extractSourceValue);
235
+ }
236
+ }
237
+ },
238
+ configurable: true,
239
+ enumerable: false
240
+ });
241
+ }
202
242
  return boundParser;
203
243
  }
204
244
  function getEnvOrDefault(state, options, mode, innerParser, innerState, exec) {
@@ -222,7 +262,7 @@ function getEnvOrDefault(state, options, mode, innerParser, innerState, exec) {
222
262
  value: options.default
223
263
  });
224
264
  if (innerParser != null) {
225
- const completeState = innerState ?? innerParser.initialState;
265
+ const completeState = innerState ?? (annotations != null && innerParser.initialState == null && Reflect.get(innerParser, inheritParentAnnotationsKey) === true ? (0, __optique_core_annotations.injectAnnotations)(innerParser.initialState, annotations) : innerParser.initialState);
226
266
  return (0, __optique_core_mode_dispatch.wrapForMode)(mode, innerParser.complete(completeState, exec));
227
267
  }
228
268
  return (0, __optique_core_mode_dispatch.wrapForMode)(mode, {
@@ -230,6 +270,45 @@ function getEnvOrDefault(state, options, mode, innerParser, innerState, exec) {
230
270
  error: __optique_core_message.message`Missing required environment variable: ${(0, __optique_core_message.envVar)(fullKey)}`
231
271
  });
232
272
  }
273
+ /**
274
+ * Resolves an env-backed dependency source with env and default fallbacks.
275
+ *
276
+ * This first checks annotations or the active env registry for the bound
277
+ * variable. If no env-backed value is available, it falls back to
278
+ * `options.default` and finally delegates to the wrapped parser's source
279
+ * extractor.
280
+ *
281
+ * @param state The wrapper state, which may carry env annotations.
282
+ * @param options The binding options with lookup and default settings.
283
+ * @param innerState The unwrapped inner state for delegated extraction.
284
+ * @param extractInnerSourceValue The wrapped parser's source extractor.
285
+ * @returns The resolved source value, an async source value, or `undefined`.
286
+ * @throws {Error} Propagates errors thrown by the env source callback
287
+ * (`sourceData.source(fullKey)`).
288
+ * @throws {Error} Propagates errors thrown by `options.parser.parse(rawValue)`.
289
+ */
290
+ function getEnvSourceValue(state, options, innerState, extractInnerSourceValue) {
291
+ const annotations = (0, __optique_core_annotations.getAnnotations)(state);
292
+ const sourceData = annotations?.[options.context.id] ?? getActiveEnvSource(options.context.id);
293
+ const fullKey = `${sourceData?.prefix ?? options.context.prefix}${options.key}`;
294
+ const rawValue = sourceData?.source(fullKey);
295
+ if (rawValue !== void 0) {
296
+ if (typeof rawValue !== "string") {
297
+ const type = rawValue === null ? "null" : Array.isArray(rawValue) ? "array" : typeof rawValue;
298
+ return {
299
+ success: false,
300
+ error: __optique_core_message.message`Environment variable ${(0, __optique_core_message.envVar)(fullKey)} must be a string, but got: ${type}.`
301
+ };
302
+ }
303
+ const parsed = options.parser.parse(rawValue);
304
+ return parsed;
305
+ }
306
+ if (options.default !== void 0) return {
307
+ success: true,
308
+ value: options.default
309
+ };
310
+ return extractInnerSourceValue(innerState);
311
+ }
233
312
  const TRUE_LITERALS = [
234
313
  "true",
235
314
  "1",
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Message } from "@optique/core/message";
2
+ import { Mode, Parser } from "@optique/core/parser";
2
3
  import { NonEmptyString, ValueParser } from "@optique/core/valueparser";
3
4
  import { SourceContext } from "@optique/core/context";
4
- import { Mode, Parser } from "@optique/core/parser";
5
5
 
6
6
  //#region src/index.d.ts
7
7
 
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
- import { annotationKey, getAnnotations } from "@optique/core/annotations";
1
+ import { annotationKey, getAnnotations, injectAnnotations, isInjectedAnnotationWrapper } from "@optique/core/annotations";
2
2
  import { envVar, message, valueSet } from "@optique/core/message";
3
3
  import { mapModeValue, wrapForMode } from "@optique/core/mode-dispatch";
4
+ import { unmatchedNonCliDependencySourceStateMarker } from "@optique/core/parser";
4
5
  import { ensureNonEmptyString, isValueParser } from "@optique/core/valueparser";
5
6
 
6
7
  //#region src/index.ts
8
+ const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
7
9
  const activeEnvSourceRegistry = /* @__PURE__ */ new Map();
8
10
  /**
9
11
  * Sets active environment source data for a context.
@@ -104,6 +106,7 @@ function bindEnv(parser, options) {
104
106
  $valueType: parser.$valueType,
105
107
  $stateType: parser.$stateType,
106
108
  priority: parser.priority,
109
+ [unmatchedNonCliDependencySourceStateMarker]: true,
107
110
  usage: options.default !== void 0 ? [{
108
111
  type: "optional",
109
112
  terms: parser.usage
@@ -111,6 +114,15 @@ function bindEnv(parser, options) {
111
114
  leadingNames: parser.leadingNames,
112
115
  acceptingAnyToken: parser.acceptingAnyToken,
113
116
  initialState: parser.initialState,
117
+ getSuggestRuntimeNodes(state, path) {
118
+ const innerState = isEnvBindState(state) ? state.cliState === void 0 ? parser.initialState : state.cliState : state;
119
+ const innerNodes = parser.getSuggestRuntimeNodes?.(innerState, path) ?? [];
120
+ return boundParser.dependencyMetadata?.source != null ? [...innerNodes, {
121
+ path,
122
+ parser: boundParser,
123
+ state
124
+ }] : innerNodes;
125
+ },
114
126
  parse: (context) => {
115
127
  const annotations = getAnnotations(context.state);
116
128
  const innerState = isEnvBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
@@ -155,7 +167,7 @@ function bindEnv(parser, options) {
155
167
  },
156
168
  complete: (state, exec) => {
157
169
  if (isEnvBindState(state) && state.hasCliValue) return parser.complete(state.cliState, exec);
158
- return getEnvOrDefault(state, options, parser.$mode, parser, isEnvBindState(state) ? state.cliState : void 0, exec);
170
+ return getEnvOrDefault(state, options, parser.$mode, parser, isEnvBindState(state) ? state.cliState : isInjectedAnnotationWrapper(state) ? void 0 : state, exec);
159
171
  },
160
172
  suggest: parser.suggest,
161
173
  ...typeof deferPromptUntilConfigResolves === "function" ? { shouldDeferCompletion: (state, exec) => deferPromptUntilConfigResolves.call(parser, state, exec) } : {},
@@ -164,6 +176,10 @@ function bindEnv(parser, options) {
164
176
  return parser.getDocFragments(state, defaultValue);
165
177
  }
166
178
  };
179
+ Object.defineProperty(boundParser, inheritParentAnnotationsKey, {
180
+ value: true,
181
+ configurable: true
182
+ });
167
183
  if ("placeholder" in parser) Object.defineProperty(boundParser, "placeholder", {
168
184
  get() {
169
185
  return parser.placeholder;
@@ -176,6 +192,30 @@ function bindEnv(parser, options) {
176
192
  configurable: true,
177
193
  enumerable: false
178
194
  });
195
+ const dependencyMetadata = parser.dependencyMetadata;
196
+ if (dependencyMetadata != null) {
197
+ const sourceMetadata = dependencyMetadata.source;
198
+ Object.defineProperty(boundParser, "dependencyMetadata", {
199
+ value: sourceMetadata == null ? dependencyMetadata : {
200
+ ...dependencyMetadata,
201
+ source: {
202
+ ...sourceMetadata,
203
+ extractSourceValue: (state) => {
204
+ if (!isEnvBindState(state)) {
205
+ if (sourceMetadata.preservesSourceValue) return getEnvSourceValue(state, options, state, sourceMetadata.extractSourceValue);
206
+ return sourceMetadata.extractSourceValue(state);
207
+ }
208
+ if (state.hasCliValue) return sourceMetadata.extractSourceValue(state.cliState);
209
+ const innerState = state.cliState ?? state;
210
+ if (!sourceMetadata.preservesSourceValue) return sourceMetadata.extractSourceValue(innerState);
211
+ return getEnvSourceValue(state, options, innerState, sourceMetadata.extractSourceValue);
212
+ }
213
+ }
214
+ },
215
+ configurable: true,
216
+ enumerable: false
217
+ });
218
+ }
179
219
  return boundParser;
180
220
  }
181
221
  function getEnvOrDefault(state, options, mode, innerParser, innerState, exec) {
@@ -199,7 +239,7 @@ function getEnvOrDefault(state, options, mode, innerParser, innerState, exec) {
199
239
  value: options.default
200
240
  });
201
241
  if (innerParser != null) {
202
- const completeState = innerState ?? innerParser.initialState;
242
+ const completeState = innerState ?? (annotations != null && innerParser.initialState == null && Reflect.get(innerParser, inheritParentAnnotationsKey) === true ? injectAnnotations(innerParser.initialState, annotations) : innerParser.initialState);
203
243
  return wrapForMode(mode, innerParser.complete(completeState, exec));
204
244
  }
205
245
  return wrapForMode(mode, {
@@ -207,6 +247,45 @@ function getEnvOrDefault(state, options, mode, innerParser, innerState, exec) {
207
247
  error: message`Missing required environment variable: ${envVar(fullKey)}`
208
248
  });
209
249
  }
250
+ /**
251
+ * Resolves an env-backed dependency source with env and default fallbacks.
252
+ *
253
+ * This first checks annotations or the active env registry for the bound
254
+ * variable. If no env-backed value is available, it falls back to
255
+ * `options.default` and finally delegates to the wrapped parser's source
256
+ * extractor.
257
+ *
258
+ * @param state The wrapper state, which may carry env annotations.
259
+ * @param options The binding options with lookup and default settings.
260
+ * @param innerState The unwrapped inner state for delegated extraction.
261
+ * @param extractInnerSourceValue The wrapped parser's source extractor.
262
+ * @returns The resolved source value, an async source value, or `undefined`.
263
+ * @throws {Error} Propagates errors thrown by the env source callback
264
+ * (`sourceData.source(fullKey)`).
265
+ * @throws {Error} Propagates errors thrown by `options.parser.parse(rawValue)`.
266
+ */
267
+ function getEnvSourceValue(state, options, innerState, extractInnerSourceValue) {
268
+ const annotations = getAnnotations(state);
269
+ const sourceData = annotations?.[options.context.id] ?? getActiveEnvSource(options.context.id);
270
+ const fullKey = `${sourceData?.prefix ?? options.context.prefix}${options.key}`;
271
+ const rawValue = sourceData?.source(fullKey);
272
+ if (rawValue !== void 0) {
273
+ if (typeof rawValue !== "string") {
274
+ const type = rawValue === null ? "null" : Array.isArray(rawValue) ? "array" : typeof rawValue;
275
+ return {
276
+ success: false,
277
+ error: message`Environment variable ${envVar(fullKey)} must be a string, but got: ${type}.`
278
+ };
279
+ }
280
+ const parsed = options.parser.parse(rawValue);
281
+ return parsed;
282
+ }
283
+ if (options.default !== void 0) return {
284
+ success: true,
285
+ value: options.default
286
+ };
287
+ return extractInnerSourceValue(innerState);
288
+ }
210
289
  const TRUE_LITERALS = [
211
290
  "true",
212
291
  "1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/env",
3
- "version": "1.0.0-dev.1616+17abc525",
3
+ "version": "1.0.0-dev.1658+b57e115b",
4
4
  "description": "Environment variable support for Optique",
5
5
  "keywords": [
6
6
  "CLI",
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "sideEffects": false,
56
56
  "dependencies": {
57
- "@optique/core": "1.0.0-dev.1616+17abc525"
57
+ "@optique/core": "1.0.0-dev.1658+b57e115b"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^20.19.9",