Skip to content

Commit 24b5262

Browse files
author
github-actions[bot]
committed
chore(schematics): updating docs
1 parent f1df09d commit 24b5262

10 files changed

Lines changed: 1684 additions & 0 deletions

File tree

schematics/docs/api.rst

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
API Reference
2+
=============
3+
4+
This section documents the internal utility modules and classes available in the
5+
``src/utils/`` directory.
6+
7+
MainGenerator
8+
-------------
9+
10+
**Module**: ``src/utils/main/main.generator.ts``
11+
12+
A builder-pattern class that programmatically generates the contents of a
13+
NanoForge ``main.ts`` entry point file. Used by the
14+
:ref:`part-main <schematic-part-main>` schematic.
15+
16+
Methods
17+
^^^^^^^
18+
19+
.. method:: generateBaseImports(hasTypes: boolean): MainGenerator
20+
21+
Adds the base NanoForge imports (``IRunOptions`` from ``@nanoforge-dev/common``
22+
and ``NanoforgeFactory`` from ``@nanoforge-dev/core``). Type imports are
23+
conditional on the ``hasTypes`` flag (true for TypeScript, false for
24+
JavaScript).
25+
26+
.. method:: generateLibsImports(libs: SaveLibrary[]): MainGenerator
27+
28+
Generates import statements for all libraries listed in the save file,
29+
sorted alphabetically by import path.
30+
31+
.. method:: generateComponentsImports(components: SaveComponent[]): MainGenerator
32+
33+
Generates import statements for all components, sorted by path.
34+
35+
.. method:: generateSystemsImports(systems: SaveSystem[]): MainGenerator
36+
37+
Generates import statements for all systems, sorted by path.
38+
39+
.. method:: generateMainFunction(hasTypes: boolean, cb: (generator: MainGenerator) => void): MainGenerator
40+
41+
Wraps a callback's output inside an ``export async function main(options) { ... }``
42+
block. The ``hasTypes`` flag controls whether the ``options`` parameter
43+
receives a type annotation.
44+
45+
.. method:: generateApp(isServer: boolean): MainGenerator
46+
47+
Emits ``const app = NanoforgeFactory.createClient()`` or
48+
``NanoforgeFactory.createServer()`` depending on the ``isServer`` flag.
49+
50+
.. method:: generateAppInit(): MainGenerator
51+
52+
Emits ``await app.init(options);``.
53+
54+
.. method:: generateAppRun(hasInitFunctions: boolean): MainGenerator
55+
56+
Emits ``await app.run();``.
57+
58+
.. method:: generateLibsInstances(libs: SaveLibrary[]): MainGenerator
59+
60+
Emits ``const <id> = new <Name>();`` for each library.
61+
62+
.. method:: generateLibsInit(libs: SaveLibrary[]): MainGenerator
63+
64+
Emits the appropriate ``app.use*(<id>);`` call for each library based on
65+
its type (see :ref:`Library Type Mapping <schematic-part-main>`).
66+
67+
.. method:: generateRegistry(libs: SaveLibrary[]): MainGenerator
68+
69+
Emits ``const registry = <ecsLib>.registry;`` where ``<ecsLib>`` is the
70+
library with type ``component-system``.
71+
72+
.. method:: generateEntities(entities: SaveEntity[]): MainGenerator
73+
74+
For each entity, emits ``registry.spawnEntity()`` followed by
75+
``registry.addComponent()`` calls for each component with its parameters.
76+
77+
.. method:: generateSystems(systems: SaveSystem[]): MainGenerator
78+
79+
Emits ``registry.addSystem(<name>);`` for each system.
80+
81+
.. method:: generateInitFunctionIfNeeded(needed: boolean, func: InitFunctionEnum): MainGenerator
82+
83+
Conditionally emits an ``await <func>(app);`` or
84+
``await <func>(app, registry);`` call based on the init function type.
85+
86+
.. method:: generateInitFunctionsImportsIfNeeded(needed: boolean): MainGenerator
87+
88+
Conditionally emits import statements for all six lifecycle init functions.
89+
90+
.. method:: toString(): string
91+
92+
Returns the accumulated generated code as a string.
93+
94+
ConfigFinder
95+
------------
96+
97+
**Module**: ``src/utils/config/config.finder.ts``
98+
99+
Searches the virtual file tree for an existing ``nanoforge.config.json``.
100+
101+
.. method:: find(tree: Tree, path: string): Config | null
102+
103+
Recursively searches from the given path upward through parent directories
104+
for a ``nanoforge.config.json`` file. Returns the parsed ``Config`` object
105+
if found, or ``null`` if no config exists in the tree.
106+
107+
ConfigDeclarator
108+
----------------
109+
110+
**Module**: ``src/utils/config/config.declarator.ts``
111+
112+
Modifies a configuration tree by merging server options.
113+
114+
.. method:: declare(tree: Tree, path: string, server: boolean): void
115+
116+
Reads the ``nanoforge.config.json`` at the given path, deep-merges the
117+
server configuration if ``server`` is ``true``, and writes the result
118+
back to the tree.
119+
120+
Formatting Utilities
121+
--------------------
122+
123+
**Module**: ``src/utils/formatting.ts``
124+
125+
.. function:: toKebabCase(str: string): string
126+
127+
Converts a string to kebab-case. Used to normalize project names for
128+
directory and package naming.
129+
130+
Examples::
131+
132+
toKebabCase("MyProject") // "my-project"
133+
toKebabCase("some string") // "some-string"
134+
135+
Name Utilities
136+
--------------
137+
138+
**Module**: ``src/utils/name.ts``
139+
140+
.. function:: resolvePackageName(path: string): string
141+
142+
Extracts the package name from a path string. Handles scoped packages
143+
(``@scope/name``) by returning only the name portion.
144+
145+
Object Utilities
146+
----------------
147+
148+
**Module**: ``src/utils/object.ts``
149+
150+
.. function:: deepMerge(...objects: object[]): object
151+
152+
Recursively merges multiple objects together. Later objects take precedence
153+
over earlier ones for primitive values. Nested objects are merged recursively
154+
rather than replaced.
155+
156+
.. function:: isObject(item: unknown): boolean
157+
158+
Type guard that returns ``true`` if the item is a plain object (not an array
159+
or null).
160+
161+
Type Definitions
162+
----------------
163+
164+
**Module**: ``src/utils/type.ts``
165+
166+
Shared TypeScript type definitions used across schematics.
167+
168+
Enums
169+
-----
170+
171+
InitFunctionEnum
172+
^^^^^^^^^^^^^^^^
173+
174+
**Module**: ``src/utils/main/enums.ts``
175+
176+
Enumerates the six lifecycle init function names:
177+
178+
.. code-block:: typescript
179+
180+
enum InitFunctionEnum {
181+
BEFORE_INIT = "beforeInit",
182+
AFTER_INIT = "afterInit",
183+
BEFORE_REGISTRY_INIT = "beforeRegistryInit",
184+
AFTER_REGISTRY_INIT = "afterRegistryInit",
185+
BEFORE_RUN = "beforeRun",
186+
AFTER_RUN = "afterRun",
187+
}
188+
189+
SaveLibraryTypeEnum
190+
^^^^^^^^^^^^^^^^^^^
191+
192+
**Module**: ``src/utils/main/save.type.ts``
193+
194+
Enumerates the known library types:
195+
196+
.. code-block:: typescript
197+
198+
enum SaveLibraryTypeEnum {
199+
COMPONENT_SYSTEM = "component-system",
200+
GRAPHICS = "graphics",
201+
ASSET_MANAGER = "asset-manager",
202+
NETWORK = "network",
203+
INPUT = "input",
204+
SOUND = "sound",
205+
}
206+
207+
Constants
208+
---------
209+
210+
LIBS_FUNCTIONS_NAME
211+
^^^^^^^^^^^^^^^^^^^
212+
213+
**Module**: ``src/utils/main/conts.ts``
214+
215+
Maps library types to the corresponding ``app.use*()`` method name:
216+
217+
.. code-block:: typescript
218+
219+
const LIBS_FUNCTIONS_NAME = {
220+
"component-system": "useComponentSystem",
221+
"graphics": "useGraphics",
222+
"asset-manager": "useAssetManager",
223+
"network": "useNetwork",
224+
"input": "useInput",
225+
"sound": "useSound",
226+
};

