diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95eeead..313b550 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log (@egomobile/documentation)
+## 0.7.0
+
+- add `appDependsOn()` and `moduleDependsOn()` function
+- add `existsIn` props to `DependencyItemWithInfo` and `ISerializableDependencyItemWithInfo` based items
+- fix documentation
+
## 0.6.0
- add optional `entities` prop to `IDependencyInformationEntity`
diff --git a/package-lock.json b/package-lock.json
index 6c093fa..6140e6a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@egomobile/documentation",
- "version": "0.6.0",
+ "version": "0.7.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@egomobile/documentation",
- "version": "0.6.0",
+ "version": "0.7.0",
"license": "LGPL-3.0",
"devDependencies": {
"@egomobile/tsconfig": "^5.0.0",
diff --git a/package.json b/package.json
index 8356d5f..644ff45 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@egomobile/documentation",
- "version": "0.6.0",
+ "version": "0.7.0",
"description": "Tools for documenting (TypeScript) code.",
"main": "lib/index.js",
"engines": {
diff --git a/src/decorators/DependsOn.ts b/src/decorators/DependsOn.ts
index 6428194..5d828f5 100644
--- a/src/decorators/DependsOn.ts
+++ b/src/decorators/DependsOn.ts
@@ -15,8 +15,8 @@
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
-import type { IDependencyInformation, IParameterDependencyItem, IPropertyDependencyItem, IMethodDependencyItem, DependencyInfoResolver, DependencyInfoCollectionArg } from "../types";
-import type { ClassPropKey, CreateDependsOnHelpersFunc, Nilable, Optional } from "../types/internal";
+import type { IDependencyInformation, IParameterDependencyItem, IPropertyDependencyItem, IMethodDependencyItem, DependencyInfoResolver, DependencyInfoCollectionArg, IStackInfo } from "../types";
+import type { ClassPropKey, CreateDependsOnHelpersFunc, Nilable, Nullable, Optional } from "../types/internal";
/**
* Adds meta for a class, property, method or parameter
@@ -100,6 +100,9 @@ export function DependsOn(
dependenciesOrResolver?: Nilable
): any {
const createDependsOnHelpers: CreateDependsOnHelpersFunc = require("../utils/internal").createDependsOnHelpers;
+ const tryGetStackInfo = require("../utils/internal").tryGetStackInfo;
+
+ const stackInfo: Nullable = tryGetStackInfo();
const {
addItem
@@ -117,7 +120,10 @@ export function DependsOn(
"type": "method"
};
- addItem(newMethodItem);
+ addItem({
+ "existsIn": stackInfo,
+ "item": newMethodItem
+ });
};
const addAsParameter = () => {
@@ -131,7 +137,10 @@ export function DependsOn(
"type": "parameter"
};
- addItem(newParameterItem);
+ addItem({
+ "existsIn": stackInfo,
+ "item": newParameterItem
+ });
};
const addAsProperty = () => {
@@ -143,7 +152,10 @@ export function DependsOn(
"type": "property"
};
- addItem(newPropertyItem);
+ addItem({
+ "existsIn": stackInfo,
+ "item": newPropertyItem
+ });
};
const addWith3Args = () => {
@@ -176,7 +188,8 @@ export function DependsOn(
classDependsOn(
target,
infoOrResolver,
- dependenciesOrResolver
+ dependenciesOrResolver,
+ stackInfo
);
}
}
diff --git a/src/functions/dependsOn.ts b/src/functions/dependsOn.ts
index 983e113..d0f4028 100644
--- a/src/functions/dependsOn.ts
+++ b/src/functions/dependsOn.ts
@@ -13,9 +13,60 @@
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
-import type { DependencyInfoCollectionArg, DependencyInfoResolver, IClassDependencyItem, IDependencyInformation, IFunctionDependencyItem } from "../types";
+import type { DependencyInfoCollectionArg, DependencyInfoResolver, IClassDependencyItem, IDependencyInformation, IFunctionDependencyItem, IModuleDependencyItem, IStackInfo } from "../types";
import type { Constructor, CreateDependsOnHelpersFunc, Func, Nilable } from "../types/internal";
+/**
+ * Adds dependency information for current app.
+ *
+ * @example
+ * ```
+ * import {
+ * appDependsOn,
+ * getDependencies
+ * } from "@egomobile/documentation"
+ *
+ * appDependsOn(
+ * {
+ * // your information here...
+ * }
+ * )
+ *
+ * console.log(
+ * getDependencies()
+ * )
+ * ```
+ *
+ * @param {IDependencyInformation|DependencyInfoResolver} infoOrResolver The dependency information or the function that resolves it.
+ * @param {Nilable} [dependenciesOrResolver] The custom collection for the dependency info items or the function that resolves it.
+ * @param {Nilable} [stackInfo] Custom stack information.
+ *
+ * @throws ReferenceError No CommonJS based main module found.
+ */
+export function appDependsOn(
+ infoOrResolver: IDependencyInformation | DependencyInfoResolver,
+ dependenciesOrResolver?: Nilable,
+ stackInfo?: Nilable
+) {
+ const mainModule = require.main;
+ if (!mainModule) {
+ throw new ReferenceError("no main module found");
+ }
+
+ const tryGetStackInfo = require("../utils/internal").tryGetStackInfo;
+
+ if (!stackInfo) {
+ stackInfo = tryGetStackInfo();
+ }
+
+ moduleDependsOn(
+ mainModule,
+ infoOrResolver,
+ dependenciesOrResolver,
+ stackInfo
+ );
+}
+
/**
* Adds dependency information for a class.
*
@@ -31,7 +82,7 @@ import type { Constructor, CreateDependsOnHelpersFunc, Func, Nilable } from "../
* }
*
* classDependsOn(
- * MyClass
+ * MyClass,
* {
* // your information here...
* }
@@ -45,14 +96,21 @@ import type { Constructor, CreateDependsOnHelpersFunc, Func, Nilable } from "../
* @param {Constructor} classConstructor The class constructor.
* @param {IDependencyInformation|DependencyInfoResolver} infoOrResolver The dependency information or the function that resolves it.
* @param {Nilable} [dependenciesOrResolver] The custom collection for the dependency info items or the function that resolves it.
+ * @param {Nilable} [stackInfo] Custom stack information.
*/
export function classDependsOn(
classConstructor: Constructor,
infoOrResolver: IDependencyInformation | DependencyInfoResolver,
- dependenciesOrResolver?: Nilable
+ dependenciesOrResolver?: Nilable,
+ stackInfo?: Nilable
) {
const createDependsOnHelpers: CreateDependsOnHelpersFunc =
require("../utils/internal").createDependsOnHelpers;
+ const tryGetStackInfo = require("../utils/internal").tryGetStackInfo;
+
+ if (!stackInfo) {
+ stackInfo = tryGetStackInfo();
+ }
const {
addItem
@@ -63,7 +121,10 @@ export function classDependsOn(
"type": "class"
};
- addItem(newClassItem);
+ addItem({
+ "existsIn": stackInfo ?? null,
+ "item": newClassItem
+ });
}
/**
@@ -81,7 +142,7 @@ export function classDependsOn(
* }
*
* functionDependsOn(
- * myFunction
+ * myFunction,
* {
* // your information here...
* }
@@ -95,14 +156,21 @@ export function classDependsOn(
* @param {Func} func The function.
* @param {IDependencyInformation|DependencyInfoResolver} infoOrResolver The dependency information or the function that resolves it.
* @param {Nilable} [dependenciesOrResolver] The custom collection for the dependency info items or the function that resolves it.
+ * @param {Nilable} [stackInfo] Custom stack information.
*/
export function functionDependsOn(
func: Func,
infoOrResolver: IDependencyInformation | DependencyInfoResolver,
- dependenciesOrResolver?: Nilable
+ dependenciesOrResolver?: Nilable,
+ stackInfo?: Nilable
) {
const createDependsOnHelpers: CreateDependsOnHelpersFunc =
require("../utils/internal").createDependsOnHelpers;
+ const tryGetStackInfo = require("../utils/internal").tryGetStackInfo;
+
+ if (!stackInfo) {
+ stackInfo = tryGetStackInfo();
+ }
const {
addItem
@@ -113,5 +181,64 @@ export function functionDependsOn(
"type": "function"
};
- addItem(newFunctionItem);
+ addItem({
+ "existsIn": stackInfo ?? null,
+ "item": newFunctionItem
+ });
+}
+
+/**
+ * Adds dependency information for a module.
+ *
+ * @example
+ * ```
+ * import {
+ * moduleDependsOn,
+ * getDependencies
+ * } from "@egomobile/documentation"
+ *
+ * moduleDependsOn(
+ * require.main,
+ * {
+ * // your information here...
+ * }
+ * )
+ *
+ * console.log(
+ * getDependencies()
+ * )
+ * ```
+ *
+ * @param {any} module The module.
+ * @param {IDependencyInformation|DependencyInfoResolver} infoOrResolver The dependency information or the function that resolves it.
+ * @param {Nilable} [dependenciesOrResolver] The custom collection for the dependency info items or the function that resolves it.
+ * @param {Nilable} [stackInfo] Custom stack information.
+ */
+export function moduleDependsOn(
+ module: any,
+ infoOrResolver: IDependencyInformation | DependencyInfoResolver,
+ dependenciesOrResolver?: Nilable,
+ stackInfo?: Nilable
+) {
+ const createDependsOnHelpers: CreateDependsOnHelpersFunc =
+ require("../utils/internal").createDependsOnHelpers;
+ const tryGetStackInfo = require("../utils/internal").tryGetStackInfo;
+
+ if (!stackInfo) {
+ stackInfo = tryGetStackInfo();
+ }
+
+ const {
+ addItem
+ } = createDependsOnHelpers(infoOrResolver, dependenciesOrResolver);
+
+ const newModuleItem: IModuleDependencyItem = {
+ module,
+ "type": "module"
+ };
+
+ addItem({
+ "existsIn": stackInfo ?? null,
+ "item": newModuleItem
+ });
}
diff --git a/src/types/dependencies.ts b/src/types/dependencies.ts
index 00ea08a..62d2a62 100644
--- a/src/types/dependencies.ts
+++ b/src/types/dependencies.ts
@@ -13,7 +13,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
-import type { IWithClassNameProp, IWithClassOrInstanceProp, IWithEffectsProps, IWithIsStaticProp, IWithReferencesProp, IWithRemarksProp, IWithTypeProp } from ".";
+import type { IStackInfo, IWithClassNameProp, IWithClassOrInstanceProp, IWithEffectsProps, IWithIsStaticProp, IWithReferencesProp, IWithRemarksProp, IWithTypeProp } from ".";
import type { ClassPropKey, Collection, Constructor, Nilable, Nullable, Optional, ReferenceValue } from "./internal";
/**
@@ -48,6 +48,7 @@ export type DependencyItem =
IClassDependencyItem |
IFunctionDependencyItem |
IMethodDependencyItem |
+ IModuleDependencyItem |
IParameterDependencyItem |
IPropertyDependencyItem;
@@ -60,6 +61,13 @@ export type DependencyItemCollectionResolver = () => Collection;
/**
* The underlying information.
*/
@@ -172,6 +180,20 @@ export interface IMethodDependencyItem extends IDependencyItem, Partial;
/**
* The underlying information.
*/
@@ -256,6 +282,20 @@ export interface ISerializableMethodDependencyItemWithInfo extends ISerializable
type: "method";
}
+/**
+ * A serizable version of an `IModuleDependencyItem`.
+ */
+export interface ISerializableModuleDependencyItemWithInfo extends ISerializableDependencyItemWithInfo {
+ /**
+ * The name/path of the module.
+ */
+ name: string;
+ /**
+ * The type.
+ */
+ type: "module";
+}
+
/**
* A serizable version of an `IParameterDependencyItem`.
*/
@@ -295,5 +335,6 @@ export type SerializableDependencyItem =
ISerializableClassDependencyItemWithInfo |
ISerializableFunctionDependencyItemWithInfo |
ISerializableMethodDependencyItemWithInfo |
+ ISerializableModuleDependencyItemWithInfo |
ISerializableParameterDependencyItemWithInfo |
ISerializablePropertyDependencyItemWithInfo;
diff --git a/src/types/index.ts b/src/types/index.ts
index eeb4503..6df884a 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -15,6 +15,20 @@
import type { ClassOrInstance, Nilable, Nullable } from "./internal";
+/**
+ * Stack information.
+ */
+export interface IStackInfo {
+ /**
+ * Path to file, if available.
+ */
+ file: Nullable;
+ /**
+ * Line of code inside `file`, if available.
+ */
+ line: Nullable;
+}
+
/**
* An object with a `className` property.
*/
diff --git a/src/types/internal.ts b/src/types/internal.ts
index 6ea6cf6..9e0f08d 100644
--- a/src/types/internal.ts
+++ b/src/types/internal.ts
@@ -13,6 +13,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
+import type { IStackInfo } from ".";
import type { DependencyInfoArg, DependencyInfoCollectionArg, DependencyItem, DependencyItemWithInfo, IDependencyInformation } from "./dependencies";
export type ClassOrInstance = T | Constructor;
@@ -31,7 +32,7 @@ export type CreateDependsOnHelpersFunc =
infoOrResolver: DependencyInfoArg,
dependenciesOrResolver: Nilable
) => {
- addItem: (item: DependencyItem) => void;
+ addItem: (options: IAddDependencyItemOptions) => void;
getDepsCollection: () => Collection;
getInfo: () => IDependencyInformation;
};
@@ -41,6 +42,11 @@ export type Func = (...args: any[]) => any;
export type GetClassNameFunc =
(classOrInstance: ClassOrInstance) => Nullable;
+export interface IAddDependencyItemOptions {
+ existsIn: Nullable;
+ item: DependencyItem;
+}
+
export interface IArrayLike {
push(item: T): any;
}
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 356a257..c99691e 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -13,7 +13,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
-import type { DependencyItemWithInfo, ISerializableClassDependencyItemWithInfo, ISerializableFunctionDependencyItemWithInfo, ISerializableMethodDependencyItemWithInfo, ISerializableParameterDependencyItemWithInfo, ISerializablePropertyDependencyItemWithInfo, SerializableDependencyItem } from "../types";
+import type { DependencyItemWithInfo, ISerializableClassDependencyItemWithInfo, ISerializableFunctionDependencyItemWithInfo, ISerializableMethodDependencyItemWithInfo, ISerializableModuleDependencyItemWithInfo, ISerializableParameterDependencyItemWithInfo, ISerializablePropertyDependencyItemWithInfo, SerializableDependencyItem } from "../types";
import type { GetClassNameFunc, IsConstructorFunc, List } from "../types/internal";
/**
@@ -30,9 +30,12 @@ export function serializeDependencies(list: List): Seria
const serializedItems: SerializableDependencyItem[] = [];
for (const item of list) {
+ const existsIn = item.existsIn || null;
+
let newSerializedItem: SerializableDependencyItem;
if (item.type === "class") {
const newClassItem: ISerializableClassDependencyItemWithInfo = {
+ existsIn,
"info": item.info,
"name": item.constructor.name,
"type": item.type
@@ -41,19 +44,21 @@ export function serializeDependencies(list: List): Seria
newSerializedItem = newClassItem;
}
else if (item.type === "method") {
- const newClassItem: ISerializableMethodDependencyItemWithInfo = {
+ const newMethodItem: ISerializableMethodDependencyItemWithInfo = {
"className": getClassName(item.classOrInstance),
+ existsIn,
"info": item.info,
"isStatic": isConstructor(item.classOrInstance),
"name": String(item.key),
"type": item.type
};
- newSerializedItem = newClassItem;
+ newSerializedItem = newMethodItem;
}
else if (item.type === "parameter") {
- const newClassItem: ISerializableParameterDependencyItemWithInfo = {
+ const newParameterItem: ISerializableParameterDependencyItemWithInfo = {
"className": getClassName(item.classOrInstance),
+ existsIn,
"info": item.info,
"index": item.index,
"isStatic": isConstructor(item.classOrInstance),
@@ -61,27 +66,39 @@ export function serializeDependencies(list: List): Seria
"type": item.type
};
- newSerializedItem = newClassItem;
+ newSerializedItem = newParameterItem;
}
else if (item.type === "property") {
- const newClassItem: ISerializablePropertyDependencyItemWithInfo = {
+ const newPropertyItem: ISerializablePropertyDependencyItemWithInfo = {
"className": getClassName(item.classOrInstance),
+ existsIn,
"info": item.info,
"isStatic": isConstructor(item.classOrInstance),
"name": String(item.key),
"type": item.type
};
- newSerializedItem = newClassItem;
+ newSerializedItem = newPropertyItem;
}
- else {
- const newClassItem: ISerializableFunctionDependencyItemWithInfo = {
+ else if (item.type === "function") {
+ const newFunctionItem: ISerializableFunctionDependencyItemWithInfo = {
+ existsIn,
"info": item.info,
"name": item.key,
"type": item.type
};
- newSerializedItem = newClassItem;
+ newSerializedItem = newFunctionItem;
+ }
+ else {
+ const newModuleItem: ISerializableModuleDependencyItemWithInfo = {
+ existsIn,
+ "info": item.info,
+ "name": String(item.module?.filename ?? ""),
+ "type": item.type
+ };
+
+ newSerializedItem = newModuleItem;
}
serializedItems.push(
diff --git a/src/utils/internal.ts b/src/utils/internal.ts
index 16f04a4..0d7898e 100644
--- a/src/utils/internal.ts
+++ b/src/utils/internal.ts
@@ -13,8 +13,8 @@
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
-import type { DependencyInfoArg, DependencyInfoCollectionArg, DependencyItem, DependencyItemWithInfo } from "../types";
-import type { ClassOrInstance, Collection, Constructor, Nilable, Nullable } from "../types/internal";
+import type { DependencyInfoArg, DependencyInfoCollectionArg, DependencyItem, DependencyItemWithInfo, IStackInfo } from "../types";
+import type { ClassOrInstance, Collection, Constructor, IAddDependencyItemOptions, Nilable, Nullable } from "../types/internal";
export function createDependsOnHelpers(
infoOrResolver: DependencyInfoArg,
@@ -39,12 +39,18 @@ export function createDependsOnHelpers(
} :
getDependencies;
- const addItem = (item: DependencyItem) => {
+ const addItem = (options: IAddDependencyItemOptions) => {
+ const {
+ existsIn,
+ item
+ } = options;
+
const deps = getDepsCollection();
const itemToAdd: DependencyItemWithInfo = {
...item,
+ existsIn,
"info": getInfo(item)
};
@@ -93,3 +99,33 @@ export function isConstructor(classOrInstance: ClassOrInsta
export function isNil(val: unknown): val is (null | undefined) {
return typeof val === "undefined" || val === null;
}
+
+export function tryGetStackInfo(): Nullable {
+ try {
+ const stackTrace = new Error().stack;
+
+ if (stackTrace) {
+ const stackTraceLines = stackTrace.split("\n");
+ const callerLine = stackTraceLines[2];
+ if (callerLine) {
+ const fileAndLineRegex = /\(?([^\s]+):(\d+):\d+\)?$/i;
+ const match = fileAndLineRegex.exec(callerLine);
+
+ if (match && match.length > 2) {
+ const file = match[1].trim();
+ const line = parseInt(match[2].trim() || "");
+
+ return {
+ "file": file || null,
+ "line": Number.isNaN(line) ? null : line
+ };
+ }
+ }
+ }
+
+ return null;
+ }
+ catch {
+ return false;
+ }
+}