@zhin.js/command 1.1.3 → 1.1.5
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/lib/command-index.d.ts +2 -2
- package/lib/command-index.js +15 -14
- package/package.json +4 -4
- package/src/command-index.ts +21 -19
package/lib/command-index.d.ts
CHANGED
|
@@ -32,8 +32,8 @@ export declare class CommandIndex {
|
|
|
32
32
|
constructor(slots: readonly Readonly<CapabilitySlot<CommandDefinition>>[], snapshot: RuntimeSnapshot, menu?: CommandMenuConfig);
|
|
33
33
|
list(): readonly CommandDescriptor[];
|
|
34
34
|
has(name: string): boolean;
|
|
35
|
-
execute(name: string, args?: readonly string[]): Promise<unknown>;
|
|
36
|
-
dispatch(input: CommandMatchInput, source?: unknown, interactionFactory?: UserInteractionFactory, commandPrefix?: string): Promise<CommandDispatchResult>;
|
|
35
|
+
execute(name: string, args?: readonly string[], operationSnapshot?: RuntimeSnapshot): Promise<unknown>;
|
|
36
|
+
dispatch(input: CommandMatchInput, source?: unknown, interactionFactory?: UserInteractionFactory, commandPrefix?: string, operationSnapshot?: RuntimeSnapshot): Promise<CommandDispatchResult>;
|
|
37
37
|
}
|
|
38
38
|
export declare function isCommandIndex(value: unknown): value is CommandIndex;
|
|
39
39
|
export declare class CommandParameterValueError extends TypeError {
|
package/lib/command-index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SegmentMatcher, TypeMatcherRegistry, } from 'segment-matcher';
|
|
2
|
-
import { operationClientAdapter } from '@zhin.js/feature-kit';
|
|
2
|
+
import { bindOperationInput, operationClientAdapter } from '@zhin.js/feature-kit';
|
|
3
3
|
import { permissionHostToken, toPermissionSubject, } from '@zhin.js/permission';
|
|
4
4
|
import { createCommandContext, resolveCommandSession, resolveDynamicParams, } from './definition.js';
|
|
5
5
|
const segmentFields = {
|
|
@@ -112,37 +112,37 @@ export class CommandIndex {
|
|
|
112
112
|
throw error;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
async execute(name, args = []) {
|
|
115
|
+
async execute(name, args = [], operationSnapshot = this.snapshot) {
|
|
116
116
|
const match = this.#match(name, true);
|
|
117
117
|
if (!match) {
|
|
118
118
|
this.#diagnoseParameter(name);
|
|
119
119
|
throw new Error(`Unknown Command: ${name}`);
|
|
120
120
|
}
|
|
121
121
|
// Host / 无 session:跳过 permit;无 source 时函数默认值得到空 session。
|
|
122
|
-
return match.command.slot.definition.execute(createCommandContext(
|
|
122
|
+
return match.command.slot.definition.execute(createCommandContext(operationSnapshot, match.command.slot.owner, args, resolveDynamicParams(match.params, undefined), undefined, Object.freeze([]), undefined, match.command.slot.definition.adapter));
|
|
123
123
|
}
|
|
124
|
-
async dispatch(input, source = undefined, interactionFactory, commandPrefix = '') {
|
|
124
|
+
async dispatch(input, source = undefined, interactionFactory, commandPrefix = '', operationSnapshot = this.snapshot) {
|
|
125
125
|
if (this.#menu) {
|
|
126
126
|
const menuValue = this.#dispatchMenu(input, commandPrefix);
|
|
127
127
|
if (menuValue !== undefined) {
|
|
128
128
|
return Object.freeze({
|
|
129
129
|
matched: true,
|
|
130
130
|
command: this.#menu.keyword,
|
|
131
|
-
owner:
|
|
131
|
+
owner: operationSnapshot.root,
|
|
132
132
|
value: menuValue,
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
const interaction = interactionFactory?.(source);
|
|
137
136
|
const shortcut = this.#matchShortcut(input);
|
|
138
137
|
if (shortcut) {
|
|
139
138
|
if (!commandAdapterMatches(shortcut.record, source)) {
|
|
140
139
|
return Object.freeze({ matched: false });
|
|
141
140
|
}
|
|
142
|
-
if (!(await this.#permitAllows(shortcut.record, source))) {
|
|
141
|
+
if (!(await this.#permitAllows(shortcut.record, source, operationSnapshot))) {
|
|
143
142
|
return Object.freeze({ matched: false });
|
|
144
143
|
}
|
|
145
|
-
const
|
|
144
|
+
const authorSource = bindOperationInput(source, shortcut.record.slot.owner, operationSnapshot);
|
|
145
|
+
const value = await shortcut.record.slot.definition.execute(createCommandContext(operationSnapshot, shortcut.record.slot.owner, Object.freeze([]), resolveDynamicParams(shortcut.params, authorSource), authorSource, Object.freeze([]), interactionFactory?.(authorSource), shortcut.record.slot.definition.adapter));
|
|
146
146
|
return Object.freeze({
|
|
147
147
|
matched: true,
|
|
148
148
|
command: shortcut.record.name,
|
|
@@ -156,11 +156,12 @@ export class CommandIndex {
|
|
|
156
156
|
if (!commandAdapterMatches(match.command, source)) {
|
|
157
157
|
return Object.freeze({ matched: false });
|
|
158
158
|
}
|
|
159
|
-
if (!(await this.#permitAllows(match.command, source))) {
|
|
159
|
+
if (!(await this.#permitAllows(match.command, source, operationSnapshot))) {
|
|
160
160
|
return Object.freeze({ matched: false });
|
|
161
161
|
}
|
|
162
162
|
const args = textArgs(match.remaining);
|
|
163
|
-
const
|
|
163
|
+
const authorSource = bindOperationInput(source, match.command.slot.owner, operationSnapshot);
|
|
164
|
+
const value = await match.command.slot.definition.execute(createCommandContext(operationSnapshot, match.command.slot.owner, args, resolveDynamicParams(match.params, authorSource), authorSource, match.remaining, interactionFactory?.(authorSource), match.command.slot.definition.adapter));
|
|
164
165
|
return Object.freeze({
|
|
165
166
|
matched: true,
|
|
166
167
|
command: match.command.name,
|
|
@@ -168,21 +169,21 @@ export class CommandIndex {
|
|
|
168
169
|
value,
|
|
169
170
|
});
|
|
170
171
|
}
|
|
171
|
-
async #permitAllows(record, source) {
|
|
172
|
+
async #permitAllows(record, source, operationSnapshot) {
|
|
172
173
|
const permits = record.permit;
|
|
173
174
|
if (!permits || permits.length === 0)
|
|
174
175
|
return true;
|
|
175
176
|
if (!hasImSession(source))
|
|
176
177
|
return true;
|
|
177
|
-
const host = this.#resolveHost();
|
|
178
|
+
const host = this.#resolveHost(operationSnapshot);
|
|
178
179
|
if (!host)
|
|
179
180
|
return false;
|
|
180
181
|
const subject = toPermissionSubject(resolveCommandSession(source));
|
|
181
182
|
return host.checkAll(permits, subject);
|
|
182
183
|
}
|
|
183
|
-
#resolveHost() {
|
|
184
|
+
#resolveHost(operationSnapshot) {
|
|
184
185
|
try {
|
|
185
|
-
const resources =
|
|
186
|
+
const resources = operationSnapshot.resources.get(operationSnapshot.root);
|
|
186
187
|
if (!resources)
|
|
187
188
|
return undefined;
|
|
188
189
|
const host = resources.get(permissionHostToken.id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/command",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Convention-based Command Feature for Zhin Plugin Runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"segment-matcher": "^1.0.5",
|
|
21
|
-
"@zhin.js/feature-kit": "1.1.
|
|
21
|
+
"@zhin.js/feature-kit": "1.1.3",
|
|
22
22
|
"@zhin.js/interaction": "1.1.0",
|
|
23
|
-
"@zhin.js/permission": "1.1.
|
|
24
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
23
|
+
"@zhin.js/permission": "1.1.4",
|
|
24
|
+
"@zhin.js/plugin-runtime": "1.1.12"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^26.1.2",
|
package/src/command-index.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
RuntimeSnapshot,
|
|
10
10
|
} from '@zhin.js/plugin-runtime';
|
|
11
11
|
import type { UserInteractionFactory } from '@zhin.js/interaction';
|
|
12
|
-
import { operationClientAdapter } from '@zhin.js/feature-kit';
|
|
12
|
+
import { bindOperationInput, operationClientAdapter } from '@zhin.js/feature-kit';
|
|
13
13
|
import {
|
|
14
14
|
permissionHostToken,
|
|
15
15
|
toPermissionSubject,
|
|
@@ -210,7 +210,7 @@ export class CommandIndex {
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
async execute(name: string, args: readonly string[] = []): Promise<unknown> {
|
|
213
|
+
async execute(name: string, args: readonly string[] = [], operationSnapshot: RuntimeSnapshot = this.snapshot): Promise<unknown> {
|
|
214
214
|
const match = this.#match(name, true);
|
|
215
215
|
if (!match) {
|
|
216
216
|
this.#diagnoseParameter(name);
|
|
@@ -219,7 +219,7 @@ export class CommandIndex {
|
|
|
219
219
|
// Host / 无 session:跳过 permit;无 source 时函数默认值得到空 session。
|
|
220
220
|
return match.command.slot.definition.execute(
|
|
221
221
|
createCommandContext(
|
|
222
|
-
|
|
222
|
+
operationSnapshot,
|
|
223
223
|
match.command.slot.owner,
|
|
224
224
|
args,
|
|
225
225
|
resolveDynamicParams(match.params, undefined),
|
|
@@ -236,6 +236,7 @@ export class CommandIndex {
|
|
|
236
236
|
source: unknown = undefined,
|
|
237
237
|
interactionFactory?: UserInteractionFactory,
|
|
238
238
|
commandPrefix = '',
|
|
239
|
+
operationSnapshot: RuntimeSnapshot = this.snapshot,
|
|
239
240
|
): Promise<CommandDispatchResult> {
|
|
240
241
|
if (this.#menu) {
|
|
241
242
|
const menuValue = this.#dispatchMenu(input, commandPrefix);
|
|
@@ -243,29 +244,29 @@ export class CommandIndex {
|
|
|
243
244
|
return Object.freeze({
|
|
244
245
|
matched: true,
|
|
245
246
|
command: this.#menu.keyword,
|
|
246
|
-
owner:
|
|
247
|
+
owner: operationSnapshot.root,
|
|
247
248
|
value: menuValue,
|
|
248
249
|
});
|
|
249
250
|
}
|
|
250
251
|
}
|
|
251
|
-
const interaction = interactionFactory?.(source);
|
|
252
252
|
const shortcut = this.#matchShortcut(input);
|
|
253
253
|
if (shortcut) {
|
|
254
254
|
if (!commandAdapterMatches(shortcut.record, source)) {
|
|
255
255
|
return Object.freeze({ matched: false });
|
|
256
256
|
}
|
|
257
|
-
if (!(await this.#permitAllows(shortcut.record, source))) {
|
|
257
|
+
if (!(await this.#permitAllows(shortcut.record, source, operationSnapshot))) {
|
|
258
258
|
return Object.freeze({ matched: false });
|
|
259
259
|
}
|
|
260
|
+
const authorSource = bindOperationInput(source, shortcut.record.slot.owner, operationSnapshot);
|
|
260
261
|
const value = await shortcut.record.slot.definition.execute(
|
|
261
262
|
createCommandContext(
|
|
262
|
-
|
|
263
|
+
operationSnapshot,
|
|
263
264
|
shortcut.record.slot.owner,
|
|
264
265
|
Object.freeze([]),
|
|
265
|
-
resolveDynamicParams(shortcut.params,
|
|
266
|
-
|
|
266
|
+
resolveDynamicParams(shortcut.params, authorSource),
|
|
267
|
+
authorSource,
|
|
267
268
|
Object.freeze([]),
|
|
268
|
-
|
|
269
|
+
interactionFactory?.(authorSource),
|
|
269
270
|
shortcut.record.slot.definition.adapter,
|
|
270
271
|
),
|
|
271
272
|
);
|
|
@@ -282,19 +283,20 @@ export class CommandIndex {
|
|
|
282
283
|
if (!commandAdapterMatches(match.command, source)) {
|
|
283
284
|
return Object.freeze({ matched: false });
|
|
284
285
|
}
|
|
285
|
-
if (!(await this.#permitAllows(match.command, source))) {
|
|
286
|
+
if (!(await this.#permitAllows(match.command, source, operationSnapshot))) {
|
|
286
287
|
return Object.freeze({ matched: false });
|
|
287
288
|
}
|
|
288
289
|
const args = textArgs(match.remaining);
|
|
290
|
+
const authorSource = bindOperationInput(source, match.command.slot.owner, operationSnapshot);
|
|
289
291
|
const value = await match.command.slot.definition.execute(
|
|
290
292
|
createCommandContext(
|
|
291
|
-
|
|
293
|
+
operationSnapshot,
|
|
292
294
|
match.command.slot.owner,
|
|
293
295
|
args,
|
|
294
|
-
resolveDynamicParams(match.params,
|
|
295
|
-
|
|
296
|
+
resolveDynamicParams(match.params, authorSource),
|
|
297
|
+
authorSource,
|
|
296
298
|
match.remaining,
|
|
297
|
-
|
|
299
|
+
interactionFactory?.(authorSource),
|
|
298
300
|
match.command.slot.definition.adapter,
|
|
299
301
|
),
|
|
300
302
|
);
|
|
@@ -306,19 +308,19 @@ export class CommandIndex {
|
|
|
306
308
|
});
|
|
307
309
|
}
|
|
308
310
|
|
|
309
|
-
async #permitAllows(record: CommandRecord, source: unknown): Promise<boolean> {
|
|
311
|
+
async #permitAllows(record: CommandRecord, source: unknown, operationSnapshot: RuntimeSnapshot): Promise<boolean> {
|
|
310
312
|
const permits = record.permit;
|
|
311
313
|
if (!permits || permits.length === 0) return true;
|
|
312
314
|
if (!hasImSession(source)) return true;
|
|
313
|
-
const host = this.#resolveHost();
|
|
315
|
+
const host = this.#resolveHost(operationSnapshot);
|
|
314
316
|
if (!host) return false;
|
|
315
317
|
const subject = toPermissionSubject(resolveCommandSession(source));
|
|
316
318
|
return host.checkAll(permits, subject);
|
|
317
319
|
}
|
|
318
320
|
|
|
319
|
-
#resolveHost(): PermissionHost | undefined {
|
|
321
|
+
#resolveHost(operationSnapshot: RuntimeSnapshot): PermissionHost | undefined {
|
|
320
322
|
try {
|
|
321
|
-
const resources =
|
|
323
|
+
const resources = operationSnapshot.resources.get(operationSnapshot.root);
|
|
322
324
|
if (!resources) return undefined;
|
|
323
325
|
const host = resources.get(permissionHostToken.id);
|
|
324
326
|
return host && typeof (host as PermissionHost).check === 'function'
|