@metamask-previews/platform-api-docs 0.0.0-preview-6235c3779 → 0.0.0-preview-a3545aef8
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/cli.cjs +13 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +14 -6
- package/dist/cli.mjs.map +1 -1
- package/dist/extraction.cjs +119 -150
- package/dist/extraction.cjs.map +1 -1
- package/dist/extraction.d.cts +0 -14
- package/dist/extraction.d.cts.map +1 -1
- package/dist/extraction.d.mts +0 -14
- package/dist/extraction.d.mts.map +1 -1
- package/dist/extraction.mjs +118 -148
- package/dist/extraction.mjs.map +1 -1
- package/dist/generate.cjs +29 -8
- package/dist/generate.cjs.map +1 -1
- package/dist/generate.d.cts +9 -0
- package/dist/generate.d.cts.map +1 -1
- package/dist/generate.d.mts +9 -0
- package/dist/generate.d.mts.map +1 -1
- package/dist/generate.mjs +27 -7
- package/dist/generate.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +0 -16
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +0 -16
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +1 -1
- package/site/docusaurus.config.ts +7 -2
package/dist/extraction.cjs
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
26
|
+
exports.extractFromSourceFile = exports.createExtractionProject = void 0;
|
|
27
27
|
const path = __importStar(require("node:path"));
|
|
28
28
|
const ts_morph_1 = require("ts-morph");
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
@@ -146,57 +146,63 @@ function hasDeprecatedJsDocTag(node) {
|
|
|
146
146
|
// Type-resolution helpers (powered by ts-morph's type checker)
|
|
147
147
|
// ---------------------------------------------------------------------------
|
|
148
148
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* name. Returns the method declaration when found.
|
|
149
|
+
* Locates the type that represents a method on a class (e.g.
|
|
150
|
+
* `Class['method']`), which itself comes from a messenger action handler.
|
|
152
151
|
*
|
|
153
|
-
* @param typeNode - The
|
|
154
|
-
* @returns The method declaration, or null.
|
|
152
|
+
* @param typeNode - The node that represents the indexed access.
|
|
153
|
+
* @returns The found method declaration, or null.
|
|
155
154
|
*/
|
|
156
|
-
function
|
|
157
|
-
if
|
|
155
|
+
function findClassMethodDeclaration(typeNode) {
|
|
156
|
+
// Fundamental check: if we don't have `Class['method']`, we can't do anything.
|
|
157
|
+
if (!ts_morph_1.Node.isIndexedAccessTypeNode(typeNode)) {
|
|
158
158
|
return null;
|
|
159
159
|
}
|
|
160
|
+
// The type that represents the class being accessed.
|
|
161
|
+
// EXAMPLE:
|
|
162
|
+
// FooController['someMethod']
|
|
163
|
+
// ^^^^^^^^^^^^^
|
|
160
164
|
const objectType = typeNode.getObjectTypeNode();
|
|
165
|
+
// The type that represents the property being accessed.
|
|
166
|
+
// EXAMPLE:
|
|
167
|
+
// FooController['someMethod']
|
|
168
|
+
// ^^^^^^^^^^^^
|
|
161
169
|
const indexType = typeNode.getIndexTypeNode();
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
// istanbul ignore next: the index in `Class['method']` is always a literal
|
|
168
|
-
// type node in valid handler syntax.
|
|
169
|
-
if (!ts_morph_1.Node.isLiteralTypeNode(indexType)) {
|
|
170
|
+
// To access a property on a type, it must be a type we can access properties of.
|
|
171
|
+
if (!ts_morph_1.Node.isTypeReference(objectType) ||
|
|
172
|
+
!ts_morph_1.Node.isLiteralTypeNode(indexType)) {
|
|
170
173
|
return null;
|
|
171
174
|
}
|
|
172
175
|
const indexLiteral = indexType.getLiteral();
|
|
173
|
-
//
|
|
174
|
-
// The first two land as `StringLiteral`; the bare template literal is a
|
|
175
|
-
// `NoSubstitutionTemplateLiteral`.
|
|
176
|
-
// istanbul ignore next: numeric/boolean indices aren't valid method names.
|
|
176
|
+
// Names of methods must be static strings; they cannot be template strings.
|
|
177
177
|
if (!ts_morph_1.Node.isStringLiteral(indexLiteral) &&
|
|
178
178
|
!ts_morph_1.Node.isNoSubstitutionTemplateLiteral(indexLiteral)) {
|
|
179
179
|
return null;
|
|
180
180
|
}
|
|
181
181
|
const methodName = indexLiteral.getLiteralValue();
|
|
182
|
+
// Reject qualified-name type names, as we need a plain identifier to
|
|
183
|
+
// resolve the symbol.
|
|
184
|
+
// EXAMPLE:
|
|
185
|
+
// import * as somePackage from '...';
|
|
186
|
+
// somePackage.FooController['someMethod']
|
|
187
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
182
188
|
const classNameNode = objectType.getTypeName();
|
|
183
|
-
// istanbul ignore next: qualified-name class references aren't used in
|
|
184
|
-
// messenger handler types.
|
|
185
189
|
if (!ts_morph_1.Node.isIdentifier(classNameNode)) {
|
|
186
190
|
return null;
|
|
187
191
|
}
|
|
192
|
+
// Since we know we have a type reference, we can assume that we have a symbol.
|
|
193
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
188
194
|
const localSymbol = classNameNode.getSymbol();
|
|
189
|
-
//
|
|
190
|
-
// in
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
//
|
|
195
|
-
//
|
|
195
|
+
// If we have a type imported from another file, ensure that when we access
|
|
196
|
+
// the declaration, it's the type declaration in the other file, not the
|
|
197
|
+
// import declaration in this file.
|
|
198
|
+
// EXAMPLE:
|
|
199
|
+
// import { FooController } from '@metamask/foo-controller';
|
|
200
|
+
// FooController['someMethod']
|
|
201
|
+
// ^^^^^^^^^^^^^
|
|
196
202
|
const symbol = localSymbol.getAliasedSymbol() ?? localSymbol;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
for (const declaration of symbol.getDeclarations()) {
|
|
204
|
+
// We must have a class to treat the property on the object type as a
|
|
205
|
+
// method.
|
|
200
206
|
if (ts_morph_1.Node.isClassDeclaration(declaration)) {
|
|
201
207
|
const method = declaration.getMethod(methodName);
|
|
202
208
|
if (method) {
|
|
@@ -204,40 +210,37 @@ function resolveIndexedAccessMethod(typeNode) {
|
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
212
|
}
|
|
207
|
-
// istanbul ignore next: only reached if the indexed method isn't declared
|
|
208
|
-
// on any of the resolved class declarations, which doesn't happen in valid
|
|
209
|
-
// handler types.
|
|
210
213
|
return null;
|
|
211
214
|
}
|
|
212
215
|
// ---------------------------------------------------------------------------
|
|
213
216
|
// Method info
|
|
214
217
|
// ---------------------------------------------------------------------------
|
|
215
218
|
/**
|
|
216
|
-
* Build
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
+
* Build the textual signature of a class method — its parameter list and
|
|
220
|
+
* return type expressed as a TypeScript function type — so a handler that
|
|
221
|
+
* references `Class['method']` can be rendered as `(arg: T) => R` instead of
|
|
222
|
+
* the bare indexed-access syntax.
|
|
219
223
|
*
|
|
220
224
|
* @param method - The method declaration.
|
|
221
|
-
* @returns The
|
|
225
|
+
* @returns The signature, e.g. `(id: number) => Promise<string>`.
|
|
222
226
|
*/
|
|
223
|
-
function
|
|
227
|
+
function buildMethodSignature(method) {
|
|
224
228
|
const signatureParams = method
|
|
225
229
|
.getParameters()
|
|
226
230
|
.map((param) => {
|
|
231
|
+
const rest = param.isRestParameter() ? '...' : '';
|
|
227
232
|
const paramName = param.getNameNode().getText();
|
|
228
233
|
const optional = param.hasQuestionToken() ? '?' : '';
|
|
229
234
|
const typeNode = param.getTypeNode();
|
|
230
235
|
const paramType = typeNode ? typeNode.getText() : 'unknown';
|
|
231
|
-
return `${paramName}${optional}: ${paramType}`;
|
|
236
|
+
return `${rest}${paramName}${optional}: ${paramType}`;
|
|
232
237
|
})
|
|
233
238
|
.join(', ');
|
|
234
239
|
const returnTypeNode = method.getReturnTypeNode();
|
|
235
240
|
const returnType = returnTypeNode ? returnTypeNode.getText() : 'void';
|
|
236
241
|
// For async methods, the declared return type already includes `Promise<>`,
|
|
237
242
|
// so we don't need to wrap again.
|
|
238
|
-
|
|
239
|
-
const { description, params, returns } = extractJsDoc(method);
|
|
240
|
-
return { jsDoc: description, params, returns, signature };
|
|
243
|
+
return `(${signatureParams}) => ${returnType}`;
|
|
241
244
|
}
|
|
242
245
|
/**
|
|
243
246
|
* Looks for Messenger types in the source file (that is, those that are type
|
|
@@ -338,13 +341,16 @@ function recursivelyFindMessengerCapabilityTypeDeclarations(node, kind, visitedT
|
|
|
338
341
|
// ^^^^^^^
|
|
339
342
|
// // Good
|
|
340
343
|
// type Actions = FooControllerSomeAction;
|
|
344
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^
|
|
341
345
|
// // Good
|
|
342
346
|
// type Actions = ControllerGetStateAction<...>;
|
|
347
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
343
348
|
if (!ts_morph_1.Node.isTypeReference(node)) {
|
|
344
349
|
return result;
|
|
345
350
|
}
|
|
346
351
|
const nameNode = node.getTypeName();
|
|
347
|
-
// Reject qualified-name type
|
|
352
|
+
// Reject qualified-name type names, as we need a plain identifier to
|
|
353
|
+
// resolve the symbol.
|
|
348
354
|
// EXAMPLE:
|
|
349
355
|
// import * as somePackage from '...';
|
|
350
356
|
// type Actions = somePackage.FooControllerSomeAction;
|
|
@@ -356,8 +362,8 @@ function recursivelyFindMessengerCapabilityTypeDeclarations(node, kind, visitedT
|
|
|
356
362
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
357
363
|
const localSymbol = nameNode.getSymbol();
|
|
358
364
|
// If we have a type imported from another file, ensure that when we access
|
|
359
|
-
// the declaration, it's the
|
|
360
|
-
//
|
|
365
|
+
// the declaration, it's the type declaration in the other file, not the
|
|
366
|
+
// import declaration in this file.
|
|
361
367
|
// EXAMPLE:
|
|
362
368
|
// import { FooControllerSomeAction } from '@metamask/foo-controller';
|
|
363
369
|
// type Actions = FooControllerSomeAction;
|
|
@@ -376,14 +382,22 @@ function recursivelyFindMessengerCapabilityTypeDeclarations(node, kind, visitedT
|
|
|
376
382
|
// If we have a type alias, then we have to handle a few scenarios.
|
|
377
383
|
// EXAMPLES:
|
|
378
384
|
// type FooControllerMethodActions = ...
|
|
385
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
379
386
|
// type FooControllerSomeAction = ...
|
|
387
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
380
388
|
if (ts_morph_1.Node.isTypeAliasDeclaration(declaration)) {
|
|
381
389
|
const body = declaration.getTypeNode();
|
|
382
|
-
// If
|
|
383
|
-
//
|
|
390
|
+
// If the body is a union type or a plain type reference (not a utility
|
|
391
|
+
// type), walk it.
|
|
392
|
+
// EXAMPLES:
|
|
384
393
|
// type FooControllerMethodActions = FooControllerSomeAction | FooControllerSomeOtherAction
|
|
385
|
-
//
|
|
386
|
-
|
|
394
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
395
|
+
// type DelegationControllerMethodActions = DelegationControllerSignDelegationAction
|
|
396
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
397
|
+
if (body &&
|
|
398
|
+
(ts_morph_1.Node.isUnionTypeNode(body) ||
|
|
399
|
+
(ts_morph_1.Node.isTypeReference(body) &&
|
|
400
|
+
body.getTypeArguments().length === 0))) {
|
|
387
401
|
const innerResult = recursivelyFindMessengerCapabilityTypeDeclarations(body, kind, result.visitedTypeDeclarations);
|
|
388
402
|
result.capabilityTypeDeclarations.push(...innerResult.capabilityTypeDeclarations);
|
|
389
403
|
for (const typeDeclaration of innerResult.visitedTypeDeclarations) {
|
|
@@ -391,32 +405,56 @@ function recursivelyFindMessengerCapabilityTypeDeclarations(node, kind, visitedT
|
|
|
391
405
|
}
|
|
392
406
|
continue;
|
|
393
407
|
}
|
|
394
|
-
//
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
-
if (body &&
|
|
402
|
-
|
|
403
|
-
|
|
408
|
+
// A TypeReference body with type arguments is a capability-type-
|
|
409
|
+
// constructor invocation (e.g. `ControllerGetStateAction<typeof name,
|
|
410
|
+
// State>`). Tag it so the constructor extractor can read `body`
|
|
411
|
+
// directly without re-checking its shape.
|
|
412
|
+
// EXAMPLE:
|
|
413
|
+
// type FooControllerSomeAction = ControllerGetStateAction<...>
|
|
414
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
415
|
+
if (body && ts_morph_1.Node.isTypeReference(body)) {
|
|
416
|
+
// Reject qualified-name constructor type names, as we need a plain
|
|
417
|
+
// identifier to match the constructor by name.
|
|
418
|
+
// EXAMPLE:
|
|
419
|
+
// // Bad
|
|
420
|
+
// import * as somePackage from '...';
|
|
421
|
+
// type FooControllerSomeAction = somePackage.ControllerGetStateAction<...>
|
|
422
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
423
|
+
const constructorTypeName = body.getTypeName();
|
|
424
|
+
if (ts_morph_1.Node.isIdentifier(constructorTypeName)) {
|
|
425
|
+
result.capabilityTypeDeclarations.push({
|
|
426
|
+
bodyShape: 'constructor',
|
|
427
|
+
kind,
|
|
428
|
+
declaration,
|
|
429
|
+
body,
|
|
430
|
+
typeName: constructorTypeName,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
404
433
|
continue;
|
|
405
434
|
}
|
|
406
|
-
//
|
|
407
|
-
//
|
|
435
|
+
// Anything else (a type literal, intersection, conditional, …) gets
|
|
436
|
+
// tagged for the literal extractor, which knows how to read members
|
|
437
|
+
// off a type literal and rejects exotic shapes.
|
|
408
438
|
// EXAMPLE:
|
|
409
439
|
// type FooControllerSomeAction = { ... }
|
|
410
440
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
411
|
-
result.capabilityTypeDeclarations.push({
|
|
441
|
+
result.capabilityTypeDeclarations.push({
|
|
442
|
+
bodyShape: 'object',
|
|
443
|
+
kind,
|
|
444
|
+
declaration,
|
|
445
|
+
});
|
|
412
446
|
}
|
|
413
|
-
//
|
|
414
|
-
//
|
|
447
|
+
// Interfaces always carry their members directly — tag for the literal
|
|
448
|
+
// extractor.
|
|
415
449
|
// EXAMPLE:
|
|
416
450
|
// interface FooControllerSomeAction { ... }
|
|
417
451
|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
418
452
|
else if (ts_morph_1.Node.isInterfaceDeclaration(declaration)) {
|
|
419
|
-
result.capabilityTypeDeclarations.push({
|
|
453
|
+
result.capabilityTypeDeclarations.push({
|
|
454
|
+
bodyShape: 'object',
|
|
455
|
+
kind,
|
|
456
|
+
declaration,
|
|
457
|
+
});
|
|
420
458
|
}
|
|
421
459
|
}
|
|
422
460
|
return result;
|
|
@@ -436,8 +474,10 @@ function recursivelyFindMessengerCapabilityTypeDeclarations(node, kind, visitedT
|
|
|
436
474
|
* (may be `null` if the type is ineligible for extraction).
|
|
437
475
|
*/
|
|
438
476
|
function extractFromMessengerCapabilityTypeDeclaration(capabilityTypeDeclaration, projectPath) {
|
|
439
|
-
|
|
440
|
-
tryToExtractFromCapabilityTypeConstructor(capabilityTypeDeclaration, projectPath)
|
|
477
|
+
if (capabilityTypeDeclaration.bodyShape === 'constructor') {
|
|
478
|
+
return tryToExtractFromCapabilityTypeConstructor(capabilityTypeDeclaration, projectPath);
|
|
479
|
+
}
|
|
480
|
+
return tryToExtractFromMessengerCapabilityTypeLiteral(capabilityTypeDeclaration, projectPath);
|
|
441
481
|
}
|
|
442
482
|
/**
|
|
443
483
|
* If a messenger capability type is a type alias or interface and its body is
|
|
@@ -457,7 +497,7 @@ function extractFromMessengerCapabilityTypeDeclaration(capabilityTypeDeclaration
|
|
|
457
497
|
*/
|
|
458
498
|
function tryToExtractFromMessengerCapabilityTypeLiteral(capabilityTypeDeclaration, projectPath) {
|
|
459
499
|
const { declaration, kind } = capabilityTypeDeclaration;
|
|
460
|
-
//
|
|
500
|
+
// We must have a object type alias or an interface, and the body must not be empty.
|
|
461
501
|
// EXAMPLES:
|
|
462
502
|
// // Good
|
|
463
503
|
// type FooControllerSomeAction = {
|
|
@@ -504,25 +544,14 @@ function tryToExtractFromMessengerCapabilityTypeLiteral(capabilityTypeDeclaratio
|
|
|
504
544
|
let handlerOrPayloadSignature = handlerOrPayloadPropertyTypeNode
|
|
505
545
|
.getText()
|
|
506
546
|
.trim();
|
|
507
|
-
|
|
508
|
-
// For actions
|
|
509
|
-
//
|
|
510
|
-
//
|
|
511
|
-
// TODO: We don't want to do this.
|
|
547
|
+
const { description: jsDoc, params, returns } = extractJsDoc(declaration);
|
|
548
|
+
// For actions that represent methods (e.g. `Class['method']`), walk the
|
|
549
|
+
// handler type to find the underlying handler signature
|
|
550
|
+
// (e.g. `(id: number) => Promise<string>`).
|
|
512
551
|
if (kind === 'action') {
|
|
513
|
-
const
|
|
514
|
-
if (
|
|
515
|
-
|
|
516
|
-
handlerOrPayloadSignature = info.signature;
|
|
517
|
-
if (!jsDoc && info.jsDoc) {
|
|
518
|
-
jsDoc = info.jsDoc;
|
|
519
|
-
}
|
|
520
|
-
if (params.length === 0 && info.params.length > 0) {
|
|
521
|
-
params = info.params;
|
|
522
|
-
}
|
|
523
|
-
if (!returns && info.returns) {
|
|
524
|
-
returns = info.returns;
|
|
525
|
-
}
|
|
552
|
+
const methodDeclaration = findClassMethodDeclaration(handlerOrPayloadPropertyTypeNode);
|
|
553
|
+
if (methodDeclaration) {
|
|
554
|
+
handlerOrPayloadSignature = buildMethodSignature(methodDeclaration);
|
|
526
555
|
}
|
|
527
556
|
}
|
|
528
557
|
const sourceFile = declaration.getSourceFile();
|
|
@@ -571,7 +600,7 @@ function getMessengerCapabilityTypeString(capabilityTypeProperties) {
|
|
|
571
600
|
// }
|
|
572
601
|
// type FooControllerSomeAction = {
|
|
573
602
|
// type: `${typeof CONTROLLER_NAME}:someAction`;
|
|
574
|
-
//
|
|
603
|
+
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
575
604
|
// }
|
|
576
605
|
const resolvedType = typeNode.getType();
|
|
577
606
|
if (resolvedType.isStringLiteral()) {
|
|
@@ -618,37 +647,7 @@ function findProperty(propertySignatures, name) {
|
|
|
618
647
|
* doesn't match.
|
|
619
648
|
*/
|
|
620
649
|
function tryToExtractFromCapabilityTypeConstructor(capabilityTypeDeclaration, projectPath) {
|
|
621
|
-
const { declaration, kind } = capabilityTypeDeclaration;
|
|
622
|
-
// Basic check: we need a type alias, otherwise the rest doesn't make sense.
|
|
623
|
-
// EXAMPLE:
|
|
624
|
-
// type FooControllerSomeAction = ...
|
|
625
|
-
if (!ts_morph_1.Node.isTypeAliasDeclaration(declaration)) {
|
|
626
|
-
return null;
|
|
627
|
-
}
|
|
628
|
-
// We want our type alias to be a reference to a utility type.
|
|
629
|
-
// Non-null assertion: We can assume the type has a body of some kind,
|
|
630
|
-
// otherwise it wouldn't compile.
|
|
631
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
632
|
-
const body = declaration.getTypeNode();
|
|
633
|
-
// We already determined in
|
|
634
|
-
// `recursivelyFindMessengerCapabilityTypeDeclarations` that the declaration
|
|
635
|
-
// is a type reference.
|
|
636
|
-
// TODO: Capture the following information ahead of time so we don't need to
|
|
637
|
-
// check this again.
|
|
638
|
-
// istanbul ignore next
|
|
639
|
-
if (!ts_morph_1.Node.isTypeReference(body)) {
|
|
640
|
-
return null;
|
|
641
|
-
}
|
|
642
|
-
const typeName = body.getTypeName();
|
|
643
|
-
// We already determined in
|
|
644
|
-
// `recursivelyFindMessengerCapabilityTypeDeclarations` that the type is an
|
|
645
|
-
// identifier.
|
|
646
|
-
// TODO: Capture the following information ahead of time so we don't need to
|
|
647
|
-
// check this again.
|
|
648
|
-
// istanbul ignore next
|
|
649
|
-
if (!ts_morph_1.Node.isIdentifier(typeName)) {
|
|
650
|
-
return null;
|
|
651
|
-
}
|
|
650
|
+
const { declaration, kind, body, typeName } = capabilityTypeDeclaration;
|
|
652
651
|
// The name of the utility type should be either `ControllerGetStateAction`
|
|
653
652
|
// (for actions) or `ControllerStateChangeEvent` (for events).
|
|
654
653
|
// EXAMPLES:
|
|
@@ -752,34 +751,4 @@ function extractFromSourceFile(sourceFile, projectPath) {
|
|
|
752
751
|
return messengerCapabilityPackets;
|
|
753
752
|
}
|
|
754
753
|
exports.extractFromSourceFile = extractFromSourceFile;
|
|
755
|
-
/**
|
|
756
|
-
* Convenience wrapper: extract from a single file by path. Loads the file
|
|
757
|
-
* and any sibling files in its parent directory into a fresh Project so
|
|
758
|
-
* relative imports resolve.
|
|
759
|
-
*
|
|
760
|
-
* For batch operations across many files, prefer
|
|
761
|
-
* {@link createExtractionProject} + {@link extractFromSourceFile} so one
|
|
762
|
-
* Project amortizes the type-checker setup across the whole run.
|
|
763
|
-
*
|
|
764
|
-
* @param filePath - The absolute path to the TypeScript file.
|
|
765
|
-
* @param projectPath - Base path for computing relative source paths.
|
|
766
|
-
* @returns A promise that resolves to the extracted capability list.
|
|
767
|
-
*/
|
|
768
|
-
async function extractFromFile(filePath, projectPath) {
|
|
769
|
-
const project = createExtractionProject();
|
|
770
|
-
const parentDir = path.dirname(filePath);
|
|
771
|
-
// Load the file's directory so single-hop relative imports resolve.
|
|
772
|
-
project.addSourceFilesAtPaths([
|
|
773
|
-
path.join(parentDir, '**/*.ts'),
|
|
774
|
-
path.join(parentDir, '**/*.d.cts'),
|
|
775
|
-
]);
|
|
776
|
-
const sourceFile = project.getSourceFile(filePath);
|
|
777
|
-
// istanbul ignore next: the path always exists since the caller just
|
|
778
|
-
// wrote the file or it was scanned from disk.
|
|
779
|
-
if (!sourceFile) {
|
|
780
|
-
return [];
|
|
781
|
-
}
|
|
782
|
-
return extractFromSourceFile(sourceFile, projectPath);
|
|
783
|
-
}
|
|
784
|
-
exports.extractFromFile = extractFromFile;
|
|
785
754
|
//# sourceMappingURL=extraction.cjs.map
|