diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 9c3b9ec8..bae3ae62 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -37,7 +37,7 @@ jobs: packages: "@nanoforge-dev/asset-manager,@nanoforge-dev/common,@nanoforge-dev/config,@nanoforge-dev/core,@nanoforge-dev/core-editor,@nanoforge-dev/ecs-client,@nanoforge-dev/ecs-lib,@nanoforge-dev/ecs-server,@nanoforge-dev/graphics-2d,@nanoforge-dev/input,@nanoforge-dev/music,@nanoforge-dev/network-client,@nanoforge-dev/network-server,@nanoforge-dev/sound" version: ${{ inputs.version }} branch-format: "releases/nanoforge@{version}" - commit-format: "chore: release nanoforge@{version}" + commit-format: "chore: release @nanoforge-dev/engine@{version}" dry: ${{ inputs.dry_run }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 964c1c2c..a86f6ca6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,3 +94,4 @@ jobs: repository: engine category: engine references: true + references-path: docs/references diff --git a/.idea/[NanoForge] Engine.iml b/.idea/[NanoForge] Engine.iml index 85b6fa8e..fc5ad77e 100644 --- a/.idea/[NanoForge] Engine.iml +++ b/.idea/[NanoForge] Engine.iml @@ -10,6 +10,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 38e317fb..68591eef 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,8 @@

Tests status - Documentation status Last commit - Contributors + Contributors

diff --git a/docs.json b/docs.json index 4edae43e..e69de29b 100644 --- a/docs.json +++ b/docs.json @@ -1,405 +0,0 @@ -{ - "documentation": { - "group": "Engine", - "pages": [ - "docs/engine/api/asset-manager/asset-manager/AssetManagerLibrary/getAsset", - "docs/engine/api/asset-manager/asset-manager/AssetManagerLibrary/__init", - "docs/engine/api/asset-manager/asset-manager/AssetManagerLibrary/__name", - "docs/engine/api/asset-manager/asset-manager/AssetManagerLibrary", - "docs/engine/api/asset-manager/asset-manager", - "docs/engine/api/asset-manager/index", - "docs/engine/api/common/common/ApplicationContext/_delta", - "docs/engine/api/common/common/ApplicationContext/delta", - "docs/engine/api/common/common/ApplicationContext/isRunning", - "docs/engine/api/common/common/ApplicationContext/muteSoundLibraries", - "docs/engine/api/common/common/ApplicationContext/setIsRunning", - "docs/engine/api/common/common/ApplicationContext", - "docs/engine/api/common/common/ASSET_MANAGER_LIBRARY", - "docs/engine/api/common/common/BaseAssetManagerLibrary/getAsset", - "docs/engine/api/common/common/BaseAssetManagerLibrary/__init", - "docs/engine/api/common/common/BaseAssetManagerLibrary", - "docs/engine/api/common/common/BaseComponentSystemLibrary/__run", - "docs/engine/api/common/common/BaseComponentSystemLibrary", - "docs/engine/api/common/common/BaseGraphicsLibrary/__run", - "docs/engine/api/common/common/BaseGraphicsLibrary", - "docs/engine/api/common/common/BaseInputLibrary", - "docs/engine/api/common/common/BaseMusicLibrary/__init", - "docs/engine/api/common/common/BaseMusicLibrary/mute", - "docs/engine/api/common/common/BaseMusicLibrary/play", - "docs/engine/api/common/common/BaseMusicLibrary", - "docs/engine/api/common/common/BaseNetworkLibrary", - "docs/engine/api/common/common/BaseSoundLibrary/__init", - "docs/engine/api/common/common/BaseSoundLibrary/mute", - "docs/engine/api/common/common/BaseSoundLibrary/play", - "docs/engine/api/common/common/BaseSoundLibrary", - "docs/engine/api/common/common/ClearContext", - "docs/engine/api/common/common/ClientLibraryManager/constructor", - "docs/engine/api/common/common/ClientLibraryManager/getAssetManager", - "docs/engine/api/common/common/ClientLibraryManager/getComponentSystem", - "docs/engine/api/common/common/ClientLibraryManager/getGraphics", - "docs/engine/api/common/common/ClientLibraryManager/getInput", - "docs/engine/api/common/common/ClientLibraryManager/get", - "docs/engine/api/common/common/ClientLibraryManager/getMusic", - "docs/engine/api/common/common/ClientLibraryManager/getNetwork", - "docs/engine/api/common/common/ClientLibraryManager/getSound", - "docs/engine/api/common/common/ClientLibraryManager", - "docs/engine/api/common/common/COMPONENT_SYSTEM_LIBRARY", - "docs/engine/api/common/common/Context/app", - "docs/engine/api/common/common/Context/constructor", - "docs/engine/api/common/common/Context/libs", - "docs/engine/api/common/common/Context", - "docs/engine/api/common/common/DefaultLibrariesEnum", - "docs/engine/api/common/common/ExecutionContext", - "docs/engine/api/common/common/GRAPHICS_LIBRARY", - "docs/engine/api/common/common/IAssetManagerLibrary/getAsset", - "docs/engine/api/common/common/IAssetManagerLibrary", - "docs/engine/api/common/common/IComponentSystemLibrary", - "docs/engine/api/common/common/IConfigRegistry/registerConfig", - "docs/engine/api/common/common/IConfigRegistry", - "docs/engine/api/common/common/IExposedLibrary", - "docs/engine/api/common/common/IGraphicsLibrary", - "docs/engine/api/common/common/IInputLibrary", - "docs/engine/api/common/common/ILibrary/__clear", - "docs/engine/api/common/common/ILibrary/__init", - "docs/engine/api/common/common/ILibrary/__name", - "docs/engine/api/common/common/ILibrary/__relationship", - "docs/engine/api/common/common/ILibrary", - "docs/engine/api/common/common/IMusicLibrary", - "docs/engine/api/common/common/IMutableLibrary/mute", - "docs/engine/api/common/common/IMutableLibrary", - "docs/engine/api/common/common/INetworkLibrary", - "docs/engine/api/common/common/InitContext/config", - "docs/engine/api/common/common/InitContext/constructor", - "docs/engine/api/common/common/InitContext/container", - "docs/engine/api/common/common/InitContext/env", - "docs/engine/api/common/common/InitContext/files", - "docs/engine/api/common/common/InitContext", - "docs/engine/api/common/common/INPUT_LIBRARY", - "docs/engine/api/common/common/IRunClientOptions/container", - "docs/engine/api/common/common/IRunClientOptions/env", - "docs/engine/api/common/common/IRunClientOptions/files", - "docs/engine/api/common/common/IRunClientOptions", - "docs/engine/api/common/common/IRunnerLibrary/__run", - "docs/engine/api/common/common/IRunnerLibrary", - "docs/engine/api/common/common/IRunOptions", - "docs/engine/api/common/common/IRunServerOptions/env", - "docs/engine/api/common/common/IRunServerOptions/files", - "docs/engine/api/common/common/IRunServerOptions", - "docs/engine/api/common/common/ISoundLibrary", - "docs/engine/api/common/common/LibraryContext/_status", - "docs/engine/api/common/common/LibraryContext/status", - "docs/engine/api/common/common/LibraryContext", - "docs/engine/api/common/common/LibraryHandle/constructor", - "docs/engine/api/common/common/LibraryHandle/context", - "docs/engine/api/common/common/LibraryHandle/library", - "docs/engine/api/common/common/LibraryHandle/symbol", - "docs/engine/api/common/common/LibraryHandle", - "docs/engine/api/common/common/LibraryManager/constructor", - "docs/engine/api/common/common/LibraryManager/getAssetManager", - "docs/engine/api/common/common/LibraryManager/getComponentSystem", - "docs/engine/api/common/common/LibraryManager/getGraphics", - "docs/engine/api/common/common/LibraryManager/getInput", - "docs/engine/api/common/common/LibraryManager/getMusic", - "docs/engine/api/common/common/LibraryManager/getNetwork", - "docs/engine/api/common/common/LibraryManager/getSound", - "docs/engine/api/common/common/LibraryManager", - "docs/engine/api/common/common/LibraryStatusEnum", - "docs/engine/api/common/common/MUSIC_LIBRARY", - "docs/engine/api/common/common/NETWORK_LIBRARY", - "docs/engine/api/common/common/NfConfigException/code", - "docs/engine/api/common/common/NfConfigException/constructor", - "docs/engine/api/common/common/NfConfigException", - "docs/engine/api/common/common/NfFetchException/code", - "docs/engine/api/common/common/NfFetchException/constructor", - "docs/engine/api/common/common/NfFetchException", - "docs/engine/api/common/common/NfFile/arrayBuffer", - "docs/engine/api/common/common/NfFile/blob", - "docs/engine/api/common/common/NfFile/bytes", - "docs/engine/api/common/common/NfFile/constructor", - "docs/engine/api/common/common/NfFile/formData", - "docs/engine/api/common/common/NfFile/json", - "docs/engine/api/common/common/NfFile/path", - "docs/engine/api/common/common/NfFile/text", - "docs/engine/api/common/common/NfFile", - "docs/engine/api/common/common/NfNotFound/code", - "docs/engine/api/common/common/NfNotFound/constructor", - "docs/engine/api/common/common/NfNotFound", - "docs/engine/api/common/common/NfNotInitializedException/code", - "docs/engine/api/common/common/NfNotInitializedException/constructor", - "docs/engine/api/common/common/NfNotInitializedException", - "docs/engine/api/common/common/SOUND_LIBRARY", - "docs/engine/api/common/common", - "docs/engine/api/common/index", - "docs/engine/api/config/config/Default", - "docs/engine/api/config/config/IsIpOrFQDN", - "docs/engine/api/config/config/TransformToBoolean", - "docs/engine/api/config/config", - "docs/engine/api/config/index", - "docs/engine/api/core/core/NanoforgeClient/useGraphics", - "docs/engine/api/core/core/NanoforgeClient/useInput", - "docs/engine/api/core/core/NanoforgeClient/useSound", - "docs/engine/api/core/core/NanoforgeClient", - "docs/engine/api/core/core/NanoforgeFactory", - "docs/engine/api/core/core/NanoforgeServer", - "docs/engine/api/core/core", - "docs/engine/api/core/index", - "docs/engine/api/core-editor/core-editor/NanoforgeClient/useGraphics", - "docs/engine/api/core-editor/core-editor/NanoforgeClient/useInput", - "docs/engine/api/core-editor/core-editor/NanoforgeClient/useSound", - "docs/engine/api/core-editor/core-editor/NanoforgeClient", - "docs/engine/api/core-editor/core-editor/NanoforgeFactory", - "docs/engine/api/core-editor/core-editor/NanoforgeServer", - "docs/engine/api/core-editor/core-editor", - "docs/engine/api/core-editor/index", - "docs/engine/api/ecs-client/ecs-client/ECSClientLibrary/constructor", - "docs/engine/api/ecs-client/ecs-client/ECSClientLibrary/__init", - "docs/engine/api/ecs-client/ecs-client/ECSClientLibrary/__name", - "docs/engine/api/ecs-client/ecs-client/ECSClientLibrary", - "docs/engine/api/ecs-client/ecs-client", - "docs/engine/api/ecs-client/index", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary/constructor", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary/module", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary/__name", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary/path", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary/_registry", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary/registry", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary/__run", - "docs/engine/api/ecs-lib/ecs-lib/AbstractECSLibrary", - "docs/engine/api/ecs-lib/ecs-lib/Component", - "docs/engine/api/ecs-lib/ecs-lib/EditorComponentManifest", - "docs/engine/api/ecs-lib/ecs-lib/EditorSystemManifest", - "docs/engine/api/ecs-lib/ecs-lib/Entity/getId", - "docs/engine/api/ecs-lib/ecs-lib/Entity", - "docs/engine/api/ecs-lib/ecs-lib/Registry/addComponent", - "docs/engine/api/ecs-lib/ecs-lib/Registry/addSystem", - "docs/engine/api/ecs-lib/ecs-lib/Registry/clearEntities", - "docs/engine/api/ecs-lib/ecs-lib/Registry/clearSystems", - "docs/engine/api/ecs-lib/ecs-lib/Registry/entityFromIndex", - "docs/engine/api/ecs-lib/ecs-lib/Registry/getComponentsConst", - "docs/engine/api/ecs-lib/ecs-lib/Registry/getComponents", - "docs/engine/api/ecs-lib/ecs-lib/Registry/getEntityComponentConst", - "docs/engine/api/ecs-lib/ecs-lib/Registry/getEntityComponent", - "docs/engine/api/ecs-lib/ecs-lib/Registry/getZipper", - "docs/engine/api/ecs-lib/ecs-lib/Registry/killEntity", - "docs/engine/api/ecs-lib/ecs-lib/Registry/maxEntities", - "docs/engine/api/ecs-lib/ecs-lib/Registry/registerComponent", - "docs/engine/api/ecs-lib/ecs-lib/Registry/removeComponent", - "docs/engine/api/ecs-lib/ecs-lib/Registry/removeSystem", - "docs/engine/api/ecs-lib/ecs-lib/Registry/runSystems", - "docs/engine/api/ecs-lib/ecs-lib/Registry/spawnEntity", - "docs/engine/api/ecs-lib/ecs-lib/Registry", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/clear", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/empty", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/erase", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/getConst", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/getIndex", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/get", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/insertAt_1", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/insertAt", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/resize", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/setByCopy", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/setByMove", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/set", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray/size", - "docs/engine/api/ecs-lib/ecs-lib/SparseArray", - "docs/engine/api/ecs-lib/ecs-lib/System", - "docs/engine/api/ecs-lib/ecs-lib", - "docs/engine/api/ecs-lib/index", - "docs/engine/api/ecs-server/ecs-server/ECSServerLibrary/constructor", - "docs/engine/api/ecs-server/ecs-server/ECSServerLibrary/__init", - "docs/engine/api/ecs-server/ecs-server/ECSServerLibrary/__name", - "docs/engine/api/ecs-server/ecs-server/ECSServerLibrary", - "docs/engine/api/ecs-server/ecs-server/Module", - "docs/engine/api/ecs-server/ecs-server", - "docs/engine/api/ecs-server/index", - "docs/engine/api/graphics-2d/graphics-2d/angleDeg", - "docs/engine/api/graphics-2d/graphics-2d/Animation_2", - "docs/engine/api/graphics-2d/graphics-2d/ArcConfig", - "docs/engine/api/graphics-2d/graphics-2d/Arc", - "docs/engine/api/graphics-2d/graphics-2d/ArrowConfig", - "docs/engine/api/graphics-2d/graphics-2d/Arrow", - "docs/engine/api/graphics-2d/graphics-2d/autoDrawEnabled", - "docs/engine/api/graphics-2d/graphics-2d/Canvas", - "docs/engine/api/graphics-2d/graphics-2d/capturePointerEventsEnabled", - "docs/engine/api/graphics-2d/graphics-2d/CircleConfig", - "docs/engine/api/graphics-2d/graphics-2d/Circle", - "docs/engine/api/graphics-2d/graphics-2d/ContainerConfig", - "docs/engine/api/graphics-2d/graphics-2d/Container", - "docs/engine/api/graphics-2d/graphics-2d/Context", - "docs/engine/api/graphics-2d/graphics-2d/dblClickWindow", - "docs/engine/api/graphics-2d/graphics-2d/DD", - "docs/engine/api/graphics-2d/graphics-2d/document_2", - "docs/engine/api/graphics-2d/graphics-2d/dragButtons", - "docs/engine/api/graphics-2d/graphics-2d/dragDistance", - "docs/engine/api/graphics-2d/graphics-2d/Easings", - "docs/engine/api/graphics-2d/graphics-2d/EllipseConfig", - "docs/engine/api/graphics-2d/graphics-2d/Ellipse", - "docs/engine/api/graphics-2d/graphics-2d/enableTrace", - "docs/engine/api/graphics-2d/graphics-2d/FastLayer", - "docs/engine/api/graphics-2d/graphics-2d/Filters", - "docs/engine/api/graphics-2d/graphics-2d/getAngle", - "docs/engine/api/graphics-2d/graphics-2d/_global", - "docs/engine/api/graphics-2d/graphics-2d/Graphics2DLibrary/baseLayer", - "docs/engine/api/graphics-2d/graphics-2d/Graphics2DLibrary/__init", - "docs/engine/api/graphics-2d/graphics-2d/Graphics2DLibrary/__name", - "docs/engine/api/graphics-2d/graphics-2d/Graphics2DLibrary/__run", - "docs/engine/api/graphics-2d/graphics-2d/Graphics2DLibrary/stage", - "docs/engine/api/graphics-2d/graphics-2d/Graphics2DLibrary", - "docs/engine/api/graphics-2d/graphics-2d/GroupConfig", - "docs/engine/api/graphics-2d/graphics-2d/Group", - "docs/engine/api/graphics-2d/graphics-2d/hitOnDragEnabled", - "docs/engine/api/graphics-2d/graphics-2d/Image_2", - "docs/engine/api/graphics-2d/graphics-2d/ImageConfig", - "docs/engine/api/graphics-2d/graphics-2d/_injectGlobal", - "docs/engine/api/graphics-2d/graphics-2d/isBrowser", - "docs/engine/api/graphics-2d/graphics-2d/isDragging", - "docs/engine/api/graphics-2d/graphics-2d/isDragReady", - "docs/engine/api/graphics-2d/graphics-2d/isTransforming", - "docs/engine/api/graphics-2d/graphics-2d/isUnminified", - "docs/engine/api/graphics-2d/graphics-2d/KonvaEventListener", - "docs/engine/api/graphics-2d/graphics-2d/KonvaEventObject", - "docs/engine/api/graphics-2d/graphics-2d/KonvaPointerEvent", - "docs/engine/api/graphics-2d/graphics-2d/LabelConfig", - "docs/engine/api/graphics-2d/graphics-2d/Label", - "docs/engine/api/graphics-2d/graphics-2d/LayerConfig", - "docs/engine/api/graphics-2d/graphics-2d/Layer", - "docs/engine/api/graphics-2d/graphics-2d/legacyTextRendering", - "docs/engine/api/graphics-2d/graphics-2d/LineConfig", - "docs/engine/api/graphics-2d/graphics-2d/Line", - "docs/engine/api/graphics-2d/graphics-2d/_mouseDblClickPointerId", - "docs/engine/api/graphics-2d/graphics-2d/_mouseInDblClickWindow", - "docs/engine/api/graphics-2d/graphics-2d/_mouseListenClick", - "docs/engine/api/graphics-2d/graphics-2d/Node_2", - "docs/engine/api/graphics-2d/graphics-2d/NodeConfig", - "docs/engine/api/graphics-2d/graphics-2d/PathConfig", - "docs/engine/api/graphics-2d/graphics-2d/Path", - "docs/engine/api/graphics-2d/graphics-2d/pixelRatio", - "docs/engine/api/graphics-2d/graphics-2d/_pointerDblClickPointerId", - "docs/engine/api/graphics-2d/graphics-2d/pointerEventsEnabled", - "docs/engine/api/graphics-2d/graphics-2d/_pointerInDblClickWindow", - "docs/engine/api/graphics-2d/graphics-2d/_pointerListenClick", - "docs/engine/api/graphics-2d/graphics-2d/RectConfig", - "docs/engine/api/graphics-2d/graphics-2d/Rect", - "docs/engine/api/graphics-2d/graphics-2d/RegularPolygonConfig", - "docs/engine/api/graphics-2d/graphics-2d/RegularPolygon", - "docs/engine/api/graphics-2d/graphics-2d/releaseCanvasOnDestroy", - "docs/engine/api/graphics-2d/graphics-2d/_renderBackend", - "docs/engine/api/graphics-2d/graphics-2d/RingConfig", - "docs/engine/api/graphics-2d/graphics-2d/Ring", - "docs/engine/api/graphics-2d/graphics-2d/ShapeConfig", - "docs/engine/api/graphics-2d/graphics-2d/Shape", - "docs/engine/api/graphics-2d/graphics-2d/shapes", - "docs/engine/api/graphics-2d/graphics-2d/showWarnings", - "docs/engine/api/graphics-2d/graphics-2d/SpriteConfig", - "docs/engine/api/graphics-2d/graphics-2d/Sprite", - "docs/engine/api/graphics-2d/graphics-2d/StageConfig", - "docs/engine/api/graphics-2d/graphics-2d/Stage", - "docs/engine/api/graphics-2d/graphics-2d/stages", - "docs/engine/api/graphics-2d/graphics-2d/StarConfig", - "docs/engine/api/graphics-2d/graphics-2d/Star", - "docs/engine/api/graphics-2d/graphics-2d/TagConfig", - "docs/engine/api/graphics-2d/graphics-2d/Tag", - "docs/engine/api/graphics-2d/graphics-2d/Text_2", - "docs/engine/api/graphics-2d/graphics-2d/TextConfig", - "docs/engine/api/graphics-2d/graphics-2d/TextPathConfig", - "docs/engine/api/graphics-2d/graphics-2d/TextPath", - "docs/engine/api/graphics-2d/graphics-2d/_touchDblClickPointerId", - "docs/engine/api/graphics-2d/graphics-2d/_touchInDblClickWindow", - "docs/engine/api/graphics-2d/graphics-2d/_touchListenClick", - "docs/engine/api/graphics-2d/graphics-2d/Transformer_2", - "docs/engine/api/graphics-2d/graphics-2d/TransformerConfig", - "docs/engine/api/graphics-2d/graphics-2d/Transform", - "docs/engine/api/graphics-2d/graphics-2d/TweenConfig", - "docs/engine/api/graphics-2d/graphics-2d/Tween", - "docs/engine/api/graphics-2d/graphics-2d/Util", - "docs/engine/api/graphics-2d/graphics-2d/Vector2d", - "docs/engine/api/graphics-2d/graphics-2d/version", - "docs/engine/api/graphics-2d/graphics-2d/WedgeConfig", - "docs/engine/api/graphics-2d/graphics-2d/Wedge", - "docs/engine/api/graphics-2d/graphics-2d", - "docs/engine/api/graphics-2d/index", - "docs/engine/api/input/index", - "docs/engine/api/input/input/InputEnum", - "docs/engine/api/input/input/InputLibrary/constructor", - "docs/engine/api/input/input/InputLibrary/getDragState", - "docs/engine/api/input/input/InputLibrary/getMousePosition", - "docs/engine/api/input/input/InputLibrary/getMouseState", - "docs/engine/api/input/input/InputLibrary/getPressedKeys", - "docs/engine/api/input/input/InputLibrary/getWheelState", - "docs/engine/api/input/input/InputLibrary/__init", - "docs/engine/api/input/input/InputLibrary/isDragging", - "docs/engine/api/input/input/InputLibrary/isKeyPressed", - "docs/engine/api/input/input/InputLibrary/__name", - "docs/engine/api/input/input/InputLibrary/__run", - "docs/engine/api/input/input/InputLibrary", - "docs/engine/api/input/input", - "docs/engine/api/music/index", - "docs/engine/api/music/music/MusicLibrary/__init", - "docs/engine/api/music/music/MusicLibrary/load", - "docs/engine/api/music/music/MusicLibrary/mute", - "docs/engine/api/music/music/MusicLibrary/__name", - "docs/engine/api/music/music/MusicLibrary/play", - "docs/engine/api/music/music/MusicLibrary", - "docs/engine/api/music/music", - "docs/engine/api/network-client/index", - "docs/engine/api/network-client/network-client/NetworkClientLibrary/__init", - "docs/engine/api/network-client/network-client/NetworkClientLibrary/__name", - "docs/engine/api/network-client/network-client/NetworkClientLibrary/tcp", - "docs/engine/api/network-client/network-client/NetworkClientLibrary/udp", - "docs/engine/api/network-client/network-client/NetworkClientLibrary", - "docs/engine/api/network-client/network-client/TCPClient/connect", - "docs/engine/api/network-client/network-client/TCPClient/constructor", - "docs/engine/api/network-client/network-client/TCPClient/getReceivedPackets", - "docs/engine/api/network-client/network-client/TCPClient/isConnected", - "docs/engine/api/network-client/network-client/TCPClient/sendData", - "docs/engine/api/network-client/network-client/TCPClient", - "docs/engine/api/network-client/network-client/UDPClient/connect", - "docs/engine/api/network-client/network-client/UDPClient/constructor", - "docs/engine/api/network-client/network-client/UDPClient/getReceivedPackets", - "docs/engine/api/network-client/network-client/UDPClient/isConnected", - "docs/engine/api/network-client/network-client/UDPClient/sendData", - "docs/engine/api/network-client/network-client/UDPClient", - "docs/engine/api/network-client/network-client", - "docs/engine/api/network-server/index", - "docs/engine/api/network-server/network-server/NetworkServerLibrary/__init", - "docs/engine/api/network-server/network-server/NetworkServerLibrary/__name", - "docs/engine/api/network-server/network-server/NetworkServerLibrary/tcp", - "docs/engine/api/network-server/network-server/NetworkServerLibrary/udp", - "docs/engine/api/network-server/network-server/NetworkServerLibrary", - "docs/engine/api/network-server/network-server/TCPServer/constructor", - "docs/engine/api/network-server/network-server/TCPServer/getConnectedClients", - "docs/engine/api/network-server/network-server/TCPServer/getReceivedPackets", - "docs/engine/api/network-server/network-server/TCPServer/listen", - "docs/engine/api/network-server/network-server/TCPServer/sendToClient", - "docs/engine/api/network-server/network-server/TCPServer/sendToEverybody", - "docs/engine/api/network-server/network-server/TCPServer", - "docs/engine/api/network-server/network-server/UDPServer/constructor", - "docs/engine/api/network-server/network-server/UDPServer/getConnectedClients", - "docs/engine/api/network-server/network-server/UDPServer/getReceivedPackets", - "docs/engine/api/network-server/network-server/UDPServer/listen", - "docs/engine/api/network-server/network-server/UDPServer/sendToClient", - "docs/engine/api/network-server/network-server/UDPServer/sendToEverybody", - "docs/engine/api/network-server/network-server/UDPServer", - "docs/engine/api/network-server/network-server", - "docs/engine/api/sound/index", - "docs/engine/api/sound/sound/SoundLibrary/__init", - "docs/engine/api/sound/sound/SoundLibrary/load", - "docs/engine/api/sound/sound/SoundLibrary/mute", - "docs/engine/api/sound/sound/SoundLibrary/__name", - "docs/engine/api/sound/sound/SoundLibrary/play", - "docs/engine/api/sound/sound/SoundLibrary", - "docs/engine/api/sound/sound", - "docs/engine/documentation", - "docs/engine/how_to_use", - "docs/engine/index", - "docs/engine/network/index", - "docs/engine/network/network-client-api", - "docs/engine/network/network-client", - "docs/engine/network/network-server-api", - "docs/engine/network/network-server", - "docs/engine/network/packet-framing", - "docs/engine/registry/index", - "docs/engine/registry/writing_web_assembly" - ] - } -} diff --git a/docs/templates/class.liquid b/docs/templates/class.liquid new file mode 100644 index 00000000..6dae92ac --- /dev/null +++ b/docs/templates/class.liquid @@ -0,0 +1,109 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if constructors and constructors.size > 0 %} + +## Constructors + +{%- for constructor in constructors %} + +### {{ constructor.title }} + +{%- if constructor.modifiers and constructor.modifiers.size > 0 %} +**Modifiers**: {{ constructor.modifiers | join: ', ' }} +{%- endif %} +{%- if constructor.description %} + +{{ constructor.description }} +{%- endif %} +{%- endfor %} +{%- endif %} + +{%- if properties and properties.size > 0 %} + +## Properties + +{%- for property in properties %} + +### {{ property.title }} + +{%- if property.modifiers and property.modifiers.size > 0 %} +**Modifiers**: {{ property.modifiers | join: ', ' }} +{%- endif %} +{%- if property.type %} +{%- assign formatted_prop_type = property.type | format_type %} +{%- if formatted_prop_type contains "```" %} +**Type**:{{ formatted_prop_type }} +{%- else %} +**Type**: {%- if property.typeRef and autolink != false %}`{{ formatted_prop_type }}`{%- elsif property.typePath %}[`{{ formatted_prop_type }}`]({{ property.typePath }}){%- else %}`{{ formatted_prop_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if property.isOptional %} +**Optional**: Yes +{%- endif %} +{%- if property.isInherited %} +**Inherited**: Yes +{%- endif %} +{%- if property.defaultValue and property.defaultValue.size > 0 %} +**Default**: `{{ property.defaultValue }}` +{%- endif %} +{%- if property.description %} + +{{ property.description }} +{%- endif %} +{%- endfor %} +{%- endif %} + +{%- if methods and methods.size > 0 %} + +## Methods + +{%- for method in methods %} + +### {{ method.title }} + +{%- if method.modifiers and method.modifiers.size > 0 %} +**Modifiers**: {{ method.modifiers | join: ', ' }} +{%- endif %} +{%- if method.isInherited %} +**Inherited**: Yes +{%- endif %} +{%- if method.description %} + +{{ method.description }} +{%- endif %} +{%- endfor %} +{%- endif %} + +{%- if events and events.size > 0 %} + +## Events + +{%- for event in events %} + +### {{ event.title }} + +{%- if event.type %} +{%- assign formatted_event_type = event.type | format_type %} +{%- if formatted_event_type contains "```" %} +**Type**:{{ formatted_event_type }} +{%- else %} +**Type**: {%- if event.typeRef and autolink != false %}`{{ formatted_event_type }}`{%- elsif event.typePath %}[`{{ formatted_event_type }}`]({{ event.typePath }}){%- else %}`{{ formatted_event_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if event.description %} + +{{ event.description }} +{%- endif %} +{%- endfor %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/constructor.liquid b/docs/templates/constructor.liquid new file mode 100644 index 00000000..5ef2b43a --- /dev/null +++ b/docs/templates/constructor.liquid @@ -0,0 +1,41 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if parameters and parameters.size > 0 %} + +## Parameters + +{%- for parameter in parameters %} + +### {{ parameter.title }} + +{%- if parameter.type %} +{%- assign formatted_param_type = parameter.type | format_type %} +{%- if formatted_param_type contains "```" %} +- **Type**:{{ formatted_param_type }} +{%- else %} +- **Type**: {%- if parameter.typeRef and autolink != false %}`{{ formatted_param_type }}`{%- elsif parameter.typePath -%}[`{{ formatted_param_type }}`]({{ parameter.typePath }}){%- else -%}`{{ formatted_param_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if parameter.isOptional %} +- **Optional**: Yes +{%- endif %} +{%- if parameter.defaultValue %} +- **Default**: `{{ parameter.defaultValue }}` +{%- endif %} +{%- if parameter.description %} + +{{ parameter.description }} +{%- endif %} +{%- endfor %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/entry-point.liquid b/docs/templates/entry-point.liquid new file mode 100644 index 00000000..7a46890e --- /dev/null +++ b/docs/templates/entry-point.liquid @@ -0,0 +1,108 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if abstractClasses and abstractClasses.size > 0 %} +## Abstract Classes + +{%- for item in abstractClasses %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if classes and classes.size > 0 %} +## Classes + +{%- for item in classes %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if enumerations and enumerations.size > 0 %} +## Enumerations + +{%- for item in enumerations %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if functions and functions.size > 0 %} +## Functions + +{%- for item in functions %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if interfaces and interfaces.size > 0 %} +## Interfaces + +{%- for item in interfaces %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if namespaces and namespaces.size > 0 %} +## Namespaces + +{%- for item in namespaces %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if typeAliases and typeAliases.size > 0 %} +## Type Aliases + +{%- for item in typeAliases %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if variables and variables.size > 0 %} +## Variables + +{%- for item in variables %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/enum-member.liquid b/docs/templates/enum-member.liquid new file mode 100644 index 00000000..21947c4e --- /dev/null +++ b/docs/templates/enum-member.liquid @@ -0,0 +1,10 @@ +{%- layout "layout" %} + +{%- block content %} +{%- if apiItem.defaultValue %} + +## Value + +`{{ apiItem.defaultValue }}` +{%- endif %} +{%- endblock %} diff --git a/docs/templates/enum.liquid b/docs/templates/enum.liquid new file mode 100644 index 00000000..9a6e157d --- /dev/null +++ b/docs/templates/enum.liquid @@ -0,0 +1,27 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if members and members.size > 0 %} +{%- assign showValues = true %} +{%- if rendering and rendering.hideStringEnumValues == true %} +{%- assign showValues = false %} +{%- endif %} + +## Members + +{%- if showValues %} +| Member | Value | Description | +| ------ | ----- | ----------- | +{%- for member in members %} +| `{{ member.title }}` | `{{ member.defaultValue }}` | {{ member.description | default: "" }} | +{%- endfor %} +{%- else %} +| Member | Description | +| ------ | ----------- | +{%- for member in members %} +| `{{ member.title }}` | {{ member.description | default: "" }} | +{%- endfor %} +{%- endif %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/function.liquid b/docs/templates/function.liquid new file mode 100644 index 00000000..abdea231 --- /dev/null +++ b/docs/templates/function.liquid @@ -0,0 +1,67 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if parameters and parameters.size > 0 or returnType %} + +## Parameters + +{%- if parameters and parameters.size > 0 %} +{%- for parameter in parameters %} + +### {{ parameter.title }} + +{%- if parameter.type %} +{%- assign formatted_param_type = parameter.type | format_type %} +{%- if formatted_param_type contains "```" %} +**Type**:{{ formatted_param_type }} +{%- else %} +**Type**: {%- if parameter.typeRef and autolink != false %}`{{ formatted_param_type }}`{%- elsif parameter.typePath -%}[`{{ formatted_param_type }}`]({{ parameter.typePath }}){%- else -%}`{{ formatted_param_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if parameter.isOptional %} +**Optional**: Yes +{%- endif %} +{%- if parameter.defaultValue %} +**Default**: `{{ parameter.defaultValue }}` +{%- endif %} +{%- if parameter.description %} + +{{ parameter.description }} +{%- endif %} +{%- endfor %} +{%- else %} + +*No parameters.* +{%- endif %} + +## Returns + +{%- if returnType and returnType.type %} +{%- assign formatted_return_type = returnType.type | format_type %} +{%- if formatted_return_type contains "```" %} + +**Type**:{{ formatted_return_type }} +{%- else %} + +**Type**: {%- if returnType.typeRef and autolink != false %}`{{ formatted_return_type }}`{%- elsif returnType.typePath -%}[`{{ formatted_return_type }}`]({{ returnType.typePath }}){%- else -%}`{{ formatted_return_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if returnType and returnType.description %} + +{{ returnType.description }} +{%- endif %} +{%- if not returnType or not returnType.type %} + +`void` +{%- endif %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/generic.liquid b/docs/templates/generic.liquid new file mode 100644 index 00000000..dacb8c60 --- /dev/null +++ b/docs/templates/generic.liquid @@ -0,0 +1,10 @@ +{%- layout "layout" %} + +{%- block content %} +{%- if apiItem.description %} + +## Description + +{{ apiItem.description }} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/interface.liquid b/docs/templates/interface.liquid new file mode 100644 index 00000000..0fd244a0 --- /dev/null +++ b/docs/templates/interface.liquid @@ -0,0 +1,88 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if properties and properties.size > 0 %} + +## Properties + +{%- for property in properties %} + +### {{ property.title }} + +{%- if property.modifiers and property.modifiers.size > 0 %} +**Modifiers**: {{ property.modifiers | join: ', ' }} +{%- endif %} +{%- if property.type %} +{%- assign formatted_prop_type = property.type | format_type %} +{%- if formatted_prop_type contains "```" %} +**Type**:{{ formatted_prop_type }} +{%- else %} +**Type**: {%- if property.typeRef and autolink != false %}`{{ formatted_prop_type }}`{%- elsif property.typePath %}[`{{ formatted_prop_type }}`]({{ property.typePath }}){%- else %}`{{ formatted_prop_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if property.isOptional %} +**Optional**: Yes +{%- endif %} +{%- if property.isInherited %} +**Inherited**: Yes +{%- endif %} +{%- if property.description %} + +{{ property.description }} +{%- endif %} +{%- endfor %} +{%- endif %} + +{%- if methods and methods.size > 0 %} + +## Methods + +{%- for method in methods %} + +### {{ method.title }} + +{%- if method.modifiers and method.modifiers.size > 0 %} +**Modifiers**: {{ method.modifiers | join: ', ' }} +{%- endif %} +{%- if method.isInherited %} +**Inherited**: Yes +{%- endif %} +{%- if method.description %} + +{{ method.description }} +{%- endif %} +{%- endfor %} +{%- endif %} + +{%- if events and events.size > 0 %} + +## Events + +{%- for event in events %} + +### {{ event.title }} + +{%- if event.type %} +{%- assign formatted_event_type = event.type | format_type %} +{%- if formatted_event_type contains "```" %} +**Type**:{{ formatted_event_type }} +{%- else %} +**Type**: {%- if event.typeRef and autolink != false %}`{{ formatted_event_type }}`{%- elsif event.typePath %}[`{{ formatted_event_type }}`]({{ event.typePath }}){%- else %}`{{ formatted_event_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if event.description %} + +{{ event.description }} +{%- endif %} +{%- endfor %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/layout.liquid b/docs/templates/layout.liquid new file mode 100644 index 00000000..5db2f048 --- /dev/null +++ b/docs/templates/layout.liquid @@ -0,0 +1,95 @@ +--- +title: "{{ page.title }}" +{%- if page.icon %} +icon: "{{ page.icon }}" +{%- endif %} +description: "{{ page.description }}" +--- + +import { PageLink } from '/snippets/tsdocs/PageLink.jsx'; +import { RefLink } from '/snippets/tsdocs/RefLink.jsx'; + +# {{ apiItem.displayName }} + +{%- block warnings %} +{%- if apiItem.isDeprecated %} + + + **Deprecated**: This {{ apiItem.kind | downcase }} is deprecated and may be removed in a future version. + +{%- endif %} +{%- if apiItem.isAlpha %} + + + **Alpha**: This {{ apiItem.kind | downcase }} is in alpha and may change without notice. + +{%- endif %} +{%- if apiItem.isBeta %} + + + **Beta**: This {{ apiItem.kind | downcase }} is in beta and may change without notice. + +{%- endif %} +{%- endblock %} + +{%- block summary %} +{%- if apiItem.summary and apiItem.summary.size > 0 %} + +## Summary + +{{ apiItem.summary | render_segments }} +{%- endif %} +{%- endblock %} + +{%- block heritage %} +{%- if heritageTypes and heritageTypes.size > 0 %} + +## Heritage + +{%- for type in heritageTypes %} +{%- if type.path %} +* [{{ type.name }}]({{ type.path }}) +{%- else %} +* {{ type.name }} +{%- endif %} +{%- endfor %} +{%- endif %} +{%- endblock %} + +{%- block content %}{% endblock %} + +{%- block remarks %} +{%- if apiItem.remarks and apiItem.remarks.size > 0 %} + +## Remarks + +{{ apiItem.remarks | render_segments }} +{%- endif %} +{%- endblock %} + +{%- block examples %} +{%- if examples and examples.size > 0 %} + +## Examples + +{%- for example in examples %} + +### Example {{ forloop.index }} + +```typescript +{{ example }} +``` +{%- endfor %} +{%- endif %} +{%- endblock %} + +{%- block guides %} +{%- if guides and guides.size > 0 %} + +## Related Documentation + +{%- for guide in guides %} +- {{ guide.description }} +{%- endfor %} +{%- endif %} +{%- endblock %} \ No newline at end of file diff --git a/docs/templates/method.liquid b/docs/templates/method.liquid new file mode 100644 index 00000000..abdea231 --- /dev/null +++ b/docs/templates/method.liquid @@ -0,0 +1,67 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if parameters and parameters.size > 0 or returnType %} + +## Parameters + +{%- if parameters and parameters.size > 0 %} +{%- for parameter in parameters %} + +### {{ parameter.title }} + +{%- if parameter.type %} +{%- assign formatted_param_type = parameter.type | format_type %} +{%- if formatted_param_type contains "```" %} +**Type**:{{ formatted_param_type }} +{%- else %} +**Type**: {%- if parameter.typeRef and autolink != false %}`{{ formatted_param_type }}`{%- elsif parameter.typePath -%}[`{{ formatted_param_type }}`]({{ parameter.typePath }}){%- else -%}`{{ formatted_param_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if parameter.isOptional %} +**Optional**: Yes +{%- endif %} +{%- if parameter.defaultValue %} +**Default**: `{{ parameter.defaultValue }}` +{%- endif %} +{%- if parameter.description %} + +{{ parameter.description }} +{%- endif %} +{%- endfor %} +{%- else %} + +*No parameters.* +{%- endif %} + +## Returns + +{%- if returnType and returnType.type %} +{%- assign formatted_return_type = returnType.type | format_type %} +{%- if formatted_return_type contains "```" %} + +**Type**:{{ formatted_return_type }} +{%- else %} + +**Type**: {%- if returnType.typeRef and autolink != false %}`{{ formatted_return_type }}`{%- elsif returnType.typePath -%}[`{{ formatted_return_type }}`]({{ returnType.typePath }}){%- else -%}`{{ formatted_return_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if returnType and returnType.description %} + +{{ returnType.description }} +{%- endif %} +{%- if not returnType or not returnType.type %} + +`void` +{%- endif %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/model.liquid b/docs/templates/model.liquid new file mode 100644 index 00000000..230abdb5 --- /dev/null +++ b/docs/templates/model.liquid @@ -0,0 +1,8 @@ +{%- layout "layout" %} + +{%- block content %} +{%- if apiItem.description %} + +{{ apiItem.description }} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/namespace.liquid b/docs/templates/namespace.liquid new file mode 100644 index 00000000..c8ab5888 --- /dev/null +++ b/docs/templates/namespace.liquid @@ -0,0 +1,116 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if abstractClasses and abstractClasses.size > 0 %} +## Abstract Classes + +{%- for item in abstractClasses %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if classes and classes.size > 0 %} +## Classes + +{%- for item in classes %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if enumerations and enumerations.size > 0 %} +## Enumerations + +{%- for item in enumerations %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if functions and functions.size > 0 %} +## Functions + +{%- for item in functions %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if interfaces and interfaces.size > 0 %} +## Interfaces + +{%- for item in interfaces %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if namespaces and namespaces.size > 0 %} +## Namespaces + +{%- for item in namespaces %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if typeAliases and typeAliases.size > 0 %} +## Type Aliases + +{%- for item in typeAliases %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if variables and variables.size > 0 %} +## Variables + +{%- for item in variables %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/package.liquid b/docs/templates/package.liquid new file mode 100644 index 00000000..7a46890e --- /dev/null +++ b/docs/templates/package.liquid @@ -0,0 +1,108 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if abstractClasses and abstractClasses.size > 0 %} +## Abstract Classes + +{%- for item in abstractClasses %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if classes and classes.size > 0 %} +## Classes + +{%- for item in classes %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if enumerations and enumerations.size > 0 %} +## Enumerations + +{%- for item in enumerations %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if functions and functions.size > 0 %} +## Functions + +{%- for item in functions %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if interfaces and interfaces.size > 0 %} +## Interfaces + +{%- for item in interfaces %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if namespaces and namespaces.size > 0 %} +## Namespaces + +{%- for item in namespaces %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if typeAliases and typeAliases.size > 0 %} +## Type Aliases + +{%- for item in typeAliases %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} + +{%- if variables and variables.size > 0 %} +## Variables + +{%- for item in variables %} +### [{{ item.title }}]({{ item.titlePath }}) + +{%- if item.description %} +{{ item.description }} +{%- endif %} + +{%- endfor %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/property.liquid b/docs/templates/property.liquid new file mode 100644 index 00000000..740bde27 --- /dev/null +++ b/docs/templates/property.liquid @@ -0,0 +1,23 @@ +{%- layout "layout" %} + +{%- block content %} +{%- if returnType %} + +## Type + +{%- if returnType.type %} +{%- assign formatted_type = returnType.type | format_type %} +{%- if formatted_type contains "```" %} + +**Type**:{{ formatted_type }} +{%- else %} + +**Type**: {%- if returnType.typePath -%}[`{{ formatted_type }}`]({{ returnType.typePath }}){%- else -%}`{{ formatted_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if returnType.description %} + +{{ returnType.description }} +{%- endif %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/type-alias.liquid b/docs/templates/type-alias.liquid new file mode 100644 index 00000000..1f1ed547 --- /dev/null +++ b/docs/templates/type-alias.liquid @@ -0,0 +1,41 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if parameters and parameters.size > 0 %} + +## Type Parameters + +{%- for parameter in parameters %} + +### {{ parameter.title }} + +{%- if parameter.type %} +{%- assign formatted_param_type = parameter.type | format_type %} +{%- if formatted_param_type contains "```" %} +**Type**:{{ formatted_param_type }} +{%- else %} +**Type**: {%- if parameter.typePath -%}[`{{ formatted_param_type }}`]({{ parameter.typePath }}){%- else -%}`{{ formatted_param_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if parameter.isOptional %} +**Optional**: Yes +{%- endif %} +{%- if parameter.defaultValue %} +**Default**: `{{ parameter.defaultValue }}` +{%- endif %} +{%- if parameter.description %} + +{{ parameter.description }} +{%- endif %} +{%- endfor %} +{%- endif %} +{%- endblock %} diff --git a/docs/templates/variable.liquid b/docs/templates/variable.liquid new file mode 100644 index 00000000..a1db6b11 --- /dev/null +++ b/docs/templates/variable.liquid @@ -0,0 +1,32 @@ +{%- layout "layout" %} + +{%- block content %} + +{%- if apiItem.signature %} +## Signature + +```typescript +{{ apiItem.signature }} +``` +{%- endif %} + +{%- if returnType %} + +## Type + +{%- if returnType.type %} +{%- assign formatted_type = returnType.type | format_type %} +{%- if formatted_type contains "```" %} + +**Type**:{{ formatted_type }} +{%- else %} + +**Type**: {%- if returnType.typeRef and autolink != false %}`{{ formatted_type }}`{%- elsif returnType.typePath -%}[`{{ formatted_type }}`]({{ returnType.typePath }}){%- else -%}`{{ formatted_type }}`{%- endif %} +{%- endif %} +{%- endif %} +{%- if returnType.description %} + +{{ returnType.description }} +{%- endif %} +{%- endif %} +{%- endblock %} diff --git a/package.json b/package.json index e54367c9..19019905 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "test:unit": "turbo run test:unit --concurrency=5", "test:e2e": "vitest run --config vitest.config.e2e.ts", "prepare": "husky", - "docs": "turbo run mint-tsdocs --concurrency=5" + "docs": "turbo run docs --concurrency=5 && ./scripts/sync-docs-references.sh" }, "devDependencies": { "@commitlint/cli": "catalog:ci", @@ -48,7 +48,7 @@ "typescript": "catalog:core", "vitest": "catalog:test" }, - "packageManager": "pnpm@11.3.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/asset-manager/README.md b/packages/asset-manager/README.md index 7000a76c..ec968ef6 100644 --- a/packages/asset-manager/README.md +++ b/packages/asset-manager/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/asset-manager/mint-tsdocs.config.json b/packages/asset-manager/mint-tsdocs.config.json index 1d45efe5..56abf931 100644 --- a/packages/asset-manager/mint-tsdocs.config.json +++ b/packages/asset-manager/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/asset-manager", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/asset-manager", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/asset-manager/package.json b/packages/asset-manager/package.json index e4f45f39..b2aaa2c0 100644 --- a/packages/asset-manager/package.json +++ b/packages/asset-manager/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/asset-manager/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*" @@ -71,7 +71,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/asset-manager/src/asset-manager.library.ts b/packages/asset-manager/src/asset-manager.library.ts index 67b28abd..df0a5e6b 100644 --- a/packages/asset-manager/src/asset-manager.library.ts +++ b/packages/asset-manager/src/asset-manager.library.ts @@ -5,17 +5,48 @@ import { NfNotFound, } from "@nanoforge-dev/common"; +/** + * Built-in asset-manager library. + * + * @remarks + * Stores the file map injected by the NanoForge loader (`nf start`) and + * exposes assets via `getAsset`. Register it with the application before + * calling `init`: + * + * ```ts + * const client = NanoforgeFactory.createClient(); + * client.useAssetManager(new AssetManagerLibrary()); + * await client.init(`container, files, env `); + * ``` + * + * File paths are normalised on lookup: leading slashes are collapsed to a + * single `/`, duplicate slashes are removed, and trailing slashes are stripped. + */ export class AssetManagerLibrary extends BaseAssetManagerLibrary { private _assets?: Map; + /** @internal */ get __name(): string { return "AssetManagerLibrary"; } + /** @internal */ public async __init(context: InitContext): Promise { this._assets = context.files; } + /** + * Retrieve a registered file asset by its virtual path. + * + * @remarks + * The path is normalised before lookup: leading and duplicate slashes are + * collapsed and trailing slashes are removed. + * + * @param path - Virtual path of the asset (e.g. "/textures/hero.png"). + * @returns An `NfFile` handle for the requested asset. + * @throws `NfNotFound` When no asset is registered at the given path. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public getAsset(path: string): NfFile { if (!this._assets) this.throwNotInitializedError(); const res = this._assets.get(this._parsePath(path)); diff --git a/packages/common/README.md b/packages/common/README.md index b64cf8ee..a874391b 100644 --- a/packages/common/README.md +++ b/packages/common/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/common/mint-tsdocs.config.json b/packages/common/mint-tsdocs.config.json index 90664b43..86e8e19a 100644 --- a/packages/common/mint-tsdocs.config.json +++ b/packages/common/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/common", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/common", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/common/package.json b/packages/common/package.json index ea745156..f101fe67 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/common/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "devDependencies": { "@favware/cliff-jumper": "catalog:ci", @@ -68,7 +68,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/common/src/common/file.ts b/packages/common/src/common/file.ts index 27e1eba7..376ac68d 100644 --- a/packages/common/src/common/file.ts +++ b/packages/common/src/common/file.ts @@ -1,41 +1,94 @@ import { NfFetchException } from "../exception"; +/** + * Represents a file asset that has been registered with the engine. + * + * @remarks + * Instances are returned by `AssetManagerLibrary.getAsset`. Each method + * lazily fetches the file from the engine's virtual file system and returns the + * content in the requested format. + * + * All read methods throw `NfFetchException` when the underlying `fetch` + * returns a non-OK response. + * + * @example + * ```ts + * const file = assetManager.getAsset("/textures/hero.png"); + * const buffer = await file.arrayBuffer(); + * ``` + */ export class NfFile { private readonly _path: string; + /** + * @param path - Internal URL path used to fetch the file. + */ constructor(path: string) { this._path = path; } + /** + * Internal URL path used to fetch the file. + */ get path(): string { return this._path; } + /** + * Fetch the file and return its content as an `ArrayBuffer`. + * + * @throws `NfFetchException` When the HTTP response is not OK. + */ public async arrayBuffer(): Promise { const res = await this._fetch(); return await res.arrayBuffer(); } + /** + * Fetch the file and return its content as a `Blob`. + * + * @throws `NfFetchException` When the HTTP response is not OK. + */ public async blob(): Promise { const res = await this._fetch(); return await res.blob(); } + /** + * Fetch the file and return its content as a `Uint8Array`. + * + * @throws `NfFetchException` When the HTTP response is not OK. + */ public async bytes(): Promise> { const res = await this._fetch(); return await res.arrayBuffer().then((buf) => new Uint8Array(buf)); } + /** + * Fetch the file and return its content as `FormData`. + * + * @throws `NfFetchException` When the HTTP response is not OK. + */ public async formData(): Promise { const res = await this._fetch(); return await res.formData(); } + /** + * Fetch the file, parse it as JSON, and return the result. + * + * @throws `NfFetchException` When the HTTP response is not OK. + */ public async json(): Promise { const res = await this._fetch(); return await res.json(); } + /** + * Fetch the file and return its content as a UTF-8 string. + * + * @throws `NfFetchException` When the HTTP response is not OK. + */ public async text(): Promise { const res = await this._fetch(); return await res.text(); diff --git a/packages/common/src/context/contexts/application.context.ts b/packages/common/src/context/contexts/application.context.ts index d294b16d..96a7f12f 100644 --- a/packages/common/src/context/contexts/application.context.ts +++ b/packages/common/src/context/contexts/application.context.ts @@ -1,18 +1,35 @@ +/** + * Holds runtime state that is shared across all libraries during the game loop. + * + * @remarks + * An instance of this class is available to every library via + * `BaseContext.application`. Libraries may read `isRunning` and `delta` + * to make frame-rate-independent decisions. + */ export abstract class ApplicationContext { private _isRunning: boolean = false; + /** @internal */ protected _delta!: number; + /** + * Whether the engine game loop is currently executing. + */ get isRunning(): boolean { return this._isRunning; } + /** + * Elapsed time in milliseconds since the last frame. + */ get delta(): number { return this._delta; } + /** @internal */ setIsRunning(value: boolean): void { this._isRunning = value; } + /** @internal */ abstract muteSoundLibraries(): void; } diff --git a/packages/common/src/context/contexts/executions/base.context.ts b/packages/common/src/context/contexts/executions/base.context.ts index c6917f4d..d5ab9e24 100644 --- a/packages/common/src/context/contexts/executions/base.context.ts +++ b/packages/common/src/context/contexts/executions/base.context.ts @@ -1,19 +1,38 @@ import { type LibraryManager } from "../../../library/manager/managers/library.manager"; import { type ApplicationContext } from "../application.context"; +/** + * Base context passed to library lifecycle hooks. + * + * @remarks + * All execution context types (`InitContext`, `ClearContext`, + * `ExecutionContext`) extend this class and expose `application` and + * `libraries`. + */ export class BaseContext { private readonly _applicationContext: ApplicationContext; private readonly _libraryManager: LibraryManager; + /** + * @param applicationContext - Shared application-level runtime state. + * @param libraryManager - Manager giving access to all registered libraries. + */ constructor(applicationContext: ApplicationContext, libraryManager: LibraryManager) { this._applicationContext = applicationContext; this._libraryManager = libraryManager; } + /** + * Shared application-level runtime state (running flag, delta time, …). + */ get application(): ApplicationContext { return this._applicationContext; } + /** + * Manager that provides typed access to every library registered with the + * current application. + */ get libraries(): LibraryManager { return this._libraryManager; } diff --git a/packages/common/src/context/contexts/executions/clear.context.ts b/packages/common/src/context/contexts/executions/clear.context.ts index 6755dc87..ba8889a4 100644 --- a/packages/common/src/context/contexts/executions/clear.context.ts +++ b/packages/common/src/context/contexts/executions/clear.context.ts @@ -1,3 +1,10 @@ import { BaseContext } from "./base.context"; +/** + * Context passed to a library's `__clear` lifecycle hook during application shutdown. + * + * @remarks + * Use the inherited `application` and `libraries` accessors to access shared + * state and other libraries while tearing down resources. + */ export class ClearContext extends BaseContext {} diff --git a/packages/common/src/context/contexts/executions/execution.context.ts b/packages/common/src/context/contexts/executions/execution.context.ts index 7876505c..eae4a5cd 100644 --- a/packages/common/src/context/contexts/executions/execution.context.ts +++ b/packages/common/src/context/contexts/executions/execution.context.ts @@ -1,3 +1,10 @@ import { BaseContext } from "./base.context"; +/** + * Context passed to a library's `__run` hook on every game-loop tick. + * + * @remarks + * Use the inherited `application` and `libraries` accessors to read the current + * delta time and interact with other libraries during the frame update. + */ export class ExecutionContext extends BaseContext {} diff --git a/packages/common/src/context/contexts/executions/init.context.ts b/packages/common/src/context/contexts/executions/init.context.ts index 7f34ea8f..328771c8 100644 --- a/packages/common/src/context/contexts/executions/init.context.ts +++ b/packages/common/src/context/contexts/executions/init.context.ts @@ -3,12 +3,34 @@ import { type IRunClientOptions, type IRunOptions } from "../../../options"; import { type ApplicationContext } from "../application.context"; import { BaseContext } from "./base.context"; +/** + * Context object passed to every library's `__init` lifecycle hook. + * + * @remarks + * Provides libraries with all the information they need during start-up: + * the canvas container, pre-loaded asset files, environment variables, and a + * config registry for loading structured configuration classes. + * + * Access it in a library's `__init` override: + * ```ts + * override async __init(ctx: InitContext) { + * const config = await ctx.config.registerConfig(MyConfig); + * const file = ctx.libraries.getAssetManager().library.getAsset("/data.json"); + * } + * ``` + */ export class InitContext extends BaseContext { private readonly _container: IRunClientOptions["container"] | undefined; private readonly _files: IRunOptions["files"]; private readonly _env: Record; private readonly _config: IConfigRegistry; + /** + * @param context - Shared application-level runtime state. + * @param libraryManager - Manager giving access to other registered libraries. + * @param configRegistry - Registry used to resolve typed configuration objects. + * @param options - Run options forwarded from NanoforgeApplication.init. + */ constructor( context: ApplicationContext, libraryManager: LibraryManager, @@ -23,18 +45,38 @@ export class InitContext extends BaseContext { this._config = configRegistry; } + /** + * The `HTMLDivElement` that should host the game canvas. + * + * @remarks + * Only available in client contexts; `undefined` on the server. + */ get container(): IRunClientOptions["container"] | undefined { return this._container; } + /** + * Map of virtual file paths to their URL strings, pre-loaded by the engine bundler. + */ get files(): IRunOptions["files"] { return this._files; } + /** + * Key/value map of environment variables made available at runtime. + */ get env(): Record { return this._env; } + /** + * Registry that resolves class-validator/class-transformer decorated + * configuration classes from the runtime environment. + * + * @remarks + * Call `ctx.config.registerConfig(MyConfigClass)` to get a validated and + * transformed instance populated from `ctx.env`. + */ get config(): IConfigRegistry { return this._config; } diff --git a/packages/common/src/context/contexts/library.context.ts b/packages/common/src/context/contexts/library.context.ts index 711473f8..1b58eb06 100644 --- a/packages/common/src/context/contexts/library.context.ts +++ b/packages/common/src/context/contexts/library.context.ts @@ -1,12 +1,25 @@ +/** + * Lifecycle states a library can be in. + */ export enum LibraryStatusEnum { + /** The library has not been initialised yet. */ UNLOADED = "UNLOADED", + /** The library has been successfully initialised and is ready to use. */ LOADED = "LOADED", + /** The library has been cleared and its resources released. */ CLEAR = "CLEAR", } +/** + * Tracks the current lifecycle state of a single library registration. + */ export class LibraryContext { + /** @internal */ protected _status: LibraryStatusEnum = LibraryStatusEnum.UNLOADED; + /** + * Current lifecycle state of the associated library. + */ get status() { return this._status; } diff --git a/packages/common/src/exception/abstracts/exception.abstract.ts b/packages/common/src/exception/abstracts/exception.abstract.ts index 0857c571..2e6e4985 100644 --- a/packages/common/src/exception/abstracts/exception.abstract.ts +++ b/packages/common/src/exception/abstracts/exception.abstract.ts @@ -1,8 +1,32 @@ import type { INfException } from "../interfaces/exception.type"; +/** + * Base class for all NanoForge engine exceptions. + * + * @remarks + * All errors thrown by the engine extend this class so that game code can + * differentiate engine errors from unrelated runtime errors. + * + * @example + * ```ts + * try { + * assetManager.getAsset("/missing.png"); + * } catch (err) { + * if (err instanceof NfException) { + * console.error(err.code, err.message); + * } + * } + * ``` + */ export abstract class NfException extends Error implements INfException { + /** + * HTTP-style numeric code identifying the error category. + */ abstract get code(): number; + /** + * @param message - Optional human-readable description of the error. + */ protected constructor(message?: string) { super( message ? `[NANOFORGE] ${message}` : "[NANOFORGE] An error occurred (Unknown exception).", diff --git a/packages/common/src/exception/exceptions/config.exception.ts b/packages/common/src/exception/exceptions/config.exception.ts index f88f9af6..3f4f4b9e 100644 --- a/packages/common/src/exception/exceptions/config.exception.ts +++ b/packages/common/src/exception/exceptions/config.exception.ts @@ -1,10 +1,23 @@ import { NfException } from "../abstracts/exception.abstract"; +/** + * Thrown when a library configuration is invalid or incomplete. + * + * @remarks + * Typically raised during `__init` when required environment variables are + * missing or fail validation. For example, `NetworkClientLibrary` throws this + * when neither `SERVER_TCP_PORT` nor `SERVER_UDP_PORT` is provided. + */ export class NfConfigException extends NfException { + /** Always `400`. */ get code(): number { return 400; } + /** + * @param message - Description of the configuration error. + * @param library - Optional library name that detected the error. + */ constructor(message: string, library?: string) { super(`Config Exception ${library ? `(${library}) ` : ""}- ${message}`); } diff --git a/packages/common/src/exception/exceptions/fetch.exception.ts b/packages/common/src/exception/exceptions/fetch.exception.ts index a37f5eea..35409e6e 100644 --- a/packages/common/src/exception/exceptions/fetch.exception.ts +++ b/packages/common/src/exception/exceptions/fetch.exception.ts @@ -1,12 +1,26 @@ import { NfException } from "../abstracts/exception.abstract"; +/** + * Thrown when an HTTP fetch performed internally by the engine fails. + * + * @remarks + * Raised by `NfFile` methods (e.g. `arrayBuffer`, `text`) when the + * underlying `fetch` call returns a non-OK HTTP response. + */ export class NfFetchException extends NfException { private readonly _code: number; + /** + * The HTTP status code returned by the failed request (e.g. `404`, `500`). + */ get code(): number { return this._code; } + /** + * @param code - HTTP status code of the failed response. + * @param text - Status text of the failed response. + */ constructor(code: number, text: string) { super(`Fetch exception : ${code} - ${text}`); this._code = code; diff --git a/packages/common/src/exception/exceptions/not-found.exception.ts b/packages/common/src/exception/exceptions/not-found.exception.ts index 220be27c..57f313e8 100644 --- a/packages/common/src/exception/exceptions/not-found.exception.ts +++ b/packages/common/src/exception/exceptions/not-found.exception.ts @@ -1,10 +1,31 @@ import { NfException } from "../abstracts/exception.abstract"; +/** + * Thrown when a requested resource (asset, sound, music track, etc.) cannot + * be found in the engine's registry. + * + * @example + * ```ts + * // Thrown automatically by AssetManagerLibrary.getAsset, SoundLibrary.play, etc. + * try { + * const file = assetManager.getAsset("/textures/hero.png"); + * } catch (err) { + * if (err instanceof NfNotFound) { + * console.error("Missing resource:", err.message); + * } + * } + * ``` + */ export class NfNotFound extends NfException { + /** Always `404`. */ get code(): number { return 404; } + /** + * @param item - Name or path of the missing resource. + * @param type - Optional category label (e.g. "Asset", "Sound"). + */ constructor(item: string, type?: string) { super(`${type ? `${type} - ` : ""}${item} not found.`); } diff --git a/packages/common/src/exception/exceptions/not-initialized.exception.ts b/packages/common/src/exception/exceptions/not-initialized.exception.ts index 02e3368d..61deec33 100644 --- a/packages/common/src/exception/exceptions/not-initialized.exception.ts +++ b/packages/common/src/exception/exceptions/not-initialized.exception.ts @@ -1,10 +1,25 @@ import { NfException } from "../abstracts/exception.abstract"; +/** + * Thrown when a method is called on a library or engine component before it + * has been initialised via `__init`. + * + * @remarks + * This exception is raised automatically by the helper method + * `Library.throwNotInitializedError()`. Ensure that + * `NanoforgeApplication.init` has resolved before interacting with any + * library. + */ export class NfNotInitializedException extends NfException { + /** Always `404`. */ get code(): number { return 404; } + /** + * @param item - Name of the uninitialised component (e.g. the library's __name). + * @param type - Optional category label (e.g. "Library"). + */ constructor(item: string, type?: string) { super(`${type ? `${type} - ` : ""}${item} not initialized.`); } diff --git a/packages/common/src/library/config/interfaces/config-registry.type.ts b/packages/common/src/library/config/interfaces/config-registry.type.ts index 9203201e..875e31a9 100644 --- a/packages/common/src/library/config/interfaces/config-registry.type.ts +++ b/packages/common/src/library/config/interfaces/config-registry.type.ts @@ -1,3 +1,36 @@ +/** + * Resolves and validates typed configuration objects from the runtime + * environment. + * + * @remarks + * An instance is available in `InitContext.config`. Configuration + * classes must be decorated with `class-transformer` (`@Expose`, `@Default`) + * and `class-validator` (`@IsPort`, `@IsIpOrFQDN`, etc.) decorators from + * `@nanoforge-dev/config`. + * + * @example + * ```ts + * import `Expose, IsPort ` from "@nanoforge-dev/config"; + * + * class MyConfig { + * \@Expose() \@IsPort() + * PORT!: string; + * } + * + * // Inside __init: + * const cfg = await ctx.config.registerConfig(MyConfig); + * console.log(cfg.PORT); + * ``` + */ export interface IConfigRegistry { + /** + * Instantiate, populate from the runtime environment, transform, and + * validate a configuration class. + * + * @typeParam T - Configuration class type. + * @param config - Constructor of the configuration class. + * @returns A validated, populated instance of the configuration class. + * @throws `NfConfigException` When validation fails. + */ registerConfig(config: new () => T): Promise; } diff --git a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts index b6fc5df0..6cf813a0 100644 --- a/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/asset-manager.library.abstract.ts @@ -3,8 +3,25 @@ import { type InitContext } from "../../../context"; import { type IAssetManagerLibrary } from "../interfaces"; import { Library } from "../library"; +/** + * Abstract base class for asset-manager libraries. + * + * @remarks + * Extend this class to implement a custom asset-manager and register it with + * `NanoforgeApplication.useAssetManager`. The built-in implementation + * is `AssetManagerLibrary`. + */ export abstract class BaseAssetManagerLibrary extends Library implements IAssetManagerLibrary { + /** @internal */ public abstract override __init(context: InitContext): Promise; + /** + * Retrieve a file asset by its virtual path. + * + * @param path - Virtual path as registered in the engine's file map (e.g. "/textures/hero.png"). + * @returns An `NfFile` handle that lazily fetches the asset content. + * @throws `NfNotFound` When no asset is registered at the given path. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public abstract getAsset(path: string): NfFile; } diff --git a/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts b/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts index 9636529d..a00f9015 100644 --- a/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/component-system.library.abstract.ts @@ -2,9 +2,19 @@ import { type Context } from "../../../context"; import { type IComponentSystemLibrary } from "../interfaces"; import { Library } from "../library"; +/** + * Abstract base class for component-system (ECS) libraries. + * + * @remarks + * Extend this class (or the higher-level `AbstractECSLibrary`) to + * implement a custom ECS back-end and register it with + * `NanoforgeApplication.useComponentSystem`. The built-in + * implementations are `ECSClientLibrary` and `ECSServerLibrary`. + */ export abstract class BaseComponentSystemLibrary extends Library implements IComponentSystemLibrary { + /** @internal */ abstract __run(context: Context): Promise; } diff --git a/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts b/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts index d26c4b66..ed1baa9b 100644 --- a/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/graphics.library.abstract.ts @@ -2,6 +2,15 @@ import { type Context } from "../../../context"; import { type IGraphicsLibrary } from "../interfaces"; import { Library } from "../library"; +/** + * Abstract base class for graphics libraries. + * + * @remarks + * Extend this class to implement a custom rendering backend and register it + * with `NanoforgeClient.useGraphics`. The built-in implementation is + * `Graphics2DLibrary`. + */ export abstract class BaseGraphicsLibrary extends Library implements IGraphicsLibrary { + /** @internal */ abstract __run(context: Context): Promise; } diff --git a/packages/common/src/library/libraries/abstracts/input.library.abstract.ts b/packages/common/src/library/libraries/abstracts/input.library.abstract.ts index 4befe142..69256a41 100644 --- a/packages/common/src/library/libraries/abstracts/input.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/input.library.abstract.ts @@ -2,6 +2,15 @@ import { type Context } from "../../../context"; import { type IInputLibrary } from "../interfaces"; import { Library } from "../library"; +/** + * Abstract base class for input libraries. + * + * @remarks + * Extend this class to implement a custom input back-end and register it with + * `NanoforgeClient.useInput`. The built-in implementation is + * `InputLibrary`. + */ export abstract class BaseInputLibrary extends Library implements IInputLibrary { + /** @internal */ public abstract __run(_context: Context): Promise; } diff --git a/packages/common/src/library/libraries/abstracts/music.library.abstract.ts b/packages/common/src/library/libraries/abstracts/music.library.abstract.ts index 0f197dcf..71614876 100644 --- a/packages/common/src/library/libraries/abstracts/music.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/music.library.abstract.ts @@ -2,13 +2,31 @@ import { type InitContext } from "../../../context"; import { type IMusicLibrary } from "../interfaces"; import { Library } from "../library"; +/** + * Abstract base class for music libraries. + * + * @remarks + * Extend this class to implement a custom music library and register it with + * `NanoforgeApplication.use` using the `MUSIC_LIBRARY` symbol. + * The built-in implementation is `MusicLibrary`. + */ export abstract class BaseMusicLibrary extends Library implements IMusicLibrary { + /** @internal */ public abstract override __init(context: InitContext): Promise; + /** + * Stop the currently playing track (if any) and start playing the requested one. + * + * @param sound - Key that identifies the music track (as passed to load). + * @throws `NfNotFound` When no track is registered under the given key. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public abstract play(sound: string): void; /** - * mutes or unmutes the sound. + * Toggle the muted state of all loaded music tracks. + * + * @throws `NfNotInitializedException` When called before `__init` has resolved. */ public abstract mute(): void; } diff --git a/packages/common/src/library/libraries/abstracts/network.library.abstract.ts b/packages/common/src/library/libraries/abstracts/network.library.abstract.ts index c32ffded..1e793150 100644 --- a/packages/common/src/library/libraries/abstracts/network.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/network.library.abstract.ts @@ -1,4 +1,12 @@ import { type INetworkLibrary } from "../interfaces"; import { Library } from "../library"; +/** + * Abstract base class for network libraries. + * + * @remarks + * Extend this class to implement a custom network library and register it with + * `NanoforgeApplication.useNetwork`. The built-in implementations are + * `NetworkClientLibrary` and `NetworkServerLibrary`. + */ export abstract class BaseNetworkLibrary extends Library implements INetworkLibrary {} diff --git a/packages/common/src/library/libraries/abstracts/sound.library.abstract.ts b/packages/common/src/library/libraries/abstracts/sound.library.abstract.ts index 5663f435..7e4ea5cb 100644 --- a/packages/common/src/library/libraries/abstracts/sound.library.abstract.ts +++ b/packages/common/src/library/libraries/abstracts/sound.library.abstract.ts @@ -2,13 +2,31 @@ import { type InitContext } from "../../../context"; import { type ISoundLibrary } from "../interfaces"; import { Library } from "../library"; +/** + * Abstract base class for sound libraries. + * + * @remarks + * Extend this class to implement a custom sound library and register it with + * `NanoforgeClient.useSound`. The built-in implementation is + * `SoundLibrary`. + */ export abstract class BaseSoundLibrary extends Library implements ISoundLibrary { + /** @internal */ public abstract override __init(context: InitContext): Promise; + /** + * Play a previously loaded sound effect. + * + * @param sound - Key that identifies the sound (as passed to load). + * @throws `NfNotFound` When no sound is registered under the given key. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public abstract play(sound: string): void; /** - * mutes or unmutes the sound. + * Toggle the muted state of all loaded sound effects. + * + * @throws `NfNotInitializedException` When called before `__init` has resolved. */ public abstract mute(): void; } diff --git a/packages/common/src/library/libraries/consts/library-label.const.ts b/packages/common/src/library/libraries/consts/library-label.const.ts index adb3051a..d99b0150 100644 --- a/packages/common/src/library/libraries/consts/library-label.const.ts +++ b/packages/common/src/library/libraries/consts/library-label.const.ts @@ -1,7 +1,64 @@ +/** + * Registration symbol for the component-system (ECS) library slot. + * + * @remarks + * Pass this symbol to `NanoforgeApplication.use` when registering a + * custom component-system library, or use the shorthand + * `NanoforgeApplication.useComponentSystem`. + */ export const COMPONENT_SYSTEM_LIBRARY = Symbol("COMPONENT_SYSTEM_LIBRARY"); + +/** + * Registration symbol for the graphics library slot. + * + * @remarks + * Pass this symbol to `NanoforgeClient.useGraphics` or use it as a + * dependency symbol in a custom library's `ILibraryOptions.dependencies`. + */ export const GRAPHICS_LIBRARY = Symbol("GRAPHICS_LIBRARY"); + +/** + * Registration symbol for the network library slot. + * + * @remarks + * Pass this symbol to `NanoforgeApplication.useNetwork` or use it as a + * dependency symbol in a custom library's `ILibraryOptions.dependencies`. + */ export const NETWORK_LIBRARY = Symbol("NETWORK_LIBRARY"); + +/** + * Registration symbol for the sound library slot. + * + * @remarks + * Pass this symbol to `NanoforgeClient.useSound` or use it as a + * dependency symbol in a custom library's `ILibraryOptions.dependencies`. + */ export const SOUND_LIBRARY = Symbol("SOUND_LIBRARY"); + +/** + * Registration symbol for the music library slot. + * + * @remarks + * Pass this symbol to `NanoforgeApplication.use` with a custom music + * library or use it as a dependency symbol in + * `ILibraryOptions.dependencies`. + */ export const MUSIC_LIBRARY = Symbol("MUSIC_LIBRARY"); + +/** + * Registration symbol for the asset-manager library slot. + * + * @remarks + * Pass this symbol to `NanoforgeApplication.useAssetManager` or use it + * as a dependency in a custom library's `ILibraryOptions.dependencies`. + */ export const ASSET_MANAGER_LIBRARY = Symbol("ASSET_MANAGER_LIBRARY"); + +/** + * Registration symbol for the input library slot. + * + * @remarks + * Pass this symbol to `NanoforgeClient.useInput` or use it as a + * dependency symbol in a custom library's `ILibraryOptions.dependencies`. + */ export const INPUT_LIBRARY = Symbol("INPUT_LIBRARY"); diff --git a/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts b/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts index d72f9f1c..fb2d18b6 100644 --- a/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/bases/exposed.library.type.ts @@ -1,3 +1,11 @@ import { type ILibrary } from "../../library.type"; +/** + * Marker interface for libraries that are directly accessible to game code via + * the `ClientLibraryManager`. + * + * @remarks + * All built-in typed library interfaces (e.g. `IAssetManagerLibrary`, + * `ISoundLibrary`) extend this interface. + */ export interface IExposedLibrary extends ILibrary {} diff --git a/packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts b/packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts index f0b52055..aa5aee08 100644 --- a/packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/bases/mutable.library.type.ts @@ -1,8 +1,14 @@ import { type ILibrary } from "../../library.type"; +/** + * Interface for libraries that support muting/unmuting audio playback. + * + * @remarks + * Implemented by `ISoundLibrary` and `IMusicLibrary`. + */ export interface IMutableLibrary extends ILibrary { /** - * mutes or unmutes the sound. + * Toggle the muted state. Mutes when currently unmuted, and vice versa. */ mute(): void; } diff --git a/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts b/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts index cf319f32..ac6df49e 100644 --- a/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/bases/runner.library.type.ts @@ -1,6 +1,15 @@ import { type Context } from "../../../../context"; import { type ILibrary } from "../../library.type"; +/** + * Interface for libraries that participate in the per-frame game loop. + * + * @remarks + * The engine calls `__run` on every tick for all registered runner libraries + * in the order determined by their `ILibraryOptions.runBefore` / + * `ILibraryOptions.runAfter` relationships. + */ export interface IRunnerLibrary extends ILibrary { + /** @internal */ __run(context: Context): Promise; } diff --git a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts index 3f4d7a24..64f1b62f 100644 --- a/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/asset-manager.library.type.ts @@ -1,6 +1,21 @@ import { type NfFile } from "../../../../common"; import { type IExposedLibrary } from "../bases/exposed.library.type"; +/** + * Interface for asset-manager libraries. + * + * @remarks + * Implemented by `BaseAssetManagerLibrary` and its concrete subclass + * `AssetManagerLibrary`. Access an instance via + * `ctx.libraries.getAssetManager().library`. + */ export interface IAssetManagerLibrary extends IExposedLibrary { + /** + * Retrieve a registered file asset by its virtual path. + * + * @param path - Virtual path of the asset (e.g. "/textures/hero.png"). + * @returns An `NfFile` handle for the requested asset. + * @throws `NfNotFound` When no asset is registered at the given path. + */ getAsset(path: string): NfFile; } diff --git a/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts index 30be76ea..8208b886 100644 --- a/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/component-system.library.type.ts @@ -1,4 +1,13 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; import { type IRunnerLibrary } from "../bases/runner.library.type"; +/** + * Interface for component-system (ECS) libraries. + * + * @remarks + * Implemented by `BaseComponentSystemLibrary` and the higher-level + * `AbstractECSLibrary`, with concrete subclasses + * `ECSClientLibrary` and `ECSServerLibrary`. Access an instance + * via `ctx.libraries.getComponentSystem().library`. + */ export interface IComponentSystemLibrary extends IExposedLibrary, IRunnerLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts index 8023a658..9509a9dd 100644 --- a/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/graphics.library.type.ts @@ -1,4 +1,12 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; import { type IRunnerLibrary } from "../bases/runner.library.type"; +/** + * Interface for graphics libraries. + * + * @remarks + * Implemented by `BaseGraphicsLibrary` and its concrete subclass + * `Graphics2DLibrary`. Access an instance via + * `ctx.libraries.getGraphics().library`. + */ export interface IGraphicsLibrary extends IExposedLibrary, IRunnerLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts index e01957b4..9dc79452 100644 --- a/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/input.library.type.ts @@ -1,4 +1,12 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; import { type IRunnerLibrary } from "../bases/runner.library.type"; +/** + * Interface for input libraries. + * + * @remarks + * Implemented by `BaseInputLibrary` and its concrete subclass + * `InputLibrary`. Access an instance via + * `ctx.libraries.getInput().library`. + */ export interface IInputLibrary extends IExposedLibrary, IRunnerLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/music.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/music.library.type.ts index 3f469d0a..653e918d 100644 --- a/packages/common/src/library/libraries/interfaces/finals/music.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/music.library.type.ts @@ -1,4 +1,12 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; import { type IMutableLibrary } from "../bases/mutable.library.type"; +/** + * Interface for music libraries. + * + * @remarks + * Implemented by `BaseMusicLibrary` and its concrete subclass + * `MusicLibrary`. Access an instance via + * `ctx.libraries.getMusic().library`. + */ export interface IMusicLibrary extends IExposedLibrary, IMutableLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts index 4ad23ad5..80d0bca5 100644 --- a/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/network.library.type.ts @@ -1,3 +1,11 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; +/** + * Interface for network libraries. + * + * @remarks + * Implemented by `BaseNetworkLibrary` and its concrete subclasses + * `NetworkClientLibrary` and `NetworkServerLibrary`. Access an + * instance via `ctx.libraries.getNetwork().library`. + */ export interface INetworkLibrary extends IExposedLibrary {} diff --git a/packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts b/packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts index 67141946..8ce0fb79 100644 --- a/packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts +++ b/packages/common/src/library/libraries/interfaces/finals/sound.library.type.ts @@ -1,4 +1,12 @@ import { type IExposedLibrary } from "../bases/exposed.library.type"; import { type IMutableLibrary } from "../bases/mutable.library.type"; +/** + * Interface for sound-effect libraries. + * + * @remarks + * Implemented by `BaseSoundLibrary` and its concrete subclass + * `SoundLibrary`. Access an instance via + * `ctx.libraries.getSound().library`. + */ export interface ISoundLibrary extends IExposedLibrary, IMutableLibrary {} diff --git a/packages/common/src/library/libraries/library.ts b/packages/common/src/library/libraries/library.ts index ec84f4a9..e7624558 100644 --- a/packages/common/src/library/libraries/library.ts +++ b/packages/common/src/library/libraries/library.ts @@ -4,9 +4,41 @@ import { RelationshipHandler } from "../relationship/relationship-handler"; import { DEFAULT_LIBRARY_OPTIONS } from "./consts/library-options-default.const"; import { type ILibrary, type ILibraryOptions } from "./library.type"; +/** + * Base class for all NanoForge libraries. + * + * @remarks + * Extend this class (or one of its typed subclasses such as + * `BaseAssetManagerLibrary`, `BaseSoundLibrary`, etc.) to create a + * custom library. At minimum you must implement the `ILibrary.__name` + * getter and register the library with the engine before calling + * `NanoforgeApplication.init`. + * + * @example + * ```ts + * import `Library, type InitContext ` from "@nanoforge-dev/common"; + * + * const MY_LIBRARY = Symbol("MY_LIBRARY"); + * + * class MyLibrary extends Library { + * get __name() `return "MyLibrary"; ` + * + * override async __init(ctx: InitContext) { + * // one-time setup here + * } + * } + * + * const client = NanoforgeFactory.createClient(); + * client.use(MY_LIBRARY, new MyLibrary()); + * await client.init(`container, files, env `); + * ``` + */ export abstract class Library implements ILibrary { protected _relationship: RelationshipHandler; + /** + * @param rawOptions - Optional dependency and execution-order overrides. + */ constructor(rawOptions?: Partial) { const options = { ...DEFAULT_LIBRARY_OPTIONS, @@ -20,18 +52,23 @@ export abstract class Library implements ILibrary { ); } + /** @internal */ get __relationship(): RelationshipHandler { return this._relationship; } + /** @internal */ abstract get __name(): string; + /** @internal */ // eslint-disable-next-line @typescript-eslint/no-unused-vars public async __init(_context: InitContext): Promise {} + /** @internal */ // eslint-disable-next-line @typescript-eslint/no-unused-vars public async __clear(_context: ClearContext): Promise {} + /** @internal */ protected throwNotInitializedError(): never { throw new NfNotInitializedException(this.__name, "Library"); } diff --git a/packages/common/src/library/libraries/library.type.ts b/packages/common/src/library/libraries/library.type.ts index c7f7cf5f..35591bf2 100644 --- a/packages/common/src/library/libraries/library.type.ts +++ b/packages/common/src/library/libraries/library.type.ts @@ -1,18 +1,51 @@ import { type ClearContext, type InitContext } from "../../context"; import { type RelationshipHandler } from "../relationship/relationship-handler"; +/** + * Core interface that every NanoForge library must satisfy. + * + * @remarks + * Implement this interface (or extend an abstract base such as `BaseAssetManagerLibrary`) + * to create a custom library and register it with the engine via + * `NanoforgeApplication.use`. + */ export interface ILibrary { + /** @internal */ get __name(): string; + /** @internal */ get __relationship(): RelationshipHandler; + /** @internal */ __init(context: InitContext): Promise; + /** @internal */ __clear(context: ClearContext): Promise; } +/** + * Options that control how a library participates in the engine's + * initialisation and execution ordering. + */ export interface ILibraryOptions { + /** + * Symbols of libraries that must be fully initialised before this library + * can be used. + * + * @remarks + * The engine will reject configurations where a dependency is missing. + */ dependencies: symbol[]; + + /** + * Symbols of libraries whose `__run` method should be called *after* this + * library's `__run`. + */ runBefore: symbol[]; + + /** + * Symbols of libraries whose `__run` method must complete *before* this + * library's `__run` is invoked. + */ runAfter: symbol[]; } diff --git a/packages/common/src/library/manager/handle/library.handle.ts b/packages/common/src/library/manager/handle/library.handle.ts index f9fee46b..32bf268c 100644 --- a/packages/common/src/library/manager/handle/library.handle.ts +++ b/packages/common/src/library/manager/handle/library.handle.ts @@ -1,25 +1,50 @@ import { type LibraryContext } from "../../../context"; import { type ILibrary } from "../../libraries"; +/** + * An opaque handle returned by `LibraryManager` accessors. + * + * @remarks + * Bundles the library instance together with its registration symbol and + * lifecycle context. Prefer using the strongly-typed accessor methods on + * `LibraryManager` or `ClientLibraryManager` rather than + * constructing handles directly. + * + * @typeParam T - Concrete library type (defaults to `ILibrary`). + */ export class LibraryHandle { private readonly _symbol: symbol; private readonly _library: T; private readonly _context: LibraryContext; + /** + * @param sym - Registration symbol for this library. + * @param library - The library instance. + * @param defaultContext - Initial lifecycle context. + */ constructor(sym: symbol, library: T, defaultContext: LibraryContext) { this._symbol = sym; this._library = library; this._context = defaultContext; } + /** + * The registration symbol used to look up this library. + */ get symbol(): symbol { return this._symbol; } + /** + * The underlying library instance. + */ get library(): T { return this._library; } + /** + * Current lifecycle context tracking the library's status. + */ get context(): LibraryContext { return this._context; } diff --git a/packages/common/src/library/manager/managers/client-library.manager.ts b/packages/common/src/library/manager/managers/client-library.manager.ts index 4dc63b8e..44127935 100644 --- a/packages/common/src/library/manager/managers/client-library.manager.ts +++ b/packages/common/src/library/manager/managers/client-library.manager.ts @@ -10,41 +10,95 @@ import { } from "../../libraries"; import { type LibraryManager } from "./library.manager"; +/** + * Convenience wrapper around `LibraryManager` that unwraps + * `LibraryHandle` values and returns the library instance directly. + * + * @remarks + * Typically accessed inside a library's lifecycle hooks through the execution + * context's `libraries` property after being constructed with a concrete + * `LibraryManager`. + */ export class ClientLibraryManager { private readonly _libraryManager: LibraryManager; + /** + * @param libraryManager - The underlying manager to delegate lookups to. + */ constructor(libraryManager: LibraryManager) { this._libraryManager = libraryManager; } + /** + * Retrieve a library registered under a custom symbol. + * + * @typeParam T - Expected library type. + * @param sym - The symbol the library was registered with. + * @returns The unwrapped library instance. + */ public get(sym: symbol): T { return this._libraryManager.get(sym).library; } + /** + * Retrieve the registered component-system (ECS) library instance. + * + * @typeParam T - Concrete component-system library type. + */ public getComponentSystem(): T { return this._libraryManager.getComponentSystem().library; } + /** + * Retrieve the registered graphics library instance. + * + * @typeParam T - Concrete graphics library type. + */ public getGraphics(): T { return this._libraryManager.getGraphics().library; } + /** + * Retrieve the registered network library instance. + * + * @typeParam T - Concrete network library type. + */ public getNetwork(): T { return this._libraryManager.getNetwork().library; } + /** + * Retrieve the registered input library instance. + * + * @typeParam T - Concrete input library type. + */ public getInput(): T { return this._libraryManager.getInput().library; } + /** + * Retrieve the registered asset-manager library instance. + * + * @typeParam T - Concrete asset-manager library type. + */ public getAssetManager(): T { return this._libraryManager.getAssetManager().library; } + /** + * Retrieve the registered sound library instance. + * + * @typeParam T - Concrete sound library type. + */ public getSound(): T { return this._libraryManager.getSound().library; } + /** + * Retrieve the registered music library instance. + * + * @typeParam T - Concrete music library type. + */ public getMusic(): T { return this._libraryManager.getMusic().library; } diff --git a/packages/common/src/library/manager/managers/library.manager.ts b/packages/common/src/library/manager/managers/library.manager.ts index 4cdf3abb..22c7df83 100644 --- a/packages/common/src/library/manager/managers/library.manager.ts +++ b/packages/common/src/library/manager/managers/library.manager.ts @@ -16,6 +16,14 @@ import { import { type LibraryHandle } from "../handle/library.handle"; import { BaseLibraryManager } from "./base-library.manager"; +/** + * Numeric index keys for the built-in library slots. + * + * @remarks + * Used internally by `LibraryManager` to keep O(1) access to the well-known + * library positions. Game code should not reference these values directly — + * use the typed accessor methods on `LibraryManager` instead. + */ export enum DefaultLibrariesEnum { ASSET_MANAGER, COMPONENT_SYSTEM, @@ -35,6 +43,24 @@ const DEFAULT_LIBRARIES: { index: DefaultLibrariesEnum; sym: symbol }[] = [ { index: DefaultLibrariesEnum.MUSIC, sym: MUSIC_LIBRARY }, ]; +/** + * Central registry for all libraries registered with a NanoForge application. + * + * @remarks + * An instance is available inside every lifecycle context via + * `BaseContext.libraries`. Use the typed accessor methods to retrieve + * any built-in library, or call `BaseLibraryManager.get` with a custom + * symbol for user-defined libraries. + * + * @example + * ```ts + * // Inside a library's __init hook: + * override async __init(ctx: InitContext) { + * const assetMgr = ctx.libraries.getAssetManager().library; + * const file = assetMgr.getAsset("/data.json"); + * } + * ``` + */ export class LibraryManager extends BaseLibraryManager { constructor() { super(); @@ -44,34 +70,76 @@ export class LibraryManager extends BaseLibraryManager { } } + /** + * Retrieve the registered component-system (ECS) library. + * + * @typeParam T - Concrete component-system library type. + * @returns A `LibraryHandle` wrapping the library instance. + */ public getComponentSystem< T extends IComponentSystemLibrary = IComponentSystemLibrary, >(): LibraryHandle { return this._get(DefaultLibrariesEnum.COMPONENT_SYSTEM); } + /** + * Retrieve the registered graphics library. + * + * @typeParam T - Concrete graphics library type. + * @returns A `LibraryHandle` wrapping the library instance. + */ public getGraphics(): LibraryHandle { return this._get(DefaultLibrariesEnum.GRAPHICS); } + /** + * Retrieve the registered network library. + * + * @typeParam T - Concrete network library type. + * @returns A `LibraryHandle` wrapping the library instance. + */ public getNetwork(): LibraryHandle { return this._get(DefaultLibrariesEnum.NETWORK); } + /** + * Retrieve the registered input library. + * + * @typeParam T - Concrete input library type. + * @returns A `LibraryHandle` wrapping the library instance. + */ public getInput(): LibraryHandle { return this._get(DefaultLibrariesEnum.INPUT); } + /** + * Retrieve the registered asset-manager library. + * + * @typeParam T - Concrete asset-manager library type. + * @returns A `LibraryHandle` wrapping the library instance. + */ public getAssetManager< T extends IAssetManagerLibrary = IAssetManagerLibrary, >(): LibraryHandle { return this._get(DefaultLibrariesEnum.ASSET_MANAGER); } + /** + * Retrieve the registered sound library. + * + * @typeParam T - Concrete sound library type. + * @returns A `LibraryHandle` wrapping the library instance. + */ public getSound(): LibraryHandle { return this._get(DefaultLibrariesEnum.SOUND); } + /** + * Retrieve the registered music library. + * + * @typeParam T - Concrete music library type. + * @returns A `LibraryHandle` wrapping the library instance. + */ public getMusic(): LibraryHandle { return this._get(DefaultLibrariesEnum.MUSIC); } diff --git a/packages/common/src/options/types/options.type.ts b/packages/common/src/options/types/options.type.ts index 63547da3..b24150ec 100644 --- a/packages/common/src/options/types/options.type.ts +++ b/packages/common/src/options/types/options.type.ts @@ -1,12 +1,63 @@ +/** + * Union of client and server run options accepted by + * `NanoforgeApplication.init`. + */ export type IRunOptions = IRunClientOptions | IRunServerOptions; +/** + * Run options for a client-side NanoForge application. + * + * @remarks + * Pass an instance to `NanoforgeApplication.init` when running in the + * browser. The engine bundler (`nf build`) automatically generates and + * injects `files` and `env` at build time. + */ export interface IRunClientOptions { + /** + * DOM element that will host the game canvas. + * + * @remarks + * The element's current `offsetWidth` and `offsetHeight` are used to set + * the initial canvas dimensions. + */ container: HTMLDivElement; + + /** + * Map of virtual file paths to their resolved URL strings. + * + * @remarks + * Populated automatically by the NanoForge bundler. Keys are normalised + * paths such as `"/textures/hero.png"`. + */ files: Map; + + /** + * Runtime environment variables available to all libraries via + * `InitContext.env`. + */ env: Record; } +/** + * Run options for a server-side NanoForge application. + * + * @remarks + * Pass an instance to `NanoforgeApplication.init` when running in a + * Node.js server process. + */ export interface IRunServerOptions { + /** + * Map of virtual file paths to their resolved URL strings. + * + * @remarks + * Populated automatically by the NanoForge bundler. Keys are normalised + * paths such as `"/data/config.json"`. + */ files: Map; + + /** + * Runtime environment variables available to all libraries via + * `InitContext.env`. + */ env: Record; } diff --git a/packages/config/README.md b/packages/config/README.md index db50b756..9f9e3d26 100644 --- a/packages/config/README.md +++ b/packages/config/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/config/mint-tsdocs.config.json b/packages/config/mint-tsdocs.config.json index 819efbed..d68b969c 100644 --- a/packages/config/mint-tsdocs.config.json +++ b/packages/config/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/config", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/config", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/config/package.json b/packages/config/package.json index 650918eb..e2f206b9 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -53,7 +53,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/config/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "class-transformer": "catalog:config", @@ -70,7 +70,7 @@ "typescript": "catalog:core", "unrun": "catalog:build" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/config/src/default.ts b/packages/config/src/default.ts index f32155c9..ed2a78c3 100644 --- a/packages/config/src/default.ts +++ b/packages/config/src/default.ts @@ -1,6 +1,26 @@ import { Transform } from "class-transformer"; import { type TransformFnParams } from "class-transformer/types/interfaces/metadata/transform-fn-params.interface"; +/** + * Property decorator that supplies a fallback value when the environment + * variable is `undefined` or `null`. + * + * @remarks + * Pairs with `class-transformer`'s `@Expose` and `class-validator` decorators. + * The default is deep-cloned via `JSON.parse(JSON.stringify(…))` so objects + * are not shared between instances. + * + * @param defaultValue - The value to use when the property is absent. + * + * @example + * ```ts + * class MyConfig { + * \@Expose() + * \@Default("localhost") + * HOST!: string; + * } + * ``` + */ export function Default(defaultValue: unknown): PropertyDecorator { return Transform( ({ value }: TransformFnParams) => value ?? JSON.parse(JSON.stringify(defaultValue)), diff --git a/packages/config/src/transformers/boolean.transformer.ts b/packages/config/src/transformers/boolean.transformer.ts index fad1a052..a6ef7a80 100644 --- a/packages/config/src/transformers/boolean.transformer.ts +++ b/packages/config/src/transformers/boolean.transformer.ts @@ -6,4 +6,24 @@ const transformStringToBoolean = ({ value }: { value: string }) => { return undefined; }; +/** + * Property decorator that transforms the string environment variable value + * `"true"` or `"false"` into a native `boolean`. + * + * @remarks + * Returns `undefined` for any value that is neither `"true"` nor `"false"`. + * Pair with `@IsBoolean()` and `@Default(false)` for a fully validated and + * defaulted boolean config property. + * + * @example + * ```ts + * class MyConfig { + * \@Expose() + * \@TransformToBoolean() + * \@IsBoolean() + * \@Default(false) + * FEATURE_FLAG!: boolean; + * } + * ``` + */ export const TransformToBoolean = () => Transform(transformStringToBoolean); diff --git a/packages/config/src/validators/is-ip-or-fqdn.validator.ts b/packages/config/src/validators/is-ip-or-fqdn.validator.ts index e9cb009a..c7e5d4de 100644 --- a/packages/config/src/validators/is-ip-or-fqdn.validator.ts +++ b/packages/config/src/validators/is-ip-or-fqdn.validator.ts @@ -1,5 +1,24 @@ import { type ValidationOptions, isFQDN, isIP, registerDecorator } from "class-validator"; +/** + * Property decorator that validates whether the value is a valid IPv4/IPv6 + * address or a fully qualified domain name (FQDN). + * + * @remarks + * Built on top of `class-validator`'s `isIP` and `isFQDN` helpers. Use on + * config properties that represent server hostnames or addresses. + * + * @param validationOptions - Optional class-validator validation options. + * + * @example + * ```ts + * class MyConfig { + * \@Expose() + * \@IsIpOrFQDN() + * SERVER_ADDRESS!: string; + * } + * ``` + */ export const IsIpOrFQDN = (validationOptions?: ValidationOptions) => { return (object: object, propertyName: string) => { registerDecorator({ diff --git a/packages/core-editor/README.md b/packages/core-editor/README.md index 19004c8d..89278938 100644 --- a/packages/core-editor/README.md +++ b/packages/core-editor/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/core-editor/mint-tsdocs.config.json b/packages/core-editor/mint-tsdocs.config.json index 411c0442..02fa5cc0 100644 --- a/packages/core-editor/mint-tsdocs.config.json +++ b/packages/core-editor/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/core-editor", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/core-editor", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/core-editor/package.json b/packages/core-editor/package.json index 6fdd6ff7..4b948902 100644 --- a/packages/core-editor/package.json +++ b/packages/core-editor/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/core-editor/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/asset-manager": "workspace:*", @@ -76,7 +76,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/core-editor/src/application/nanoforge-application.ts b/packages/core-editor/src/application/nanoforge-application.ts index 66bb18eb..bef673db 100644 --- a/packages/core-editor/src/application/nanoforge-application.ts +++ b/packages/core-editor/src/application/nanoforge-application.ts @@ -12,11 +12,22 @@ import { EditableApplicationContext } from "../../../core/src/common/context/con import { type IEditorRunOptions } from "../common/context/options.type"; import { Core } from "../core/core"; +/** + * Base class for editor-mode NanoForge applications. + * + * @remarks + * Mirror of `NanoforgeApplication` from `@nanoforge-dev/core` with an + * extended `init` signature that accepts `IEditorRunOptions`. Use + * `NanoforgeFactory` from this package to create instances. + */ export abstract class NanoforgeApplication { protected applicationConfig: ApplicationConfig; private _core?: Core; private readonly _options: IApplicationOptions; + /** + * @param options - Optional application-level settings such as tickRate. + */ constructor(options?: Partial) { this.applicationConfig = new ApplicationConfig(); @@ -26,22 +37,48 @@ export abstract class NanoforgeApplication { }; } + /** + * Register a library under a custom symbol. + * + * @param sym - Unique symbol identifying the library slot. + * @param library - Library instance to register. + */ public use(sym: symbol, library: ILibrary): void { this.applicationConfig.useLibrary(sym, library); } + /** + * Register the component-system (ECS) library. + * + * @param library - ECS library instance. + */ public useComponentSystem(library: IComponentSystemLibrary) { this.applicationConfig.useComponentSystemLibrary(library); } + /** + * Register the network library. + * + * @param library - Network library instance. + */ public useNetwork(library: INetworkLibrary) { this.applicationConfig.useNetworkLibrary(library); } + /** + * Register the asset-manager library. + * + * @param library - Asset manager instance. + */ public useAssetManager(library: IAssetManagerLibrary) { this.applicationConfig.useAssetManagerLibrary(library); } + /** + * Initialise all registered libraries and prepare the engine for the game loop. + * + * @param options - Editor run options including save/load callbacks and canvas container. + */ public init(options: IEditorRunOptions): Promise { this._core = new Core( this.applicationConfig, @@ -50,6 +87,11 @@ export abstract class NanoforgeApplication { return this._core.init(options, this._options); } + /** + * Start the game loop. + * + * @throws `NfNotInitializedException` When called before `init`. + */ public run() { if (!this._core) throw new NfNotInitializedException("Core"); return this._core?.run(); diff --git a/packages/core-editor/src/application/nanoforge-client.ts b/packages/core-editor/src/application/nanoforge-client.ts index 1ddfe4ac..8f799fde 100644 --- a/packages/core-editor/src/application/nanoforge-client.ts +++ b/packages/core-editor/src/application/nanoforge-client.ts @@ -6,15 +6,37 @@ import { import { NanoforgeApplication } from "./nanoforge-application"; +/** + * Client-side NanoForge application for editor mode. + * + * @remarks + * Extends `NanoforgeApplication` with graphics, input, and sound library + * slots. Create via the `core-editor` `NanoforgeFactory`. + */ export class NanoforgeClient extends NanoforgeApplication { + /** + * Register the graphics library. + * + * @param library - Graphics library instance (e.g. Graphics2DLibrary). + */ public useGraphics(library: IGraphicsLibrary) { this.applicationConfig.useGraphicsLibrary(library); } + /** + * Register the input library. + * + * @param library - Input library instance (e.g. InputLibrary). + */ public useInput(library: IInputLibrary) { this.applicationConfig.useInputLibrary(library); } + /** + * Register the sound-effect library. + * + * @param library - Sound library instance (e.g. SoundLibrary). + */ public useSound(library: ISoundLibrary) { this.applicationConfig.useSoundLibrary(library); } diff --git a/packages/core-editor/src/application/nanoforge-factory.ts b/packages/core-editor/src/application/nanoforge-factory.ts index 98ec685e..b0599cbf 100644 --- a/packages/core-editor/src/application/nanoforge-factory.ts +++ b/packages/core-editor/src/application/nanoforge-factory.ts @@ -3,13 +3,41 @@ import { NanoforgeClient } from "./nanoforge-client"; import { NanoforgeServer } from "./nanoforge-server"; class NanoforgeFactoryStatic { + /** + * Create a new editor-mode client application. + * + * @param options - Optional application settings (e.g. tickRate). + * @returns A pre-configured `NanoforgeClient` instance. + */ createClient(options?: Partial): NanoforgeClient { return new NanoforgeClient(options); } + /** + * Create a new editor-mode server application. + * + * @param options - Optional application settings (e.g. tickRate). + * @returns A pre-configured `NanoforgeServer` instance. + */ createServer(options?: Partial): NanoforgeServer { return new NanoforgeServer(options); } } +/** + * Singleton factory for creating editor-mode NanoForge client and server + * applications. + * + * @remarks + * Use `NanoforgeFactory.createClient` or + * `NanoforgeFactory.createServer` to obtain an application instance that + * accepts `IEditorRunOptions` on `init`. + * + * @example + * ```ts + * import `NanoforgeFactory ` from "@nanoforge-dev/core-editor"; + * + * const client = NanoforgeFactory.createClient(); + * ``` + */ export const NanoforgeFactory = new NanoforgeFactoryStatic(); diff --git a/packages/core-editor/src/application/nanoforge-server.ts b/packages/core-editor/src/application/nanoforge-server.ts index 74cca8a8..5dfdb20d 100644 --- a/packages/core-editor/src/application/nanoforge-server.ts +++ b/packages/core-editor/src/application/nanoforge-server.ts @@ -1,3 +1,10 @@ import { NanoforgeApplication } from "./nanoforge-application"; +/** + * Server-side NanoForge application for editor mode. + * + * @remarks + * Extends `NanoforgeApplication` for use in server processes during + * editor sessions. Create via the `core-editor` `NanoforgeFactory`. + */ export class NanoforgeServer extends NanoforgeApplication {} diff --git a/packages/core-editor/src/common/context/event-emitter.type.ts b/packages/core-editor/src/common/context/event-emitter.type.ts index c90caba3..790bddd1 100644 --- a/packages/core-editor/src/common/context/event-emitter.type.ts +++ b/packages/core-editor/src/common/context/event-emitter.type.ts @@ -1,24 +1,67 @@ +/** + * Events that the NanoForge editor can emit to the running engine. + */ export enum EventTypeEnum { + /** Reload modules without restarting the engine (live-patch). */ HOT_RELOAD = "hot-reload", + /** Fully restart the engine with the latest changes. */ HARD_RELOAD = "hard-reload", } +/** Callback signature for event listeners. */ export type ListenerType = (...args: any[]) => void; +/** + * Simple event emitter interface used for communication between the NanoForge + * editor and the running engine. + * + * @remarks + * Listeners are queued and processed via `runEvents` to keep the engine + * loop deterministic. + */ export interface IEventEmitter { + /** Map of event names to their registered listeners. */ listeners: Record; + /** Queue of events waiting to be dispatched by `runEvents`. */ eventQueue: { event: EventTypeEnum | string; args: any[] }[]; + /** Drain the event queue and invoke all matching listeners. */ runEvents: () => void; + /** + * Enqueue an event for dispatching on the next `runEvents` call. + * + * @param event - Event name or EventTypeEnum value. + * @param args - Optional arguments forwarded to listeners. + */ emitEvent: (event: EventTypeEnum, ...args: any) => void; + /** + * Register a listener for an event. Alias: `on`. + * + * @param event - Event name to subscribe to. + * @param listener - Callback invoked when the event fires. + */ addListener: (event: EventTypeEnum | string, listener: ListenerType) => void; + /** Alias for `addListener`. */ on: (event: EventTypeEnum | string, listener: ListenerType) => void; + /** + * Remove a previously registered listener. Alias: `off`. + * + * @param event - Event name to unsubscribe from. + * @param listener - The exact listener function to remove. + */ removeListener: (event: EventTypeEnum | string, listener: ListenerType) => void; + /** Alias for `removeListener`. */ off: (event: EventTypeEnum | string, listener: ListenerType) => void; + /** + * Remove all listeners registered for a specific event. + * + * @param event - Event name whose listeners should be cleared. + */ removeListenersForEvent: (event: EventTypeEnum | string) => void; + /** Remove every registered listener across all events. */ removeAllListeners: () => void; } diff --git a/packages/core-editor/src/common/context/options.type.ts b/packages/core-editor/src/common/context/options.type.ts index 6fde00b6..d8a09fdf 100644 --- a/packages/core-editor/src/common/context/options.type.ts +++ b/packages/core-editor/src/common/context/options.type.ts @@ -1,24 +1,54 @@ import { type IEventEmitter } from "./event-emitter.type"; import { type Save } from "./save.type"; +/** + * Union of client and server editor run options accepted by + * `NanoforgeApplication.init` in editor mode. + */ export type IEditorRunOptions = IEditorRunClientOptions | IEditorRunServerOptions; +/** + * Run options for a client-side editor application. + * + * @remarks + * Extends the base run options with editor-specific communication channels. + */ export interface IEditorRunClientOptions { + /** DOM element that will host the game canvas. */ container: HTMLDivElement; + /** Map of virtual file paths to their resolved URL strings. */ files: Map; + /** Runtime environment variables available to all libraries. */ env: Record; + /** Editor integration hooks. */ editor: { + /** Serialised scene state loaded or saved by the editor. */ save: Save; + /** Event emitter for core-to-editor communication. */ coreEvents: IEventEmitter; + /** Event emitter for editor-to-core communication. */ editorEvents: IEventEmitter; }; } + +/** + * Run options for a server-side editor application. + * + * @remarks + * Extends the base server run options with editor-specific communication channels. + */ export interface IEditorRunServerOptions { + /** Map of virtual file paths to their resolved URL strings. */ files: Map; + /** Runtime environment variables available to all libraries. */ env: Record; + /** Editor integration hooks. */ editor: { + /** Serialised scene state loaded or saved by the editor. */ save: Save; + /** Event emitter for core-to-editor communication. */ coreEvents: IEventEmitter; + /** Event emitter for editor-to-core communication. */ editorEvents: IEventEmitter; }; } diff --git a/packages/core-editor/src/common/context/save.type.ts b/packages/core-editor/src/common/context/save.type.ts index 36372a33..2337b8bc 100644 --- a/packages/core-editor/src/common/context/save.type.ts +++ b/packages/core-editor/src/common/context/save.type.ts @@ -1,3 +1,6 @@ +/** + * Identifies the role a library plays in a saved scene. + */ export enum SaveLibraryTypeEnum { COMPONENT_SYSTEM = "component-system", GRAPHICS = "graphics", @@ -7,32 +10,62 @@ export enum SaveLibraryTypeEnum { SOUND = "sound", } +/** + * Serialised representation of a registered library in a saved scene. + */ export interface SaveLibrary { + /** Unique identifier for this library instance in the scene. */ id: string; + /** Library role (one of `SaveLibraryTypeEnum` or a custom string). */ type: SaveLibraryTypeEnum | string; + /** Human-readable name of the library. */ name: string; + /** Module path used to import the library at runtime. */ path: string; } +/** + * Serialised representation of an ECS component type in a saved scene. + */ export interface SaveComponent { + /** Component class name. */ name: string; + /** Module path used to import the component at runtime. */ path: string; + /** Names of the constructor parameters exposed in the editor. */ paramsNames: string[]; } +/** + * Serialised representation of an ECS system in a saved scene. + */ export interface SaveSystem { + /** System class name. */ name: string; + /** Module path used to import the system at runtime. */ path: string; } +/** + * Serialised representation of an entity and its component data. + */ export interface SaveEntity { + /** Unique identifier for this entity instance. */ id: string; + /** Map of component name to its property values. */ components: Record>; } +/** + * Root serialised scene state exchanged between the editor and the engine. + */ export interface Save { + /** All libraries registered in the scene. */ libraries: SaveLibrary[]; + /** All component types available in the scene. */ components: SaveComponent[]; + /** All systems active in the scene. */ systems: SaveSystem[]; + /** All spawned entities and their component data. */ entities: SaveEntity[]; } diff --git a/packages/core/README.md b/packages/core/README.md index 7bddd539..c6579dfe 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/core/mint-tsdocs.config.json b/packages/core/mint-tsdocs.config.json index 8e8507c9..e20a2061 100644 --- a/packages/core/mint-tsdocs.config.json +++ b/packages/core/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/core", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/core", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/core/package.json b/packages/core/package.json index 81ad0f04..4758dd4f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/core/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/asset-manager": "workspace:*", @@ -75,7 +75,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/core/src/application/application-options.type.ts b/packages/core/src/application/application-options.type.ts index 57ecc833..071d99ab 100644 --- a/packages/core/src/application/application-options.type.ts +++ b/packages/core/src/application/application-options.type.ts @@ -1,3 +1,12 @@ +/** + * Options accepted by `NanoforgeFactory.createClient` and + * `NanoforgeFactory.createServer`. + */ export interface IApplicationOptions { + /** + * Target game-loop frequency in ticks per second. + * + * @default 60 + */ tickRate: number; } diff --git a/packages/core/src/application/nanoforge-application.ts b/packages/core/src/application/nanoforge-application.ts index 7a5fa520..0c650f45 100644 --- a/packages/core/src/application/nanoforge-application.ts +++ b/packages/core/src/application/nanoforge-application.ts @@ -12,11 +12,31 @@ import { Core } from "../core/core"; import { ApplicationConfig } from "./application-config"; import type { IApplicationOptions } from "./application-options.type"; +/** + * Base class for client and server NanoForge applications. + * + * @remarks + * Do not instantiate directly — use `NanoforgeFactory.createClient` or + * `NanoforgeFactory.createServer` to get a fully configured instance of + * `NanoforgeClient` or `NanoforgeServer`. + * + * @example + * ```ts + * const client = NanoforgeFactory.createClient(`tickRate: 30 `); + * client.useAssetManager(new AssetManagerLibrary()); + * client.useGraphics(new Graphics2DLibrary()); + * await client.init(`container, files, env `); + * client.run(); + * ``` + */ export abstract class NanoforgeApplication { protected applicationConfig: ApplicationConfig; private _core?: Core; private readonly _options: IApplicationOptions; + /** + * @param options - Optional application-level settings such as tickRate. + */ constructor(options?: Partial) { this.applicationConfig = new ApplicationConfig(); @@ -26,22 +46,59 @@ export abstract class NanoforgeApplication { }; } + /** + * Register a library under a custom symbol. + * + * @remarks + * Use this method for libraries that do not have a dedicated shorthand (e.g. + * game-specific custom libraries). For built-in library types prefer the + * typed helpers such as `useAssetManager`, `useNetwork`, etc. + * + * @param sym - Unique symbol identifying the library slot. + * @param library - Library instance to register. + */ public use(sym: symbol, library: ILibrary): void { this.applicationConfig.useLibrary(sym, library); } + /** + * Register the component-system (ECS) library. + * + * @param library - ECS library instance (e.g. ECSClientLibrary or ECSServerLibrary). + */ public useComponentSystem(library: IComponentSystemLibrary) { this.applicationConfig.useComponentSystemLibrary(library); } + /** + * Register the network library. + * + * @param library - Network library instance (e.g. NetworkClientLibrary or NetworkServerLibrary). + */ public useNetwork(library: INetworkLibrary) { this.applicationConfig.useNetworkLibrary(library); } + /** + * Register the asset-manager library. + * + * @param library - Asset manager instance (e.g. AssetManagerLibrary). + */ public useAssetManager(library: IAssetManagerLibrary) { this.applicationConfig.useAssetManagerLibrary(library); } + /** + * Initialise all registered libraries in dependency order and prepare the + * engine for the game loop. + * + * @remarks + * Must be called before `run`. Resolves once every library's `__init` + * hook has completed. + * + * @param options - Run options providing the canvas container, files map, and + * environment variables. + */ public init(options: IRunOptions): Promise { this._core = new Core( this.applicationConfig, @@ -50,6 +107,14 @@ export abstract class NanoforgeApplication { return this._core.init(options, this._options); } + /** + * Start the game loop. + * + * @remarks + * Must be called after `init` has resolved. + * + * @throws `NfNotInitializedException` When called before `init`. + */ public run() { if (!this._core) throw new NfNotInitializedException("Core"); return this._core?.run(); diff --git a/packages/core/src/application/nanoforge-client.ts b/packages/core/src/application/nanoforge-client.ts index 1ddfe4ac..684e132f 100644 --- a/packages/core/src/application/nanoforge-client.ts +++ b/packages/core/src/application/nanoforge-client.ts @@ -6,15 +6,49 @@ import { import { NanoforgeApplication } from "./nanoforge-application"; +/** + * Client-side NanoForge application. + * + * @remarks + * Extends `NanoforgeApplication` with client-specific library slots for + * graphics, input, and sound. Create an instance via + * `NanoforgeFactory.createClient`. + * + * @example + * ```ts + * const client = NanoforgeFactory.createClient(); + * client.useAssetManager(new AssetManagerLibrary()); + * client.useGraphics(new Graphics2DLibrary()); + * client.useInput(new InputLibrary()); + * client.useSound(new SoundLibrary()); + * await client.init(`container, files, env `); + * client.run(); + * ``` + */ export class NanoforgeClient extends NanoforgeApplication { + /** + * Register the graphics library used to render the game. + * + * @param library - Graphics library instance (e.g. Graphics2DLibrary). + */ public useGraphics(library: IGraphicsLibrary) { this.applicationConfig.useGraphicsLibrary(library); } + /** + * Register the input library used to read keyboard and mouse state. + * + * @param library - Input library instance (e.g. InputLibrary). + */ public useInput(library: IInputLibrary) { this.applicationConfig.useInputLibrary(library); } + /** + * Register the sound-effect library. + * + * @param library - Sound library instance (e.g. SoundLibrary). + */ public useSound(library: ISoundLibrary) { this.applicationConfig.useSoundLibrary(library); } diff --git a/packages/core/src/application/nanoforge-factory.ts b/packages/core/src/application/nanoforge-factory.ts index 84711a6d..1c275243 100644 --- a/packages/core/src/application/nanoforge-factory.ts +++ b/packages/core/src/application/nanoforge-factory.ts @@ -3,13 +3,60 @@ import { NanoforgeClient } from "./nanoforge-client"; import { NanoforgeServer } from "./nanoforge-server"; class NanoforgeFactoryStatic { + /** + * Create a new client-side NanoForge application. + * + * @remarks + * Returns a `NanoforgeClient` on which you can call + * `useGraphics`, `useInput`, `useSound`, `useAssetManager`, etc. before + * calling `init` and `run`. + * + * @param options - Optional application settings (e.g. tickRate). + * @returns A pre-configured `NanoforgeClient` instance. + * + * @example + * ```ts + * const client = NanoforgeFactory.createClient(`tickRate: 60 `); + * ``` + */ createClient(options?: Partial): NanoforgeClient { return new NanoforgeClient(options); } + /** + * Create a new server-side NanoForge application. + * + * @remarks + * Returns a `NanoforgeServer` on which you can call + * `useNetwork`, `useAssetManager`, `useComponentSystem`, etc. before calling + * `init` and `run`. + * + * @param options - Optional application settings (e.g. tickRate). + * @returns A pre-configured `NanoforgeServer` instance. + * + * @example + * ```ts + * const server = NanoforgeFactory.createServer(`tickRate: 20 `); + * ``` + */ createServer(options?: Partial): NanoforgeServer { return new NanoforgeServer(options); } } +/** + * Singleton factory for creating NanoForge client and server applications. + * + * @remarks + * Use `NanoforgeFactory.createClient` or + * `NanoforgeFactory.createServer` to obtain a new application instance, + * then attach libraries and call `init` / `run`. + * + * @example + * ```ts + * import `NanoforgeFactory ` from "@nanoforge-dev/core"; + * + * const client = NanoforgeFactory.createClient(); + * ``` + */ export const NanoforgeFactory = new NanoforgeFactoryStatic(); diff --git a/packages/core/src/application/nanoforge-server.ts b/packages/core/src/application/nanoforge-server.ts index 74cca8a8..5612515b 100644 --- a/packages/core/src/application/nanoforge-server.ts +++ b/packages/core/src/application/nanoforge-server.ts @@ -1,3 +1,20 @@ import { NanoforgeApplication } from "./nanoforge-application"; +/** + * Server-side NanoForge application. + * + * @remarks + * Extends `NanoforgeApplication` for use in Node.js server processes. + * Create an instance via `NanoforgeFactory.createServer`. + * + * @example + * ```ts + * const server = NanoforgeFactory.createServer(); + * server.useAssetManager(new AssetManagerLibrary()); + * server.useNetwork(new NetworkServerLibrary()); + * server.useComponentSystem(new ECSServerLibrary()); + * await server.init(`files, env `); + * server.run(); + * ``` + */ export class NanoforgeServer extends NanoforgeApplication {} diff --git a/packages/ecs-client/README.md b/packages/ecs-client/README.md index 946e03bc..08a05abb 100644 --- a/packages/ecs-client/README.md +++ b/packages/ecs-client/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/ecs-client/mint-tsdocs.config.json b/packages/ecs-client/mint-tsdocs.config.json index c3949bc2..142757d9 100644 --- a/packages/ecs-client/mint-tsdocs.config.json +++ b/packages/ecs-client/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/ecs-client", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/ecs-client", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/ecs-client/package.json b/packages/ecs-client/package.json index 554030f3..5280b94a 100644 --- a/packages/ecs-client/package.json +++ b/packages/ecs-client/package.json @@ -59,7 +59,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/ecs-client/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*", @@ -80,7 +80,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/ecs-client/src/ecs-client-library.ts b/packages/ecs-client/src/ecs-client-library.ts index 07073a37..a5aaab4a 100644 --- a/packages/ecs-client/src/ecs-client-library.ts +++ b/packages/ecs-client/src/ecs-client-library.ts @@ -3,16 +3,35 @@ import { AbstractECSLibrary } from "@nanoforge-dev/ecs-lib"; import { default as Module } from "../lib/libecs"; +/** + * Client-side ECS library backed by the compiled WASM module. + * + * @remarks + * Loads `libecs.wasm` from the asset manager and initialises the entity + * registry. Register with the application: + * + * ```ts + * client.useComponentSystem(new ECSClientLibrary()); + * ``` + * + * Access the registry in game code: + * ```ts + * const ecs = ctx.libraries.getComponentSystem().library; + * const entity = ecs.registry.spawnEntity(); + * ``` + */ export class ECSClientLibrary extends AbstractECSLibrary { constructor() { super(); this.path = "libecs.wasm"; } + /** @internal */ get __name(): string { return "ECSLibrary"; } + /** @internal */ override async __init(context: InitContext): Promise { const wasmFile = context.libraries.getAssetManager().library.getAsset(this.path); this.module = await Module({ locateFile: () => wasmFile.path }); diff --git a/packages/ecs-lib/README.md b/packages/ecs-lib/README.md index 4034c004..26e3cb9d 100644 --- a/packages/ecs-lib/README.md +++ b/packages/ecs-lib/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/ecs-lib/docs/Doxyfile b/packages/ecs-lib/docs/Doxyfile deleted file mode 100644 index ac943517..00000000 --- a/packages/ecs-lib/docs/Doxyfile +++ /dev/null @@ -1,7 +0,0 @@ -GENERATE_XML = YES -GENERATE_HTML = NO -GENERATE_LATEX = NO - -INPUT = ../wasm - -OUTPUT_DIRECTORY = . diff --git a/packages/ecs-lib/docs/index.rst b/packages/ecs-lib/docs/index.rst deleted file mode 100644 index 12c7339a..00000000 --- a/packages/ecs-lib/docs/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -ECS Documentation -================= - -.. toctree:: - - - wasm.rst - api/typescript.rst diff --git a/packages/ecs-lib/docs/typescript.rst b/packages/ecs-lib/docs/typescript.rst deleted file mode 100644 index 04058040..00000000 --- a/packages/ecs-lib/docs/typescript.rst +++ /dev/null @@ -1,8 +0,0 @@ -Typescript -========== - -.. .. js:autoclass:: AbstractECSLibrary -.. :members: - -.. .. js::typealias:: ECSElementDefaults -.. :members: diff --git a/packages/ecs-lib/docs/wasm.rst b/packages/ecs-lib/docs/wasm.rst deleted file mode 100644 index bd9ea6b2..00000000 --- a/packages/ecs-lib/docs/wasm.rst +++ /dev/null @@ -1,11 +0,0 @@ -C++ classes ------------ - -.. doxygenclass:: nfo::Registry - :members: - -.. doxygenclass:: nfo::Entity - :members: - -.. doxygenclass:: nfo::SparseArray - :members: diff --git a/packages/ecs-lib/mint-tsdocs.config.json b/packages/ecs-lib/mint-tsdocs.config.json index c6cbbc4c..c8a98897 100644 --- a/packages/ecs-lib/mint-tsdocs.config.json +++ b/packages/ecs-lib/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/ecs-lib", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/ecs-lib", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/ecs-lib/package.json b/packages/ecs-lib/package.json index 0b434c5b..d45d34ff 100644 --- a/packages/ecs-lib/package.json +++ b/packages/ecs-lib/package.json @@ -57,7 +57,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/ecs-lib/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*" @@ -75,7 +75,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/ecs-lib/src/ecs-library.abstract.ts b/packages/ecs-lib/src/ecs-library.abstract.ts index fa1ebecd..8914aec0 100644 --- a/packages/ecs-lib/src/ecs-library.abstract.ts +++ b/packages/ecs-lib/src/ecs-library.abstract.ts @@ -8,12 +8,24 @@ import { import { type MainModule, type Registry } from "../lib/libecs"; /** - * Abstract class representing an ECS (Entity Component System) library. - * Extends the BaseComponentSystemLibrary to provide ECS-specific functionality. - * Manages a registry of systems and ensures proper initialization before use. - * @abstract - * @class AbstractECSLibrary - * @extends {BaseComponentSystemLibrary} + * Abstract base class for WASM-backed ECS (Entity Component System) libraries. + * + * @remarks + * Loads a compiled `libecs.wasm` binary via the asset manager and initialises + * a `Registry` from the resulting module. Concrete subclasses only need to + * set `this.path` (the asset path to the `.wasm` file) and call `super()` + * — see `ECSClientLibrary` and `ECSServerLibrary`. + * + * Requires the `ASSET_MANAGER_LIBRARY` dependency and runs after + * `GRAPHICS_LIBRARY`. + * + * @example + * ```ts + * // Inside a system's __run hook: + * const ecs = ctx.libraries.getComponentSystem().library; + * const player = ecs.registry.spawnEntity(); + * ecs.registry.addComponent(player, new PositionComponent(0, 0)); + * ``` */ export abstract class AbstractECSLibrary extends BaseComponentSystemLibrary { protected module?: MainModule; @@ -28,22 +40,23 @@ export abstract class AbstractECSLibrary extends BaseComponentSystemLibrary { }); } + /** @internal */ abstract override get __name(): string; - /** - * Runs the ECS systems using the provided context. - * @param ctx - The context to be used for running the systems. - * @returns A promise that resolves when the systems have been run. - */ + /** @internal */ async __run(ctx: Context): Promise { if (!this._registry) this.throwNotInitializedError(); this._registry.runSystems(ctx); } /** - * Gets the registry. - * @throws Will throw an error if the library is not initialized. - * @returns The registry. + * The WASM-backed entity/component registry. + * + * @remarks + * Use this to spawn entities, register components, add systems, and query + * component data. + * + * @throws `NfNotInitializedException` When accessed before `__init` has resolved. */ get registry(): Registry { if (!this._registry) this.throwNotInitializedError(); diff --git a/packages/ecs-server/README.md b/packages/ecs-server/README.md index 1682813e..104b97e6 100644 --- a/packages/ecs-server/README.md +++ b/packages/ecs-server/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/ecs-server/mint-tsdocs.config.json b/packages/ecs-server/mint-tsdocs.config.json index fe7a6504..ee0748a4 100644 --- a/packages/ecs-server/mint-tsdocs.config.json +++ b/packages/ecs-server/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/ecs-server", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/ecs-server", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/ecs-server/package.json b/packages/ecs-server/package.json index 32c75cb0..7262cd51 100644 --- a/packages/ecs-server/package.json +++ b/packages/ecs-server/package.json @@ -59,7 +59,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/ecs-server/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*", @@ -80,7 +80,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/ecs-server/src/ecs-server-library.ts b/packages/ecs-server/src/ecs-server-library.ts index ba77c21f..efa17691 100644 --- a/packages/ecs-server/src/ecs-server-library.ts +++ b/packages/ecs-server/src/ecs-server-library.ts @@ -3,16 +3,35 @@ import { AbstractECSLibrary } from "@nanoforge-dev/ecs-lib"; import { default as Module } from "../lib/libecs"; +/** + * Server-side ECS library backed by the compiled WASM module. + * + * @remarks + * Loads `libecs.wasm` from the asset manager and initialises the entity + * registry. Register with the application: + * + * ```ts + * server.useComponentSystem(new ECSServerLibrary()); + * ``` + * + * Access the registry in game code: + * ```ts + * const ecs = ctx.libraries.getComponentSystem().library; + * const entity = ecs.registry.spawnEntity(); + * ``` + */ export class ECSServerLibrary extends AbstractECSLibrary { constructor() { super(); this.path = "libecs.wasm"; } + /** @internal */ get __name(): string { return "ECSLibrary"; } + /** @internal */ override async __init(context: InitContext): Promise { const wasmFile = context.libraries.getAssetManager().library.getAsset(this.path); this.module = await Module({ locateFile: () => wasmFile.path }); diff --git a/packages/graphics-2d/README.md b/packages/graphics-2d/README.md index 3323f6e9..2781e486 100644 --- a/packages/graphics-2d/README.md +++ b/packages/graphics-2d/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/graphics-2d/mint-tsdocs.config.json b/packages/graphics-2d/mint-tsdocs.config.json index 7a7a6b03..79d49bd5 100644 --- a/packages/graphics-2d/mint-tsdocs.config.json +++ b/packages/graphics-2d/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/graphics-2d", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/graphics-2d", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/graphics-2d/package.json b/packages/graphics-2d/package.json index 1c94a9a3..62d0f722 100644 --- a/packages/graphics-2d/package.json +++ b/packages/graphics-2d/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/graphics-2d/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*", @@ -72,7 +72,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/graphics-2d/src/exports/konva.ts b/packages/graphics-2d/src/exports/konva.ts index cbc371b4..77c76cf1 100644 --- a/packages/graphics-2d/src/exports/konva.ts +++ b/packages/graphics-2d/src/exports/konva.ts @@ -160,72 +160,107 @@ export type Wedge = Konva.Wedge; export type WedgeConfig = Konva.WedgeConfig; +/** @internal */ export const _global = Konva._global; +/** @internal */ export const _injectGlobal = Konva._injectGlobal; +/** @internal */ export const _mouseDblClickPointerId = Konva._mouseDblClickPointerId; +/** @internal */ export const _mouseInDblClickWindow = Konva._mouseInDblClickWindow; +/** @internal */ export const _mouseListenClick = Konva._mouseListenClick; +/** @internal */ export const _pointerDblClickPointerId = Konva._pointerDblClickPointerId; +/** @internal */ export const _pointerInDblClickWindow = Konva._pointerInDblClickWindow; +/** @internal */ export const _pointerListenClick = Konva._pointerListenClick; +/** @internal */ export const _renderBackend = Konva._renderBackend; +/** @internal */ export const _touchDblClickPointerId = Konva._touchDblClickPointerId; +/** @internal */ export const _touchInDblClickWindow = Konva._touchInDblClickWindow; +/** @internal */ export const _touchListenClick = Konva._touchListenClick; +/** @internal */ export const angleDeg = Konva.angleDeg; +/** @internal */ export const autoDrawEnabled = Konva.autoDrawEnabled; +/** @internal */ export const capturePointerEventsEnabled = Konva.capturePointerEventsEnabled; +/** @internal */ export const dblClickWindow = Konva.dblClickWindow; +/** @internal */ export const document = Konva.document; +/** @internal */ export const dragButtons = Konva.dragButtons; +/** @internal */ export const dragDistance = Konva.dragDistance; +/** @internal */ export const enableTrace = Konva.enableTrace; +/** @internal */ export const getAngle = Konva.getAngle; +/** @internal */ export const hitOnDragEnabled = Konva.hitOnDragEnabled; +/** @internal */ export const isBrowser = Konva.isBrowser; +/** @internal */ export const isDragReady = Konva.isDragReady; +/** @internal */ export const isDragging = Konva.isDragging; +/** @internal */ export const isTransforming = Konva.isTransforming; +/** @internal */ export const isUnminified = Konva.isUnminified; +/** @internal */ export const legacyTextRendering = Konva.legacyTextRendering; +/** @internal */ export const pixelRatio = Konva.pixelRatio; +/** @internal */ export const pointerEventsEnabled = Konva.pointerEventsEnabled; +/** @internal */ export const releaseCanvasOnDestroy = Konva.releaseCanvasOnDestroy; +/** @internal */ export const shapes = Konva.shapes; +/** @internal */ export const showWarnings = Konva.showWarnings; +/** @internal */ export const stages = Konva.stages; +/** @internal */ export const version = Konva.version; diff --git a/packages/graphics-2d/src/graphics-2d.library.ts b/packages/graphics-2d/src/graphics-2d.library.ts index 7237cffa..87810256 100644 --- a/packages/graphics-2d/src/graphics-2d.library.ts +++ b/packages/graphics-2d/src/graphics-2d.library.ts @@ -2,24 +2,61 @@ import { BaseGraphicsLibrary, type InitContext } from "@nanoforge-dev/common"; import * as Graphics from "./exports/konva"; +/** + * Built-in 2D graphics library powered by [Konva](https://konvajs.org/). + * + * @remarks + * Creates a full-window Konva `Stage` and a default `Layer` during + * initialisation. Game code interacts with the stage and layer directly to + * add shapes, images, and animations. Register with the application: + * + * ```ts + * client.useGraphics(new Graphics2DLibrary()); + * ``` + * + * Access in game code: + * ```ts + * const gfx = ctx.libraries.getGraphics().library; + * const rect = new Konva.Rect(`x: 10, y: 10, width: 100, height: 50, fill: "red" `); + * gfx.baseLayer.add(rect); + * ``` + */ export class Graphics2DLibrary extends BaseGraphicsLibrary { private _stage?: Graphics.Stage; private _baseLayer?: Graphics.Layer; + /** @internal */ get __name(): string { return "Graphics2DLibrary"; } + /** + * The Konva `Stage` that covers the container element. + * + * @remarks + * Initialised to the container's `offsetWidth` × `offsetHeight` dimensions. + * + * @throws `NfNotInitializedException` When accessed before `__init` has resolved. + */ get stage(): Graphics.Stage { if (!this._stage) this.throwNotInitializedError(); return this._stage; } + /** + * The default Konva `Layer` automatically added to the stage. + * + * @remarks + * Add shapes and nodes to this layer for them to appear on screen. + * + * @throws `NfNotInitializedException` When accessed before `__init` has resolved. + */ get baseLayer(): Graphics.Layer { if (!this._baseLayer) this.throwNotInitializedError(); return this._baseLayer; } + /** @internal */ public override async __init(context: InitContext): Promise { if (!context.container) { throw new Error("Can't initialize the container context"); @@ -33,5 +70,6 @@ export class Graphics2DLibrary extends BaseGraphicsLibrary { this._stage.add(this._baseLayer); } + /** @internal */ public async __run(): Promise {} } diff --git a/packages/input/README.md b/packages/input/README.md index 37f1c75b..8b0d0b41 100644 --- a/packages/input/README.md +++ b/packages/input/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/input/mint-tsdocs.config.json b/packages/input/mint-tsdocs.config.json index 14ab24e0..9d091683 100644 --- a/packages/input/mint-tsdocs.config.json +++ b/packages/input/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/input", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/input", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/input/package.json b/packages/input/package.json index d43566ac..af79aa65 100644 --- a/packages/input/package.json +++ b/packages/input/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/input/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*" @@ -71,7 +71,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/input/src/input.enum.ts b/packages/input/src/input.enum.ts index 1cb53165..b52421a1 100644 --- a/packages/input/src/input.enum.ts +++ b/packages/input/src/input.enum.ts @@ -1,3 +1,22 @@ +/** + * Enumeration of keyboard keys and mouse buttons supported by + * `InputLibrary`. + * + * @remarks + * Values correspond to the `KeyboardEvent.code` string for keyboard keys and + * to synthetic button identifiers for mouse buttons. Use with + * `InputLibrary.isKeyPressed` and `InputLibrary.isDragging`. + * + * @example + * ```ts + * if (input.isKeyPressed(InputEnum.Space)) { + * player.jump(); + * } + * if (input.isDragging(InputEnum.MouseLeft)) { + * camera.pan(input.getDragState()); + * } + * ``` + */ export enum InputEnum { Escape = "Escape", Digit1 = "Digit1", diff --git a/packages/input/src/input.library.ts b/packages/input/src/input.library.ts index 103d93f3..4dfb13da 100644 --- a/packages/input/src/input.library.ts +++ b/packages/input/src/input.library.ts @@ -4,6 +4,26 @@ import { InputHandler } from "./input-handler"; import { type InputEnum } from "./input.enum"; import { type DragState, type MouseState, type WheelState } from "./mouse.types"; +/** + * Built-in input library. + * + * @remarks + * Listens to browser `keydown`, `keyup`, `mousedown`, `mouseup`, `mousemove`, + * and `wheel` events and exposes a per-frame snapshot of the current input + * state. Must be registered after the graphics library because it uses + * `runAfter: [GRAPHICS_LIBRARY]`. + * + * Register with the application: + * ```ts + * client.useInput(new InputLibrary()); + * ``` + * + * Access in a system's `__run` hook: + * ```ts + * const input = ctx.libraries.getInput().library; + * if (input.isKeyPressed(InputEnum.Space)) player.jump(); + * ``` + */ export class InputLibrary extends BaseInputLibrary { private _inputHandler?: InputHandler; @@ -11,24 +31,41 @@ export class InputLibrary extends BaseInputLibrary { super({ runAfter: [GRAPHICS_LIBRARY] }); } + /** @internal */ get __name(): string { return "InputLibrary"; } + /** @internal */ public override async __init(): Promise { this._inputHandler = new InputHandler(); } + /** @internal */ public override async __run() { if (!this._inputHandler) this.throwNotInitializedError(); this._inputHandler.resetPerFrame(); } + /** + * Return whether a key or mouse button is currently held down. + * + * @param key - The key or button to query (see InputEnum). + * @returns `true` when the key is pressed, `false` when released, + * `undefined` when the key has never been seen. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public isKeyPressed(key: InputEnum): boolean | undefined { if (!this._inputHandler) this.throwNotInitializedError(); return this._inputHandler.getKeyStatus(key); } + /** + * Return a list of all keys and mouse buttons that are currently pressed. + * + * @returns Array of `InputEnum` values for all currently-down inputs. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public getPressedKeys(): InputEnum[] { if (!this._inputHandler) this.throwNotInitializedError(); const res: InputEnum[] = []; @@ -39,26 +76,61 @@ export class InputLibrary extends BaseInputLibrary { return res; } + /** + * Return the current mouse cursor position. + * + * @returns Object with `x` and `y` in CSS pixels. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public getMousePosition(): { x: number; y: number } { if (!this._inputHandler) this.throwNotInitializedError(); return this._inputHandler.getMousePosition(); } + /** + * Return the full mouse state snapshot for the current frame. + * + * @returns `MouseState` containing position, previous position, deltas, and focus. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public getMouseState(): MouseState { if (!this._inputHandler) this.throwNotInitializedError(); return this._inputHandler.mouse; } + /** + * Return whether a drag operation is in progress. + * + * @param button - If provided, only returns true when a drag was started + * with this specific button. + * @returns `true` when a drag is active (optionally matching the given button). + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public isDragging(button?: InputEnum): boolean { if (!this._inputHandler) this.throwNotInitializedError(); return this._inputHandler.isDragging(button); } + /** + * Return the current drag state. + * + * @returns `DragState` with start position, current position, and deltas. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public getDragState(): DragState { if (!this._inputHandler) this.throwNotInitializedError(); return this._inputHandler.drag; } + /** + * Return the scroll-wheel state accumulated during the current frame. + * + * @remarks + * All deltas are reset to `0` at the start of the next frame. + * + * @returns `WheelState` with `deltaX`, `deltaY`, and `deltaZ`. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public getWheelState(): WheelState { if (!this._inputHandler) this.throwNotInitializedError(); return this._inputHandler.wheel; diff --git a/packages/input/src/mouse.types.ts b/packages/input/src/mouse.types.ts index b6d95f13..ccc4945a 100644 --- a/packages/input/src/mouse.types.ts +++ b/packages/input/src/mouse.types.ts @@ -1,27 +1,70 @@ import { InputEnum } from "./input.enum"; +/** + * Snapshot of mouse cursor state for the current frame. + * + * @remarks + * Returned by `InputLibrary.getMouseState`. `deltaX` / `deltaY` are + * reset to `0` at the beginning of each frame. + */ export type MouseState = { + /** Current horizontal cursor position in CSS pixels. */ x: number; + /** Current vertical cursor position in CSS pixels. */ y: number; + /** Horizontal cursor position from the previous frame. */ prevX: number; + /** Vertical cursor position from the previous frame. */ prevY: number; + /** Horizontal movement since the previous frame. */ deltaX: number; + /** Vertical movement since the previous frame. */ deltaY: number; + /** `true` while the cursor is inside the game window. */ focus: boolean; }; +/** + * Snapshot of the current drag operation. + * + * @remarks + * Returned by `InputLibrary.getDragState`. A drag becomes active on + * `mousedown` and inactive on `mouseup`. + */ export type DragState = { + /** `true` when a drag is in progress. */ active: boolean; + /** The mouse button that initiated the drag, or `undefined` when inactive. */ button?: InputEnum | undefined; + /** Horizontal cursor position when the drag started. */ startX: number; + /** Vertical cursor position when the drag started. */ startY: number; + /** Current horizontal cursor position during the drag. */ x: number; + /** Current vertical cursor position during the drag. */ y: number; + /** Total horizontal distance dragged from the start position. */ deltaX: number; + /** Total vertical distance dragged from the start position. */ deltaY: number; }; -export type WheelState = { deltaX: number; deltaY: number; deltaZ: number }; +/** + * Snapshot of the scroll wheel state for the current frame. + * + * @remarks + * Returned by `InputLibrary.getWheelState`. All deltas accumulate + * within the frame and are reset to `0` at the start of the next frame. + */ +export type WheelState = { + /** Accumulated horizontal scroll delta. */ + deltaX: number; + /** Accumulated vertical scroll delta. */ + deltaY: number; + /** Accumulated depth (z-axis) scroll delta. */ + deltaZ: number; +}; export const MOUSE_BUTTON_MAP: Partial> = { 0: InputEnum.MouseLeft, diff --git a/packages/music/README.md b/packages/music/README.md index 543e58d5..6cf40351 100644 --- a/packages/music/README.md +++ b/packages/music/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/music/mint-tsdocs.config.json b/packages/music/mint-tsdocs.config.json index 47ae1054..10ddd89b 100644 --- a/packages/music/mint-tsdocs.config.json +++ b/packages/music/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/music", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/music", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/music/package.json b/packages/music/package.json index 217d3297..58e880f9 100644 --- a/packages/music/package.json +++ b/packages/music/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/music/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*" @@ -71,7 +71,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/music/src/music.library.ts b/packages/music/src/music.library.ts index 4c6a0d2c..1a9b904e 100644 --- a/packages/music/src/music.library.ts +++ b/packages/music/src/music.library.ts @@ -1,19 +1,45 @@ import { BaseMusicLibrary, NfNotFound } from "@nanoforge-dev/common"; +/** + * Built-in music library. + * + * @remarks + * Manages a collection of named `HTMLAudioElement` instances and ensures only + * one track plays at a time. Load tracks with `load` and start + * playback with `play`. Register with the application: + * + * ```ts + * client.use(MUSIC_LIBRARY, new MusicLibrary()); + * ``` + * + * Access in game code: + * ```ts + * const music = ctx.libraries.getMusic().library; + * music.load("theme", "/music/main-theme.mp3"); + * music.play("theme"); + * ``` + */ export class MusicLibrary extends BaseMusicLibrary { private muted: boolean = true; private musics?: Map; private current: HTMLAudioElement | null = null; + /** @internal */ get __name(): string { return "NfMusic"; } + /** @internal */ public async __init(): Promise { this.musics = new Map(); this.muted = true; } + /** + * Toggle the muted state of all loaded music tracks. + * + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public mute(): void { if (!this.musics) this.throwNotInitializedError(); this.muted = !this.muted; @@ -24,6 +50,13 @@ export class MusicLibrary extends BaseMusicLibrary { } } + /** + * Stop the currently playing track and start the requested one. + * + * @param music - Key that identifies the track (as passed to load). + * @throws `NfNotFound` When no track is registered under the given key. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public play(music: string): void { if (!this.musics) this.throwNotInitializedError(); const musicElement = this.musics.get(music); @@ -43,6 +76,17 @@ export class MusicLibrary extends BaseMusicLibrary { } } + /** + * Register a music track under a unique key. + * + * @remarks + * Creates an `HTMLAudioElement` from the provided URL. The track respects + * the current muted state at load time. + * + * @param music - Unique key used to reference this track (e.g. "theme"). + * @param file - URL or path to the audio file. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public load(music: string, file: string) { if (!this.musics) this.throwNotInitializedError(); const element = new Audio(file); diff --git a/packages/network-client/README.md b/packages/network-client/README.md index 5bb7313e..4c5ee072 100644 --- a/packages/network-client/README.md +++ b/packages/network-client/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/network-client/mint-tsdocs.config.json b/packages/network-client/mint-tsdocs.config.json index f2a10088..f2b37a87 100644 --- a/packages/network-client/mint-tsdocs.config.json +++ b/packages/network-client/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/network-client", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/network-client", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/network-client/package.json b/packages/network-client/package.json index 6fb4eca3..099314dd 100644 --- a/packages/network-client/package.json +++ b/packages/network-client/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/network-client/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*", @@ -72,7 +72,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/network-client/src/client.network.library.ts b/packages/network-client/src/client.network.library.ts index 76c98189..a3fade86 100644 --- a/packages/network-client/src/client.network.library.ts +++ b/packages/network-client/src/client.network.library.ts @@ -4,17 +4,50 @@ import { ClientConfigNetwork } from "./config.client.network"; import { TCPClient } from "./tcp.client.network"; import { UDPClient } from "./udp.client.network"; +/** + * Built-in network library for client-side applications. + * + * @remarks + * Reads network configuration from the environment via + * `ClientConfigNetwork` and automatically connects to the server over + * TCP (WebSocket), UDP (WebRTC data channel), or both. Register with: + * + * ```ts + * client.useNetwork(new NetworkClientLibrary()); + * ``` + * + * Configuration (via environment variables): + * - `SERVER_ADDRESS` — hostname or IP of the server (required). + * - `SERVER_TCP_PORT` — WebSocket port for TCP (optional). + * - `SERVER_UDP_PORT` — signaling port for UDP/WebRTC (optional). + * - `MAGIC_VALUE` — packet framing delimiter (default: `"PACKET_END"`). + * - `WSS` — set to `"true"` to use `wss://` / `https://` (default: `false`). + * + * After `init`, access the connections via `tcp` and `udp`. + */ export class NetworkClientLibrary extends BaseNetworkLibrary { - // Fast but less reliable send/receive of packets to a UDP server - public udp!: UDPClient; - - // Reliable ordered send/receive of packets to a TCP server + /** + * Reliable, ordered WebSocket-based connection to the server. + * + * @remarks + * Only available when `SERVER_TCP_PORT` was specified in the environment. + */ public tcp!: TCPClient; + /** + * Unreliable, unordered WebRTC data-channel connection to the server. + * + * @remarks + * Only available when `SERVER_UDP_PORT` was specified in the environment. + */ + public udp!: UDPClient; + + /** @internal */ get __name(): string { return "NetworkClientLibrary"; } + /** @internal */ public override async __init(context: InitContext): Promise { const config: ClientConfigNetwork = await context.config.registerConfig(ClientConfigNetwork); diff --git a/packages/network-client/src/config.client.network.ts b/packages/network-client/src/config.client.network.ts index cbbf1044..5ce77966 100644 --- a/packages/network-client/src/config.client.network.ts +++ b/packages/network-client/src/config.client.network.ts @@ -9,26 +9,57 @@ import { TransformToBoolean, } from "@nanoforge-dev/config"; +/** + * Environment-variable configuration for `NetworkClientLibrary`. + * + * @remarks + * Resolved automatically by `IConfigRegistry.registerConfig` during `__init`. + * Set these variables in the environment (or pass them via + * `IRunClientOptions.env`) before running the application. + */ export class ClientConfigNetwork { + /** + * Port of the server's TCP WebSocket endpoint. + * + * @remarks + * Either this or `SERVER_UDP_PORT` (or both) must be set. + */ @Expose() @IsOptional() @IsPort() SERVER_TCP_PORT?: string; + /** + * Port of the server's UDP (WebRTC signaling) endpoint. + * + * @remarks + * Either this or `SERVER_TCP_PORT` (or both) must be set. + */ @Expose() @IsOptional() @IsPort() SERVER_UDP_PORT?: string; + /** Hostname or IP address of the game server. */ @Expose() @IsIpOrFQDN() SERVER_ADDRESS!: string; + /** + * Delimiter bytes appended to each packet for framing. + * + * @default "PACKET_END" + */ @Expose() @Default("PACKET_END") @IsByteLength(2, 64) MAGIC_VALUE!: string; + /** + * Use secure WebSocket (`wss://`) connections. + * + * @default false + */ @Expose() @TransformToBoolean() @IsBoolean() diff --git a/packages/network-client/src/tcp.client.network.ts b/packages/network-client/src/tcp.client.network.ts index 35003e26..33073047 100644 --- a/packages/network-client/src/tcp.client.network.ts +++ b/packages/network-client/src/tcp.client.network.ts @@ -1,7 +1,15 @@ import { buildMagicPacket, parsePacketsFromChunks } from "./utils"; -/** TCPClient - * Reliable ordered send/receive of packets to a TCP server +/** + * Reliable, ordered WebSocket-based client connection to a NanoForge TCP server. + * + * @remarks + * Packets are framed with a configurable magic delimiter so that partial + * WebSocket frames can be reassembled. The connection is established by + * calling `connect` and status can be queried with `isConnected`. + * + * Typical usage is through `NetworkClientLibrary` which instantiates and + * connects this class automatically during `__init`. */ export class TCPClient { private _channel: WebSocket | null = null; @@ -19,9 +27,12 @@ export class TCPClient { } /** - * Initiate a WebSocket connection to the server (e.g. `ws://:`). + * Initiate a WebSocket connection to the server. * - * @returns Promise + * @remarks + * Connects to `ws[s]://:`. Resolves as soon as the connection + * attempt is dispatched (the socket may not be fully open yet — check + * `isConnected`). */ public async connect(): Promise { this.connectToServerWebSocket(); @@ -29,8 +40,6 @@ export class TCPClient { /** * Return `true` when the underlying WebSocket is open. - * - * @returns boolean */ public isConnected(): boolean { return this._channel !== null && this._channel.readyState === WebSocket.OPEN; @@ -39,8 +48,10 @@ export class TCPClient { /** * Send a payload to the server. * - * @param data Uint8Array — raw payload bytes. - * @returns void + * @remarks + * The payload is wrapped in a magic framing packet before being sent. + * + * @param data - Raw payload bytes. */ public sendData(data: Uint8Array): void { if (!this._channel) { @@ -51,9 +62,13 @@ export class TCPClient { } /** - * Return an array of complete packets that were reassembled from received chunks. + * Parse and return all complete packets received since the last call. + * + * @remarks + * Partial packets are retained internally and combined with future chunks + * until they are complete. Call this method once per frame. * - * @returns Uint8Array[] — array of packet buffers. + * @returns Array of complete packet buffers. */ public getReceivedPackets(): Uint8Array[] { const { packets, data, chunkedData } = parsePacketsFromChunks( diff --git a/packages/network-client/src/udp.client.network.ts b/packages/network-client/src/udp.client.network.ts index 3d20e1e6..c15bb0ab 100644 --- a/packages/network-client/src/udp.client.network.ts +++ b/packages/network-client/src/udp.client.network.ts @@ -1,7 +1,16 @@ import { buildMagicPacket, parsePacketsFromChunks } from "./utils"; -/** UDPClient - * Fast but less reliable send/receive of packets to a UDP server +/** + * Unreliable, unordered WebRTC data-channel client connection to a NanoForge + * UDP server. + * + * @remarks + * Uses a WebSocket signaling channel to perform the SDP/ICE handshake and then + * communicates over an RTCDataChannel with `ordered: false` and + * `maxRetransmits: 0` for minimal latency. + * + * Typical usage is through `NetworkClientLibrary` which instantiates and + * connects this class automatically during `__init`. */ export class UDPClient { private _channel: RTCDataChannel | null = null; @@ -19,9 +28,12 @@ export class UDPClient { } /** - * Open a WebSocket for signaling, create an RTCPeerConnection and initiate an SDP offer. + * Open the WebSocket signaling channel, create an RTCPeerConnection, and + * complete the SDP/ICE handshake with the server. * - * @returns Promise + * @remarks + * Resolves once the offer has been dispatched. The data channel may become + * open shortly after — check `isConnected`. */ public async connect(): Promise { const webSocket: WebSocket = this.connectToServerWebSocket(); @@ -32,8 +44,6 @@ export class UDPClient { /** * Return `true` when the RTCDataChannel is open. - * - * @returns boolean */ public isConnected(): boolean { return this._channel !== null && this._channel.readyState === "open"; @@ -42,8 +52,10 @@ export class UDPClient { /** * Send a payload on the data channel. * - * @param data Uint8Array — raw payload bytes. - * @returns void + * @remarks + * The payload is wrapped in a magic framing packet before being sent. + * + * @param data - Raw payload bytes. */ public sendData(data: Uint8Array): void { if (!this._channel) { @@ -54,9 +66,13 @@ export class UDPClient { } /** - * Return an array of complete packets reassembled from received data-channel chunks. + * Parse and return all complete packets received since the last call. + * + * @remarks + * Partial packets are retained internally and combined with future chunks + * until they are complete. Call this method once per frame. * - * @returns Uint8Array[] — array of packet buffers. + * @returns Array of complete packet buffers. */ public getReceivedPackets(): Uint8Array[] { const { packets, data, chunkedData } = parsePacketsFromChunks( diff --git a/packages/network-server/README.md b/packages/network-server/README.md index 70de4131..aeb5b00a 100644 --- a/packages/network-server/README.md +++ b/packages/network-server/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/network-server/mint-tsdocs.config.json b/packages/network-server/mint-tsdocs.config.json index 2af3457b..ce8756c1 100644 --- a/packages/network-server/mint-tsdocs.config.json +++ b/packages/network-server/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/network-server", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/network-server", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/network-server/package.json b/packages/network-server/package.json index 10de3887..e2915192 100644 --- a/packages/network-server/package.json +++ b/packages/network-server/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/network-server/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@mapbox/node-pre-gyp": "catalog:network", @@ -76,7 +76,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/network-server/src/config.server.network.ts b/packages/network-server/src/config.server.network.ts index 13923997..b70914df 100644 --- a/packages/network-server/src/config.server.network.ts +++ b/packages/network-server/src/config.server.network.ts @@ -8,32 +8,74 @@ import { IsString, } from "@nanoforge-dev/config"; +/** + * Environment-variable configuration for `NetworkServerLibrary`. + * + * @remarks + * Resolved automatically by `IConfigRegistry.registerConfig` during `__init`. + * Set these variables in the environment (or pass them via + * `IRunServerOptions.env`) before running the application. + */ export class ServerConfigNetwork { + /** + * Port on which the TCP WebSocket server listens. + * + * @remarks + * Either this or `LISTENING_UDP_PORT` (or both) must be set. + */ @Expose() @IsOptional() @IsPort() LISTENING_TCP_PORT?: string; + /** + * Port on which the UDP (WebRTC signaling) WebSocket server listens. + * + * @remarks + * Either this or `LISTENING_TCP_PORT` (or both) must be set. + */ @Expose() @IsOptional() @IsPort() LISTENING_UDP_PORT?: string; + /** + * Network interface address the server binds to. + * + * @default "0.0.0.0" + */ @Expose() @Default("0.0.0.0") @IsIpOrFQDN() LISTENING_INTERFACE!: string; + /** + * Delimiter bytes appended to each packet for framing. + * + * @default "PACKET_END" + */ @Expose() @Default("PACKET_END") @IsByteLength(2, 64) MAGIC_VALUE!: string; + /** + * Path to the TLS certificate file for WSS support. + * + * @remarks + * Must be set together with `WSS_KEY`. + */ @Expose() @IsString() @IsOptional() WSS_CERT?: string; + /** + * Path to the TLS private key file for WSS support. + * + * @remarks + * Must be set together with `WSS_CERT`. + */ @Expose() @IsString() @IsOptional() diff --git a/packages/network-server/src/server.network.library.ts b/packages/network-server/src/server.network.library.ts index c7514b84..a422970d 100644 --- a/packages/network-server/src/server.network.library.ts +++ b/packages/network-server/src/server.network.library.ts @@ -4,17 +4,50 @@ import { ServerConfigNetwork } from "./config.server.network"; import { TCPServer } from "./tcp.server.network"; import { UDPServer } from "./udp.server.network"; +/** + * Built-in network library for server-side applications. + * + * @remarks + * Reads network configuration from the environment via + * `ServerConfigNetwork` and starts TCP (WebSocket) and/or UDP (WebRTC) + * servers. Register with: + * + * ```ts + * server.useNetwork(new NetworkServerLibrary()); + * ``` + * + * Configuration (via environment variables): + * - `LISTENING_INTERFACE` — bind address (default: `"0.0.0.0"`). + * - `LISTENING_TCP_PORT` — WebSocket listen port for TCP (optional). + * - `LISTENING_UDP_PORT` — signaling listen port for UDP (optional). + * - `MAGIC_VALUE` — packet framing delimiter (default: `"PACKET_END"`). + * - `WSS_CERT` / `WSS_KEY` — paths to TLS certificate and key files for WSS (optional). + * + * After `init`, access the servers via `tcp` and `udp`. + */ export class NetworkServerLibrary extends BaseNetworkLibrary { - // Fast but less reliable unordered send/receive to multiple UDP clients + /** + * Unreliable, unordered WebRTC data-channel server for connected clients. + * + * @remarks + * Only available when `LISTENING_UDP_PORT` was specified in the environment. + */ public udp!: UDPServer; - // Reliable ordered send/receive of packets to multiple TCP clients + /** + * Reliable, ordered WebSocket-based server for connected clients. + * + * @remarks + * Only available when `LISTENING_TCP_PORT` was specified in the environment. + */ public tcp!: TCPServer; + /** @internal */ get __name(): string { return "NetworkServerLibrary"; } + /** @internal */ public override async __init(context: InitContext): Promise { const config: ServerConfigNetwork = await context.config.registerConfig(ServerConfigNetwork); diff --git a/packages/network-server/src/tcp.server.network.ts b/packages/network-server/src/tcp.server.network.ts index 10e55344..49394d07 100644 --- a/packages/network-server/src/tcp.server.network.ts +++ b/packages/network-server/src/tcp.server.network.ts @@ -4,8 +4,17 @@ import { type RawData, type WebSocket, WebSocketServer } from "ws"; import { buildMagicPacket, parsePacketsFromChunks, rawDataToUint8Array } from "./utils"; -/** TCPServer - * Reliable ordered send/receive of packets to multiple TCP clients +/** + * Reliable, ordered WebSocket-based server that manages multiple TCP clients. + * + * @remarks + * Each client that connects is assigned a numeric ID. Use + * `getConnectedClients` to enumerate active clients, + * `sendToClient` / `sendToEverybody` to push data, and + * `getReceivedPackets` to consume incoming packets per frame. + * + * Typical usage is through `NetworkServerLibrary` which instantiates and + * starts this class automatically during `__init`. */ export class TCPServer { private _clients = new Map< diff --git a/packages/network-server/src/udp.server.network.ts b/packages/network-server/src/udp.server.network.ts index fd1eaea4..c8dad07c 100644 --- a/packages/network-server/src/udp.server.network.ts +++ b/packages/network-server/src/udp.server.network.ts @@ -5,8 +5,19 @@ import { type RawData, type WebSocket, WebSocketServer } from "ws"; import { buildMagicPacket, parsePacketsFromChunks } from "./utils"; -/** UDPServer - * Fast but less reliable unordered send/receive to multiple UDP clients +/** + * Unreliable, unordered WebRTC data-channel server that manages multiple UDP + * clients. + * + * @remarks + * Uses a WebSocket signaling server to complete SDP/ICE handshakes and then + * communicates over RTCDataChannels. Each connected client is assigned a + * numeric ID. Use `getConnectedClients` to enumerate active clients, + * `sendToClient` / `sendToEverybody` to push data, and + * `getReceivedPackets` to consume incoming packets per frame. + * + * Typical usage is through `NetworkServerLibrary` which instantiates and + * starts this class automatically during `__init`. */ export class UDPServer { private _clients = new Map< @@ -109,7 +120,7 @@ export class UDPServer { * The packet will be framed with the server's configured magic terminator * bytes before being sent. * - * @param clientId - Numeric client identifier returned by `listen()` events + * @param clientId - Numeric client identifier returned by listen() events * @param data - Raw packet bytes (Uint8Array) to send * @returns void */ diff --git a/packages/sound/README.md b/packages/sound/README.md index 93bbc8c2..63e83f28 100644 --- a/packages/sound/README.md +++ b/packages/sound/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/packages/sound/mint-tsdocs.config.json b/packages/sound/mint-tsdocs.config.json index c5b9faee..f28a3e8a 100644 --- a/packages/sound/mint-tsdocs.config.json +++ b/packages/sound/mint-tsdocs.config.json @@ -1,10 +1,13 @@ { "$schema": "./node_modules/mint-tsdocs/lib/schemas/config.schema.json", - "entryPoint": "dist/index.d.cts", - "outputFolder": "../../references/sound", + "entryPoint": "dist/index.d.ts", + "outputFolder": "../../docs/references/sound", "lint": { "eslint": { "enabled": true } + }, + "templates": { + "userTemplateDir": "../../docs/templates" } } diff --git a/packages/sound/package.json b/packages/sound/package.json index 434d2ebd..4c7b3b23 100644 --- a/packages/sound/package.json +++ b/packages/sound/package.json @@ -54,7 +54,7 @@ "prepack": "pnpm run build && pnpm run lint", "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/sound/*'", "release": "cliff-jumper", - "mint-tsdocs": "mint-tsdocs generate" + "docs": "mint-tsdocs generate" }, "dependencies": { "@nanoforge-dev/common": "workspace:*" @@ -71,7 +71,7 @@ "unrun": "catalog:build", "vitest": "catalog:test" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/packages/sound/src/sound.library.ts b/packages/sound/src/sound.library.ts index 986db947..1fd753d9 100644 --- a/packages/sound/src/sound.library.ts +++ b/packages/sound/src/sound.library.ts @@ -1,18 +1,44 @@ import { BaseSoundLibrary, NfNotFound } from "@nanoforge-dev/common"; +/** + * Built-in sound-effect library. + * + * @remarks + * Manages a collection of named `HTMLAudioElement` instances. Load sounds + * with `load` and trigger playback with `play`. Register with + * the application: + * + * ```ts + * client.useSound(new SoundLibrary()); + * ``` + * + * Access in game code: + * ```ts + * const sound = ctx.libraries.getSound().library; + * sound.load("explosion", "/sounds/explosion.mp3"); + * sound.play("explosion"); + * ``` + */ export class SoundLibrary extends BaseSoundLibrary { private muted: boolean = true; private sounds?: Map; + /** @internal */ get __name(): string { return "NfSound"; } + /** @internal */ public async __init(): Promise { this.sounds = new Map(); this.muted = true; } + /** + * Toggle the muted state of all loaded sound effects. + * + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public mute(): void { if (!this.sounds) this.throwNotInitializedError(); this.muted = !this.muted; @@ -23,6 +49,13 @@ export class SoundLibrary extends BaseSoundLibrary { } } + /** + * Play a previously loaded sound effect. + * + * @param sound - Key that identifies the sound (as passed to load). + * @throws `NfNotFound` When no sound is registered under the given key. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public play(sound: string): void { if (!this.sounds) this.throwNotInitializedError(); const soundElement = this.sounds.get(sound); @@ -39,6 +72,17 @@ export class SoundLibrary extends BaseSoundLibrary { } } + /** + * Register a sound effect under a unique key. + * + * @remarks + * Creates an `HTMLAudioElement` from the provided URL. The sound respects + * the current muted state at load time. + * + * @param sound - Unique key used to reference this sound (e.g. "explosion"). + * @param file - URL or path to the audio file. + * @throws `NfNotInitializedException` When called before `__init` has resolved. + */ public load(sound: string, file: string) { if (!this.sounds) this.throwNotInitializedError(); const element = new Audio(file); diff --git a/scripts/sync-docs-references.sh b/scripts/sync-docs-references.sh new file mode 100755 index 00000000..75463387 --- /dev/null +++ b/scripts/sync-docs-references.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT="$SCRIPT_DIR/.." +REFS="$ROOT/docs/references" +PKGS="$ROOT/packages" + +for pkg_dir in "$REFS"/*/; do + pkg="$(basename "$pkg_dir")" + + # skip non-package entries + [[ "$pkg" == "snippets" ]] && continue + [[ ! -d "$PKGS/$pkg" ]] && continue + + inner="$REFS/$pkg/$pkg" + [[ ! -d "$inner" ]] && continue + + echo "Processing: $pkg" + + # delete everything in docs/references/ except the / subdirectory + find "$REFS/$pkg" -mindepth 1 -maxdepth 1 ! -name "$pkg" -exec rm -rf {} + + + # copy the contents of docs/references/// into docs/references// + cp -r "$inner"/. "$REFS/$pkg/" + + # remove the now-redundant inner directory + rm -rf "$inner" + + # copy packages//README.md as 0-index.mdx with a Mintlify title frontmatter + readme="$PKGS/$pkg/README.md" + if [[ -f "$readme" ]]; then + title="$(echo "$pkg" | sed 's/-/ /g; s/\b\(.\)/\u\1/g')" + { printf -- '---\ntitle: "%s"\n---\n\n' "$title"; cat "$readme"; } > "$REFS/$pkg/0-index.mdx" + else + echo " WARNING: no README.md found for $pkg" + fi +done + +echo "Done." \ No newline at end of file diff --git a/turbo.json b/turbo.json index 4a11ab4f..ee6450f8 100644 --- a/turbo.json +++ b/turbo.json @@ -43,17 +43,18 @@ "outputs": [], "outputLogs": "errors-only" }, - "mint-tsdocs": { - "dependsOn": ["^mint-tsdocs"], + "docs": { + "dependsOn": ["^docs"], "inputs": [ "src/**", "wasm/**", "test/**", "package.json", "tsconfig.json", - "mint-tsdocs.config.ts" + "mint-tsdocs.config.ts", + "../../docs/templates/**" ], - "outputs": ["../../references"], + "outputs": ["../../docs/references/**"], "outputLogs": "errors-only" } } diff --git a/utils/eslint-config/README.md b/utils/eslint-config/README.md index e82c032e..107d53c5 100644 --- a/utils/eslint-config/README.md +++ b/utils/eslint-config/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/utils/eslint-config/package.json b/utils/eslint-config/package.json index 92306c86..25790056 100644 --- a/utils/eslint-config/package.json +++ b/utils/eslint-config/package.json @@ -58,7 +58,7 @@ "eslint": "catalog:lint", "prettier": "catalog:lint" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" }, diff --git a/utils/prettier-config/README.md b/utils/prettier-config/README.md index 1705c838..b381f4f6 100644 --- a/utils/prettier-config/README.md +++ b/utils/prettier-config/README.md @@ -7,10 +7,9 @@

npm version npm downloads - Tests status - Documentation status + Tests status Last commit - Contributors + Contributors

diff --git a/utils/prettier-config/package.json b/utils/prettier-config/package.json index 3a86d25e..e05118a0 100644 --- a/utils/prettier-config/package.json +++ b/utils/prettier-config/package.json @@ -47,7 +47,7 @@ "@trivago/prettier-plugin-sort-imports": "catalog:lint", "prettier": "catalog:lint" }, - "packageManager": "pnpm@10.33.0", + "packageManager": "pnpm@11.5.2", "engines": { "node": "25" },