@openwebf/webf 0.23.10 → 0.24.1
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/README.md +8 -0
- package/bin/webf.js +9 -1
- package/dist/agents.js +245 -0
- package/dist/commands.js +101 -7
- package/dist/generator.js +37 -36
- package/dist/module.js +43 -14
- package/dist/peerDeps.js +27 -0
- package/dist/react.js +10 -18
- package/dist/vue.js +138 -132
- package/package.json +2 -1
- package/src/agents.ts +267 -0
- package/src/commands.ts +110 -8
- package/src/generator.ts +38 -37
- package/src/module.ts +53 -21
- package/src/peerDeps.ts +21 -0
- package/src/react.ts +10 -18
- package/src/vue.ts +157 -142
- package/templates/react.component.tsx.tpl +2 -2
- package/templates/react.index.ts.tpl +2 -1
- package/templates/react.package.json.tpl +3 -4
- package/templates/react.tsconfig.json.tpl +8 -1
- package/templates/react.tsup.config.ts.tpl +1 -1
- package/templates/vue.component.partial.tpl +4 -4
- package/templates/vue.components.d.ts.tpl +24 -9
- package/templates/vue.package.json.tpl +3 -1
- package/test/agents-init.test.ts +80 -0
- package/test/commands.test.ts +5 -12
- package/test/generator.test.ts +17 -10
- package/test/peerDeps.test.ts +30 -0
- package/test/react-consts.test.ts +9 -3
- package/test/standard-props.test.ts +14 -14
- package/test/templates.test.ts +17 -0
- package/test/vue.test.ts +36 -11
- package/dist/constants.js +0 -242
package/dist/peerDeps.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readJsonFile = readJsonFile;
|
|
7
|
+
exports.getPackageTypesFileFromDir = getPackageTypesFileFromDir;
|
|
8
|
+
exports.isPackageTypesReady = isPackageTypesReady;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
function readJsonFile(jsonPath) {
|
|
12
|
+
return JSON.parse(fs_1.default.readFileSync(jsonPath, 'utf-8'));
|
|
13
|
+
}
|
|
14
|
+
function getPackageTypesFileFromDir(pkgDir) {
|
|
15
|
+
const pkgJsonPath = path_1.default.join(pkgDir, 'package.json');
|
|
16
|
+
if (!fs_1.default.existsSync(pkgJsonPath))
|
|
17
|
+
return null;
|
|
18
|
+
const pkgJson = readJsonFile(pkgJsonPath);
|
|
19
|
+
const typesRel = pkgJson.types;
|
|
20
|
+
if (!typesRel)
|
|
21
|
+
return null;
|
|
22
|
+
return path_1.default.join(pkgDir, typesRel);
|
|
23
|
+
}
|
|
24
|
+
function isPackageTypesReady(pkgDir) {
|
|
25
|
+
const typesFile = getPackageTypesFileFromDir(pkgDir);
|
|
26
|
+
return typesFile ? fs_1.default.existsSync(typesFile) : true;
|
|
27
|
+
}
|
package/dist/react.js
CHANGED
|
@@ -55,14 +55,13 @@ function generateReturnType(type) {
|
|
|
55
55
|
return pointerType;
|
|
56
56
|
}
|
|
57
57
|
if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
|
|
58
|
-
const elemType = (
|
|
59
|
-
|
|
60
|
-
if (elemType === 'Type')
|
|
58
|
+
const elemType = generateReturnType(type.value);
|
|
59
|
+
if (!elemType)
|
|
61
60
|
return 'any[]';
|
|
62
|
-
if (
|
|
63
|
-
return
|
|
61
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
62
|
+
return `${elemType}[]`;
|
|
64
63
|
}
|
|
65
|
-
return
|
|
64
|
+
return `(${elemType})[]`;
|
|
66
65
|
}
|
|
67
66
|
switch (type.value) {
|
|
68
67
|
case declaration_1.FunctionArgumentType.int:
|
|
@@ -348,20 +347,13 @@ function generateReactComponent(blob, packageName, relativeDir) {
|
|
|
348
347
|
return pointerType;
|
|
349
348
|
}
|
|
350
349
|
if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
|
|
351
|
-
const elemType = (
|
|
352
|
-
if (elemType
|
|
350
|
+
const elemType = genRT(type.value);
|
|
351
|
+
if (!elemType)
|
|
353
352
|
return 'any[]';
|
|
354
|
-
if (
|
|
355
|
-
|
|
356
|
-
return `(typeof __webfTypes.${ident})[]`;
|
|
357
|
-
}
|
|
358
|
-
if (typeof elemType === 'string' && /^(?:[A-Za-z_][A-Za-z0-9_]*)(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
359
|
-
const base = elemType.split('.')[0];
|
|
360
|
-
if (!localTypeNames.has(base)) {
|
|
361
|
-
return `__webfTypes.${elemType}[]`;
|
|
362
|
-
}
|
|
353
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
354
|
+
return `${elemType}[]`;
|
|
363
355
|
}
|
|
364
|
-
return
|
|
356
|
+
return `(${elemType})[]`;
|
|
365
357
|
}
|
|
366
358
|
switch (type.value) {
|
|
367
359
|
case declaration_1.FunctionArgumentType.int:
|
package/dist/vue.js
CHANGED
|
@@ -8,7 +8,6 @@ const lodash_1 = __importDefault(require("lodash"));
|
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const declaration_1 = require("./declaration");
|
|
11
|
-
const logger_1 = require("./logger");
|
|
12
11
|
const utils_1 = require("./utils");
|
|
13
12
|
function readTemplate(name) {
|
|
14
13
|
return fs_1.default.readFileSync(path_1.default.join(__dirname, '../templates/' + name + '.tpl'), { encoding: 'utf-8' });
|
|
@@ -50,19 +49,18 @@ function generateReturnType(type) {
|
|
|
50
49
|
return 'any';
|
|
51
50
|
if (typeof pointerType === 'string' && pointerType.startsWith('typeof ')) {
|
|
52
51
|
const ident = pointerType.substring('typeof '.length).trim();
|
|
53
|
-
return `typeof
|
|
52
|
+
return `typeof ${ident}`;
|
|
54
53
|
}
|
|
55
54
|
return pointerType;
|
|
56
55
|
}
|
|
57
56
|
if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
|
|
58
|
-
const elemType = (
|
|
59
|
-
if (elemType
|
|
57
|
+
const elemType = generateReturnType(type.value);
|
|
58
|
+
if (!elemType)
|
|
60
59
|
return 'any[]';
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
return `(typeof __webfTypes.${ident})[]`;
|
|
60
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(elemType)) {
|
|
61
|
+
return `${elemType}[]`;
|
|
64
62
|
}
|
|
65
|
-
return
|
|
63
|
+
return `(${elemType})[]`;
|
|
66
64
|
}
|
|
67
65
|
switch (type.value) {
|
|
68
66
|
case declaration_1.FunctionArgumentType.int:
|
|
@@ -111,125 +109,111 @@ function generateMethodDeclaration(method) {
|
|
|
111
109
|
var returnType = generateReturnType(method.returnType);
|
|
112
110
|
return `${methodName}(${args}): ${returnType};`;
|
|
113
111
|
}
|
|
114
|
-
function
|
|
115
|
-
const classObjects = blob.objects;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
112
|
+
function getVueComponentSpecs(blob) {
|
|
113
|
+
const classObjects = blob.objects.filter(obj => obj instanceof declaration_1.ClassObject);
|
|
114
|
+
if (classObjects.length === 0)
|
|
115
|
+
return [];
|
|
116
|
+
const properties = classObjects.filter(object => object.name.endsWith('Properties'));
|
|
117
|
+
const events = classObjects.filter(object => object.name.endsWith('Events'));
|
|
118
|
+
const methods = classObjects.filter(object => object.name.endsWith('Methods'));
|
|
119
|
+
const componentMap = new Map();
|
|
120
|
+
properties.forEach(prop => {
|
|
121
|
+
const className = prop.name.replace(/Properties$/, '');
|
|
122
|
+
if (!componentMap.has(className))
|
|
123
|
+
componentMap.set(className, { className });
|
|
124
|
+
componentMap.get(className).properties = prop;
|
|
125
125
|
});
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
events.forEach(ev => {
|
|
127
|
+
const className = ev.name.replace(/Events$/, '');
|
|
128
|
+
if (!componentMap.has(className))
|
|
129
|
+
componentMap.set(className, { className });
|
|
130
|
+
componentMap.get(className).events = ev;
|
|
128
131
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
methods.forEach(m => {
|
|
133
|
+
const className = m.name.replace(/Methods$/, '');
|
|
134
|
+
if (!componentMap.has(className))
|
|
135
|
+
componentMap.set(className, { className });
|
|
136
|
+
componentMap.get(className).methods = m;
|
|
132
137
|
});
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
return Array.from(componentMap.values())
|
|
139
|
+
.filter(spec => spec.className.trim().length > 0)
|
|
140
|
+
.sort((a, b) => a.className.localeCompare(b.className));
|
|
141
|
+
}
|
|
142
|
+
function renderSupportingInterface(object) {
|
|
143
|
+
const hasProps = !!object.props && object.props.length > 0;
|
|
144
|
+
const hasMethods = !!object.methods && object.methods.length > 0;
|
|
145
|
+
if (!hasProps && !hasMethods) {
|
|
146
|
+
return '';
|
|
147
|
+
}
|
|
148
|
+
const interfaceLines = [];
|
|
149
|
+
if (object.documentation && object.documentation.trim().length > 0) {
|
|
150
|
+
interfaceLines.push('/**');
|
|
151
|
+
object.documentation.split('\n').forEach(line => {
|
|
152
|
+
interfaceLines.push(` * ${line}`);
|
|
153
|
+
});
|
|
154
|
+
interfaceLines.push(' */');
|
|
155
|
+
}
|
|
156
|
+
interfaceLines.push(`export interface ${object.name} {`);
|
|
157
|
+
const propLines = (object.props || []).map(prop => {
|
|
158
|
+
const lines = [];
|
|
159
|
+
if (prop.documentation && prop.documentation.trim().length > 0) {
|
|
160
|
+
lines.push(' /**');
|
|
161
|
+
prop.documentation.split('\n').forEach(line => {
|
|
162
|
+
lines.push(` * ${line}`);
|
|
142
163
|
});
|
|
143
|
-
|
|
164
|
+
lines.push(' */');
|
|
144
165
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
lines.push(' */');
|
|
154
|
-
}
|
|
155
|
-
const optionalToken = prop.optional ? '?' : '';
|
|
156
|
-
lines.push(` ${prop.name}${optionalToken}: ${generateReturnType(prop.type)};`);
|
|
157
|
-
return lines.join('\n');
|
|
166
|
+
const optionalToken = prop.optional ? '?' : '';
|
|
167
|
+
lines.push(` ${prop.name}${optionalToken}: ${generateReturnType(prop.type)};`);
|
|
168
|
+
return lines.join('\n');
|
|
169
|
+
});
|
|
170
|
+
interfaceLines.push(propLines.join('\n'));
|
|
171
|
+
if (object.methods && object.methods.length > 0) {
|
|
172
|
+
const methodLines = object.methods.map(method => {
|
|
173
|
+
return ` ${generateMethodDeclaration(method)}`;
|
|
158
174
|
});
|
|
159
|
-
interfaceLines.push(
|
|
160
|
-
interfaceLines.push('}');
|
|
161
|
-
return interfaceLines.join('\n');
|
|
162
|
-
}).filter(dep => dep.trim() !== '').join('\n\n');
|
|
163
|
-
const componentProperties = properties.length > 0 ? properties[0] : undefined;
|
|
164
|
-
const componentEvents = events.length > 0 ? events[0] : undefined;
|
|
165
|
-
const className = (() => {
|
|
166
|
-
if (componentProperties) {
|
|
167
|
-
return componentProperties.name.replace(/Properties$/, '');
|
|
168
|
-
}
|
|
169
|
-
if (componentEvents) {
|
|
170
|
-
return componentEvents.name.replace(/Events$/, '');
|
|
171
|
-
}
|
|
172
|
-
return '';
|
|
173
|
-
})();
|
|
174
|
-
if (!className) {
|
|
175
|
-
return '';
|
|
175
|
+
interfaceLines.push(methodLines.join('\n'));
|
|
176
176
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
properties: componentProperties,
|
|
180
|
-
events: componentEvents,
|
|
181
|
-
classObjectDictionary,
|
|
182
|
-
dependencies,
|
|
183
|
-
blob,
|
|
184
|
-
generateReturnType,
|
|
185
|
-
generateMethodDeclaration,
|
|
186
|
-
generateEventHandlerType,
|
|
187
|
-
});
|
|
188
|
-
const result = content.split('\n').filter(str => {
|
|
189
|
-
return str.trim().length > 0;
|
|
190
|
-
}).join('\n');
|
|
191
|
-
return result;
|
|
177
|
+
interfaceLines.push('}');
|
|
178
|
+
return interfaceLines.join('\n');
|
|
192
179
|
}
|
|
193
|
-
function toVueTagName(
|
|
180
|
+
function toVueTagName(rawClassName) {
|
|
181
|
+
const className = rawClassName.trim();
|
|
194
182
|
if (className.startsWith('WebF')) {
|
|
195
183
|
const withoutPrefix = className.substring(4);
|
|
196
|
-
|
|
184
|
+
const suffix = lodash_1.default.kebabCase(withoutPrefix);
|
|
185
|
+
return suffix.length > 0 ? 'webf-' + suffix : 'webf';
|
|
197
186
|
}
|
|
198
|
-
|
|
187
|
+
if (className.startsWith('Flutter')) {
|
|
199
188
|
const withoutPrefix = className.substring(7);
|
|
200
|
-
|
|
189
|
+
const suffix = lodash_1.default.kebabCase(withoutPrefix);
|
|
190
|
+
return suffix.length > 0 ? 'flutter-' + suffix : 'flutter';
|
|
201
191
|
}
|
|
202
|
-
|
|
192
|
+
const kebab = lodash_1.default.kebabCase(className);
|
|
193
|
+
return kebab.replace(/^web-f-/, 'webf-');
|
|
203
194
|
}
|
|
204
195
|
function generateVueTypings(blobs) {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return object.name.endsWith('Events');
|
|
212
|
-
});
|
|
213
|
-
const componentProperties = properties.length > 0 ? properties[0] : undefined;
|
|
214
|
-
const componentEvents = events.length > 0 ? events[0] : undefined;
|
|
215
|
-
const className = (() => {
|
|
216
|
-
if (componentProperties) {
|
|
217
|
-
return componentProperties.name.replace(/Properties$/, '');
|
|
218
|
-
}
|
|
219
|
-
if (componentEvents) {
|
|
220
|
-
return componentEvents.name.replace(/Events$/, '');
|
|
221
|
-
}
|
|
222
|
-
return '';
|
|
223
|
-
})();
|
|
224
|
-
return className;
|
|
225
|
-
}).filter(name => {
|
|
226
|
-
return name.length > 0;
|
|
196
|
+
const componentSpecMap = new Map();
|
|
197
|
+
blobs
|
|
198
|
+
.flatMap(blob => getVueComponentSpecs(blob))
|
|
199
|
+
.forEach(spec => {
|
|
200
|
+
if (!componentSpecMap.has(spec.className))
|
|
201
|
+
componentSpecMap.set(spec.className, spec);
|
|
227
202
|
});
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
203
|
+
const componentSpecs = Array.from(componentSpecMap.values()).sort((a, b) => a.className.localeCompare(b.className));
|
|
204
|
+
const componentNames = componentSpecs.map(spec => spec.className);
|
|
205
|
+
const components = componentSpecs.map(spec => {
|
|
206
|
+
const content = lodash_1.default.template(readTemplate('vue.component.partial'))({
|
|
207
|
+
className: spec.className,
|
|
208
|
+
properties: spec.properties,
|
|
209
|
+
events: spec.events,
|
|
210
|
+
methods: spec.methods,
|
|
211
|
+
generateReturnType,
|
|
212
|
+
generateMethodDeclaration,
|
|
213
|
+
generateEventHandlerType,
|
|
214
|
+
});
|
|
215
|
+
return content.split('\n').filter(str => str.trim().length > 0).join('\n');
|
|
216
|
+
}).filter(Boolean).join('\n\n');
|
|
233
217
|
// Collect declare consts across blobs and render as exported ambient declarations
|
|
234
218
|
const consts = blobs
|
|
235
219
|
.flatMap(blob => blob.objects)
|
|
@@ -241,34 +225,55 @@ function generateVueTypings(blobs) {
|
|
|
241
225
|
uniqueConsts.set(c.name, c);
|
|
242
226
|
});
|
|
243
227
|
const constDeclarations = Array.from(uniqueConsts.values())
|
|
228
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
244
229
|
.map(c => `export declare const ${c.name}: ${c.type};`)
|
|
245
230
|
.join('\n');
|
|
246
231
|
// Collect declare enums across blobs
|
|
247
232
|
const enums = blobs
|
|
248
233
|
.flatMap(blob => blob.objects)
|
|
249
234
|
.filter(obj => obj instanceof declaration_1.EnumObject);
|
|
250
|
-
const
|
|
235
|
+
const uniqueEnums = new Map();
|
|
236
|
+
enums.forEach(e => {
|
|
237
|
+
if (!uniqueEnums.has(e.name))
|
|
238
|
+
uniqueEnums.set(e.name, e);
|
|
239
|
+
});
|
|
240
|
+
const enumDeclarations = Array.from(uniqueEnums.values())
|
|
241
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
242
|
+
.map(e => {
|
|
251
243
|
const members = e.members.map(m => m.initializer ? `${m.name} = ${m.initializer}` : `${m.name}`).join(', ');
|
|
252
244
|
return `export declare enum ${e.name} { ${members} }`;
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
245
|
+
})
|
|
246
|
+
.join('\n');
|
|
247
|
+
// Collect type aliases across blobs and render as exported declarations.
|
|
248
|
+
const typeAliases = blobs
|
|
249
|
+
.flatMap(blob => blob.objects)
|
|
250
|
+
.filter(obj => obj instanceof declaration_1.TypeAliasObject);
|
|
251
|
+
const uniqueTypeAliases = new Map();
|
|
252
|
+
typeAliases.forEach(t => {
|
|
253
|
+
if (!uniqueTypeAliases.has(t.name))
|
|
254
|
+
uniqueTypeAliases.set(t.name, t);
|
|
255
|
+
});
|
|
256
|
+
const typeAliasDeclarations = Array.from(uniqueTypeAliases.values())
|
|
257
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
258
|
+
.map(t => `export type ${t.name} = ${t.type};`)
|
|
259
|
+
.join('\n');
|
|
260
|
+
// Collect supporting interfaces (non-component interfaces) so referenced types exist.
|
|
261
|
+
const supportingInterfaces = blobs
|
|
262
|
+
.flatMap(blob => blob.objects)
|
|
263
|
+
.filter(obj => obj instanceof declaration_1.ClassObject);
|
|
264
|
+
const supporting = supportingInterfaces.filter(obj => {
|
|
265
|
+
return !obj.name.endsWith('Properties') && !obj.name.endsWith('Events') && !obj.name.endsWith('Methods');
|
|
266
|
+
});
|
|
267
|
+
const uniqueSupporting = new Map();
|
|
268
|
+
supporting.forEach(obj => {
|
|
269
|
+
if (!uniqueSupporting.has(obj.name))
|
|
270
|
+
uniqueSupporting.set(obj.name, obj);
|
|
271
|
+
});
|
|
272
|
+
const supportingDeclarations = Array.from(uniqueSupporting.values())
|
|
273
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
274
|
+
.map(obj => renderSupportingInterface(obj))
|
|
275
|
+
.filter(Boolean)
|
|
276
|
+
.join('\n\n');
|
|
272
277
|
// Build mapping of template tag names to class names for GlobalComponents
|
|
273
278
|
const componentMetas = componentNames.map(className => ({
|
|
274
279
|
className,
|
|
@@ -284,7 +289,8 @@ function generateVueTypings(blobs) {
|
|
|
284
289
|
components,
|
|
285
290
|
consts: constDeclarations,
|
|
286
291
|
enums: enumDeclarations,
|
|
287
|
-
|
|
292
|
+
typeAliases: typeAliasDeclarations,
|
|
293
|
+
dependencies: supportingDeclarations,
|
|
288
294
|
});
|
|
289
295
|
return content.split('\n').filter(str => {
|
|
290
296
|
return str.trim().length > 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwebf/webf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.1",
|
|
4
4
|
"description": "Command line tools for WebF",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@microsoft/tsdoc": "^0.15.1",
|
|
41
41
|
"@microsoft/tsdoc-config": "^0.17.1",
|
|
42
|
+
"@openwebf/claude-code-skills": "^1.0.1",
|
|
42
43
|
"commander": "^14.0.0",
|
|
43
44
|
"glob": "^10.4.5",
|
|
44
45
|
"inquirer": "^8.2.6",
|