@dereekb/dbx-cli 13.13.0 → 13.15.0
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/firebase-api-manifest/main.js +65 -7
- package/firebase-api-manifest/package.json +3 -3
- package/generate-firestore-indexes/main.js +2 -2
- package/generate-firestore-indexes/package.json +2 -2
- package/generate-mcp-manifest/main.js +94 -14
- package/generate-mcp-manifest/package.json +3 -3
- package/index.cjs.js +142 -10
- package/index.esm.js +134 -11
- package/lint-cache/package.json +2 -2
- package/manifest-extract/index.cjs.js +138 -4
- package/manifest-extract/index.esm.js +138 -4
- package/manifest-extract/package.json +2 -2
- package/manifest-extract/src/lib/types.d.ts +19 -0
- package/package.json +15 -6
- package/src/lib/manifest/types.d.ts +136 -0
- package/src/lib/util/output.d.ts +11 -3
- package/test/package.json +9 -9
|
@@ -57,6 +57,11 @@ var SUPPORTED_VERBS = new Set([
|
|
|
57
57
|
'query',
|
|
58
58
|
'invoke'
|
|
59
59
|
]);
|
|
60
|
+
/**
|
|
61
|
+
* JSDoc tag (without leading `@`) on a CRUD leaf naming the interface that a handler's
|
|
62
|
+
* `mapSuccessfulResult` produces for MCP. When present, the MCP manifest output schema is
|
|
63
|
+
* synthesized from this type instead of the raw result type.
|
|
64
|
+
*/ var DBX_MODEL_API_MCP_RESULT_MARKER = 'dbxModelApiMcpResult';
|
|
60
65
|
/**
|
|
61
66
|
* Walks a `<model>.api.ts` source and returns one {@link CrudEntry} per
|
|
62
67
|
* callable leaf (CRUD or standalone). Best-effort: malformed configs return
|
|
@@ -136,6 +141,7 @@ function extractCrudEntries(source) {
|
|
|
136
141
|
valueNode: verbValueNode,
|
|
137
142
|
entries: entries,
|
|
138
143
|
fallbackDescription: readJsDocSummary(verbMember),
|
|
144
|
+
fallbackMcpResultTypeName: readJsDocTagValue(verbMember, DBX_MODEL_API_MCP_RESULT_MARKER),
|
|
139
145
|
resolveTypeDocs: resolveTypeDocs
|
|
140
146
|
});
|
|
141
147
|
}
|
|
@@ -187,6 +193,8 @@ function extractCrudEntries(source) {
|
|
|
187
193
|
var tuple = valueNode1 ? readTupleParamsResult(valueNode1) : undefined;
|
|
188
194
|
var paramsDocs = resolveTypeDocs(tuple === null || tuple === void 0 ? void 0 : tuple.params);
|
|
189
195
|
var resultDocs = resolveTypeDocs(tuple === null || tuple === void 0 ? void 0 : tuple.result);
|
|
196
|
+
var mcpResultTypeName = readJsDocTagValue(member1, DBX_MODEL_API_MCP_RESULT_MARKER);
|
|
197
|
+
var mcpResultDocs = resolveTypeDocs(mcpResultTypeName);
|
|
190
198
|
entries.push({
|
|
191
199
|
model: key,
|
|
192
200
|
verb: 'standalone',
|
|
@@ -199,7 +207,10 @@ function extractCrudEntries(source) {
|
|
|
199
207
|
paramsFields: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.fields,
|
|
200
208
|
paramsHasApiParamsTag: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.hasApiParamsTag,
|
|
201
209
|
resultTypeDescription: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.typeDescription,
|
|
202
|
-
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields
|
|
210
|
+
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields,
|
|
211
|
+
mcpResultTypeName: mcpResultTypeName,
|
|
212
|
+
mcpResultTypeDescription: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.typeDescription,
|
|
213
|
+
mcpResultFields: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.fields
|
|
203
214
|
});
|
|
204
215
|
}
|
|
205
216
|
} catch (err) {
|
|
@@ -355,7 +366,7 @@ function isNullLiteralType(node) {
|
|
|
355
366
|
}
|
|
356
367
|
function collectVerbEntries(input) {
|
|
357
368
|
var _readTupleParamsResult;
|
|
358
|
-
var modelName = input.modelName, verb = input.verb, valueNode = input.valueNode, entries = input.entries, fallbackDescription = input.fallbackDescription, resolveTypeDocs = input.resolveTypeDocs;
|
|
369
|
+
var modelName = input.modelName, verb = input.verb, valueNode = input.valueNode, entries = input.entries, fallbackDescription = input.fallbackDescription, fallbackMcpResultTypeName = input.fallbackMcpResultTypeName, resolveTypeDocs = input.resolveTypeDocs;
|
|
359
370
|
if (tsMorph.Node.isTypeLiteral(valueNode)) {
|
|
360
371
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
361
372
|
try {
|
|
@@ -370,6 +381,8 @@ function collectVerbEntries(input) {
|
|
|
370
381
|
var leaf = leafNode ? (_readTupleParamsResult1 = readTupleParamsResult(leafNode)) !== null && _readTupleParamsResult1 !== void 0 ? _readTupleParamsResult1 : readBareParams(leafNode) : undefined;
|
|
371
382
|
var paramsDocs = resolveTypeDocs(leaf === null || leaf === void 0 ? void 0 : leaf.params);
|
|
372
383
|
var resultDocs = resolveTypeDocs(leaf === null || leaf === void 0 ? void 0 : leaf.result);
|
|
384
|
+
var mcpResultTypeName = readJsDocTagValue(specMember, DBX_MODEL_API_MCP_RESULT_MARKER);
|
|
385
|
+
var mcpResultDocs = resolveTypeDocs(mcpResultTypeName);
|
|
373
386
|
entries.push({
|
|
374
387
|
model: modelName,
|
|
375
388
|
verb: verb,
|
|
@@ -382,7 +395,10 @@ function collectVerbEntries(input) {
|
|
|
382
395
|
paramsFields: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.fields,
|
|
383
396
|
paramsHasApiParamsTag: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.hasApiParamsTag,
|
|
384
397
|
resultTypeDescription: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.typeDescription,
|
|
385
|
-
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields
|
|
398
|
+
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields,
|
|
399
|
+
mcpResultTypeName: mcpResultTypeName,
|
|
400
|
+
mcpResultTypeDescription: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.typeDescription,
|
|
401
|
+
mcpResultFields: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.fields
|
|
386
402
|
});
|
|
387
403
|
}
|
|
388
404
|
} catch (err) {
|
|
@@ -404,6 +420,7 @@ function collectVerbEntries(input) {
|
|
|
404
420
|
var leaf1 = (_readTupleParamsResult = readTupleParamsResult(valueNode)) !== null && _readTupleParamsResult !== void 0 ? _readTupleParamsResult : readBareParams(valueNode);
|
|
405
421
|
var paramsDocs1 = resolveTypeDocs(leaf1 === null || leaf1 === void 0 ? void 0 : leaf1.params);
|
|
406
422
|
var resultDocs1 = resolveTypeDocs(leaf1 === null || leaf1 === void 0 ? void 0 : leaf1.result);
|
|
423
|
+
var mcpResultDocs1 = resolveTypeDocs(fallbackMcpResultTypeName);
|
|
407
424
|
entries.push({
|
|
408
425
|
model: modelName,
|
|
409
426
|
verb: verb,
|
|
@@ -416,7 +433,10 @@ function collectVerbEntries(input) {
|
|
|
416
433
|
paramsFields: paramsDocs1 === null || paramsDocs1 === void 0 ? void 0 : paramsDocs1.fields,
|
|
417
434
|
paramsHasApiParamsTag: paramsDocs1 === null || paramsDocs1 === void 0 ? void 0 : paramsDocs1.hasApiParamsTag,
|
|
418
435
|
resultTypeDescription: resultDocs1 === null || resultDocs1 === void 0 ? void 0 : resultDocs1.typeDescription,
|
|
419
|
-
resultFields: resultDocs1 === null || resultDocs1 === void 0 ? void 0 : resultDocs1.fields
|
|
436
|
+
resultFields: resultDocs1 === null || resultDocs1 === void 0 ? void 0 : resultDocs1.fields,
|
|
437
|
+
mcpResultTypeName: fallbackMcpResultTypeName,
|
|
438
|
+
mcpResultTypeDescription: mcpResultDocs1 === null || mcpResultDocs1 === void 0 ? void 0 : mcpResultDocs1.typeDescription,
|
|
439
|
+
mcpResultFields: mcpResultDocs1 === null || mcpResultDocs1 === void 0 ? void 0 : mcpResultDocs1.fields
|
|
420
440
|
});
|
|
421
441
|
}
|
|
422
442
|
function readTupleParamsResult(node) {
|
|
@@ -569,6 +589,64 @@ function readTypeDocs(sourceFile, typeName) {
|
|
|
569
589
|
}
|
|
570
590
|
return result;
|
|
571
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Reads the value token of a JSDoc tag (e.g. the `Foo` in `@dbxModelApiMcpResult Foo`).
|
|
594
|
+
*
|
|
595
|
+
* Used for value-carrying tags like `@dbxModelApiMcpResult` where the first token after the tag
|
|
596
|
+
* name names a type. Returns the first whitespace-delimited token of the tag's comment text.
|
|
597
|
+
*
|
|
598
|
+
* @param node - Any JSDocable ts-morph node (property signature, etc.).
|
|
599
|
+
* @param tagName - Tag name without the leading `@` (e.g. `'dbxModelApiMcpResult'`).
|
|
600
|
+
* @returns The first token of the tag's value, or `undefined` when the tag is absent or empty.
|
|
601
|
+
*/ function readJsDocTagValue(node, tagName) {
|
|
602
|
+
var result;
|
|
603
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
604
|
+
try {
|
|
605
|
+
for(var _iterator = node.getJsDocs()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
606
|
+
var doc = _step.value;
|
|
607
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
608
|
+
try {
|
|
609
|
+
for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
610
|
+
var tag = _step1.value;
|
|
611
|
+
if (tag.getTagName() === tagName) {
|
|
612
|
+
var _tag_getCommentText;
|
|
613
|
+
var token = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim().split(/\s+/)[0];
|
|
614
|
+
if (token) {
|
|
615
|
+
result = token;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
} catch (err) {
|
|
620
|
+
_didIteratorError1 = true;
|
|
621
|
+
_iteratorError1 = err;
|
|
622
|
+
} finally{
|
|
623
|
+
try {
|
|
624
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
625
|
+
_iterator1.return();
|
|
626
|
+
}
|
|
627
|
+
} finally{
|
|
628
|
+
if (_didIteratorError1) {
|
|
629
|
+
throw _iteratorError1;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
} catch (err) {
|
|
635
|
+
_didIteratorError = true;
|
|
636
|
+
_iteratorError = err;
|
|
637
|
+
} finally{
|
|
638
|
+
try {
|
|
639
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
640
|
+
_iterator.return();
|
|
641
|
+
}
|
|
642
|
+
} finally{
|
|
643
|
+
if (_didIteratorError) {
|
|
644
|
+
throw _iteratorError;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
572
650
|
function readJsDocSummary(node) {
|
|
573
651
|
var result;
|
|
574
652
|
var docs = node.getJsDocs();
|
|
@@ -617,7 +695,9 @@ var READ_LEVEL_VALUES = new Set([
|
|
|
617
695
|
'permissions'
|
|
618
696
|
]);
|
|
619
697
|
var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
|
|
698
|
+
var MCP_TOOL_NAME_SEGMENT_TAG = 'dbxModelMcpToolNameSegment';
|
|
620
699
|
var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
|
|
700
|
+
var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
|
|
621
701
|
/**
|
|
622
702
|
* TS utility/structural wrappers that don't change the field surface for
|
|
623
703
|
* inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
|
|
@@ -803,6 +883,7 @@ function buildInterface(decl) {
|
|
|
803
883
|
var jsDocs = decl.getJsDocs();
|
|
804
884
|
var hasDbxModelTag = jsDocsHaveTag(jsDocs, 'dbxModel');
|
|
805
885
|
var dbxModelRead = readDbxModelReadTag(jsDocs);
|
|
886
|
+
var mcpToolNameSegment = readMcpToolNameSegmentTag(jsDocs);
|
|
806
887
|
var extendsNames = decl.getExtends().map(resolveExtendsName);
|
|
807
888
|
var props = [];
|
|
808
889
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -847,8 +928,61 @@ function buildInterface(decl) {
|
|
|
847
928
|
props: props
|
|
848
929
|
}, dbxModelRead === undefined ? {} : {
|
|
849
930
|
dbxModelRead: dbxModelRead
|
|
931
|
+
}, mcpToolNameSegment === undefined ? {} : {
|
|
932
|
+
mcpToolNameSegment: mcpToolNameSegment
|
|
850
933
|
});
|
|
851
934
|
}
|
|
935
|
+
function readMcpToolNameSegmentTag(jsDocs) {
|
|
936
|
+
var result;
|
|
937
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
938
|
+
try {
|
|
939
|
+
for(var _iterator = jsDocs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
940
|
+
var doc = _step.value;
|
|
941
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
942
|
+
try {
|
|
943
|
+
for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
944
|
+
var tag = _step1.value;
|
|
945
|
+
var _tag_getCommentText;
|
|
946
|
+
if (tag.getTagName() !== MCP_TOOL_NAME_SEGMENT_TAG) continue;
|
|
947
|
+
if (result !== undefined) continue;
|
|
948
|
+
var raw = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim();
|
|
949
|
+
if (raw === undefined || raw.length === 0) continue;
|
|
950
|
+
var firstToken = raw.split(/\s+/)[0];
|
|
951
|
+
if (TOOL_NAME_SEGMENT_PATTERN.test(firstToken)) {
|
|
952
|
+
result = firstToken;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
} catch (err) {
|
|
956
|
+
_didIteratorError1 = true;
|
|
957
|
+
_iteratorError1 = err;
|
|
958
|
+
} finally{
|
|
959
|
+
try {
|
|
960
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
961
|
+
_iterator1.return();
|
|
962
|
+
}
|
|
963
|
+
} finally{
|
|
964
|
+
if (_didIteratorError1) {
|
|
965
|
+
throw _iteratorError1;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
} catch (err) {
|
|
971
|
+
_didIteratorError = true;
|
|
972
|
+
_iteratorError = err;
|
|
973
|
+
} finally{
|
|
974
|
+
try {
|
|
975
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
976
|
+
_iterator.return();
|
|
977
|
+
}
|
|
978
|
+
} finally{
|
|
979
|
+
if (_didIteratorError) {
|
|
980
|
+
throw _iteratorError;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
return result;
|
|
985
|
+
}
|
|
852
986
|
function readDbxModelReadTag(jsDocs) {
|
|
853
987
|
var result;
|
|
854
988
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -55,6 +55,11 @@ var SUPPORTED_VERBS = new Set([
|
|
|
55
55
|
'query',
|
|
56
56
|
'invoke'
|
|
57
57
|
]);
|
|
58
|
+
/**
|
|
59
|
+
* JSDoc tag (without leading `@`) on a CRUD leaf naming the interface that a handler's
|
|
60
|
+
* `mapSuccessfulResult` produces for MCP. When present, the MCP manifest output schema is
|
|
61
|
+
* synthesized from this type instead of the raw result type.
|
|
62
|
+
*/ var DBX_MODEL_API_MCP_RESULT_MARKER = 'dbxModelApiMcpResult';
|
|
58
63
|
/**
|
|
59
64
|
* Walks a `<model>.api.ts` source and returns one {@link CrudEntry} per
|
|
60
65
|
* callable leaf (CRUD or standalone). Best-effort: malformed configs return
|
|
@@ -134,6 +139,7 @@ function extractCrudEntries(source) {
|
|
|
134
139
|
valueNode: verbValueNode,
|
|
135
140
|
entries: entries,
|
|
136
141
|
fallbackDescription: readJsDocSummary(verbMember),
|
|
142
|
+
fallbackMcpResultTypeName: readJsDocTagValue(verbMember, DBX_MODEL_API_MCP_RESULT_MARKER),
|
|
137
143
|
resolveTypeDocs: resolveTypeDocs
|
|
138
144
|
});
|
|
139
145
|
}
|
|
@@ -185,6 +191,8 @@ function extractCrudEntries(source) {
|
|
|
185
191
|
var tuple = valueNode1 ? readTupleParamsResult(valueNode1) : undefined;
|
|
186
192
|
var paramsDocs = resolveTypeDocs(tuple === null || tuple === void 0 ? void 0 : tuple.params);
|
|
187
193
|
var resultDocs = resolveTypeDocs(tuple === null || tuple === void 0 ? void 0 : tuple.result);
|
|
194
|
+
var mcpResultTypeName = readJsDocTagValue(member1, DBX_MODEL_API_MCP_RESULT_MARKER);
|
|
195
|
+
var mcpResultDocs = resolveTypeDocs(mcpResultTypeName);
|
|
188
196
|
entries.push({
|
|
189
197
|
model: key,
|
|
190
198
|
verb: 'standalone',
|
|
@@ -197,7 +205,10 @@ function extractCrudEntries(source) {
|
|
|
197
205
|
paramsFields: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.fields,
|
|
198
206
|
paramsHasApiParamsTag: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.hasApiParamsTag,
|
|
199
207
|
resultTypeDescription: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.typeDescription,
|
|
200
|
-
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields
|
|
208
|
+
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields,
|
|
209
|
+
mcpResultTypeName: mcpResultTypeName,
|
|
210
|
+
mcpResultTypeDescription: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.typeDescription,
|
|
211
|
+
mcpResultFields: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.fields
|
|
201
212
|
});
|
|
202
213
|
}
|
|
203
214
|
} catch (err) {
|
|
@@ -353,7 +364,7 @@ function isNullLiteralType(node) {
|
|
|
353
364
|
}
|
|
354
365
|
function collectVerbEntries(input) {
|
|
355
366
|
var _readTupleParamsResult;
|
|
356
|
-
var modelName = input.modelName, verb = input.verb, valueNode = input.valueNode, entries = input.entries, fallbackDescription = input.fallbackDescription, resolveTypeDocs = input.resolveTypeDocs;
|
|
367
|
+
var modelName = input.modelName, verb = input.verb, valueNode = input.valueNode, entries = input.entries, fallbackDescription = input.fallbackDescription, fallbackMcpResultTypeName = input.fallbackMcpResultTypeName, resolveTypeDocs = input.resolveTypeDocs;
|
|
357
368
|
if (Node.isTypeLiteral(valueNode)) {
|
|
358
369
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
359
370
|
try {
|
|
@@ -368,6 +379,8 @@ function collectVerbEntries(input) {
|
|
|
368
379
|
var leaf = leafNode ? (_readTupleParamsResult1 = readTupleParamsResult(leafNode)) !== null && _readTupleParamsResult1 !== void 0 ? _readTupleParamsResult1 : readBareParams(leafNode) : undefined;
|
|
369
380
|
var paramsDocs = resolveTypeDocs(leaf === null || leaf === void 0 ? void 0 : leaf.params);
|
|
370
381
|
var resultDocs = resolveTypeDocs(leaf === null || leaf === void 0 ? void 0 : leaf.result);
|
|
382
|
+
var mcpResultTypeName = readJsDocTagValue(specMember, DBX_MODEL_API_MCP_RESULT_MARKER);
|
|
383
|
+
var mcpResultDocs = resolveTypeDocs(mcpResultTypeName);
|
|
371
384
|
entries.push({
|
|
372
385
|
model: modelName,
|
|
373
386
|
verb: verb,
|
|
@@ -380,7 +393,10 @@ function collectVerbEntries(input) {
|
|
|
380
393
|
paramsFields: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.fields,
|
|
381
394
|
paramsHasApiParamsTag: paramsDocs === null || paramsDocs === void 0 ? void 0 : paramsDocs.hasApiParamsTag,
|
|
382
395
|
resultTypeDescription: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.typeDescription,
|
|
383
|
-
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields
|
|
396
|
+
resultFields: resultDocs === null || resultDocs === void 0 ? void 0 : resultDocs.fields,
|
|
397
|
+
mcpResultTypeName: mcpResultTypeName,
|
|
398
|
+
mcpResultTypeDescription: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.typeDescription,
|
|
399
|
+
mcpResultFields: mcpResultDocs === null || mcpResultDocs === void 0 ? void 0 : mcpResultDocs.fields
|
|
384
400
|
});
|
|
385
401
|
}
|
|
386
402
|
} catch (err) {
|
|
@@ -402,6 +418,7 @@ function collectVerbEntries(input) {
|
|
|
402
418
|
var leaf1 = (_readTupleParamsResult = readTupleParamsResult(valueNode)) !== null && _readTupleParamsResult !== void 0 ? _readTupleParamsResult : readBareParams(valueNode);
|
|
403
419
|
var paramsDocs1 = resolveTypeDocs(leaf1 === null || leaf1 === void 0 ? void 0 : leaf1.params);
|
|
404
420
|
var resultDocs1 = resolveTypeDocs(leaf1 === null || leaf1 === void 0 ? void 0 : leaf1.result);
|
|
421
|
+
var mcpResultDocs1 = resolveTypeDocs(fallbackMcpResultTypeName);
|
|
405
422
|
entries.push({
|
|
406
423
|
model: modelName,
|
|
407
424
|
verb: verb,
|
|
@@ -414,7 +431,10 @@ function collectVerbEntries(input) {
|
|
|
414
431
|
paramsFields: paramsDocs1 === null || paramsDocs1 === void 0 ? void 0 : paramsDocs1.fields,
|
|
415
432
|
paramsHasApiParamsTag: paramsDocs1 === null || paramsDocs1 === void 0 ? void 0 : paramsDocs1.hasApiParamsTag,
|
|
416
433
|
resultTypeDescription: resultDocs1 === null || resultDocs1 === void 0 ? void 0 : resultDocs1.typeDescription,
|
|
417
|
-
resultFields: resultDocs1 === null || resultDocs1 === void 0 ? void 0 : resultDocs1.fields
|
|
434
|
+
resultFields: resultDocs1 === null || resultDocs1 === void 0 ? void 0 : resultDocs1.fields,
|
|
435
|
+
mcpResultTypeName: fallbackMcpResultTypeName,
|
|
436
|
+
mcpResultTypeDescription: mcpResultDocs1 === null || mcpResultDocs1 === void 0 ? void 0 : mcpResultDocs1.typeDescription,
|
|
437
|
+
mcpResultFields: mcpResultDocs1 === null || mcpResultDocs1 === void 0 ? void 0 : mcpResultDocs1.fields
|
|
418
438
|
});
|
|
419
439
|
}
|
|
420
440
|
function readTupleParamsResult(node) {
|
|
@@ -567,6 +587,64 @@ function readTypeDocs(sourceFile, typeName) {
|
|
|
567
587
|
}
|
|
568
588
|
return result;
|
|
569
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Reads the value token of a JSDoc tag (e.g. the `Foo` in `@dbxModelApiMcpResult Foo`).
|
|
592
|
+
*
|
|
593
|
+
* Used for value-carrying tags like `@dbxModelApiMcpResult` where the first token after the tag
|
|
594
|
+
* name names a type. Returns the first whitespace-delimited token of the tag's comment text.
|
|
595
|
+
*
|
|
596
|
+
* @param node - Any JSDocable ts-morph node (property signature, etc.).
|
|
597
|
+
* @param tagName - Tag name without the leading `@` (e.g. `'dbxModelApiMcpResult'`).
|
|
598
|
+
* @returns The first token of the tag's value, or `undefined` when the tag is absent or empty.
|
|
599
|
+
*/ function readJsDocTagValue(node, tagName) {
|
|
600
|
+
var result;
|
|
601
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
602
|
+
try {
|
|
603
|
+
for(var _iterator = node.getJsDocs()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
604
|
+
var doc = _step.value;
|
|
605
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
606
|
+
try {
|
|
607
|
+
for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
608
|
+
var tag = _step1.value;
|
|
609
|
+
if (tag.getTagName() === tagName) {
|
|
610
|
+
var _tag_getCommentText;
|
|
611
|
+
var token = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim().split(/\s+/)[0];
|
|
612
|
+
if (token) {
|
|
613
|
+
result = token;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
} catch (err) {
|
|
618
|
+
_didIteratorError1 = true;
|
|
619
|
+
_iteratorError1 = err;
|
|
620
|
+
} finally{
|
|
621
|
+
try {
|
|
622
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
623
|
+
_iterator1.return();
|
|
624
|
+
}
|
|
625
|
+
} finally{
|
|
626
|
+
if (_didIteratorError1) {
|
|
627
|
+
throw _iteratorError1;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
} catch (err) {
|
|
633
|
+
_didIteratorError = true;
|
|
634
|
+
_iteratorError = err;
|
|
635
|
+
} finally{
|
|
636
|
+
try {
|
|
637
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
638
|
+
_iterator.return();
|
|
639
|
+
}
|
|
640
|
+
} finally{
|
|
641
|
+
if (_didIteratorError) {
|
|
642
|
+
throw _iteratorError;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return result;
|
|
647
|
+
}
|
|
570
648
|
function readJsDocSummary(node) {
|
|
571
649
|
var result;
|
|
572
650
|
var docs = node.getJsDocs();
|
|
@@ -615,7 +693,9 @@ var READ_LEVEL_VALUES = new Set([
|
|
|
615
693
|
'permissions'
|
|
616
694
|
]);
|
|
617
695
|
var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
|
|
696
|
+
var MCP_TOOL_NAME_SEGMENT_TAG = 'dbxModelMcpToolNameSegment';
|
|
618
697
|
var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
|
|
698
|
+
var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
|
|
619
699
|
/**
|
|
620
700
|
* TS utility/structural wrappers that don't change the field surface for
|
|
621
701
|
* inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
|
|
@@ -801,6 +881,7 @@ function buildInterface(decl) {
|
|
|
801
881
|
var jsDocs = decl.getJsDocs();
|
|
802
882
|
var hasDbxModelTag = jsDocsHaveTag(jsDocs, 'dbxModel');
|
|
803
883
|
var dbxModelRead = readDbxModelReadTag(jsDocs);
|
|
884
|
+
var mcpToolNameSegment = readMcpToolNameSegmentTag(jsDocs);
|
|
804
885
|
var extendsNames = decl.getExtends().map(resolveExtendsName);
|
|
805
886
|
var props = [];
|
|
806
887
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -845,8 +926,61 @@ function buildInterface(decl) {
|
|
|
845
926
|
props: props
|
|
846
927
|
}, dbxModelRead === undefined ? {} : {
|
|
847
928
|
dbxModelRead: dbxModelRead
|
|
929
|
+
}, mcpToolNameSegment === undefined ? {} : {
|
|
930
|
+
mcpToolNameSegment: mcpToolNameSegment
|
|
848
931
|
});
|
|
849
932
|
}
|
|
933
|
+
function readMcpToolNameSegmentTag(jsDocs) {
|
|
934
|
+
var result;
|
|
935
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
936
|
+
try {
|
|
937
|
+
for(var _iterator = jsDocs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
938
|
+
var doc = _step.value;
|
|
939
|
+
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
940
|
+
try {
|
|
941
|
+
for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
942
|
+
var tag = _step1.value;
|
|
943
|
+
var _tag_getCommentText;
|
|
944
|
+
if (tag.getTagName() !== MCP_TOOL_NAME_SEGMENT_TAG) continue;
|
|
945
|
+
if (result !== undefined) continue;
|
|
946
|
+
var raw = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim();
|
|
947
|
+
if (raw === undefined || raw.length === 0) continue;
|
|
948
|
+
var firstToken = raw.split(/\s+/)[0];
|
|
949
|
+
if (TOOL_NAME_SEGMENT_PATTERN.test(firstToken)) {
|
|
950
|
+
result = firstToken;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
} catch (err) {
|
|
954
|
+
_didIteratorError1 = true;
|
|
955
|
+
_iteratorError1 = err;
|
|
956
|
+
} finally{
|
|
957
|
+
try {
|
|
958
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
959
|
+
_iterator1.return();
|
|
960
|
+
}
|
|
961
|
+
} finally{
|
|
962
|
+
if (_didIteratorError1) {
|
|
963
|
+
throw _iteratorError1;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
} catch (err) {
|
|
969
|
+
_didIteratorError = true;
|
|
970
|
+
_iteratorError = err;
|
|
971
|
+
} finally{
|
|
972
|
+
try {
|
|
973
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
974
|
+
_iterator.return();
|
|
975
|
+
}
|
|
976
|
+
} finally{
|
|
977
|
+
if (_didIteratorError) {
|
|
978
|
+
throw _iteratorError;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return result;
|
|
983
|
+
}
|
|
850
984
|
function readDbxModelReadTag(jsDocs) {
|
|
851
985
|
var result;
|
|
852
986
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli/manifest-extract",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.15.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"ts-morph": "^21.0.0"
|
|
7
7
|
},
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"@dereekb/firebase": "13.
|
|
9
|
+
"@dereekb/firebase": "13.15.0"
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
12
|
"./package.json": "./package.json",
|
|
@@ -77,6 +77,20 @@ export interface CrudEntry {
|
|
|
77
77
|
* Per-field JSDocs read from the result interface's properties.
|
|
78
78
|
*/
|
|
79
79
|
readonly resultFields?: readonly CrudEntryDocField[];
|
|
80
|
+
/**
|
|
81
|
+
* Name of the MCP-mapped result interface declared via the `@dbxModelApiMcpResult <TypeName>`
|
|
82
|
+
* JSDoc tag on the leaf. Present only when a handler remaps its success result for MCP; the
|
|
83
|
+
* MCP manifest output schema is synthesized from this type instead of the raw result.
|
|
84
|
+
*/
|
|
85
|
+
readonly mcpResultTypeName?: string;
|
|
86
|
+
/**
|
|
87
|
+
* JSDoc summary on the MCP-mapped result interface itself (resolved from `mcpResultTypeName`).
|
|
88
|
+
*/
|
|
89
|
+
readonly mcpResultTypeDescription?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Per-field JSDocs read from the MCP-mapped result interface's properties.
|
|
92
|
+
*/
|
|
93
|
+
readonly mcpResultFields?: readonly CrudEntryDocField[];
|
|
80
94
|
}
|
|
81
95
|
export interface CrudExtraction {
|
|
82
96
|
/**
|
|
@@ -142,6 +156,11 @@ export interface ModelExtractionInterface {
|
|
|
142
156
|
* / `permissions`). Absent when the interface omits the tag or declares an invalid value.
|
|
143
157
|
*/
|
|
144
158
|
readonly dbxModelRead?: 'system' | 'owner' | 'admin-only' | 'permissions';
|
|
159
|
+
/**
|
|
160
|
+
* Per-model MCP tool-name segment from `@dbxModelMcpToolNameSegment <segment>`. Replaces the model
|
|
161
|
+
* type in generated tool names (e.g. the collection prefix). Absent when the tag is omitted or invalid.
|
|
162
|
+
*/
|
|
163
|
+
readonly mcpToolNameSegment?: string;
|
|
145
164
|
}
|
|
146
165
|
/**
|
|
147
166
|
* One field inside a converter's `fields` map.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"bin": {
|
|
@@ -28,12 +28,21 @@
|
|
|
28
28
|
"import": "./manifest-extract/index.cjs.mjs",
|
|
29
29
|
"default": "./manifest-extract/index.cjs.js"
|
|
30
30
|
},
|
|
31
|
+
"./model-test": {
|
|
32
|
+
"module": "./model-test/index.esm.js",
|
|
33
|
+
"types": "./model-test/index.d.ts",
|
|
34
|
+
"import": "./model-test/index.cjs.mjs",
|
|
35
|
+
"default": "./model-test/index.cjs.js"
|
|
36
|
+
},
|
|
31
37
|
"./test": {
|
|
32
38
|
"module": "./test/index.esm.js",
|
|
33
39
|
"types": "./test/index.d.ts",
|
|
34
40
|
"import": "./test/index.cjs.mjs",
|
|
35
41
|
"default": "./test/index.cjs.js"
|
|
36
42
|
},
|
|
43
|
+
"./validate": {
|
|
44
|
+
"default": "./validate/index.js"
|
|
45
|
+
},
|
|
37
46
|
"./package.json": "./package.json",
|
|
38
47
|
".": {
|
|
39
48
|
"import": "./index.esm.js",
|
|
@@ -41,11 +50,11 @@
|
|
|
41
50
|
}
|
|
42
51
|
},
|
|
43
52
|
"peerDependencies": {
|
|
44
|
-
"@dereekb/date": "13.
|
|
45
|
-
"@dereekb/firebase": "13.
|
|
46
|
-
"@dereekb/model": "13.
|
|
47
|
-
"@dereekb/nestjs": "13.
|
|
48
|
-
"@dereekb/util": "13.
|
|
53
|
+
"@dereekb/date": "13.15.0",
|
|
54
|
+
"@dereekb/firebase": "13.15.0",
|
|
55
|
+
"@dereekb/model": "13.15.0",
|
|
56
|
+
"@dereekb/nestjs": "13.15.0",
|
|
57
|
+
"@dereekb/util": "13.15.0",
|
|
49
58
|
"@nestjs/common": "^11.1.19",
|
|
50
59
|
"arktype": "^2.2.0",
|
|
51
60
|
"jiti": "2.6.1",
|