@appium/typedoc-plugin-appium
Version:
TypeDoc plugin for Appium & its extensions
234 lines • 9.32 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExecMethodData = exports.CommandData = exports.BaseCommandData = void 0;
const lodash_1 = __importDefault(require("lodash"));
const typedoc_1 = require("typedoc");
const converter_1 = require("../converter");
const utils_1 = require("../utils");
/**
* Set of type names which should be converted to `null`
* @see https://github.com/appium/appium/issues/18269
*/
const NULL_TYPES = new Set(['undefined', 'void']);
/**
* Abstract representation of metadata for some sort of Appium command
*/
class BaseCommandData {
constructor(log, command, methodRefl, opts = {}) {
this.opts = opts;
this.command = command;
this.methodRefl = methodRefl;
this.log = log;
this.optionalParams = opts.optionalParams;
this.requiredParams = opts.requiredParams;
this.commentSource = opts.commentSource;
this.parentRefl = opts.parentRefl;
this.knownBuiltinMethods = opts.knownBuiltinMethods;
this.isPluginCommand = Boolean(opts.isPluginCommand);
const extractedExamples = (0, converter_1.extractExamples)(opts.comment);
if (extractedExamples?.comment) {
this.comment = extractedExamples.comment;
}
if (extractedExamples?.examples) {
this.examples = extractedExamples.examples;
}
this.parameters = this.rewriteParameters();
this.signature = this.rewriteSignature();
}
/**
* Returns `true` if the method or execute map defined parameters for this command
*/
get hasCommandParams() {
return Boolean(this.optionalParams?.length || this.requiredParams?.length);
}
/**
* Returns a list of `ParameterReflection` objects in the command's method declaration;
* rewrites them to prefer the method map parameter list (and the param names)
*/
rewriteParameters() {
if (!this.hasCommandParams) {
return;
}
const sig = (0, utils_1.findCallSignature)(this.methodRefl);
if (!sig?.parameters?.length) {
// no parameters
return;
}
const { knownBuiltinMethods: builtinMethods, isPluginCommand } = this;
const newParamRefls = [
...(0, converter_1.createNewParamRefls)(sig, {
builtinMethods,
commandParams: this.requiredParams,
isPluginCommand,
}),
...(0, converter_1.createNewParamRefls)(sig, {
builtinMethods,
commandParams: this.optionalParams,
isPluginCommand,
isOptional: true,
}),
];
return newParamRefls;
}
/**
*
* Rewrites a method's return value for documentation.
*
* Given a command having a method declaration, creates a clone of its call signature wherein the
* return type is unwrapped from `Promise`. In other words, if a method returns `Promise<T>`,
* this changes the return type in the signature to `T`.
*
* Note that the return type of a command's method declaration should always be a `ReferenceType` having
* name `Promise`.
*/
rewriteSignature() {
const callSig = (0, utils_1.findCallSignature)(this.methodRefl);
if (!callSig) {
return;
}
if (callSig.type instanceof typedoc_1.ReferenceType && callSig.type.name === 'Promise') {
// this does the actual unwrapping. `Promise` only has a single type argument `T`,
// so we can safely use the first one.
let typeArg = lodash_1.default.first(callSig.type.typeArguments);
// swaps `void`/`undefined` for `null`
if (typeArg instanceof typedoc_1.IntrinsicType && NULL_TYPES.has(typeArg.name)) {
typeArg = new typedoc_1.LiteralType(null);
}
const newCallSig = (0, converter_1.cloneCallSignatureReflection)(callSig, this.methodRefl, typeArg);
if (!newCallSig.type) {
this.log.warn('(%s) No type arg T found for return type Promise<T> in %s; this is a bug', this.parentRefl.name, this.methodRefl.name);
return;
}
newCallSig.comment = (0, converter_1.deriveComment)({
refl: newCallSig,
knownMethods: this.knownBuiltinMethods,
})?.comment;
return newCallSig;
}
}
}
exports.BaseCommandData = BaseCommandData;
/**
* Represents a generic WD or Appium-specific endpoint
*/
class CommandData extends BaseCommandData {
/**
* Use {@linkcode CommandData.create} instead
*/
constructor(log, command, methodRefl, httpMethod, route, opts = {}) {
super(log, command, methodRefl, opts);
this.httpMethod = httpMethod;
this.route = route;
}
/**
* Creates a **shallow** clone of this instance.
*
* @param commandData Instance to clone
* @param ctx Context
* @param overrides Override any properties of the instance here (including {@linkcode CommandData.opts})
* @returns Cloned instance
*/
static clone(commandData, ctx, overrides) {
const { log, command, methodRefl, httpMethod, route, opts } = lodash_1.default.defaults(overrides, {
log: commandData.log,
command: commandData.command,
methodRefl: commandData.methodRefl,
httpMethod: commandData.httpMethod,
route: commandData.route,
opts: lodash_1.default.defaults(overrides?.opts, commandData.opts),
});
return CommandData.create(ctx, log, command, methodRefl, httpMethod, route, opts);
}
/**
* Creates a new instance of {@linkcode CommandData} and registers any newly-created reflections
* with TypeDoc.
* @param ctx Context
* @param log Logger
* @param command Command name
* @param methodRefl Command method reflection
* @param httpMethod HTTP method of route
* @param route Route path
* @param opts Options
* @returns
*/
static create(ctx, log, command, methodRefl, httpMethod, route, opts = {}) {
const commandData = new CommandData(log, command, methodRefl, httpMethod, route, opts);
if (commandData.signature) {
ctx.registerReflection(commandData.signature, undefined);
}
if (commandData.parameters) {
for (const param of commandData.parameters) {
ctx.registerReflection(param, undefined);
}
}
return commandData;
}
}
exports.CommandData = CommandData;
/**
* Represents an "execute command" ("execute method")
*
* Each will have a unique `script` property which is provided as the script to run via the
* `execute` WD endpoint.
*
* All of these share the same `execute` route, so it is omitted from this interface.
*/
class ExecMethodData extends BaseCommandData {
/**
* Use {@linkcode ExecMethodData.create} instead
* @param log Logger
* @param command Command name
* @param methodRefl method reflection
* @param script Script name (not the same as command name); this is what is passed to the `execute` endpoint
*/
constructor(log, command, methodRefl, script, opts = {}) {
super(log, command, methodRefl, opts);
this.script = script;
this.opts = opts;
}
/**
* Creates a **shallow** clone of this instance.
*
* @param execMethodData Instance to clone
* @param ctx Context
* @param overrides Override any properties of the instance here (including {@linkcode ExecMethodData.opts})
* @returns Cloned instance
*/
static clone(execMethodData, ctx, overrides) {
const { log, command, methodRefl, script, opts } = lodash_1.default.defaults(overrides, {
log: execMethodData.log,
command: execMethodData.command,
methodRefl: execMethodData.methodRefl,
script: execMethodData.script,
opts: lodash_1.default.defaults(overrides?.opts, execMethodData.opts),
});
return ExecMethodData.create(ctx, log, command, methodRefl, script, opts);
}
/**
* Creates a new instance of {@linkcode CommandData} and registers any newly-created reflections
* with TypeDoc.
* @param ctx Context
* @param log Logger
* @param command Command name
* @param script Script name
* @param route Route path
* @param opts Options
*/
static create(ctx, log, command, methodRefl, script, opts = {}) {
const execMethodData = new ExecMethodData(log, command, methodRefl, script, opts);
if (execMethodData.signature) {
ctx.registerReflection(execMethodData.signature, undefined);
}
if (execMethodData.parameters) {
for (const param of execMethodData.parameters) {
ctx.registerReflection(param, undefined);
}
}
return execMethodData;
}
}
exports.ExecMethodData = ExecMethodData;
//# sourceMappingURL=command-data.js.map