schematics/docs/architecture.rst

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
Architecture
2+
============
3+
4+
Overview
5+
--------
6+
7+
NanoForge Schematics is built on top of the `Angular DevKit Schematics
8+
<https://angular.dev/tools/cli/schematics>`_ framework. It provides code
9+
generation templates (schematics) that scaffold NanoForge game engine projects,
10+
including project structure, configuration, client/server base code, and
11+
dynamically generated main entry points.
12+
13+
The package is published to npm as ``@nanoforge-dev/schematics`` and ships both
14+
ESM and CommonJS bundles.
15+
16+
Technology Stack
17+
----------------
18+
19+
.. list-table::
20+
:header-rows: 1
21+
:widths: 30 70
22+
23+
* - Component
24+
- Technology
25+
* - Language
26+
- TypeScript (strict mode)
27+
* - Schematic Framework
28+
- Angular DevKit Schematics 21.x
29+
* - Build Tool
30+
- tsup (esbuild-based bundler)
31+
* - Module Formats
32+
- ESM + CJS (dual package)
33+
* - Target
34+
- ES2022
35+
* - Package Manager
36+
- pnpm 10.x
37+
* - Node Version
38+
- 25
39+
* - Linter
40+
- ESLint 9.x
41+
* - Formatter
42+
- Prettier 3.x
43+
* - CI/CD
44+
- GitHub Actions
45+
46+
Project Structure
47+
-----------------
48+
49+
::
50+
51+
src/
52+
+-- index.ts # Public API exports
53+
+-- defaults.ts # Default option values
54+
+-- collection.json # Schematics collection manifest
55+
+-- libs/ # Schematic implementations
56+
| +-- application/ # Application scaffolding
57+
| | +-- application.factory.ts
58+
| | +-- application.options.d.ts
59+
| | +-- application.schema.d.ts
60+
| | +-- schema.json
61+
| | +-- files/ # EJS templates (ts/ and js/)
62+
| +-- configuration/ # Config file generation
63+
| | +-- configuration.factory.ts
64+
| | +-- schema.json
65+
| | +-- files/
66+
| +-- part-base/ # Client/server base structure
67+
| | +-- part-base.factory.ts
68+
| | +-- schema.json
69+
| | +-- files/
70+
| +-- part-main/ # Main file code generation
71+
| +-- part-main.factory.ts
72+
| +-- schema.json
73+
+-- utils/ # Shared utilities
74+
+-- index.ts
75+
+-- formatting.ts # String formatting helpers
76+
+-- name.ts # Package name resolution
77+
+-- object.ts # Deep merge utilities
78+
+-- type.ts # Shared type definitions
79+
+-- config/ # Configuration helpers
80+
| +-- config.type.ts
81+
| +-- config.finder.ts
82+
| +-- config.declarator.ts
83+
+-- main/ # Main file generation
84+
+-- main.generator.ts
85+
+-- main-functions.ts
86+
+-- save.type.ts
87+
+-- enums.ts
88+
+-- conts.ts
89+
90+
Factory Pattern
91+
---------------
92+
93+
Every schematic follows a three-phase factory pattern:
94+
95+
1. **Transform** -- Convert raw schema input (user-provided or prompted values)
96+
into validated internal options with defaults applied.
97+
2. **Generate** -- Load EJS template files from the ``files/`` directory,
98+
interpolate options into the templates, and produce a virtual file tree.
99+
3. **Merge** -- Combine the generated file tree into the target project
100+
directory using Angular DevKit merge strategies.
101+
102+
Each factory module exports a ``main`` function that receives the schema and
103+
returns an Angular DevKit ``Rule``.
104+
105+
.. code-block:: typescript
106+
107+
// Typical factory structure
108+
const transform = (schema: Schema): Options => { /* ... */ };
109+
const generate = (options: Options, path: string): Source => { /* ... */ };
110+
export const main = (schema: Schema): Rule => {
111+
const options = transform(schema);
112+
return mergeWith(generate(options, schema.directory ?? options.name));
113+
};
114+
115+
Collection Manifest
116+
-------------------
117+
118+
The ``collection.json`` file registers all available schematics. Each entry
119+
specifies the factory function, a human-readable description, and the JSON
120+
Schema for input validation.
121+
122+
.. code-block:: json
123+
124+
{
125+
"schematics": {
126+
"application": {
127+
"factory": "./libs/application/application.factory#main",
128+
"description": "Create a NanoForge Base application.",
129+
"schema": "./libs/application/schema.json"
130+
},
131+
"configuration": {
132+
"factory": "./libs/configuration/configuration.factory#main",
133+
"description": "Create a NanoForge Configuration.",
134+
"schema": "./libs/configuration/schema.json"
135+
},
136+
"part-base": {
137+
"factory": "./libs/part-base/part-base.factory#main",
138+
"description": "Create a NanoForge Base for client or server.",
139+
"schema": "./libs/part-base/schema.json"
140+
},
141+
"part-main": {
142+
"factory": "./libs/part-main/part-main.factory#main",
143+
"description": "Create a Main file for client or server.",
144+
"schema": "./libs/part-main/schema.json"
145+
}
146+
}
147+
}
148+
149+
Build Pipeline
150+
--------------
151+
152+
The project uses ``tsup`` for bundling. The build produces:
153+
154+
- A main bundle (ESM + CJS) from ``src/index.ts``
155+
- Per-schematic ESM bundles from each ``*.factory.ts``
156+
- Type declarations (``.d.ts`` and ``.d.cts``)
157+
- Source maps
158+
159+
A ``postbuild`` step copies non-TypeScript assets (``collection.json``, JSON
160+
schemas, and template files) into the ``dist/`` directory using ``cpx2``.
161+
162+
.. code-block:: bash
163+
164+
# Full build
165+
pnpm run build
166+
167+
# What happens internally:
168+
# 1. tsc --noEmit (type checking)
169+
# 2. tsup (bundling)
170+
# 3. copy:collection (collection.json + schema.json files)
171+
# 4. copy:lib (template files)

0 commit comments

Comments
 (0)