@optique/core 1.0.0-dev.1798 → 1.0.0-dev.1801

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.
@@ -132,8 +132,11 @@ interface SourceContext<TRequiredOptions = void> {
132
132
  * successfully. Dynamic contexts can use this to load external data
133
133
  * (e.g., reading a config file whose path was determined in the first
134
134
  * pass). Deferred or otherwise unresolved fields may be `undefined`.
135
- * If the runner cannot extract a usable value at all, this second call
136
- * is skipped and the original parse failure is reported instead.
135
+ * This second return value is treated as the context's final annotation
136
+ * snapshot for the second parse pass, replacing that context's phase-one
137
+ * contribution. If the runner cannot extract a usable value at all, this
138
+ * second call is skipped and the original parse failure is reported
139
+ * instead.
137
140
  *
138
141
  * @param parsed Optional parsed result from a previous parse pass.
139
142
  * Static contexts can ignore this parameter.
@@ -141,8 +144,10 @@ interface SourceContext<TRequiredOptions = void> {
141
144
  * @param options Optional context-required options provided by the caller
142
145
  * of `runWith()`. These are the options declared via the
143
146
  * `TRequiredOptions` type parameter.
144
- * @returns Annotations to merge into the parsing session. Can be a Promise
145
- * for async operations (e.g., loading config files).
147
+ * @returns Annotations to merge into the parsing session. During phase 2,
148
+ * returning `{}` clears any annotations this context contributed
149
+ * during phase 1. Can be a Promise for async operations (e.g.,
150
+ * loading config files).
146
151
  */
147
152
  getAnnotations(parsed?: unknown, options?: unknown): Promise<Annotations> | Annotations;
148
153
  /**
package/dist/context.d.ts CHANGED
@@ -132,8 +132,11 @@ interface SourceContext<TRequiredOptions = void> {
132
132
  * successfully. Dynamic contexts can use this to load external data
133
133
  * (e.g., reading a config file whose path was determined in the first
134
134
  * pass). Deferred or otherwise unresolved fields may be `undefined`.
135
- * If the runner cannot extract a usable value at all, this second call
136
- * is skipped and the original parse failure is reported instead.
135
+ * This second return value is treated as the context's final annotation
136
+ * snapshot for the second parse pass, replacing that context's phase-one
137
+ * contribution. If the runner cannot extract a usable value at all, this
138
+ * second call is skipped and the original parse failure is reported
139
+ * instead.
137
140
  *
138
141
  * @param parsed Optional parsed result from a previous parse pass.
139
142
  * Static contexts can ignore this parameter.
@@ -141,8 +144,10 @@ interface SourceContext<TRequiredOptions = void> {
141
144
  * @param options Optional context-required options provided by the caller
142
145
  * of `runWith()`. These are the options declared via the
143
146
  * `TRequiredOptions` type parameter.
144
- * @returns Annotations to merge into the parsing session. Can be a Promise
145
- * for async operations (e.g., loading config files).
147
+ * @returns Annotations to merge into the parsing session. During phase 2,
148
+ * returning `{}` clears any annotations this context contributed
149
+ * during phase 1. Can be a Promise for async operations (e.g.,
150
+ * loading config files).
146
151
  */
147
152
  getAnnotations(parsed?: unknown, options?: unknown): Promise<Annotations> | Annotations;
148
153
  /**
package/dist/facade.cjs CHANGED
@@ -1101,7 +1101,6 @@ async function collectPhase1Annotations(contexts, options) {
1101
1101
  }
1102
1102
  return {
1103
1103
  annotations: mergeAnnotations(annotationsList),
1104
- annotationsList,
1105
1104
  hasDynamic
1106
1105
  };
1107
1106
  }
@@ -1125,10 +1124,7 @@ async function collectAnnotations(contexts, parsed, options, deferred, deferredK
1125
1124
  });
1126
1125
  annotationsList.push(mergedAnnotations);
1127
1126
  }
1128
- return {
1129
- annotations: mergeAnnotations(annotationsList),
1130
- annotationsList
1131
- };
1127
+ return { annotations: mergeAnnotations(annotationsList) };
1132
1128
  }
1133
1129
  /**
1134
1130
  * Collects phase 1 annotations from all contexts synchronously and determines
@@ -1151,7 +1147,6 @@ function collectPhase1AnnotationsSync(contexts, options) {
1151
1147
  }
1152
1148
  return {
1153
1149
  annotations: mergeAnnotations(annotationsList),
1154
- annotationsList,
1155
1150
  hasDynamic
1156
1151
  };
1157
1152
  }
@@ -1188,16 +1183,7 @@ function collectAnnotationsSync(contexts, parsed, options, deferred, deferredKey
1188
1183
  });
1189
1184
  annotationsList.push(mergedAnnotations);
1190
1185
  }
1191
- return {
1192
- annotations: mergeAnnotations(annotationsList),
1193
- annotationsList
1194
- };
1195
- }
1196
- function mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList) {
1197
- const mergedPerContext = [];
1198
- const length = Math.max(phase1AnnotationsList.length, phase2AnnotationsList.length);
1199
- for (let i = 0; i < length; i++) mergedPerContext.push(mergeAnnotations([phase2AnnotationsList[i] ?? {}, phase1AnnotationsList[i] ?? {}]));
1200
- return mergeAnnotations(mergedPerContext);
1186
+ return { annotations: mergeAnnotations(annotationsList) };
1201
1187
  }
1202
1188
  /**
1203
1189
  * Disposes all contexts that implement `AsyncDisposable` or `Disposable`.
@@ -1247,7 +1233,7 @@ async function runWithBody(parser, programName, contexts, args, options) {
1247
1233
  return Promise.resolve(runParser(parser, programName, args, options));
1248
1234
  }
1249
1235
  const ctxOptions = options.contextOptions;
1250
- const { annotations: phase1Annotations, annotationsList: phase1AnnotationsList, hasDynamic: needsTwoPhase } = await collectPhase1Annotations(contexts, ctxOptions);
1236
+ const { annotations: phase1Annotations, hasDynamic: needsTwoPhase } = await collectPhase1Annotations(contexts, ctxOptions);
1251
1237
  if (!needsTwoPhase) {
1252
1238
  const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1253
1239
  if (parser.$mode === "async") return runParser(augmentedParser, programName, args, options);
@@ -1260,8 +1246,7 @@ async function runWithBody(parser, programName, contexts, args, options) {
1260
1246
  if (parser.$mode === "async") return runParser(augmentedParser, programName, args, options);
1261
1247
  return Promise.resolve(runParser(augmentedParser, programName, args, options));
1262
1248
  }
1263
- const { annotationsList: phase2AnnotationsList } = await collectAnnotations(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1264
- const finalAnnotations = mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList);
1249
+ const { annotations: finalAnnotations } = await collectAnnotations(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1265
1250
  const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
1266
1251
  if (parser.$mode === "async") return runParser(augmentedParser2, programName, args, options);
1267
1252
  return Promise.resolve(runParser(augmentedParser2, programName, args, options));
@@ -1283,8 +1268,10 @@ async function runWithBody(parser, programName, contexts, args, options) {
1283
1268
  * instead.
1284
1269
  * 3. *Phase 2*: Call `getAnnotations(parsed)` on all contexts with the first
1285
1270
  * pass value. Deferred or otherwise unresolved fields in `parsed` may be
1286
- * `undefined`.
1287
- * 4. *Second parse*: Parse again with merged annotations from both phases.
1271
+ * `undefined`. Each context's phase-two return value replaces its own
1272
+ * phase-one contribution for the final parse, so returning `{}` clears any
1273
+ * annotations that context provided during phase 1.
1274
+ * 4. *Second parse*: Parse again with the merged phase-two annotations.
1288
1275
  *
1289
1276
  * If all contexts are static (no dynamic contexts), the second parse is
1290
1277
  * skipped for optimization. Phase 2 is also skipped when the first pass does
@@ -1357,7 +1344,7 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1357
1344
  require_validate.validateContextIds(contexts);
1358
1345
  if (needsEarlyExit(args, options)) return runParser(parser, programName, args, options);
1359
1346
  const ctxOptions = options.contextOptions;
1360
- const { annotations: phase1Annotations, annotationsList: phase1AnnotationsList, hasDynamic: needsTwoPhase } = collectPhase1AnnotationsSync(contexts, ctxOptions);
1347
+ const { annotations: phase1Annotations, hasDynamic: needsTwoPhase } = collectPhase1AnnotationsSync(contexts, ctxOptions);
1361
1348
  if (!needsTwoPhase) {
1362
1349
  const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1363
1350
  return runParser(augmentedParser, programName, args, options);
@@ -1368,8 +1355,7 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1368
1355
  const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1369
1356
  return runParser(augmentedParser, programName, args, options);
1370
1357
  }
1371
- const { annotationsList: phase2AnnotationsList } = collectAnnotationsSync(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1372
- const finalAnnotations = mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList);
1358
+ const { annotations: finalAnnotations } = collectAnnotationsSync(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1373
1359
  const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
1374
1360
  return runParser(augmentedParser2, programName, args, options);
1375
1361
  }
@@ -1379,7 +1365,9 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1379
1365
  * This is the sync-only variant of {@link runWith}. All contexts must return
1380
1366
  * annotations synchronously (not Promises). It uses the same two-phase
1381
1367
  * best-effort seed extraction as {@link runWith} when dynamic contexts are
1382
- * present.
1368
+ * present. In two-phase runs, each context's phase-two return value replaces
1369
+ * that context's phase-one contribution for the final parse, so returning `{}`
1370
+ * clears any annotations that context provided during phase 1.
1383
1371
  *
1384
1372
  * @template TParser The sync parser type.
1385
1373
  * @template THelp Return type when help is shown.
package/dist/facade.d.cts CHANGED
@@ -419,8 +419,10 @@ type ContextOptionsParam<TContexts extends readonly SourceContext<unknown>[], TV
419
419
  * instead.
420
420
  * 3. *Phase 2*: Call `getAnnotations(parsed)` on all contexts with the first
421
421
  * pass value. Deferred or otherwise unresolved fields in `parsed` may be
422
- * `undefined`.
423
- * 4. *Second parse*: Parse again with merged annotations from both phases.
422
+ * `undefined`. Each context's phase-two return value replaces its own
423
+ * phase-one contribution for the final parse, so returning `{}` clears any
424
+ * annotations that context provided during phase 1.
425
+ * 4. *Second parse*: Parse again with the merged phase-two annotations.
424
426
  *
425
427
  * If all contexts are static (no dynamic contexts), the second parse is
426
428
  * skipped for optimization. Phase 2 is also skipped when the first pass does
@@ -468,7 +470,9 @@ declare function runWith<TParser extends Parser<Mode, unknown, unknown>, TContex
468
470
  * This is the sync-only variant of {@link runWith}. All contexts must return
469
471
  * annotations synchronously (not Promises). It uses the same two-phase
470
472
  * best-effort seed extraction as {@link runWith} when dynamic contexts are
471
- * present.
473
+ * present. In two-phase runs, each context's phase-two return value replaces
474
+ * that context's phase-one contribution for the final parse, so returning `{}`
475
+ * clears any annotations that context provided during phase 1.
472
476
  *
473
477
  * @template TParser The sync parser type.
474
478
  * @template THelp Return type when help is shown.
package/dist/facade.d.ts CHANGED
@@ -419,8 +419,10 @@ type ContextOptionsParam<TContexts extends readonly SourceContext<unknown>[], TV
419
419
  * instead.
420
420
  * 3. *Phase 2*: Call `getAnnotations(parsed)` on all contexts with the first
421
421
  * pass value. Deferred or otherwise unresolved fields in `parsed` may be
422
- * `undefined`.
423
- * 4. *Second parse*: Parse again with merged annotations from both phases.
422
+ * `undefined`. Each context's phase-two return value replaces its own
423
+ * phase-one contribution for the final parse, so returning `{}` clears any
424
+ * annotations that context provided during phase 1.
425
+ * 4. *Second parse*: Parse again with the merged phase-two annotations.
424
426
  *
425
427
  * If all contexts are static (no dynamic contexts), the second parse is
426
428
  * skipped for optimization. Phase 2 is also skipped when the first pass does
@@ -468,7 +470,9 @@ declare function runWith<TParser extends Parser<Mode, unknown, unknown>, TContex
468
470
  * This is the sync-only variant of {@link runWith}. All contexts must return
469
471
  * annotations synchronously (not Promises). It uses the same two-phase
470
472
  * best-effort seed extraction as {@link runWith} when dynamic contexts are
471
- * present.
473
+ * present. In two-phase runs, each context's phase-two return value replaces
474
+ * that context's phase-one contribution for the final parse, so returning `{}`
475
+ * clears any annotations that context provided during phase 1.
472
476
  *
473
477
  * @template TParser The sync parser type.
474
478
  * @template THelp Return type when help is shown.
package/dist/facade.js CHANGED
@@ -1101,7 +1101,6 @@ async function collectPhase1Annotations(contexts, options) {
1101
1101
  }
1102
1102
  return {
1103
1103
  annotations: mergeAnnotations(annotationsList),
1104
- annotationsList,
1105
1104
  hasDynamic
1106
1105
  };
1107
1106
  }
@@ -1125,10 +1124,7 @@ async function collectAnnotations(contexts, parsed, options, deferred, deferredK
1125
1124
  });
1126
1125
  annotationsList.push(mergedAnnotations);
1127
1126
  }
1128
- return {
1129
- annotations: mergeAnnotations(annotationsList),
1130
- annotationsList
1131
- };
1127
+ return { annotations: mergeAnnotations(annotationsList) };
1132
1128
  }
1133
1129
  /**
1134
1130
  * Collects phase 1 annotations from all contexts synchronously and determines
@@ -1151,7 +1147,6 @@ function collectPhase1AnnotationsSync(contexts, options) {
1151
1147
  }
1152
1148
  return {
1153
1149
  annotations: mergeAnnotations(annotationsList),
1154
- annotationsList,
1155
1150
  hasDynamic
1156
1151
  };
1157
1152
  }
@@ -1188,16 +1183,7 @@ function collectAnnotationsSync(contexts, parsed, options, deferred, deferredKey
1188
1183
  });
1189
1184
  annotationsList.push(mergedAnnotations);
1190
1185
  }
1191
- return {
1192
- annotations: mergeAnnotations(annotationsList),
1193
- annotationsList
1194
- };
1195
- }
1196
- function mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList) {
1197
- const mergedPerContext = [];
1198
- const length = Math.max(phase1AnnotationsList.length, phase2AnnotationsList.length);
1199
- for (let i = 0; i < length; i++) mergedPerContext.push(mergeAnnotations([phase2AnnotationsList[i] ?? {}, phase1AnnotationsList[i] ?? {}]));
1200
- return mergeAnnotations(mergedPerContext);
1186
+ return { annotations: mergeAnnotations(annotationsList) };
1201
1187
  }
1202
1188
  /**
1203
1189
  * Disposes all contexts that implement `AsyncDisposable` or `Disposable`.
@@ -1247,7 +1233,7 @@ async function runWithBody(parser, programName, contexts, args, options) {
1247
1233
  return Promise.resolve(runParser(parser, programName, args, options));
1248
1234
  }
1249
1235
  const ctxOptions = options.contextOptions;
1250
- const { annotations: phase1Annotations, annotationsList: phase1AnnotationsList, hasDynamic: needsTwoPhase } = await collectPhase1Annotations(contexts, ctxOptions);
1236
+ const { annotations: phase1Annotations, hasDynamic: needsTwoPhase } = await collectPhase1Annotations(contexts, ctxOptions);
1251
1237
  if (!needsTwoPhase) {
1252
1238
  const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1253
1239
  if (parser.$mode === "async") return runParser(augmentedParser, programName, args, options);
@@ -1260,8 +1246,7 @@ async function runWithBody(parser, programName, contexts, args, options) {
1260
1246
  if (parser.$mode === "async") return runParser(augmentedParser, programName, args, options);
1261
1247
  return Promise.resolve(runParser(augmentedParser, programName, args, options));
1262
1248
  }
1263
- const { annotationsList: phase2AnnotationsList } = await collectAnnotations(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1264
- const finalAnnotations = mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList);
1249
+ const { annotations: finalAnnotations } = await collectAnnotations(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1265
1250
  const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
1266
1251
  if (parser.$mode === "async") return runParser(augmentedParser2, programName, args, options);
1267
1252
  return Promise.resolve(runParser(augmentedParser2, programName, args, options));
@@ -1283,8 +1268,10 @@ async function runWithBody(parser, programName, contexts, args, options) {
1283
1268
  * instead.
1284
1269
  * 3. *Phase 2*: Call `getAnnotations(parsed)` on all contexts with the first
1285
1270
  * pass value. Deferred or otherwise unresolved fields in `parsed` may be
1286
- * `undefined`.
1287
- * 4. *Second parse*: Parse again with merged annotations from both phases.
1271
+ * `undefined`. Each context's phase-two return value replaces its own
1272
+ * phase-one contribution for the final parse, so returning `{}` clears any
1273
+ * annotations that context provided during phase 1.
1274
+ * 4. *Second parse*: Parse again with the merged phase-two annotations.
1288
1275
  *
1289
1276
  * If all contexts are static (no dynamic contexts), the second parse is
1290
1277
  * skipped for optimization. Phase 2 is also skipped when the first pass does
@@ -1357,7 +1344,7 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1357
1344
  validateContextIds(contexts);
1358
1345
  if (needsEarlyExit(args, options)) return runParser(parser, programName, args, options);
1359
1346
  const ctxOptions = options.contextOptions;
1360
- const { annotations: phase1Annotations, annotationsList: phase1AnnotationsList, hasDynamic: needsTwoPhase } = collectPhase1AnnotationsSync(contexts, ctxOptions);
1347
+ const { annotations: phase1Annotations, hasDynamic: needsTwoPhase } = collectPhase1AnnotationsSync(contexts, ctxOptions);
1361
1348
  if (!needsTwoPhase) {
1362
1349
  const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1363
1350
  return runParser(augmentedParser, programName, args, options);
@@ -1368,8 +1355,7 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1368
1355
  const augmentedParser = injectAnnotationsIntoParser(parser, phase1Annotations);
1369
1356
  return runParser(augmentedParser, programName, args, options);
1370
1357
  }
1371
- const { annotationsList: phase2AnnotationsList } = collectAnnotationsSync(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1372
- const finalAnnotations = mergeTwoPhaseAnnotations(phase1AnnotationsList, phase2AnnotationsList);
1358
+ const { annotations: finalAnnotations } = collectAnnotationsSync(contexts, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
1373
1359
  const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
1374
1360
  return runParser(augmentedParser2, programName, args, options);
1375
1361
  }
@@ -1379,7 +1365,9 @@ function runWithSyncBody(parser, programName, contexts, args, options) {
1379
1365
  * This is the sync-only variant of {@link runWith}. All contexts must return
1380
1366
  * annotations synchronously (not Promises). It uses the same two-phase
1381
1367
  * best-effort seed extraction as {@link runWith} when dynamic contexts are
1382
- * present.
1368
+ * present. In two-phase runs, each context's phase-two return value replaces
1369
+ * that context's phase-one contribution for the final parse, so returning `{}`
1370
+ * clears any annotations that context provided during phase 1.
1383
1371
  *
1384
1372
  * @template TParser The sync parser type.
1385
1373
  * @template THelp Return type when help is shown.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.1798+d306f46e",
3
+ "version": "1.0.0-dev.1801+3b666460",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",