@optique/config 1.0.0-dev.664 → 1.0.0-dev.670
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 +132 -5
- package/dist/index.js +132 -5
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,10 @@ const __optique_core_message = __toESM(require("@optique/core/message"));
|
|
|
28
28
|
const __optique_core_mode_dispatch = __toESM(require("@optique/core/mode-dispatch"));
|
|
29
29
|
|
|
30
30
|
//#region src/index.ts
|
|
31
|
+
const deferPromptUntilConfigResolvesKey = Symbol.for("@optique/config/deferPromptUntilResolved");
|
|
32
|
+
const phase1ConfigAnnotationsKey = Symbol.for("@optique/config/phase1PromptAnnotations");
|
|
33
|
+
const phase2UndefinedParsedValueKey = Symbol.for("@optique/config/phase2UndefinedParsedValue");
|
|
34
|
+
const deferredPromptValueKey = Symbol.for("@optique/inquirer/deferredPromptValue");
|
|
31
35
|
/**
|
|
32
36
|
* Internal registry for active config data during config context execution.
|
|
33
37
|
* This is a workaround for the limitation that object() doesn't propagate
|
|
@@ -40,6 +44,117 @@ const activeConfigRegistry = /* @__PURE__ */ new Map();
|
|
|
40
44
|
* @internal
|
|
41
45
|
*/
|
|
42
46
|
const activeConfigMetaRegistry = /* @__PURE__ */ new Map();
|
|
47
|
+
const phase1ConfigAnnotationMarker = Symbol("@optique/config/phase1Annotation");
|
|
48
|
+
function isDeferredPromptValue(value) {
|
|
49
|
+
return value != null && typeof value === "object" && deferredPromptValueKey in value;
|
|
50
|
+
}
|
|
51
|
+
function isPhase2UndefinedParsedValue(value) {
|
|
52
|
+
return value != null && typeof value === "object" && phase2UndefinedParsedValueKey in value;
|
|
53
|
+
}
|
|
54
|
+
function isPlainObject(value) {
|
|
55
|
+
const proto = Object.getPrototypeOf(value);
|
|
56
|
+
return proto === Object.prototype || proto === null;
|
|
57
|
+
}
|
|
58
|
+
function shouldSkipCollectionOwnKey(value, key) {
|
|
59
|
+
if (Array.isArray(value)) return key === "length" || typeof key === "string" && Number.isInteger(Number(key)) && String(Number(key)) === key;
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
function containsDeferredPromptValuesInOwnProperties(value, seen) {
|
|
63
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
64
|
+
if (shouldSkipCollectionOwnKey(value, key)) continue;
|
|
65
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
66
|
+
if (descriptor != null && "value" in descriptor && containsDeferredPromptValues(descriptor.value, seen)) return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
function copySanitizedOwnProperties(source, target, seen) {
|
|
71
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
72
|
+
if (shouldSkipCollectionOwnKey(source, key)) continue;
|
|
73
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
74
|
+
if (descriptor == null) continue;
|
|
75
|
+
if ("value" in descriptor) descriptor.value = stripDeferredPromptValues(descriptor.value, seen);
|
|
76
|
+
Object.defineProperty(target, key, descriptor);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function containsDeferredPromptValues(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
80
|
+
if (isDeferredPromptValue(value)) return true;
|
|
81
|
+
if (value == null || typeof value !== "object") return false;
|
|
82
|
+
if (seen.has(value)) return false;
|
|
83
|
+
seen.add(value);
|
|
84
|
+
if (Array.isArray(value)) {
|
|
85
|
+
if (value.some((item) => containsDeferredPromptValues(item, seen))) return true;
|
|
86
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
87
|
+
}
|
|
88
|
+
if (value instanceof Set) {
|
|
89
|
+
for (const entryValue of value) if (containsDeferredPromptValues(entryValue, seen)) return true;
|
|
90
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
91
|
+
}
|
|
92
|
+
if (value instanceof Map) {
|
|
93
|
+
for (const [key, entryValue] of value) if (containsDeferredPromptValues(key, seen) || containsDeferredPromptValues(entryValue, seen)) return true;
|
|
94
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
95
|
+
}
|
|
96
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
97
|
+
}
|
|
98
|
+
function createSanitizedNonPlainView(value, seen) {
|
|
99
|
+
const proxy = new Proxy(value, {
|
|
100
|
+
get(target, key, receiver) {
|
|
101
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
102
|
+
if (descriptor != null && "value" in descriptor) return stripDeferredPromptValues(descriptor.value, seen);
|
|
103
|
+
return Reflect.get(target, key, receiver);
|
|
104
|
+
},
|
|
105
|
+
getOwnPropertyDescriptor(target, key) {
|
|
106
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
107
|
+
if (descriptor == null || !("value" in descriptor)) return descriptor;
|
|
108
|
+
return {
|
|
109
|
+
...descriptor,
|
|
110
|
+
value: stripDeferredPromptValues(descriptor.value, seen)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
seen.set(value, proxy);
|
|
115
|
+
return proxy;
|
|
116
|
+
}
|
|
117
|
+
function stripDeferredPromptValues(value, seen = /* @__PURE__ */ new WeakMap()) {
|
|
118
|
+
if (isDeferredPromptValue(value)) return void 0;
|
|
119
|
+
if (value == null || typeof value !== "object") return value;
|
|
120
|
+
const cached = seen.get(value);
|
|
121
|
+
if (cached !== void 0) return cached;
|
|
122
|
+
if (Array.isArray(value)) {
|
|
123
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
124
|
+
const clone$1 = new Array(value.length);
|
|
125
|
+
seen.set(value, clone$1);
|
|
126
|
+
for (let i = 0; i < value.length; i++) clone$1[i] = stripDeferredPromptValues(value[i], seen);
|
|
127
|
+
copySanitizedOwnProperties(value, clone$1, seen);
|
|
128
|
+
return clone$1;
|
|
129
|
+
}
|
|
130
|
+
if (value instanceof Set) {
|
|
131
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
132
|
+
const clone$1 = /* @__PURE__ */ new Set();
|
|
133
|
+
seen.set(value, clone$1);
|
|
134
|
+
for (const entryValue of value) clone$1.add(stripDeferredPromptValues(entryValue, seen));
|
|
135
|
+
copySanitizedOwnProperties(value, clone$1, seen);
|
|
136
|
+
return clone$1;
|
|
137
|
+
}
|
|
138
|
+
if (value instanceof Map) {
|
|
139
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
140
|
+
const clone$1 = /* @__PURE__ */ new Map();
|
|
141
|
+
seen.set(value, clone$1);
|
|
142
|
+
for (const [key, entryValue] of value) clone$1.set(stripDeferredPromptValues(key, seen), stripDeferredPromptValues(entryValue, seen));
|
|
143
|
+
copySanitizedOwnProperties(value, clone$1, seen);
|
|
144
|
+
return clone$1;
|
|
145
|
+
}
|
|
146
|
+
if (!isPlainObject(value)) return containsDeferredPromptValues(value) ? createSanitizedNonPlainView(value, seen) : value;
|
|
147
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
148
|
+
const clone = Object.create(Object.getPrototypeOf(value));
|
|
149
|
+
seen.set(value, clone);
|
|
150
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
151
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
152
|
+
if (descriptor == null) continue;
|
|
153
|
+
if ("value" in descriptor) descriptor.value = stripDeferredPromptValues(descriptor.value, seen);
|
|
154
|
+
Object.defineProperty(clone, key, descriptor);
|
|
155
|
+
}
|
|
156
|
+
return clone;
|
|
157
|
+
}
|
|
43
158
|
/**
|
|
44
159
|
* Sets active config data for a context.
|
|
45
160
|
* @internal
|
|
@@ -130,15 +245,20 @@ function validateWithSchema(schema, rawData) {
|
|
|
130
245
|
*/
|
|
131
246
|
function createConfigContext(options) {
|
|
132
247
|
const contextId = Symbol(`@optique/config:${Math.random()}`);
|
|
133
|
-
|
|
248
|
+
const context = {
|
|
134
249
|
id: contextId,
|
|
135
250
|
schema: options.schema,
|
|
136
251
|
mode: "dynamic",
|
|
252
|
+
[phase1ConfigAnnotationsKey](parsed, annotations) {
|
|
253
|
+
if (parsed === void 0) return { [contextId]: phase1ConfigAnnotationMarker };
|
|
254
|
+
return Object.getOwnPropertySymbols(annotations).includes(contextId) ? void 0 : { [contextId]: void 0 };
|
|
255
|
+
},
|
|
137
256
|
getAnnotations(parsed, runtimeOptions) {
|
|
138
257
|
if (parsed === void 0) return {};
|
|
139
258
|
const opts = runtimeOptions;
|
|
140
259
|
if (!opts || !opts.getConfigPath && !opts.load) throw new TypeError("Either getConfigPath or load must be provided in the runner options when using ConfigContext.");
|
|
141
|
-
const parsedValue = parsed;
|
|
260
|
+
const parsedValue = isPhase2UndefinedParsedValue(parsed) ? void 0 : stripDeferredPromptValues(parsed);
|
|
261
|
+
const parsedPlaceholder = parsedValue;
|
|
142
262
|
const buildAnnotations = (configData, configMeta) => {
|
|
143
263
|
if (configData === void 0 || configData === null) return {};
|
|
144
264
|
setActiveConfig(contextId, configData);
|
|
@@ -157,12 +277,12 @@ function createConfigContext(options) {
|
|
|
157
277
|
return buildAnnotations(validated, configMeta);
|
|
158
278
|
};
|
|
159
279
|
if (opts.load) {
|
|
160
|
-
const loaded = opts.load(
|
|
280
|
+
const loaded = opts.load(parsedPlaceholder);
|
|
161
281
|
if (loaded instanceof Promise) return loaded.then(({ config, meta }) => validateAndBuildAnnotations(config, meta));
|
|
162
282
|
return validateAndBuildAnnotations(loaded.config, loaded.meta);
|
|
163
283
|
}
|
|
164
284
|
if (opts.getConfigPath) {
|
|
165
|
-
const configPath = opts.getConfigPath(
|
|
285
|
+
const configPath = opts.getConfigPath(parsedPlaceholder);
|
|
166
286
|
if (!configPath) return {};
|
|
167
287
|
const absoluteConfigPath = (0, node_path.resolve)(configPath);
|
|
168
288
|
const singleFileMeta = {
|
|
@@ -191,6 +311,7 @@ function createConfigContext(options) {
|
|
|
191
311
|
clearActiveConfigMeta(contextId);
|
|
192
312
|
}
|
|
193
313
|
};
|
|
314
|
+
return context;
|
|
194
315
|
}
|
|
195
316
|
/**
|
|
196
317
|
* Binds a parser to configuration values with fallback priority.
|
|
@@ -228,7 +349,11 @@ function bindConfig(parser, options) {
|
|
|
228
349
|
function isConfigBindState(value) {
|
|
229
350
|
return value != null && typeof value === "object" && configBindStateKey in value;
|
|
230
351
|
}
|
|
231
|
-
|
|
352
|
+
function shouldDeferPromptUntilConfigResolves(state) {
|
|
353
|
+
const annotations = (0, __optique_core_annotations.getAnnotations)(state);
|
|
354
|
+
return annotations?.[options.context.id] === phase1ConfigAnnotationMarker;
|
|
355
|
+
}
|
|
356
|
+
const boundParser = {
|
|
232
357
|
$mode: parser.$mode,
|
|
233
358
|
$valueType: parser.$valueType,
|
|
234
359
|
$stateType: parser.$stateType,
|
|
@@ -285,11 +410,13 @@ function bindConfig(parser, options) {
|
|
|
285
410
|
return (0, __optique_core_mode_dispatch.wrapForMode)(parser.$mode, getConfigOrDefault(state, options));
|
|
286
411
|
},
|
|
287
412
|
suggest: parser.suggest,
|
|
413
|
+
[deferPromptUntilConfigResolvesKey]: shouldDeferPromptUntilConfigResolves,
|
|
288
414
|
getDocFragments(state, upperDefaultValue) {
|
|
289
415
|
const defaultValue = upperDefaultValue ?? options.default;
|
|
290
416
|
return parser.getDocFragments(state, defaultValue);
|
|
291
417
|
}
|
|
292
418
|
};
|
|
419
|
+
return boundParser;
|
|
293
420
|
}
|
|
294
421
|
/**
|
|
295
422
|
* Helper function to get value from config or default.
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,10 @@ import { message } from "@optique/core/message";
|
|
|
5
5
|
import { mapModeValue, wrapForMode } from "@optique/core/mode-dispatch";
|
|
6
6
|
|
|
7
7
|
//#region src/index.ts
|
|
8
|
+
const deferPromptUntilConfigResolvesKey = Symbol.for("@optique/config/deferPromptUntilResolved");
|
|
9
|
+
const phase1ConfigAnnotationsKey = Symbol.for("@optique/config/phase1PromptAnnotations");
|
|
10
|
+
const phase2UndefinedParsedValueKey = Symbol.for("@optique/config/phase2UndefinedParsedValue");
|
|
11
|
+
const deferredPromptValueKey = Symbol.for("@optique/inquirer/deferredPromptValue");
|
|
8
12
|
/**
|
|
9
13
|
* Internal registry for active config data during config context execution.
|
|
10
14
|
* This is a workaround for the limitation that object() doesn't propagate
|
|
@@ -17,6 +21,117 @@ const activeConfigRegistry = /* @__PURE__ */ new Map();
|
|
|
17
21
|
* @internal
|
|
18
22
|
*/
|
|
19
23
|
const activeConfigMetaRegistry = /* @__PURE__ */ new Map();
|
|
24
|
+
const phase1ConfigAnnotationMarker = Symbol("@optique/config/phase1Annotation");
|
|
25
|
+
function isDeferredPromptValue(value) {
|
|
26
|
+
return value != null && typeof value === "object" && deferredPromptValueKey in value;
|
|
27
|
+
}
|
|
28
|
+
function isPhase2UndefinedParsedValue(value) {
|
|
29
|
+
return value != null && typeof value === "object" && phase2UndefinedParsedValueKey in value;
|
|
30
|
+
}
|
|
31
|
+
function isPlainObject(value) {
|
|
32
|
+
const proto = Object.getPrototypeOf(value);
|
|
33
|
+
return proto === Object.prototype || proto === null;
|
|
34
|
+
}
|
|
35
|
+
function shouldSkipCollectionOwnKey(value, key) {
|
|
36
|
+
if (Array.isArray(value)) return key === "length" || typeof key === "string" && Number.isInteger(Number(key)) && String(Number(key)) === key;
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
function containsDeferredPromptValuesInOwnProperties(value, seen) {
|
|
40
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
41
|
+
if (shouldSkipCollectionOwnKey(value, key)) continue;
|
|
42
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
43
|
+
if (descriptor != null && "value" in descriptor && containsDeferredPromptValues(descriptor.value, seen)) return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
function copySanitizedOwnProperties(source, target, seen) {
|
|
48
|
+
for (const key of Reflect.ownKeys(source)) {
|
|
49
|
+
if (shouldSkipCollectionOwnKey(source, key)) continue;
|
|
50
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, key);
|
|
51
|
+
if (descriptor == null) continue;
|
|
52
|
+
if ("value" in descriptor) descriptor.value = stripDeferredPromptValues(descriptor.value, seen);
|
|
53
|
+
Object.defineProperty(target, key, descriptor);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function containsDeferredPromptValues(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
57
|
+
if (isDeferredPromptValue(value)) return true;
|
|
58
|
+
if (value == null || typeof value !== "object") return false;
|
|
59
|
+
if (seen.has(value)) return false;
|
|
60
|
+
seen.add(value);
|
|
61
|
+
if (Array.isArray(value)) {
|
|
62
|
+
if (value.some((item) => containsDeferredPromptValues(item, seen))) return true;
|
|
63
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
64
|
+
}
|
|
65
|
+
if (value instanceof Set) {
|
|
66
|
+
for (const entryValue of value) if (containsDeferredPromptValues(entryValue, seen)) return true;
|
|
67
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
68
|
+
}
|
|
69
|
+
if (value instanceof Map) {
|
|
70
|
+
for (const [key, entryValue] of value) if (containsDeferredPromptValues(key, seen) || containsDeferredPromptValues(entryValue, seen)) return true;
|
|
71
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
72
|
+
}
|
|
73
|
+
return containsDeferredPromptValuesInOwnProperties(value, seen);
|
|
74
|
+
}
|
|
75
|
+
function createSanitizedNonPlainView(value, seen) {
|
|
76
|
+
const proxy = new Proxy(value, {
|
|
77
|
+
get(target, key, receiver) {
|
|
78
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
79
|
+
if (descriptor != null && "value" in descriptor) return stripDeferredPromptValues(descriptor.value, seen);
|
|
80
|
+
return Reflect.get(target, key, receiver);
|
|
81
|
+
},
|
|
82
|
+
getOwnPropertyDescriptor(target, key) {
|
|
83
|
+
const descriptor = Object.getOwnPropertyDescriptor(target, key);
|
|
84
|
+
if (descriptor == null || !("value" in descriptor)) return descriptor;
|
|
85
|
+
return {
|
|
86
|
+
...descriptor,
|
|
87
|
+
value: stripDeferredPromptValues(descriptor.value, seen)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
seen.set(value, proxy);
|
|
92
|
+
return proxy;
|
|
93
|
+
}
|
|
94
|
+
function stripDeferredPromptValues(value, seen = /* @__PURE__ */ new WeakMap()) {
|
|
95
|
+
if (isDeferredPromptValue(value)) return void 0;
|
|
96
|
+
if (value == null || typeof value !== "object") return value;
|
|
97
|
+
const cached = seen.get(value);
|
|
98
|
+
if (cached !== void 0) return cached;
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
101
|
+
const clone$1 = new Array(value.length);
|
|
102
|
+
seen.set(value, clone$1);
|
|
103
|
+
for (let i = 0; i < value.length; i++) clone$1[i] = stripDeferredPromptValues(value[i], seen);
|
|
104
|
+
copySanitizedOwnProperties(value, clone$1, seen);
|
|
105
|
+
return clone$1;
|
|
106
|
+
}
|
|
107
|
+
if (value instanceof Set) {
|
|
108
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
109
|
+
const clone$1 = /* @__PURE__ */ new Set();
|
|
110
|
+
seen.set(value, clone$1);
|
|
111
|
+
for (const entryValue of value) clone$1.add(stripDeferredPromptValues(entryValue, seen));
|
|
112
|
+
copySanitizedOwnProperties(value, clone$1, seen);
|
|
113
|
+
return clone$1;
|
|
114
|
+
}
|
|
115
|
+
if (value instanceof Map) {
|
|
116
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
117
|
+
const clone$1 = /* @__PURE__ */ new Map();
|
|
118
|
+
seen.set(value, clone$1);
|
|
119
|
+
for (const [key, entryValue] of value) clone$1.set(stripDeferredPromptValues(key, seen), stripDeferredPromptValues(entryValue, seen));
|
|
120
|
+
copySanitizedOwnProperties(value, clone$1, seen);
|
|
121
|
+
return clone$1;
|
|
122
|
+
}
|
|
123
|
+
if (!isPlainObject(value)) return containsDeferredPromptValues(value) ? createSanitizedNonPlainView(value, seen) : value;
|
|
124
|
+
if (!containsDeferredPromptValues(value)) return value;
|
|
125
|
+
const clone = Object.create(Object.getPrototypeOf(value));
|
|
126
|
+
seen.set(value, clone);
|
|
127
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
128
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
129
|
+
if (descriptor == null) continue;
|
|
130
|
+
if ("value" in descriptor) descriptor.value = stripDeferredPromptValues(descriptor.value, seen);
|
|
131
|
+
Object.defineProperty(clone, key, descriptor);
|
|
132
|
+
}
|
|
133
|
+
return clone;
|
|
134
|
+
}
|
|
20
135
|
/**
|
|
21
136
|
* Sets active config data for a context.
|
|
22
137
|
* @internal
|
|
@@ -107,15 +222,20 @@ function validateWithSchema(schema, rawData) {
|
|
|
107
222
|
*/
|
|
108
223
|
function createConfigContext(options) {
|
|
109
224
|
const contextId = Symbol(`@optique/config:${Math.random()}`);
|
|
110
|
-
|
|
225
|
+
const context = {
|
|
111
226
|
id: contextId,
|
|
112
227
|
schema: options.schema,
|
|
113
228
|
mode: "dynamic",
|
|
229
|
+
[phase1ConfigAnnotationsKey](parsed, annotations) {
|
|
230
|
+
if (parsed === void 0) return { [contextId]: phase1ConfigAnnotationMarker };
|
|
231
|
+
return Object.getOwnPropertySymbols(annotations).includes(contextId) ? void 0 : { [contextId]: void 0 };
|
|
232
|
+
},
|
|
114
233
|
getAnnotations(parsed, runtimeOptions) {
|
|
115
234
|
if (parsed === void 0) return {};
|
|
116
235
|
const opts = runtimeOptions;
|
|
117
236
|
if (!opts || !opts.getConfigPath && !opts.load) throw new TypeError("Either getConfigPath or load must be provided in the runner options when using ConfigContext.");
|
|
118
|
-
const parsedValue = parsed;
|
|
237
|
+
const parsedValue = isPhase2UndefinedParsedValue(parsed) ? void 0 : stripDeferredPromptValues(parsed);
|
|
238
|
+
const parsedPlaceholder = parsedValue;
|
|
119
239
|
const buildAnnotations = (configData, configMeta) => {
|
|
120
240
|
if (configData === void 0 || configData === null) return {};
|
|
121
241
|
setActiveConfig(contextId, configData);
|
|
@@ -134,12 +254,12 @@ function createConfigContext(options) {
|
|
|
134
254
|
return buildAnnotations(validated, configMeta);
|
|
135
255
|
};
|
|
136
256
|
if (opts.load) {
|
|
137
|
-
const loaded = opts.load(
|
|
257
|
+
const loaded = opts.load(parsedPlaceholder);
|
|
138
258
|
if (loaded instanceof Promise) return loaded.then(({ config, meta }) => validateAndBuildAnnotations(config, meta));
|
|
139
259
|
return validateAndBuildAnnotations(loaded.config, loaded.meta);
|
|
140
260
|
}
|
|
141
261
|
if (opts.getConfigPath) {
|
|
142
|
-
const configPath = opts.getConfigPath(
|
|
262
|
+
const configPath = opts.getConfigPath(parsedPlaceholder);
|
|
143
263
|
if (!configPath) return {};
|
|
144
264
|
const absoluteConfigPath = resolve(configPath);
|
|
145
265
|
const singleFileMeta = {
|
|
@@ -168,6 +288,7 @@ function createConfigContext(options) {
|
|
|
168
288
|
clearActiveConfigMeta(contextId);
|
|
169
289
|
}
|
|
170
290
|
};
|
|
291
|
+
return context;
|
|
171
292
|
}
|
|
172
293
|
/**
|
|
173
294
|
* Binds a parser to configuration values with fallback priority.
|
|
@@ -205,7 +326,11 @@ function bindConfig(parser, options) {
|
|
|
205
326
|
function isConfigBindState(value) {
|
|
206
327
|
return value != null && typeof value === "object" && configBindStateKey in value;
|
|
207
328
|
}
|
|
208
|
-
|
|
329
|
+
function shouldDeferPromptUntilConfigResolves(state) {
|
|
330
|
+
const annotations = getAnnotations(state);
|
|
331
|
+
return annotations?.[options.context.id] === phase1ConfigAnnotationMarker;
|
|
332
|
+
}
|
|
333
|
+
const boundParser = {
|
|
209
334
|
$mode: parser.$mode,
|
|
210
335
|
$valueType: parser.$valueType,
|
|
211
336
|
$stateType: parser.$stateType,
|
|
@@ -262,11 +387,13 @@ function bindConfig(parser, options) {
|
|
|
262
387
|
return wrapForMode(parser.$mode, getConfigOrDefault(state, options));
|
|
263
388
|
},
|
|
264
389
|
suggest: parser.suggest,
|
|
390
|
+
[deferPromptUntilConfigResolvesKey]: shouldDeferPromptUntilConfigResolves,
|
|
265
391
|
getDocFragments(state, upperDefaultValue) {
|
|
266
392
|
const defaultValue = upperDefaultValue ?? options.default;
|
|
267
393
|
return parser.getDocFragments(state, defaultValue);
|
|
268
394
|
}
|
|
269
395
|
};
|
|
396
|
+
return boundParser;
|
|
270
397
|
}
|
|
271
398
|
/**
|
|
272
399
|
* Helper function to get value from config or default.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/config",
|
|
3
|
-
"version": "1.0.0-dev.
|
|
3
|
+
"version": "1.0.0-dev.670+a142c6c9",
|
|
4
4
|
"description": "Configuration file support for Optique with Standard Schema validation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@standard-schema/spec": "^1.1.0"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@optique/core": "1.0.0-dev.
|
|
62
|
+
"@optique/core": "1.0.0-dev.670+a142c6c9"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@standard-schema/spec": "^1.1.0",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"tsdown": "^0.13.0",
|
|
68
68
|
"typescript": "^5.8.3",
|
|
69
69
|
"zod": "^3.25.0 || ^4.0.0",
|
|
70
|
-
"@optique/env": "1.0.0-dev.
|
|
70
|
+
"@optique/env": "1.0.0-dev.670+a142c6c9"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsdown",
|