@optique/core 1.0.0-dev.1808 → 1.0.0-dev.1818
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/constructs.cjs +1 -0
- package/dist/constructs.js +1 -0
- package/dist/facade.cjs +309 -160
- package/dist/facade.js +312 -163
- package/dist/modifiers.cjs +1 -0
- package/dist/modifiers.js +1 -0
- package/dist/parser.d.cts +10 -0
- package/dist/parser.d.ts +10 -0
- package/dist/primitives.cjs +10 -1
- package/dist/primitives.js +10 -1
- package/dist/validate.cjs +7 -39
- package/dist/validate.js +7 -39
- package/package.json +1 -1
package/dist/parser.d.ts
CHANGED
|
@@ -378,6 +378,16 @@ interface ExecutionContext {
|
|
|
378
378
|
* resolution and completion.
|
|
379
379
|
*/
|
|
380
380
|
readonly path: readonly PropertyKey[];
|
|
381
|
+
/**
|
|
382
|
+
* Matched command names in parse order.
|
|
383
|
+
*
|
|
384
|
+
* This is tracked separately from {@link path} because parse-tree paths also
|
|
385
|
+
* include object fields and other wrapper segments. Runners use it to
|
|
386
|
+
* recover subcommand help context from partial parses.
|
|
387
|
+
*
|
|
388
|
+
* @internal
|
|
389
|
+
*/
|
|
390
|
+
readonly commandPath?: readonly string[];
|
|
381
391
|
/**
|
|
382
392
|
* Immutable trace of raw primitive inputs recorded during parsing.
|
|
383
393
|
*
|
package/dist/primitives.cjs
CHANGED
|
@@ -33,6 +33,7 @@ function mergeChildExec(parent, child) {
|
|
|
33
33
|
trace: child.trace ?? parent.trace,
|
|
34
34
|
dependencyRuntime: child.dependencyRuntime ?? parent.dependencyRuntime,
|
|
35
35
|
dependencyRegistry: child.dependencyRegistry ?? parent.dependencyRegistry,
|
|
36
|
+
commandPath: child.commandPath ?? parent.commandPath,
|
|
36
37
|
preCompletedByParser: child.preCompletedByParser ?? parent.preCompletedByParser,
|
|
37
38
|
excludedSourceFields: child.excludedSourceFields ?? parent.excludedSourceFields
|
|
38
39
|
};
|
|
@@ -1180,6 +1181,13 @@ function getCommandChildState(commandState, childState, parser) {
|
|
|
1180
1181
|
function createCommandState(sourceState, state) {
|
|
1181
1182
|
return require_annotations.annotateFreshArray(sourceState, state);
|
|
1182
1183
|
}
|
|
1184
|
+
function appendCommandPath(exec, name) {
|
|
1185
|
+
if (exec == null) return void 0;
|
|
1186
|
+
return {
|
|
1187
|
+
...exec,
|
|
1188
|
+
commandPath: [...exec.commandPath ?? [], name]
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1183
1191
|
function* suggestCommandSync(context, prefix, name, parser, options) {
|
|
1184
1192
|
if (require_usage.isSuggestionHidden(options.hidden)) return;
|
|
1185
1193
|
const state = normalizeCommandState(context.state);
|
|
@@ -1293,7 +1301,8 @@ function command(name, parser, options = {}) {
|
|
|
1293
1301
|
next: {
|
|
1294
1302
|
...context,
|
|
1295
1303
|
buffer: context.buffer.slice(1),
|
|
1296
|
-
state: createCommandState(context.state, ["matched", name])
|
|
1304
|
+
state: createCommandState(context.state, ["matched", name]),
|
|
1305
|
+
...context.exec != null ? { exec: appendCommandPath(context.exec, name) } : {}
|
|
1297
1306
|
},
|
|
1298
1307
|
consumed: context.buffer.slice(0, 1)
|
|
1299
1308
|
};
|
package/dist/primitives.js
CHANGED
|
@@ -33,6 +33,7 @@ function mergeChildExec(parent, child) {
|
|
|
33
33
|
trace: child.trace ?? parent.trace,
|
|
34
34
|
dependencyRuntime: child.dependencyRuntime ?? parent.dependencyRuntime,
|
|
35
35
|
dependencyRegistry: child.dependencyRegistry ?? parent.dependencyRegistry,
|
|
36
|
+
commandPath: child.commandPath ?? parent.commandPath,
|
|
36
37
|
preCompletedByParser: child.preCompletedByParser ?? parent.preCompletedByParser,
|
|
37
38
|
excludedSourceFields: child.excludedSourceFields ?? parent.excludedSourceFields
|
|
38
39
|
};
|
|
@@ -1180,6 +1181,13 @@ function getCommandChildState(commandState, childState, parser) {
|
|
|
1180
1181
|
function createCommandState(sourceState, state) {
|
|
1181
1182
|
return annotateFreshArray(sourceState, state);
|
|
1182
1183
|
}
|
|
1184
|
+
function appendCommandPath(exec, name) {
|
|
1185
|
+
if (exec == null) return void 0;
|
|
1186
|
+
return {
|
|
1187
|
+
...exec,
|
|
1188
|
+
commandPath: [...exec.commandPath ?? [], name]
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1183
1191
|
function* suggestCommandSync(context, prefix, name, parser, options) {
|
|
1184
1192
|
if (isSuggestionHidden(options.hidden)) return;
|
|
1185
1193
|
const state = normalizeCommandState(context.state);
|
|
@@ -1293,7 +1301,8 @@ function command(name, parser, options = {}) {
|
|
|
1293
1301
|
next: {
|
|
1294
1302
|
...context,
|
|
1295
1303
|
buffer: context.buffer.slice(1),
|
|
1296
|
-
state: createCommandState(context.state, ["matched", name])
|
|
1304
|
+
state: createCommandState(context.state, ["matched", name]),
|
|
1305
|
+
...context.exec != null ? { exec: appendCommandPath(context.exec, name) } : {}
|
|
1297
1306
|
},
|
|
1298
1307
|
consumed: context.buffer.slice(0, 1)
|
|
1299
1308
|
};
|
package/dist/validate.cjs
CHANGED
|
@@ -63,27 +63,22 @@ function validateCommandNames(names, label) {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
|
-
* Validates that there are no name collisions among meta features
|
|
67
|
-
* (help, version, completion)
|
|
66
|
+
* Validates that there are no name collisions among active meta features
|
|
67
|
+
* (help, version, completion).
|
|
68
68
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* against *leading* user names (those reachable before any positional gate).
|
|
73
|
-
* - Meta **option** entries use lenient scanners that match anywhere in
|
|
74
|
-
* `argv`, so they are checked against *all* user names at every depth,
|
|
75
|
-
* including literal values from conditional discriminators.
|
|
69
|
+
* User parser names are accepted even when they overlap with meta names.
|
|
70
|
+
* Runtime parsing resolves those cases parser-first so ordinary parser data
|
|
71
|
+
* can shadow built-in meta behavior.
|
|
76
72
|
*
|
|
77
73
|
* Meta-vs-meta collisions are always checked in a unified namespace,
|
|
78
74
|
* because a meta command named `"--help"` and a meta option named
|
|
79
75
|
* `"--help"` both compete for the same token.
|
|
80
76
|
*
|
|
81
|
-
* @param userNames User parser names extracted at different scopes.
|
|
82
77
|
* @param metaEntries Active meta feature entries annotated with their kind.
|
|
83
|
-
* @throws {TypeError} If any collision or duplicate is detected.
|
|
78
|
+
* @throws {TypeError} If any meta/meta collision or duplicate is detected.
|
|
84
79
|
* @since 1.0.0
|
|
85
80
|
*/
|
|
86
|
-
function validateMetaNameCollisions(
|
|
81
|
+
function validateMetaNameCollisions(metaEntries) {
|
|
87
82
|
for (const [, label, names] of metaEntries) {
|
|
88
83
|
const seen = /* @__PURE__ */ new Set();
|
|
89
84
|
for (const name of names) {
|
|
@@ -112,33 +107,6 @@ function validateMetaNameCollisions(userNames, metaEntries) {
|
|
|
112
107
|
}
|
|
113
108
|
}
|
|
114
109
|
}
|
|
115
|
-
for (const [kind, label, names, prefixMatch] of metaEntries) for (const name of names) {
|
|
116
|
-
if (kind === "command") {
|
|
117
|
-
if (userNames.leadingNames.has(name)) if (userNames.allOptions.has(name)) throw new TypeError(`User-defined option "${name}" conflicts with the built-in ${label}.`);
|
|
118
|
-
else if (userNames.allCommands.has(name)) throw new TypeError(`User-defined command "${name}" conflicts with the built-in ${label}.`);
|
|
119
|
-
else if (userNames.allLiterals.has(name)) throw new TypeError(`Literal value "${name}" conflicts with the built-in ${label}.`);
|
|
120
|
-
else throw new TypeError(`User-defined name "${name}" conflicts with the built-in ${label}.`);
|
|
121
|
-
} else {
|
|
122
|
-
if (userNames.allOptions.has(name)) throw new TypeError(`User-defined option "${name}" conflicts with the built-in ${label}.`);
|
|
123
|
-
if (userNames.allCommands.has(name)) throw new TypeError(`User-defined command "${name}" conflicts with the built-in ${label}.`);
|
|
124
|
-
if (userNames.allLiterals.has(name)) throw new TypeError(`Literal value "${name}" conflicts with the built-in ${label}.`);
|
|
125
|
-
}
|
|
126
|
-
if (prefixMatch) {
|
|
127
|
-
const prefix = name + "=";
|
|
128
|
-
const checkSets = kind === "command" ? [userNames.leadingNames] : [
|
|
129
|
-
userNames.allOptions,
|
|
130
|
-
userNames.allCommands,
|
|
131
|
-
userNames.allLiterals
|
|
132
|
-
];
|
|
133
|
-
for (const nameSet of checkSets) for (const userName of nameSet) {
|
|
134
|
-
if (!userName.startsWith(prefix)) continue;
|
|
135
|
-
if (userNames.allOptions.has(userName)) throw new TypeError(`User-defined option "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
136
|
-
else if (userNames.allCommands.has(userName)) throw new TypeError(`User-defined command "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
137
|
-
else if (userNames.allLiterals.has(userName)) throw new TypeError(`Literal value "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
138
|
-
else throw new TypeError(`User-defined name "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
110
|
}
|
|
143
111
|
function capitalize(s) {
|
|
144
112
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
package/dist/validate.js
CHANGED
|
@@ -62,27 +62,22 @@ function validateCommandNames(names, label) {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
|
-
* Validates that there are no name collisions among meta features
|
|
66
|
-
* (help, version, completion)
|
|
65
|
+
* Validates that there are no name collisions among active meta features
|
|
66
|
+
* (help, version, completion).
|
|
67
67
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* against *leading* user names (those reachable before any positional gate).
|
|
72
|
-
* - Meta **option** entries use lenient scanners that match anywhere in
|
|
73
|
-
* `argv`, so they are checked against *all* user names at every depth,
|
|
74
|
-
* including literal values from conditional discriminators.
|
|
68
|
+
* User parser names are accepted even when they overlap with meta names.
|
|
69
|
+
* Runtime parsing resolves those cases parser-first so ordinary parser data
|
|
70
|
+
* can shadow built-in meta behavior.
|
|
75
71
|
*
|
|
76
72
|
* Meta-vs-meta collisions are always checked in a unified namespace,
|
|
77
73
|
* because a meta command named `"--help"` and a meta option named
|
|
78
74
|
* `"--help"` both compete for the same token.
|
|
79
75
|
*
|
|
80
|
-
* @param userNames User parser names extracted at different scopes.
|
|
81
76
|
* @param metaEntries Active meta feature entries annotated with their kind.
|
|
82
|
-
* @throws {TypeError} If any collision or duplicate is detected.
|
|
77
|
+
* @throws {TypeError} If any meta/meta collision or duplicate is detected.
|
|
83
78
|
* @since 1.0.0
|
|
84
79
|
*/
|
|
85
|
-
function validateMetaNameCollisions(
|
|
80
|
+
function validateMetaNameCollisions(metaEntries) {
|
|
86
81
|
for (const [, label, names] of metaEntries) {
|
|
87
82
|
const seen = /* @__PURE__ */ new Set();
|
|
88
83
|
for (const name of names) {
|
|
@@ -111,33 +106,6 @@ function validateMetaNameCollisions(userNames, metaEntries) {
|
|
|
111
106
|
}
|
|
112
107
|
}
|
|
113
108
|
}
|
|
114
|
-
for (const [kind, label, names, prefixMatch] of metaEntries) for (const name of names) {
|
|
115
|
-
if (kind === "command") {
|
|
116
|
-
if (userNames.leadingNames.has(name)) if (userNames.allOptions.has(name)) throw new TypeError(`User-defined option "${name}" conflicts with the built-in ${label}.`);
|
|
117
|
-
else if (userNames.allCommands.has(name)) throw new TypeError(`User-defined command "${name}" conflicts with the built-in ${label}.`);
|
|
118
|
-
else if (userNames.allLiterals.has(name)) throw new TypeError(`Literal value "${name}" conflicts with the built-in ${label}.`);
|
|
119
|
-
else throw new TypeError(`User-defined name "${name}" conflicts with the built-in ${label}.`);
|
|
120
|
-
} else {
|
|
121
|
-
if (userNames.allOptions.has(name)) throw new TypeError(`User-defined option "${name}" conflicts with the built-in ${label}.`);
|
|
122
|
-
if (userNames.allCommands.has(name)) throw new TypeError(`User-defined command "${name}" conflicts with the built-in ${label}.`);
|
|
123
|
-
if (userNames.allLiterals.has(name)) throw new TypeError(`Literal value "${name}" conflicts with the built-in ${label}.`);
|
|
124
|
-
}
|
|
125
|
-
if (prefixMatch) {
|
|
126
|
-
const prefix = name + "=";
|
|
127
|
-
const checkSets = kind === "command" ? [userNames.leadingNames] : [
|
|
128
|
-
userNames.allOptions,
|
|
129
|
-
userNames.allCommands,
|
|
130
|
-
userNames.allLiterals
|
|
131
|
-
];
|
|
132
|
-
for (const nameSet of checkSets) for (const userName of nameSet) {
|
|
133
|
-
if (!userName.startsWith(prefix)) continue;
|
|
134
|
-
if (userNames.allOptions.has(userName)) throw new TypeError(`User-defined option "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
135
|
-
else if (userNames.allCommands.has(userName)) throw new TypeError(`User-defined command "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
136
|
-
else if (userNames.allLiterals.has(userName)) throw new TypeError(`Literal value "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
137
|
-
else throw new TypeError(`User-defined name "${userName}" conflicts with the built-in ${label} (prefix "${prefix}").`);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
109
|
}
|
|
142
110
|
function capitalize(s) {
|
|
143
111
|
return s.charAt(0).toUpperCase() + s.slice(1);
|