@zhin.js/command 1.0.3 → 1.0.4
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/provider.js +30 -3
- package/package.json +2 -2
- package/src/provider.ts +29 -3
package/lib/provider.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { basename, join, parse } from 'node:path';
|
|
1
|
+
import { basename, join, parse, sep } from 'node:path';
|
|
2
2
|
import { featureId } from '@zhin.js/plugin-runtime';
|
|
3
3
|
import { defineFeatureProvider, } from '@zhin.js/feature-kit';
|
|
4
4
|
import { CommandIndex } from './command-index.js';
|
|
@@ -20,6 +20,23 @@ const commandFiles = {
|
|
|
20
20
|
async function* discoverCommandDirectory(context, directory, ancestors) {
|
|
21
21
|
const entries = [...await context.host.list(directory)]
|
|
22
22
|
.sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
|
|
23
|
+
const files = entries.flatMap((entry) => {
|
|
24
|
+
if (entry.kind !== 'file')
|
|
25
|
+
return [];
|
|
26
|
+
const parsed = parseCommandFile(entry.name);
|
|
27
|
+
return parsed ? [{ entry, parsed }] : [];
|
|
28
|
+
});
|
|
29
|
+
const preferJavaScript = context.packageRoot
|
|
30
|
+
.split(sep)
|
|
31
|
+
.includes('node_modules');
|
|
32
|
+
const preferredFiles = new Map();
|
|
33
|
+
for (const { entry, parsed } of files) {
|
|
34
|
+
const current = preferredFiles.get(parsed.localSegment);
|
|
35
|
+
if (!current || commandFilePriority(entry.name, preferJavaScript)
|
|
36
|
+
< commandFilePriority(current, preferJavaScript)) {
|
|
37
|
+
preferredFiles.set(parsed.localSegment, entry.name);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
23
40
|
for (const entry of entries) {
|
|
24
41
|
if (entry.kind === 'directory' && isCommandSegment(entry.name)) {
|
|
25
42
|
yield* discoverCommandDirectory(context, join(directory, entry.name), [...ancestors, entry.name]);
|
|
@@ -30,6 +47,8 @@ async function* discoverCommandDirectory(context, directory, ancestors) {
|
|
|
30
47
|
const file = parseCommandFile(entry.name);
|
|
31
48
|
if (!file)
|
|
32
49
|
continue;
|
|
50
|
+
if (preferredFiles.get(file.localSegment) !== entry.name)
|
|
51
|
+
continue;
|
|
33
52
|
yield {
|
|
34
53
|
localName: [...ancestors, file.localSegment].join('/'),
|
|
35
54
|
source: join(directory, entry.name),
|
|
@@ -40,7 +59,7 @@ async function* discoverCommandDirectory(context, directory, ancestors) {
|
|
|
40
59
|
function isCommandSegment(value) {
|
|
41
60
|
return /^[a-z0-9][a-z0-9-]*$/.test(value);
|
|
42
61
|
}
|
|
43
|
-
const dynamicCommandFilePattern = /^\[([a-z][a-zA-Z0-9]*):([a-z][a-z0-9-]*)(?:=([^\]]*))?\]\.tsx
|
|
62
|
+
const dynamicCommandFilePattern = /^\[([a-z][a-zA-Z0-9]*):([a-z][a-z0-9-]*)(?:=([^\]]*))?\]\.(?:tsx?|[cm]?js)$/;
|
|
44
63
|
const commandParameterTypes = new Set([
|
|
45
64
|
'string',
|
|
46
65
|
'number',
|
|
@@ -58,7 +77,7 @@ const commandParameterTypes = new Set([
|
|
|
58
77
|
'rps',
|
|
59
78
|
]);
|
|
60
79
|
function parseCommandFile(value) {
|
|
61
|
-
if (/^[a-z0-9][a-z0-9-]*\.tsx
|
|
80
|
+
if (/^[a-z0-9][a-z0-9-]*\.(?:tsx?|[cm]?js)$/.test(value)) {
|
|
62
81
|
return { localSegment: parse(value).name };
|
|
63
82
|
}
|
|
64
83
|
const match = dynamicCommandFilePattern.exec(value);
|
|
@@ -79,6 +98,14 @@ function parseCommandFile(value) {
|
|
|
79
98
|
}
|
|
80
99
|
return undefined;
|
|
81
100
|
}
|
|
101
|
+
function commandFilePriority(value, preferJavaScript) {
|
|
102
|
+
const extension = value.slice(value.lastIndexOf('.') + 1);
|
|
103
|
+
const order = preferJavaScript
|
|
104
|
+
? ['js', 'mjs', 'cjs', 'ts', 'tsx']
|
|
105
|
+
: ['ts', 'tsx', 'js', 'mjs', 'cjs'];
|
|
106
|
+
const priority = order.indexOf(extension);
|
|
107
|
+
return priority < 0 ? Number.MAX_SAFE_INTEGER : priority;
|
|
108
|
+
}
|
|
82
109
|
function parseParameterValue(name, type, value, source) {
|
|
83
110
|
if (type === 'string' || type === 'word' || type === 'text')
|
|
84
111
|
return value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/command",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Convention-based Command Feature for Zhin Plugin Runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"segment-matcher": "^1.0.5",
|
|
21
|
-
"@zhin.js/feature-kit": "1.0.
|
|
21
|
+
"@zhin.js/feature-kit": "1.0.4",
|
|
22
22
|
"@zhin.js/plugin-runtime": "1.1.1"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
package/src/provider.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { basename, join, parse } from 'node:path';
|
|
1
|
+
import { basename, join, parse, sep } from 'node:path';
|
|
2
2
|
import { featureId } from '@zhin.js/plugin-runtime';
|
|
3
3
|
import {
|
|
4
4
|
defineFeatureProvider,
|
|
@@ -38,6 +38,22 @@ async function* discoverCommandDirectory(
|
|
|
38
38
|
): AsyncIterable<DiscoveredSource> {
|
|
39
39
|
const entries = [...await context.host.list(directory)]
|
|
40
40
|
.sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
|
|
41
|
+
const files = entries.flatMap((entry) => {
|
|
42
|
+
if (entry.kind !== 'file') return [];
|
|
43
|
+
const parsed = parseCommandFile(entry.name);
|
|
44
|
+
return parsed ? [{ entry, parsed }] : [];
|
|
45
|
+
});
|
|
46
|
+
const preferJavaScript = context.packageRoot
|
|
47
|
+
.split(sep)
|
|
48
|
+
.includes('node_modules');
|
|
49
|
+
const preferredFiles = new Map<string, string>();
|
|
50
|
+
for (const { entry, parsed } of files) {
|
|
51
|
+
const current = preferredFiles.get(parsed.localSegment);
|
|
52
|
+
if (!current || commandFilePriority(entry.name, preferJavaScript)
|
|
53
|
+
< commandFilePriority(current, preferJavaScript)) {
|
|
54
|
+
preferredFiles.set(parsed.localSegment, entry.name);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
41
57
|
for (const entry of entries) {
|
|
42
58
|
if (entry.kind === 'directory' && isCommandSegment(entry.name)) {
|
|
43
59
|
yield* discoverCommandDirectory(
|
|
@@ -50,6 +66,7 @@ async function* discoverCommandDirectory(
|
|
|
50
66
|
if (entry.kind !== 'file') continue;
|
|
51
67
|
const file = parseCommandFile(entry.name);
|
|
52
68
|
if (!file) continue;
|
|
69
|
+
if (preferredFiles.get(file.localSegment) !== entry.name) continue;
|
|
53
70
|
yield {
|
|
54
71
|
localName: [...ancestors, file.localSegment].join('/'),
|
|
55
72
|
source: join(directory, entry.name),
|
|
@@ -68,7 +85,7 @@ interface ParsedCommandFile {
|
|
|
68
85
|
}
|
|
69
86
|
|
|
70
87
|
const dynamicCommandFilePattern =
|
|
71
|
-
/^\[([a-z][a-zA-Z0-9]*):([a-z][a-z0-9-]*)(?:=([^\]]*))?\]\.tsx
|
|
88
|
+
/^\[([a-z][a-zA-Z0-9]*):([a-z][a-z0-9-]*)(?:=([^\]]*))?\]\.(?:tsx?|[cm]?js)$/;
|
|
72
89
|
|
|
73
90
|
const commandParameterTypes = new Set<CommandParameterType>([
|
|
74
91
|
'string',
|
|
@@ -88,7 +105,7 @@ const commandParameterTypes = new Set<CommandParameterType>([
|
|
|
88
105
|
]);
|
|
89
106
|
|
|
90
107
|
function parseCommandFile(value: string): ParsedCommandFile | undefined {
|
|
91
|
-
if (/^[a-z0-9][a-z0-9-]*\.tsx
|
|
108
|
+
if (/^[a-z0-9][a-z0-9-]*\.(?:tsx?|[cm]?js)$/.test(value)) {
|
|
92
109
|
return { localSegment: parse(value).name };
|
|
93
110
|
}
|
|
94
111
|
const match = dynamicCommandFilePattern.exec(value);
|
|
@@ -110,6 +127,15 @@ function parseCommandFile(value: string): ParsedCommandFile | undefined {
|
|
|
110
127
|
return undefined;
|
|
111
128
|
}
|
|
112
129
|
|
|
130
|
+
function commandFilePriority(value: string, preferJavaScript: boolean): number {
|
|
131
|
+
const extension = value.slice(value.lastIndexOf('.') + 1);
|
|
132
|
+
const order = preferJavaScript
|
|
133
|
+
? ['js', 'mjs', 'cjs', 'ts', 'tsx']
|
|
134
|
+
: ['ts', 'tsx', 'js', 'mjs', 'cjs'];
|
|
135
|
+
const priority = order.indexOf(extension);
|
|
136
|
+
return priority < 0 ? Number.MAX_SAFE_INTEGER : priority;
|
|
137
|
+
}
|
|
138
|
+
|
|
113
139
|
function parseParameterValue(
|
|
114
140
|
name: string,
|
|
115
141
|
type: CommandParameterType,
|