dets
Version:
A TypeScript declaration file bundler.
1,516 lines (1,496 loc) • 276 kB
JavaScript
#!/usr/bin/env node
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __esm = (fn, res) => function __init() {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/helpers/comments.ts
function isUnique(value, index, self) {
return self.indexOf(value) === index;
}
function getAllJsDocs(checker, decls) {
const allDocs = decls.map((decl) => getJsDocs(checker, decl));
return {
comment: allDocs.map((m) => m.comment).reduce((p, c) => [...p, ...c], []).filter(isUnique),
tags: allDocs.map((m) => m.tags).reduce((p, c) => [...p, ...c], []).filter(isUnique)
};
}
function getJsDocs(checker, node) {
if ((0, import_typescript.isMethodDeclaration)(node) || (0, import_typescript.isMethodSignature)(node) || (0, import_typescript.isCallSignatureDeclaration)(node)) {
const sign = checker.getSignatureFromDeclaration(node);
if (sign) {
return {
comment: sign.getDocumentationComment(checker),
tags: sign.getJsDocTags()
};
}
}
return {
comment: node.symbol?.getDocumentationComment(checker),
tags: node.symbol?.getJsDocTags()
};
}
function stringifyJsDocTagText(txt) {
if (typeof txt === "string") {
if (txt.startsWith("http ://") || txt.startsWith("https ://")) {
return txt.replace(" ", "");
}
return txt;
} else if (Array.isArray(txt)) {
return txt.map((s) => s.text).join("");
}
return "";
}
function stringifyJsDocs(doc) {
const tags = (doc.tags || []).filter((m) => !removedTags.includes(m.name)).map((m) => `@${m.name}${newLineTags.includes(m.name) ? "\n" : m.text ? " " : ""}${stringifyJsDocTagText(m.text)}`);
const result = doc.comment?.map((m) => m.text) ?? [];
if (tags && result.length) {
return [result.join(""), ...tags].join("\n");
} else if (tags) {
return tags.join("\n");
} else {
return result.join("");
}
}
function shouldDrop(canDrop, tags) {
let found = false;
if (tags) {
for (const tag of tags) {
switch (tag.name) {
case "ignore":
found = canDrop;
break;
case "dets_ignore":
return true;
case "dets_preserve":
return false;
}
}
}
return found;
}
function getCommentOrDrop(checker, node, canDrop = false) {
const doc = getJsDocs(checker, node);
if (shouldDrop(canDrop, doc.tags)) {
return void 0;
}
return stringifyJsDocs(doc);
}
function getComment(checker, node) {
const doc = getJsDocs(checker, node);
return stringifyJsDocs(doc);
}
var import_typescript, newLineTags, removedTags;
var init_comments = __esm({
"src/helpers/comments.ts"() {
import_typescript = require("typescript");
newLineTags = ["example"];
removedTags = ["dets_removeprop", "dets_removeclause", "dets_preserve", "dets_ignore"];
}
});
// src/helpers/constants.ts
var tslibRoot, tslibPrefix, globalFiles, globalIndicator, modulesRoot, typesRoot;
var init_constants = __esm({
"src/helpers/constants.ts"() {
tslibRoot = "/node_modules/typescript/lib";
tslibPrefix = "lib.";
globalFiles = ["globals.d.ts", "global.d.ts"];
globalIndicator = "__global";
modulesRoot = "/node_modules/";
typesRoot = "/node_modules/@types/";
}
});
// src/helpers/identifiers.ts
function getLibRefName(libName) {
if (libName[0] === "@") {
libName = libName.substring(1);
}
const parts = libName.split(/[\/\-\.]/g);
return parts.map((p) => p[0].toUpperCase() + p.substring(1)).join("");
}
function getTypeRefName(name) {
if ((0, import_typescript2.isIdentifier)(name)) {
return name.text;
} else {
const ns = getTypeRefName(name.left);
return `${ns}.${name.right.text}`;
}
}
function getPredicateName(name) {
if ((0, import_typescript2.isIdentifier)(name)) {
return name.text;
} else {
return "this";
}
}
function getExportName(name) {
if (!name) {
return void 0;
} else if ((0, import_typescript2.isIdentifier)(name)) {
return name.text;
} else if ((0, import_typescript2.isStringLiteral)(name)) {
return name.text;
} else {
return name.text;
}
}
function getParameterElement(element) {
const spread = "dotDotDotToken" in element && element.dotDotDotToken ? "..." : "";
const name = (0, import_typescript2.isBindingElement)(element) ? getParameterName(element.name) : getParameterName(element);
return `${spread}${name}`;
}
function getParameterName(name) {
if ((0, import_typescript2.isIdentifier)(name)) {
return name.text;
} else if ((0, import_typescript2.isObjectBindingPattern)(name)) {
const content = name.elements.map(getParameterElement).join(", ");
return `{ ${content} }`;
} else if ((0, import_typescript2.isArrayBindingPattern)(name)) {
const content = name.elements.map(getParameterElement).join(", ");
return `[${content}]`;
} else {
return "";
}
}
function makeModule(fileName, root2) {
const relFile = (0, import_path5.relative)(root2, fileName);
const ext = (0, import_path5.extname)(fileName);
const file = !relFile.startsWith(".") ? `./${relFile}` : relFile;
return file.substring(0, file.length - ext.length);
}
function getLibName(fileName, root2) {
if (fileName) {
if (fileName.indexOf(typesRoot) !== -1) {
const start = fileName.lastIndexOf(typesRoot) + typesRoot.length;
const name = fileName.substring(start).split("/").shift();
if (name.indexOf("__") !== -1) {
const [scope, lib] = name.split("__");
return `@${scope}/${lib}`;
}
return name;
} else if (fileName.indexOf(modulesRoot) !== -1) {
const start = fileName.lastIndexOf(modulesRoot) + modulesRoot.length;
const [scope, lib] = fileName.substring(start).split("/");
if (scope.indexOf("@") === 0) {
return `${scope}/${lib}`;
}
return scope;
} else {
return makeModule(fileName, root2);
}
}
return void 0;
}
var import_typescript2, import_path5;
var init_identifiers = __esm({
"src/helpers/identifiers.ts"() {
import_typescript2 = require("typescript");
import_path5 = require("path");
init_constants();
}
});
// src/helpers/node.ts
function getModule(node) {
while (node) {
if ((0, import_typescript3.isModuleDeclaration)(node) && (0, import_typescript3.isSourceFile)(node.parent) && (0, import_typescript3.isStringLiteral)(node.name)) {
return node.name.text;
}
node = node.parent;
}
return void 0;
}
function getDeclarationFromSymbol(checker, symbol) {
if (!symbol) {
return void 0;
} else if (symbol.flags === import_typescript3.SymbolFlags.Alias) {
const aliasSymbol = checker.getAliasedSymbol(symbol);
return getDeclarationFromSymbol(checker, aliasSymbol);
} else {
const decl = symbol.valueDeclaration || symbol.declarations?.[0];
if (decl && (0, import_typescript3.isImportSpecifier)(decl)) {
return getDeclarationFromNode(checker, decl.name);
}
return decl;
}
}
function getDeclarationFromNode(checker, node) {
const symbol = getSymbol(checker, node);
return getDeclarationFromSymbol(checker, symbol);
}
function getSymbol(checker, node) {
const symbol = node.aliasSymbol ?? node.symbol;
if (symbol) {
return symbol;
} else if ((0, import_typescript3.isTypeReferenceNode)(node)) {
const ref = node.typeName;
return ref.aliasSymbol ?? ref.symbol ?? checker.getSymbolAtLocation(ref);
} else {
return checker.getSymbolAtLocation(node);
}
}
function isDefaultExport(node) {
return node.symbol?.name === "default";
}
function shouldInclude(node) {
return (0, import_typescript3.isModuleDeclaration)(node) || (0, import_typescript3.isExportDeclaration)(node) || isNodeExported(node);
}
function isNodeExported(node, alsoTopLevel = false) {
return (0, import_typescript3.isExportAssignment)(node) || ((0, import_typescript3.getCombinedModifierFlags)(node) & import_typescript3.ModifierFlags.Export) !== 0 || alsoTopLevel && !!node.parent && node.parent.kind === import_typescript3.SyntaxKind.SourceFile;
}
function isPrivate(type) {
return type.kind === import_typescript3.SyntaxKind.PrivateKeyword;
}
function isPublic(type) {
return type.kind === import_typescript3.SyntaxKind.PublicKeyword;
}
function isStatic(type) {
return type.kind === import_typescript3.SyntaxKind.StaticKeyword;
}
function isProtected(type) {
return type.kind === import_typescript3.SyntaxKind.ProtectedKeyword;
}
function isReadonly(type) {
return type.kind === import_typescript3.SyntaxKind.ReadonlyKeyword;
}
var import_typescript3;
var init_node = __esm({
"src/helpers/node.ts"() {
import_typescript3 = require("typescript");
}
});
// src/helpers/paths.ts
function findAppRoot(root2, app) {
return (0, import_path6.resolve)(root2, app);
}
function isBaseLib(path) {
if (path in pathCache) {
return pathCache[path];
} else if (path) {
const parts = path.split("/");
const part = parts.pop();
const newPath = parts.join("/");
const result = newPath.endsWith(tslibRoot) && part.startsWith(tslibPrefix) || globalFiles.includes(part);
pathCache[path] = result;
return result;
} else {
return false;
}
}
var import_path6, pathCache;
var init_paths = __esm({
"src/helpers/paths.ts"() {
import_path6 = require("path");
init_constants();
pathCache = {};
}
});
// src/helpers/strings.ts
function makeIdentifier(identifier) {
return checkIdentifier.test(identifier) ? identifier : JSON.stringify(identifier);
}
function formatContent(content) {
return content.split("\n").map((line) => line ? ` ${line}
` : "\n").join("");
}
function toContent(lines, terminator) {
const content = lines.map((line) => `${line}${terminator}`).join("\n");
return formatContent(content);
}
function toBlock(lines, terminator) {
if (lines.length > 0) {
return `{
${toContent(lines, terminator)}}`;
}
return "{}";
}
var checkIdentifier;
var init_strings = __esm({
"src/helpers/strings.ts"() {
checkIdentifier = /^[a-zA-Z\_\$][a-zA-Z0-9\_\$]*$/;
}
});
// src/helpers/symbol.ts
function fullyQualifiedName(symbol, delimiter) {
const parts = [];
do {
parts.push(symbol.name);
symbol = symbol.parent;
} while (symbol && symbol.flags === import_typescript4.SymbolFlags.NamespaceModule && symbol.name !== globalIndicator);
return parts.reverse().join(delimiter);
}
function isGlobal(symbol) {
const parent = symbol?.parent;
if (parent) {
if (parent.name === globalIndicator) {
return true;
}
return isGlobal(parent);
}
return false;
}
function getSymbolName(symbol) {
if (symbol.flags === import_typescript4.SymbolFlags.EnumMember) {
return `${symbol.parent.name}.${symbol.name}`;
} else if (symbol.parent?.flags === import_typescript4.SymbolFlags.NamespaceModule) {
return fullyQualifiedName(symbol, ".");
}
return symbol.name;
}
function getModifiers(symbol) {
const decorators = [];
if (symbol) {
const modifiers = symbol.declarations?.[0]?.modifiers ?? [];
modifiers.some(isPrivate) && decorators.push("private");
modifiers.some(isPublic) && decorators.push("public");
modifiers.some(isProtected) && decorators.push("protected");
modifiers.some(isStatic) && decorators.push("static");
modifiers.some(isReadonly) && decorators.push("readonly");
}
return decorators.join(" ");
}
var import_typescript4;
var init_symbol = __esm({
"src/helpers/symbol.ts"() {
import_typescript4 = require("typescript");
init_constants();
init_node();
}
});
// src/helpers/index.ts
var init_helpers = __esm({
"src/helpers/index.ts"() {
init_comments();
init_identifiers();
init_node();
init_paths();
init_strings();
init_symbol();
}
});
// src/output/stringify.ts
function stringifyComment(type) {
if (type.comment) {
const lines = type.comment.split("\n").map((line) => ` * ${line}
`).join("");
return `/**
${lines} */
`;
}
return "";
}
function stringifyPropName(name) {
return typeof name === "string" ? makeIdentifier(name) : `[${stringifyNode(name)}]`;
}
function stringifyTupleProp(type) {
const target = type.valueType;
const comment = stringifyComment(type);
const isOpt = type.optional ? "?" : "";
const name = stringifyPropName(type.name);
if (typeof target === "undefined") {
return `${comment}${name}${isOpt}: any`;
} else if (target.kind === "function") {
return `${comment}${name}${isOpt}: ${stringifySignature(target, 0 /* default */)}`;
} else {
return `${comment}${name}${isOpt}: ${stringifyNode(target)}`;
}
}
function stringifyProp(type) {
const target = type.valueType;
const comment = stringifyComment(type);
const isOpt = type.optional ? "?" : "";
const modifier = type.modifiers ? `${type.modifiers} ` : "";
const name = stringifyPropName(type.name);
if (typeof target === "undefined") {
return `${comment}${modifier}${name}${isOpt}: any`;
} else if (target.kind === "function") {
return `${comment}${modifier}${name}${isOpt}${stringifySignature(target, 1 /* property */)}`;
} else {
return `${comment}${modifier}${name}${isOpt}: ${stringifyNode(target)}`;
}
}
function stringifyParameter(param, allowModifiers = true) {
const isOpt = param.optional ? "?" : "";
const spread = param.spread ? "..." : "";
const modifiers = allowModifiers && param.modifiers ? `${param.modifiers} ` : "";
return `${modifiers}${spread}${param.param}${isOpt}: ${stringifyNode(param.value)}`;
}
function stringifyParameters(params, allowModifiers = true) {
return params.map((p) => stringifyParameter(p, allowModifiers)).join(", ");
}
function stringifySignature(type, mode, anonymous = false) {
const ctor = type.kind === "new" ? "new " : "";
const prop = (mode & 1 /* property */) !== 0;
const paren = (mode & 2 /* parenthesis */) !== 0;
const comment = anonymous ? stringifyComment(type) : "";
const parameters = stringifyParameters(type.parameters);
const ta = stringifyTypeArgs(type);
const rt = stringifyNode(type.returnType);
const del = prop ? ": " : " => ";
const result = `${ctor}${ta}(${parameters})${del}${rt}`;
const fn = paren ? `(${result})` : result;
return `${comment}${fn}`;
}
function stringifyConstructor(type) {
const modifiedParameters = type.parameters.filter((m) => m.modifiers);
const parameters = stringifyParameters(type.parameters, false);
const modifiers = type.modifiers ? `${type.modifiers} ` : "";
const body = modifiedParameters.map((p) => {
const isOpt = p.optional ? "?" : "";
const type2 = stringifyNode(p.value);
return `${p.modifiers} ${p.param}${isOpt}: ${type2};`;
}).join("\n");
const head = `${modifiers}constructor(${parameters})`;
return [body, head].filter(Boolean).join("\n");
}
function stringifyIndex(type) {
const isOpt = type.optional ? "?" : "";
const index = stringifyParameters(type.parameters);
return `[${index}]${isOpt}: ${stringifyNode(type.valueType)}`;
}
function stringifyMapped(type) {
const isOpt = type.optional ? "?" : "";
const index = `${type.name} in ${stringifyNode(type.constraint)}`;
return `[${index}]${isOpt}: ${stringifyNode(type.value)}`;
}
function stringifyAccess(type) {
const right2 = stringifyNode(type.name);
const left2 = stringifyNode(type.object);
return `${left2}.${right2}`;
}
function stringifyIndexedAccess(type) {
const right2 = stringifyNode(type.index);
const left2 = stringifyNode(type.object);
return `${left2}[${right2}]`;
}
function stringifyInterface(type) {
const lines = type.props.map((p) => stringifyNode(p, 1 /* property */));
if (type.mapped) {
lines.push(stringifyMapped(type.mapped));
}
return toBlock(lines, ";");
}
function stringifyClass(type) {
const lines = type.props.map((p) => stringifyNode(p));
return toBlock(lines, ";");
}
function stringifyEnum(values) {
const lines = values.map((p) => stringifyNode(p));
return toBlock(lines, ",");
}
function stringifyExtends(type) {
const { extends: es } = type;
return es.length ? ` extends ${es.map((t) => stringifyNode(t)).join(", ")}` : "";
}
function stringifyImplements(type) {
const { implements: is } = type;
return is.length ? ` implements ${is.map((t) => stringifyNode(t)).join(", ")}` : "";
}
function stringifyTypes(types) {
return types.map((t) => stringifyNode(t)).join(", ");
}
function stringifyTypeArgs(type) {
if (type.types?.length > 0) {
return `<${stringifyTypes(type.types)}>`;
}
return "";
}
function stringifyTypeParameter(type) {
const name = stringifyNode(type.parameter);
const constraint = stringifyNode(type.constraint);
const defaults = stringifyNode(type.default);
const constraintClause = constraint ? ` extends ${constraint}` : "";
const defaultsClause = defaults ? ` = ${defaults}` : "";
return `${name}${constraintClause}${defaultsClause}`;
}
function stringifyTernary(condition) {
const t = stringifyNode(condition.check);
const e = stringifyNode(condition.extends);
const p = stringifyNode(condition.primary);
const a = stringifyNode(condition.alternate);
return `${t} extends ${e} ? ${p} : ${a}`;
}
function stringifyMember(member) {
const key = stringifyPropName(member.name);
const name = `${stringifyComment(member)}${key}`;
if (member.value) {
return `${name} = ${stringifyNode(member.value)}`;
}
return name;
}
function stringifySetAccessor(accessor) {
const comment = stringifyComment(accessor);
const modifier = accessor.modifiers ? `${accessor.modifiers} ` : "";
const args = stringifyParameters(accessor.parameters);
return `${comment}${modifier}set ${accessor.name}(${args})`;
}
function stringifyGetAccessor(accessor) {
const comment = stringifyComment(accessor);
const modifier = accessor.modifiers ? `${accessor.modifiers} ` : "";
const result = stringifyNode(accessor.type);
return `${comment}${modifier}get ${accessor.name}(): ${result}`;
}
function stringifyPredicate(predicate) {
const type = stringifyNode(predicate.value);
return `${predicate.name} is ${type}`;
}
function stringifyImport(type) {
const head = `import(${stringifyNode(type.value)})`;
if (type.qualifier) {
return `${head}.${type.qualifier}`;
}
return head;
}
function stringifyReadonly(type) {
const value = type.value;
if (value.kind === "ref" && value.refName === "Array" && value.types.length === 1) {
const [arg] = value.types;
return `readonly ${stringifyNode(arg)}[]`;
}
return `readonly ${stringifyNode(value)}`;
}
function stringifyNode(type, mode = 0 /* default */) {
switch (type?.kind) {
case "interface":
return stringifyInterface(type);
case "prop":
return stringifyProp(type);
case "tuple-prop":
return stringifyTupleProp(type);
case "ref":
return `${type.refName}${stringifyTypeArgs(type)}`;
case "typeParameter":
return stringifyTypeParameter(type);
case "union":
return type.types.map((u) => stringifyNode(u, 2 /* parenthesis */)).join(" | ");
case "intersection":
return type.types.map((u) => stringifyNode(u)).join(" & ");
case "member":
return stringifyMember(type);
case "conditional":
return stringifyTernary(type);
case "readonly":
return stringifyReadonly(type);
case "unique":
return `unique ${stringifyNode(type.value)}`;
case "keyof":
return `keyof ${stringifyNode(type.value)}`;
case "import":
return stringifyImport(type);
case "infer":
return `infer ${stringifyNode(type.parameter)}`;
case "any":
case "null":
case "void":
case "undefined":
case "boolean":
case "unknown":
case "bigint":
case "number":
case "never":
case "string":
return type.kind;
case "nonPrimitive":
return type.name || "object";
case "esSymbol":
return "symbol";
case "unidentified":
return "any";
case "literal":
return `${type.value}`;
case "access":
return stringifyAccess(type);
case "indexedAccess":
return stringifyIndexedAccess(type);
case "index":
return stringifyIndex(type);
case "class":
return `class ${stringifyClass(type)}`;
case "constructor":
return stringifyConstructor(type);
case "mapped":
return stringifyMapped(type);
case "substitution":
return stringifyNode(type.variable);
case "rest":
return `...${stringifyNode(type.value)}`;
case "new":
case "function":
return stringifySignature(type, mode, true);
case "tuple":
return `[${stringifyTypes(type.types)}]`;
case "set":
return stringifySetAccessor(type);
case "get":
return stringifyGetAccessor(type);
case "predicate":
return stringifyPredicate(type);
case "template":
return `\`${type.parts.map((p) => typeof p === "string" ? p : `\${${stringifyNode(p)}}`).join("")}\``;
case "parenthesis":
return `(${stringifyNode(type.value)})`;
}
return "";
}
var init_stringify = __esm({
"src/output/stringify.ts"() {
init_helpers();
}
});
// src/output/exports.ts
function stringifyExport(type) {
switch (type?.kind) {
case "interface":
return `${stringifyComment(type)}export interface ${type.name}${stringifyTypeArgs(type)}${stringifyExtends(
type
)} ${stringifyInterface(type)}`;
case "class":
return `${stringifyComment(type)}export class ${type.name}${stringifyTypeArgs(type)}${stringifyExtends(
type
)}${stringifyImplements(type)} ${stringifyClass(type)}`;
case "alias":
return `${stringifyComment(type)}export type ${type.name}${stringifyTypeArgs(type)} = ${stringifyNode(
type.child
)};`;
case "enumLiteral":
return `${stringifyComment(type)}export ${type.const ? "const enum" : "enum"} ${type.name} ${stringifyEnum(
type.values
)}`;
case "const":
return `${stringifyComment(type)}export const ${type.name}: ${stringifyNode(type.value)};`;
case "function":
return `${stringifyComment(type)}export function ${type.name}${stringifySignature(
type,
1 /* property */
)};`;
case "default":
const sc = type.value.kind === "class" ? "" : ";";
return `${stringifyComment(type)}export default ${stringifyNode(type.value)}${sc}`;
}
return "";
}
function stringifyExports(refs) {
return refs.map((r) => stringifyExport(r)).filter((m) => !!m).join("\n\n");
}
var init_exports = __esm({
"src/output/exports.ts"() {
init_stringify();
}
});
// src/output/module.ts
function stringifyModule(name, refs) {
const content = stringifyExports(refs);
const formattedContent = formatContent(content);
return `declare module "${name}" {
${formattedContent}}`;
}
var init_module = __esm({
"src/output/module.ts"() {
init_exports();
init_helpers();
}
});
// src/output/declaration.ts
function stringifyDeclaration(context) {
const { noModuleDeclaration } = context.flags;
const modules = Object.keys(context.modules).filter((moduleName) => Object.keys(context.modules[moduleName]).length > 0).map((moduleName) => {
const refs = context.modules[moduleName];
if (noModuleDeclaration && moduleName === context.name) {
return stringifyExports(refs);
}
return stringifyModule(moduleName, refs);
}).join("\n\n");
const preamble = context.usedImports.map((lib) => `import * as ${getLibRefName(lib)} from '${lib}';`).join("\n");
if (preamble) {
return `${preamble}
${modules}`;
}
return modules;
}
var init_declaration = __esm({
"src/output/declaration.ts"() {
init_module();
init_exports();
init_helpers();
}
});
// src/output/index.ts
var init_output = __esm({
"src/output/index.ts"() {
init_declaration();
init_exports();
init_module();
}
});
// src/logger.ts
var defaultLogger, wrapLogger;
var init_logger = __esm({
"src/logger.ts"() {
defaultLogger = {
error(message) {
throw new Error(message);
},
warn(message) {
console.warn(message);
},
info(message) {
console.info(message);
},
verbose(message) {
console.log(message);
}
};
wrapLogger = (logger, level) => {
return {
error(message) {
level >= 1 && logger.error(message);
},
warn(message) {
level >= 2 && logger.warn(message);
},
info(message) {
level >= 3 && logger.info(message);
},
verbose(message) {
level >= 4 && logger.verbose(message);
}
};
};
}
});
// src/input/api.ts
function includeApi(context, node, interfaceName) {
if ((0, import_typescript5.isInterfaceDeclaration)(node) && node.name.text === interfaceName) {
context.exports.push(node);
} else {
context.log.verbose(`Skipping API using interface "${interfaceName}" from node: ${node}`);
}
}
var import_typescript5;
var init_api = __esm({
"src/input/api.ts"() {
import_typescript5 = require("typescript");
}
});
// src/input/exports.ts
function includeExports(context, key, symbol) {
const defs = {};
if (symbol) {
context.checker.getExportsOfModule(symbol).forEach((exp) => {
const decl = exp.valueDeclaration || exp.declarations?.[0];
if (!decl) {
} else if (ts.isExportSpecifier(decl)) {
const name = decl.name?.text;
if (name) {
defs[name] = getDeclarationFromNode(context.checker, decl);
}
} else if (ts.isExportAssignment(decl)) {
defs["default"] = getDeclarationFromNode(context.checker, decl);
} else if (ts.isVariableDeclaration(decl)) {
defs[getParameterName(decl.name)] = decl;
} else if (ts.isFunctionDeclaration(decl) || ts.isInterfaceDeclaration(decl) || ts.isClassDeclaration(decl) || ts.isTypeAliasDeclaration(decl) || ts.isEnumDeclaration(decl)) {
const name = isDefaultExport(decl) ? "default" : decl.name?.text;
if (name) {
defs[name] = decl;
}
} else if (ts.isMethodDeclaration(decl) || ts.isPropertyDeclaration(decl)) {
} else if (ts.isModuleDeclaration(decl)) {
defs[decl.name.text] = decl;
} else if (ts.isImportEqualsDeclaration(decl)) {
} else if (ts.isNamespaceExport(decl)) {
defs[decl.name.text] = decl;
} else {
context.log.warn(`Skipping import of unknown node (kind: ${decl.kind}).`);
}
});
}
context.availableImports[key] = defs;
}
var ts;
var init_exports2 = __esm({
"src/input/exports.ts"() {
ts = __toESM(require("typescript"));
init_helpers();
}
});
// src/input/utils.ts
function createBinding(context, lib, name) {
if (!context.usedImports.includes(lib)) {
context.usedImports.push(lib);
}
return `${getLibRefName(lib)}.${name}`;
}
function getDefault(value) {
return {
kind: "default",
name: "default",
value
};
}
function getRef(refName, types = []) {
return {
kind: "ref",
refName,
types
};
}
function getSymbolName2(imports, node) {
if (imports) {
for (const name of Object.keys(imports)) {
if (imports[name] === node) {
return name;
}
}
}
return void 0;
}
function isImportedFile(node, root2, imports) {
const fn = node.getSourceFile()?.fileName;
if (fn) {
const libName = getLibName(fn, root2);
return Object.keys(imports).some((name) => name === libName);
}
return false;
}
function getPackage(node, symbol, root2, imports) {
const fn = node.getSourceFile()?.fileName;
const base = isBaseLib(fn) || false;
const global = isGlobal(symbol);
if (!base) {
const libName = getLibName(fn, root2);
const [lib] = Object.keys(imports).filter((name) => {
if (global) {
return name === libName;
}
const exports2 = Object.values(imports[name]);
if (exports2.includes(node)) {
return true;
} else if (symbol?.parent?.flags === ts2.SymbolFlags.NamespaceModule) {
const parentNode = symbol.parent?.declarations[0];
return exports2.includes(parentNode);
}
return false;
});
const symbolName = getSymbolName2(imports[lib], node);
return {
external: !!lib,
moduleName: lib && getModule(node) || lib,
symbolName,
global,
base,
lib,
fn
};
}
return {
external: true,
moduleName: void 0,
symbolName: void 0,
global,
base,
lib: void 0,
fn
};
}
var ts2;
var init_utils = __esm({
"src/input/utils.ts"() {
ts2 = __toESM(require("typescript"));
init_helpers();
}
});
// src/input/includes.ts
function isText(actual, expected) {
if (typeof actual === "string") {
return actual === expected;
} else if (Array.isArray(actual)) {
return actual.some((m) => m.text === expected);
}
return false;
}
function includeClauses(context, clauses, newClause, tags = []) {
const types = [];
for (const clause of newClause.types) {
const decl = getDeclarationFromNode(context.checker, clause.expression);
const name = decl?.symbol?.name;
if (decl && !tags.some((m) => m.name === "dets_removeclause" && isText(m.text, name))) {
types.push(clause);
}
}
clauses.push({
...newClause,
types: ts3.factory.createNodeArray(types)
});
}
function includeProp(props, newProp, getPropName, tags = []) {
const name = getPropName(newProp.name);
if (tags.some((m) => m.name === "dets_removeprop" && isText(m.text, name))) {
return;
}
for (const oldProp of props) {
if (oldProp.kind === newProp.kind && getPropName(oldProp.name) === name) {
if (!ts3.isMethodSignature(newProp) && !ts3.isCallSignatureDeclaration(newProp)) {
return;
}
}
}
props.push(newProp);
}
var ts3;
var init_includes = __esm({
"src/input/includes.ts"() {
ts3 = __toESM(require("typescript"));
init_helpers();
}
});
// src/input/node.ts
var ts4, DeclVisitor;
var init_node2 = __esm({
"src/input/node.ts"() {
ts4 = __toESM(require("typescript"));
init_utils();
init_includes();
init_helpers();
DeclVisitor = class {
constructor(context) {
this.context = context;
this.queue = [];
this.modules = [];
this.processed = [];
const [defaultModule] = Object.keys(context.modules ?? {});
this.refs = context.modules[defaultModule] ?? [];
this.names = context.moduleNames[defaultModule] ?? /* @__PURE__ */ new Map();
for (const node of context.exports) {
this.enqueue(node);
}
}
logVerbose(message) {
this.context.log.verbose(message);
}
logWarn(message) {
this.context.log.warn(message);
}
printWarning(type, node) {
this.logWarn(
`Could not resolve ${type} at position ${node.pos} of "${node.getSourceFile()?.fileName}". Kind: ${node.kind}.`
);
}
swapName(oldName, newName) {
const refs = this.refs;
const last = refs.pop();
if (!last) {
} else if (last.kind === "default") {
if (last.value.kind === "ref") {
const name = last.value.refName;
for (let i = refs.length; i--; ) {
const ref = refs[i];
if (ref.name === name) {
refs.splice(i, 1, {
...ref,
name: newName
});
break;
}
}
}
} else if ("name" in last && last.name === oldName) {
refs.push({
...last,
name: newName
});
} else {
refs.push(last);
}
}
findName(node) {
return this.names.get(node);
}
createName(name) {
const altStart = `${name}___`;
const available = /* @__PURE__ */ new Set();
for (const m of this.names.values()) {
if (m === name || m.startsWith(altStart)) {
available.add(m);
}
}
const count = available.size;
if (count) {
return `${altStart}${count}`;
}
return name;
}
getName(node, suggested) {
const existing = this.findName(node);
if (!existing) {
this.logVerbose(`Missing "name". Retrieving with suggestion "${suggested}".`);
const name = this.createName(suggested);
const decls = node.symbol?.declarations ?? [node];
decls.forEach((decl) => this.names.set(decl, name));
return name;
}
return existing;
}
normalizeName(node) {
const c = this.context;
const symbol = node.symbol ?? node.aliasSymbol ?? c.checker.getSymbolAtLocation(node);
const { moduleName, lib, symbolName, global } = getPackage(node, symbol, c.root, c.availableImports);
if (!lib) {
const name = global ? fullyQualifiedName(symbol, "_") : getSymbolName(symbol);
return this.getName(node, name);
} else if (global) {
return fullyQualifiedName(symbol, ".");
} else {
return createBinding(c, moduleName, symbolName ?? getSymbolName(symbol));
}
}
convertToTypeNodeFromType(type) {
const c = this.context.checker;
return c.typeToTypeNode(type, void 0, ts4.NodeBuilderFlags.NoTruncation);
}
convertToTypeNodeFromNode(node) {
const type = this.context.checker.getTypeAtLocation(node);
return this.convertToTypeNodeFromType(type);
}
valueFromLiteral(node) {
switch (node.literal.kind) {
case ts4.SyntaxKind.StringLiteral:
return JSON.stringify(node.literal.text);
case ts4.SyntaxKind.TrueKeyword:
return "true";
case ts4.SyntaxKind.FalseKeyword:
return "false";
case ts4.SyntaxKind.NumericLiteral:
case ts4.SyntaxKind.BigIntLiteral:
return node.literal.text;
case ts4.SyntaxKind.NullKeyword:
return "null";
default:
this.logVerbose(`No match for literal node kind "${node.literal.kind}". Trying to get from type node...`);
const type = this.context.checker.getTypeFromTypeNode(node);
return type?.intrinsicName ?? type?.value;
}
}
getInferredType(node) {
const typeNode = this.convertToTypeNodeFromNode(node);
return this.getTypeNode(typeNode);
}
getUnion(node) {
return {
kind: "union",
types: node.types.map((m) => this.getNode(m))
};
}
getLiteral(node) {
return {
kind: "literal",
value: this.valueFromLiteral(node)
};
}
getNode(node) {
if (ts4.isTypeNode(node)) {
return this.getTypeNode(node);
} else if (ts4.isTypeAliasDeclaration(node) || ts4.isFunctionDeclaration(node) || ts4.isInterfaceDeclaration(node) || ts4.isClassDeclaration(node)) {
this.enqueue(node);
return getRef(this.normalizeName(node), this.getTypeParameters(node.typeParameters));
} else if (isDefaultExport(node) || ts4.isVariableDeclaration(node) || ts4.isVariableStatement(node)) {
this.enqueue(node);
return getRef(this.normalizeName(node));
} else if (ts4.isPropertyAssignment(node)) {
return {
kind: "prop",
modifiers: getModifiers(node.symbol),
name: node.symbol.name,
//@ts-ignore
optional: node.questionToken !== void 0,
valueType: this.getExpression(node.initializer)
};
}
this.logVerbose(`Node is presumably a reference. Found kind "${node.kind}".`);
return getRef(node.symbol.name);
}
getPropDeclaration(node) {
const type = node.type ?? this.convertToTypeNodeFromNode(node);
return this.getTypeNode(type);
}
getPropValue(node) {
if (ts4.isPropertySignature(node)) {
return this.getTypeNode(node.type);
} else if (ts4.isMethodSignature(node)) {
return this.getMethodSignature(node);
} else if (ts4.isPropertyDeclaration(node)) {
return this.getPropDeclaration(node);
} else if (ts4.isMethodDeclaration(node)) {
return this.getMethodSignature(node);
}
this.printWarning("property", node);
}
getNormalProp(node) {
const { checker, flags } = this.context;
const canDrop = !flags.noIgnore;
const comment = getCommentOrDrop(checker, node.emitNode?.commentRange ?? node, canDrop);
if (typeof comment === "string") {
return {
kind: "prop",
name: this.getPropName(node.name),
modifiers: getModifiers(node.symbol),
optional: node.questionToken !== void 0,
comment,
valueType: this.getPropValue(node)
};
}
this.logVerbose(`The prop "${this.getPropName(node.name)}" was skipped due to @ignore.`);
return void 0;
}
getIndexProp(node) {
return {
kind: "index",
parameters: this.getFunctionParameters(node.parameters),
optional: node.questionToken !== void 0,
valueType: this.getTypeNode(node.type)
};
}
getConstructor(node) {
return {
kind: "constructor",
parameters: this.getFunctionParameters(node.parameters),
modifiers: getModifiers(node.symbol),
comment: getComment(this.context.checker, node)
};
}
getClassMember(node) {
const { checker, flags } = this.context;
const canDrop = !flags.noIgnore;
const comment = getCommentOrDrop(checker, node, canDrop);
if (node.name) {
if (typeof comment === "string") {
return {
kind: "prop",
name: node.name.getText(),
modifiers: getModifiers(node.symbol),
optional: false,
comment,
valueType: this.getPropValue(node)
};
}
this.logVerbose(`The member "${node.name.getText()}" was skipped due to @ignore.`);
}
return void 0;
}
getProps(nodes) {
const props = [];
nodes?.forEach((node) => {
if (ts4.isIndexSignatureDeclaration(node)) {
props.push(this.getIndexProp(node));
} else if (ts4.isCallSignatureDeclaration(node)) {
props.push(this.getMethodSignature(node));
} else if (ts4.isConstructSignatureDeclaration(node)) {
props.push(this.getConstructorCall(node));
} else if (ts4.isGetAccessor(node)) {
const prop = this.getGetAccessor(node);
prop && props.push(prop);
} else if (ts4.isSetAccessor(node)) {
const prop = this.getSetAccessor(node);
prop && props.push(prop);
} else if (ts4.isPropertySignature(node)) {
const prop = this.getNormalProp(node);
prop && props.push(prop);
} else {
this.logVerbose(`Getting props - assuming node of kind "${node?.kind}" is a normal prop.`);
const prop = this.getNormalProp(node);
prop && props.push(prop);
}
});
return props;
}
getClassMembers(nodes) {
const members = [];
nodes?.forEach((node) => {
if (ts4.isConstructorDeclaration(node)) {
members.push(this.getConstructor(node));
} else if (ts4.isCallSignatureDeclaration(node)) {
members.push(this.getMethodSignature(node));
} else if (ts4.isConstructSignatureDeclaration(node)) {
members.push(this.getConstructorCall(node));
} else if (ts4.isGetAccessor(node)) {
const member = this.getGetAccessor(node);
member && members.push(member);
} else if (ts4.isSetAccessor(node)) {
const member = this.getSetAccessor(node);
member && members.push(member);
} else if (ts4.isIndexSignatureDeclaration(node)) {
members.push(this.getIndexProp(node));
} else {
this.logVerbose(`Getting class members - assuming node of kind "${node?.kind}" is a class member.`);
const member = this.getClassMember(node);
member && members.push(member);
}
});
return members;
}
getEnumMember(node) {
const value = node.initializer;
return {
kind: "member",
name: this.getPropName(node.name),
value: value && this.getExpression(value),
comment: getComment(this.context.checker, node)
};
}
getEnumMembers(nodes) {
return nodes?.map((node) => this.getEnumMember(node)) ?? [];
}
getReturnType(node) {
const checker = this.context.checker;
const type = node.type ?? this.convertToTypeNodeFromType(checker.getReturnTypeOfSignature(checker.getSignatureFromDeclaration(node)));
return this.getTypeNode(type);
}
getFunctionDeclaration(node) {
const name = this.getName(node, node.name.text);
return {
...this.getMethodSignature(node),
name
};
}
getMethodSignature(node) {
return {
kind: "function",
name: void 0,
parameters: this.getFunctionParameters(node.parameters),
returnType: this.getReturnType(node),
types: this.getTypeParameters(node.typeParameters),
comment: getComment(this.context.checker, node)
};
}
getConstructorCall(node) {
return {
kind: "new",
parameters: this.getFunctionParameters(node.parameters),
returnType: this.getTypeNode(node.type),
types: this.getTypeParameters(node.typeParameters),
comment: getComment(this.context.checker, node)
};
}
getTypeParameter(node) {
return {
kind: "typeParameter",
parameter: getRef(node.name.text),
constraint: node.constraint && this.getTypeNode(node.constraint),
default: node.default && this.getTypeNode(node.default)
};
}
getTypeParameters(nodes) {
return nodes?.map((node) => this.getTypeParameter(node)) ?? [];
}
getTypeArguments(nodes) {
return nodes?.map((node) => this.getTypeNode(node)) ?? [];
}
getFunctionParameterValue(node) {
if (node.type) {
return this.getTypeNode(node.type);
}
const typeNode = this.convertToTypeNodeFromNode(node);
if (typeNode) {
return this.getTypeNode(typeNode);
} else if (node.initializer) {
return this.getExpression(node.initializer);
} else {
this.logVerbose(
`Found unidentified node of kind "${node.kind}" in function parameter value. Falling back to "any".`
);
return {
kind: "any"
};
}
}
getFunctionParameter(node) {
return {
kind: "parameter",
param: getParameterName(node.name),
spread: node.dotDotDotToken !== void 0,
optional: node.questionToken !== void 0 || node.initializer !== void 0,
modifiers: getModifiers(node.symbol),
value: this.getFunctionParameterValue(node)
};
}
getFunctionParameters(nodes) {
return nodes?.map((node) => this.getFunctionParameter(node)) ?? [];
}
getIndexAccess(node) {
return {
kind: "indexedAccess",
index: this.getTypeNode(node.indexType),
object: this.getTypeNode(node.objectType)
};
}
getTypeOperator(node) {
switch (node.operator) {
case ts4.SyntaxKind.KeyOfKeyword:
return {
kind: "keyof",
value: this.getTypeNode(node.type)
};
case ts4.SyntaxKind.UniqueKeyword:
return {
kind: "unique",
value: this.getTypeNode(node.type)
};
case ts4.SyntaxKind.ReadonlyKeyword:
return {
kind: "readonly",
value: this.getTypeNode(node.type)
};
default:
this.logWarn(`Found unknown type operator node of kind "${node.kind}".`);
}
}
getMappedType(node) {
const p = node.typeParameter;
return {
kind: "interface",
name: void 0,
extends: [],
props: [],
types: [],
comment: getComment(this.context.checker, node),
mapped: {
kind: "mapped",
constraint: this.getTypeNode(p.constraint),
name: p.name.text,
optional: node.questionToken !== void 0,
value: this.getTypeNode(node.type)
}
};
}
getConditionalType(node) {
return {
kind: "conditional",
alternate: this.getTypeNode(node.falseType),
check: this.getTypeNode(node.checkType),
extends: this.getTypeNode(node.extendsType),
primary: this.getTypeNode(node.trueType)
};
}
getPredicate(node) {
return {
kind: "predicate",
name: getPredicateName(node.parameterName),
value: this.getTypeNode(node.type)
};
}
getSetAccessor(node) {
const { checker, flags } = this.context;
const canDrop = !flags.noIgnore;
const comment = getCommentOrDrop(checker, node, canDrop);
if (typeof comment === "string") {
return {
kind: "set",
name: this.getPropName(node.name),
parameters: this.getFunctionParameters(node.parameters),
comment,
modifiers: getModifiers(node.symbol)
};
}
this.logVerbose(`The setter "${this.getPropName(node.name)}" was skipped due to @ignore.`);
return void 0;
}
getGetAccessor(node) {
const { checker, flags } = this.context;
const canDrop = !flags.noIgnore;
const comment = getCommentOrDrop(checker, node, canDrop);
if (typeof comment === "string") {
return {
kind: "get",
name: this.getPropName(node.name),
type: this.getReturnType(node),
comment,
modifiers: getModifiers(node.symbol)
};
}
this.logVerbose(`The getter "${this.getPropName(node.name)}" was skipped due to @ignore.`);
return void 0;
}
getTypeReference(node) {
const c = this.context.checker;
const decl = getDeclarationFromNode(c, node);
if (decl && !ts4.isTypeParameterDeclaration(decl)) {
this.enqueue(decl);
return getRef(this.normalizeName(decl), this.getTypeArguments(node.typeArguments));
}
return getRef(getTypeRefName(node.typeName), this.getTypeArguments(node.typeArguments));
}
getTypeLiteral(node) {
return {
kind: "interface",
name: void 0,
comment: getComment(this.context.checker, node),
extends: [],
props: this.getProps(node.members),
types: []
};
}
getExpressionWithTypeArguments(node) {
const decl = getDeclarationFromNode(this.context.checker, node.expression);
if (decl) {
this.enqueue(decl);
return getRef(this.normalizeName(decl), this.getTypeArguments(node.typeArguments));
}
return {
kind: "ref",
refName: "any",
types: []
};
}
getArray(node) {
return getRef("Array", [this.getTypeNode(node.elementType)]);
}
getInfer(node) {
return {
kind: "infer",
parameter: this.getTypeParameter(node.typeParameter)
};
}
getIntersection(node) {
return {
kind: "intersection",
types: node.types.map((n) => this.getTypeNode(n))
};
}
getTuple(node) {
return {
kind: "tuple",
types: (node["elementTypes"] ?? node.elements).map((n) => this.getTypeNode(n))
};
}
getParenthesis(node) {
return {
kind: "parenthesis",
value: this.getTypeNode(node.type)
};
}
getTypeQueryNode(node) {
const symbol = this.context.checker.getSymbolAtLocation(node.exprName);
if (sy