@nanoforge-dev/schematics 0.0.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/collection.json +14 -4
  2. package/dist/libs/application/files/js/package.json +9 -1
  3. package/dist/libs/application/files/ts/package.json +9 -1
  4. package/dist/libs/configuration/configuration.factory.d.ts +2 -66
  5. package/dist/libs/configuration/configuration.factory.js +3 -2
  6. package/dist/libs/configuration/configuration.factory.js.map +1 -1
  7. package/dist/libs/configuration/schema.json +2 -73
  8. package/dist/libs/part-base/files/js/__nanoforgeFolder__/client.save.json +69 -0
  9. package/dist/libs/part-base/files/js/__nanoforgeFolder__/server.save.json +41 -0
  10. package/dist/libs/part-base/files/js/__part__/components/example.component.js +72 -0
  11. package/dist/libs/part-base/files/js/__part__/init/after-init.js +12 -0
  12. package/dist/libs/part-base/files/js/__part__/init/after-registry-init.js +14 -0
  13. package/dist/libs/part-base/files/js/__part__/init/after-run.js +12 -0
  14. package/dist/libs/part-base/files/js/__part__/init/before-init.js +13 -0
  15. package/dist/libs/part-base/files/js/__part__/init/before-registry-init.js +14 -0
  16. package/dist/libs/part-base/files/js/__part__/init/before-run.js +12 -0
  17. package/dist/libs/part-base/files/js/__part__/systems/example.system.js +44 -0
  18. package/dist/libs/part-base/files/ts/__nanoforgeFolder__/client.save.json +69 -0
  19. package/dist/libs/part-base/files/ts/__nanoforgeFolder__/server.save.json +41 -0
  20. package/dist/libs/part-base/files/ts/__part__/components/example.component.ts +55 -0
  21. package/dist/libs/part-base/files/ts/__part__/init/after-init.ts +5 -0
  22. package/dist/libs/part-base/files/ts/__part__/init/after-registry-init.ts +6 -0
  23. package/dist/libs/part-base/files/ts/__part__/init/after-run.ts +5 -0
  24. package/dist/libs/part-base/files/ts/__part__/init/before-init.ts +5 -0
  25. package/dist/libs/part-base/files/ts/__part__/init/before-registry-init.ts +6 -0
  26. package/dist/libs/part-base/files/ts/__part__/init/before-run.ts +5 -0
  27. package/dist/libs/part-base/files/ts/__part__/systems/example.system.ts +31 -0
  28. package/dist/libs/part-base/part-base.factory.d.ts +32 -0
  29. package/dist/libs/part-base/part-base.factory.js +71 -0
  30. package/dist/libs/part-base/part-base.factory.js.map +1 -0
  31. package/dist/libs/part-base/schema.json +38 -0
  32. package/dist/libs/part-main/part-main.factory.d.ts +37 -0
  33. package/dist/libs/part-main/part-main.factory.js +223 -0
  34. package/dist/libs/part-main/part-main.factory.js.map +1 -0
  35. package/dist/libs/part-main/schema.json +42 -0
  36. package/package.json +12 -10
@@ -2,14 +2,24 @@
2
2
  "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
3
3
  "schematics": {
4
4
  "application": {
5
- "factory": "./lib/application/application.factory#main",
5
+ "factory": "./libs/application/application.factory#main",
6
6
  "description": "Create a NanoForge Base application.",
7
- "schema": "./lib/application/schema.json"
7
+ "schema": "./libs/application/schema.json"
8
8
  },
9
9
  "configuration": {
10
- "factory": "./lib/configuration/configuration.factory#main",
10
+ "factory": "./libs/configuration/configuration.factory#main",
11
11
  "description": "Create a NanoForge Configuration.",
12
- "schema": "./lib/configuration/schema.json"
12
+ "schema": "./libs/configuration/schema.json"
13
+ },
14
+ "part-base": {
15
+ "factory": "./libs/part-base/part-base.factory#main",
16
+ "description": "Create a NanoForge Base for client or server.",
17
+ "schema": "./libs/part-base/schema.json"
18
+ },
19
+ "part-main": {
20
+ "factory": "./libs/part-main/part-main.factory#main",
21
+ "description": "Create a Main file for client or server.",
22
+ "schema": "./libs/part-main/schema.json"
13
23
  }
14
24
  }
15
25
  }
@@ -9,10 +9,18 @@
9
9
  "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.js\"",
10
10
  "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.js\""
11
11
  },
12
- "dependencies": {},
13
12
  "devDependencies": {
14
13
  "@eslint/js": "^9.39.0",
14
+ "@nanoforge-dev/asset-manager": "^0.0.1",
15
15
  "@nanoforge-dev/cli": "^0.0.1",
16
+ "@nanoforge-dev/common": "^0.0.1",
17
+ "@nanoforge-dev/config": "^0.0.1",
18
+ "@nanoforge-dev/core": "^0.0.1",
19
+ "@nanoforge-dev/ecs": "^0.0.1",
20
+ "@nanoforge-dev/graphics-2d": "^0.0.1",
21
+ "@nanoforge-dev/input": "^0.0.1",
22
+ "@nanoforge-dev/music": "^0.0.1",
23
+ "@nanoforge-dev/sound": "^0.0.1",
16
24
  "eslint": "^9.39.0",
17
25
  "eslint-config-prettier": "^10.1.8",
18
26
  "eslint-plugin-prettier": "^5.5.4",
@@ -9,10 +9,18 @@
9
9
  "lint": "prettier --check . && eslint --format=pretty \"{client,server}/**/*.ts\"",
10
10
  "format": "prettier --write . && eslint --fix --format=pretty \"{client,server}/**/*.ts\""
11
11
  },
12
- "dependencies": {},
13
12
  "devDependencies": {
14
13
  "@eslint/js": "^9.39.0",
14
+ "@nanoforge-dev/asset-manager": "^0.0.1",
15
15
  "@nanoforge-dev/cli": "^0.0.1",
16
+ "@nanoforge-dev/common": "^0.0.1",
17
+ "@nanoforge-dev/config": "^0.0.1",
18
+ "@nanoforge-dev/core": "^0.0.1",
19
+ "@nanoforge-dev/ecs": "^0.0.1",
20
+ "@nanoforge-dev/graphics-2d": "^0.0.1",
21
+ "@nanoforge-dev/input": "^0.0.1",
22
+ "@nanoforge-dev/music": "^0.0.1",
23
+ "@nanoforge-dev/sound": "^0.0.1",
16
24
  "@typescript-eslint/eslint-plugin": "^8.46.2",
17
25
  "@typescript-eslint/parser": "^8.46.2",
18
26
  "eslint": "^9.39.0",
@@ -1,24 +1,5 @@
1
1
  import { Rule } from '@angular-devkit/schematics';
2
2
 
3
- interface BuildConfigurationSchema {
4
- /**
5
- * Entry file of the application
6
- */
7
- entryFile?: string;
8
-
9
- /**
10
- * Output directory of the application
11
- */
12
- outDir?: string;
13
- }
14
-
15
- interface RunConfigurationSchema {
16
- /**
17
- * Directory of the application
18
- */
19
- dir?: string;
20
- }
21
-
22
3
  interface ConfigurationSchema {
23
4
  /**
24
5
  * The name of the application
@@ -31,54 +12,9 @@ interface ConfigurationSchema {
31
12
  directory?: string;
32
13
 
33
14
  /**
34
- * Client configuration
35
- */
36
- client?: {
37
- /**
38
- * Client port
39
- */
40
- port?: string;
41
-
42
- /**
43
- * Game exposure port
44
- */
45
- gameExposurePort?: string;
46
-
47
- /**
48
- * Build configuration
49
- */
50
- build?: BuildConfigurationSchema;
51
-
52
- /**
53
- * Runtime configuration
54
- */
55
- runtime?: RunConfigurationSchema;
56
- };
57
-
58
- /**
59
- * Server configuration
15
+ * Configure a server for the application
60
16
  */
61
- server?: {
62
- /**
63
- * Enable server configuration
64
- */
65
- enable?: boolean;
66
-
67
- /**
68
- * Server port
69
- */
70
- port?: string;
71
-
72
- /**
73
- * Build configuration
74
- */
75
- build?: BuildConfigurationSchema;
76
-
77
- /**
78
- * Runtime configuration
79
- */
80
- runtime?: RunConfigurationSchema;
81
- };
17
+ server?: boolean;
82
18
  }
83
19
 
84
20
  declare const main: (schema: ConfigurationSchema) => Rule;
@@ -131,8 +131,9 @@ var resolvePackageName = /* @__PURE__ */ __name((path) => {
131
131
  // src/libs/configuration/configuration.factory.ts
132
132
  var transform = /* @__PURE__ */ __name((schema) => {
133
133
  return {
134
- client: schema.client,
135
- server: schema.server
134
+ server: {
135
+ enable: schema.server ?? false
136
+ }
136
137
  };
137
138
  }, "transform");
138
139
  var generate = /* @__PURE__ */ __name((options, path) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/libs/configuration/configuration.factory.ts","../../../src/utils/object.ts","../../../src/defaults.ts","../../../src/utils/config/config.declarator.ts","../../../src/utils/config/config.finder.ts","../../../src/utils/formatting.ts","../../../src/utils/name.ts"],"sourcesContent":["import { type Path, join, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n branchAndMerge,\n chain,\n mergeWith,\n move,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { ConfigDeclarator } from \"@utils/config/config.declarator\";\nimport { ConfigFinder } from \"@utils/config/config.finder\";\nimport { toKebabCase } from \"@utils/formatting\";\nimport { resolvePackageName } from \"@utils/name\";\n\nimport { DEFAULT_APP_NAME } from \"~/defaults\";\n\nimport { type ConfigurationOptions } from \"./configuration.options\";\nimport { type ConfigurationSchema } from \"./configuration.schema\";\n\nconst transform = (schema: ConfigurationSchema): ConfigurationOptions => {\n return {\n client: schema.client,\n server: schema.server,\n };\n};\n\nconst generate = (options: ConfigurationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path)), [\n template({\n ...strings,\n ...options,\n }),\n move(path),\n ]);\n};\n\nconst addConfiguration = (options: ConfigurationOptions, path: Path) => {\n return (tree: Tree) => {\n const config = new ConfigFinder(tree).find(path);\n if (!config) return tree;\n\n const content = tree.read(config)?.toString();\n const declarator = new ConfigDeclarator();\n\n if (!content) return tree;\n\n tree.overwrite(config, declarator.declare(content, options));\n return tree;\n };\n};\n\nexport const main = (schema: ConfigurationSchema): Rule => {\n const options = transform(schema);\n const directory =\n schema.directory ??\n resolvePackageName(toKebabCase(schema.name?.toString() ?? DEFAULT_APP_NAME));\n\n return branchAndMerge(\n chain([mergeWith(generate(options, directory)), addConfiguration(options, directory as Path)]),\n );\n};\n","export const isObject = (item: any) => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const deepMerge = (target: any, ...sources: [any, ...any[]]): any => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n deepMerge(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return deepMerge(target, ...sources);\n};\n","export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_VERSION = \"0.0.0\";\nexport const DEFAULT_AUTHOR = \"\";\nexport const DEFAULT_DESCRIPTION = \"\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\nexport const DEFAULT_CONFIG = {\n client: {\n build: {\n entryFile: \"client/main.ts\",\n outDir: \".nanoforge/client\",\n },\n runtime: {\n dir: \".nanoforge/client\",\n },\n },\n};\nexport const DEFAULT_SERVER_CONFIG = {\n server: {\n enable: true,\n build: {\n entryFile: \"server/main.ts\",\n outDir: \".nanoforge/server\",\n },\n runtime: {\n dir: \".nanoforge/server\",\n },\n },\n};\n","import { type Config } from \"@utils/config/config.type\";\nimport { deepMerge } from \"@utils/object\";\nimport { type DeepPartial } from \"@utils/type\";\n\nimport { DEFAULT_CONFIG, DEFAULT_SERVER_CONFIG } from \"~/defaults\";\n\nexport class ConfigDeclarator {\n public declare(baseContent: string, options: DeepPartial<Config>): string {\n const content = JSON.parse(baseContent);\n const hasServer = content.server?.enable ?? options.server?.enable ?? false;\n return JSON.stringify(\n deepMerge(\n DEFAULT_CONFIG,\n hasServer ? DEFAULT_SERVER_CONFIG : undefined,\n baseContent,\n options,\n ),\n null,\n 2,\n );\n }\n}\n","import { type Path, join } from \"@angular-devkit/core\";\nimport { type DirEntry, type Tree } from \"@angular-devkit/schematics\";\n\nexport interface FindOptions {\n path: Path;\n}\n\nexport class ConfigFinder {\n constructor(private tree: Tree) {}\n\n public find(path: Path): Path | null {\n const dir = this.tree.getDir(path);\n return this.findIn(dir);\n }\n\n /**\n * Recursively searches for the module file in the given directory.\n *\n * @param directory - The directory to search in.\n * @returns The path to the module file, or null if not found.\n */\n private findIn(directory: DirEntry | null): Path | null {\n if (!directory) {\n return null;\n }\n const moduleFilename = directory.subfiles.find((filename) =>\n /^nanoforge.config.json$/.test(filename),\n );\n return moduleFilename !== undefined\n ? join(directory.path, moduleFilename.valueOf())\n : this.findIn(directory.parent);\n }\n}\n","export const toKebabCase = (str: string): string => {\n return str\n .replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase();\n};\n","import { basename, parse } from \"path\";\n\nexport const resolvePackageName = (path: string): string => {\n const { base: baseFilename, dir: dirname } = parse(path);\n if (baseFilename === \".\") {\n return basename(process.cwd());\n }\n if (dirname.match(/^@[^\\s]/)) {\n return `${dirname}/${baseFilename}`;\n }\n return baseFilename;\n};\n"],"mappings":"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","names":["join","join"]}
1
+ {"version":3,"sources":["../../../src/libs/configuration/configuration.factory.ts","../../../src/utils/object.ts","../../../src/defaults.ts","../../../src/utils/config/config.declarator.ts","../../../src/utils/config/config.finder.ts","../../../src/utils/formatting.ts","../../../src/utils/name.ts"],"sourcesContent":["import { type Path, join, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n branchAndMerge,\n chain,\n mergeWith,\n move,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { ConfigDeclarator } from \"@utils/config/config.declarator\";\nimport { ConfigFinder } from \"@utils/config/config.finder\";\nimport { toKebabCase } from \"@utils/formatting\";\nimport { resolvePackageName } from \"@utils/name\";\n\nimport { DEFAULT_APP_NAME } from \"~/defaults\";\n\nimport { type ConfigurationOptions } from \"./configuration.options\";\nimport { type ConfigurationSchema } from \"./configuration.schema\";\n\nconst transform = (schema: ConfigurationSchema): ConfigurationOptions => {\n return {\n server: {\n enable: schema.server ?? false,\n },\n };\n};\n\nconst generate = (options: ConfigurationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path)), [\n template({\n ...strings,\n ...options,\n }),\n move(path),\n ]);\n};\n\nconst addConfiguration = (options: ConfigurationOptions, path: Path) => {\n return (tree: Tree) => {\n const config = new ConfigFinder(tree).find(path);\n if (!config) return tree;\n\n const content = tree.read(config)?.toString();\n const declarator = new ConfigDeclarator();\n\n if (!content) return tree;\n\n tree.overwrite(config, declarator.declare(content, options));\n return tree;\n };\n};\n\nexport const main = (schema: ConfigurationSchema): Rule => {\n const options = transform(schema);\n const directory =\n schema.directory ??\n resolvePackageName(toKebabCase(schema.name?.toString() ?? DEFAULT_APP_NAME));\n\n return branchAndMerge(\n chain([mergeWith(generate(options, directory)), addConfiguration(options, directory as Path)]),\n );\n};\n","export const isObject = (item: any) => {\n return item && typeof item === \"object\" && !Array.isArray(item);\n};\n\nexport const deepMerge = (target: any, ...sources: [any, ...any[]]): any => {\n if (!sources.length) return target;\n const source = sources.shift();\n\n if (isObject(target) && isObject(source)) {\n for (const key in source) {\n if (isObject(source[key])) {\n if (!target[key]) Object.assign(target, { [key]: {} });\n deepMerge(target[key], source[key]);\n } else {\n Object.assign(target, { [key]: source[key] });\n }\n }\n }\n\n return deepMerge(target, ...sources);\n};\n","export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_VERSION = \"0.0.0\";\nexport const DEFAULT_AUTHOR = \"\";\nexport const DEFAULT_DESCRIPTION = \"\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\nexport const DEFAULT_CONFIG = {\n client: {\n build: {\n entryFile: \"client/main.ts\",\n outDir: \".nanoforge/client\",\n },\n runtime: {\n dir: \".nanoforge/client\",\n },\n },\n};\nexport const DEFAULT_SERVER_CONFIG = {\n server: {\n enable: true,\n build: {\n entryFile: \"server/main.ts\",\n outDir: \".nanoforge/server\",\n },\n runtime: {\n dir: \".nanoforge/server\",\n },\n },\n};\n","import { type Config } from \"@utils/config/config.type\";\nimport { deepMerge } from \"@utils/object\";\nimport { type DeepPartial } from \"@utils/type\";\n\nimport { DEFAULT_CONFIG, DEFAULT_SERVER_CONFIG } from \"~/defaults\";\n\nexport class ConfigDeclarator {\n public declare(baseContent: string, options: DeepPartial<Config>): string {\n const content = JSON.parse(baseContent);\n const hasServer = content.server?.enable ?? options.server?.enable ?? false;\n return JSON.stringify(\n deepMerge(\n DEFAULT_CONFIG,\n hasServer ? DEFAULT_SERVER_CONFIG : undefined,\n baseContent,\n options,\n ),\n null,\n 2,\n );\n }\n}\n","import { type Path, join } from \"@angular-devkit/core\";\nimport { type DirEntry, type Tree } from \"@angular-devkit/schematics\";\n\nexport interface FindOptions {\n path: Path;\n}\n\nexport class ConfigFinder {\n constructor(private tree: Tree) {}\n\n public find(path: Path): Path | null {\n const dir = this.tree.getDir(path);\n return this.findIn(dir);\n }\n\n /**\n * Recursively searches for the module file in the given directory.\n *\n * @param directory - The directory to search in.\n * @returns The path to the module file, or null if not found.\n */\n private findIn(directory: DirEntry | null): Path | null {\n if (!directory) {\n return null;\n }\n const moduleFilename = directory.subfiles.find((filename) =>\n /^nanoforge.config.json$/.test(filename),\n );\n return moduleFilename !== undefined\n ? join(directory.path, moduleFilename.valueOf())\n : this.findIn(directory.parent);\n }\n}\n","export const toKebabCase = (str: string): string => {\n return str\n .replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase();\n};\n","import { basename, parse } from \"path\";\n\nexport const resolvePackageName = (path: string): string => {\n const { base: baseFilename, dir: dirname } = parse(path);\n if (baseFilename === \".\") {\n return basename(process.cwd());\n }\n if (dirname.match(/^@[^\\s]/)) {\n return `${dirname}/${baseFilename}`;\n }\n return baseFilename;\n};\n"],"mappings":"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","names":["join","join"]}
@@ -17,81 +17,10 @@
17
17
  "type": "string",
18
18
  "description": "NanoForge application destination directory"
19
19
  },
20
- "client": {
21
- "type": "object",
22
- "description": "Client configuration",
23
- "properties": {
24
- "port": {
25
- "type": "string",
26
- "description": "Client port"
27
- },
28
- "gameExposurePort": {
29
- "type": "string",
30
- "description": "Game exposure port"
31
- },
32
- "build": {
33
- "type": "object",
34
- "description": "Build configuration",
35
- "properties": {
36
- "entryFile": {
37
- "type": "string",
38
- "description": "Entry file of the application"
39
- },
40
- "outDir": {
41
- "type": "string",
42
- "description": "Output directory of the application"
43
- }
44
- }
45
- },
46
- "runtime": {
47
- "type": "object",
48
- "description": "Runtime configuration",
49
- "properties": {
50
- "dir": {
51
- "type": "string",
52
- "description": "Directory of the application"
53
- }
54
- }
55
- }
56
- }
57
- },
58
20
  "server": {
59
- "type": "object",
21
+ "type": "boolean",
60
22
  "description": "Server configuration",
61
- "properties": {
62
- "enable": {
63
- "type": "boolean",
64
- "description": "Enable server configuration"
65
- },
66
- "port": {
67
- "type": "string",
68
- "description": "Server port"
69
- },
70
- "build": {
71
- "type": "object",
72
- "description": "Build configuration",
73
- "properties": {
74
- "entryFile": {
75
- "type": "string",
76
- "description": "Entry file of the application"
77
- },
78
- "outDir": {
79
- "type": "string",
80
- "description": "Output directory of the application"
81
- }
82
- }
83
- },
84
- "runtime": {
85
- "type": "object",
86
- "description": "Runtime configuration",
87
- "properties": {
88
- "dir": {
89
- "type": "string",
90
- "description": "Directory of the application"
91
- }
92
- }
93
- }
94
- }
23
+ "default": false
95
24
  }
96
25
  },
97
26
  "required": ["name"]
@@ -0,0 +1,69 @@
1
+ {
2
+ "libraries": [
3
+ {
4
+ "id": "assetManagerLibrary",
5
+ "type": "asset-manager",
6
+ "name": "AssetManagerLibrary",
7
+ "path": "@nanoforge-dev/asset-manager",
8
+ "params": []
9
+ },
10
+ {
11
+ "id": "ecsLibrary",
12
+ "type": "component-system",
13
+ "name": "ECSLibrary",
14
+ "path": "@nanoforge-dev/ecs",
15
+ "params": ["\"client\""]
16
+ },
17
+ {
18
+ "id": "graphicsLibrary",
19
+ "type": "graphics",
20
+ "name": "Graphics2DLibrary",
21
+ "path": "@nanoforge-dev/graphics-2d",
22
+ "params": []
23
+ },
24
+ {
25
+ "id": "inputLibrary",
26
+ "type": "input",
27
+ "name": "InputLibrary",
28
+ "path": "@nanoforge-dev/input",
29
+ "params": []
30
+ },
31
+ {
32
+ "id": "musicLibrary",
33
+ "type": "music",
34
+ "name": "MusicLibrary",
35
+ "path": "@nanoforge-dev/music",
36
+ "params": []
37
+ },
38
+ {
39
+ "id": "soundLibrary",
40
+ "type": "sound",
41
+ "name": "SoundLibrary",
42
+ "path": "@nanoforge-dev/sound",
43
+ "params": []
44
+ }
45
+ ],
46
+ "components": [
47
+ {
48
+ "name": "ExampleComponent",
49
+ "path": "./components/example.component"
50
+ }
51
+ ],
52
+ "systems": [
53
+ {
54
+ "name": "exampleSystem",
55
+ "path": "./systems/example.system"
56
+ }
57
+ ],
58
+ "entities": [
59
+ {
60
+ "id": "exampleEntity",
61
+ "components": [
62
+ {
63
+ "name": "ExampleComponent",
64
+ "params": ["\"example\"", "10"]
65
+ }
66
+ ]
67
+ }
68
+ ]
69
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "libraries": [
3
+ {
4
+ "id": "assetManagerLibrary",
5
+ "type": "asset-manager",
6
+ "name": "AssetManagerLibrary",
7
+ "path": "@nanoforge-dev/asset-manager",
8
+ "params": []
9
+ },
10
+ {
11
+ "id": "ecsLibrary",
12
+ "type": "component-system",
13
+ "name": "ECSLibrary",
14
+ "path": "@nanoforge-dev/ecs",
15
+ "params": ["\"server\""]
16
+ }
17
+ ],
18
+ "components": [
19
+ {
20
+ "name": "ExampleComponent",
21
+ "path": "./components/example.component"
22
+ }
23
+ ],
24
+ "systems": [
25
+ {
26
+ "name": "exampleSystem",
27
+ "path": "./systems/example.system"
28
+ }
29
+ ],
30
+ "entities": [
31
+ {
32
+ "id": "exampleEntity",
33
+ "components": [
34
+ {
35
+ "name": "ExampleComponent",
36
+ "params": ["\"example\"", "10"]
37
+ }
38
+ ]
39
+ }
40
+ ]
41
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/ecs").EditorComponentManifest} EditorComponentManifest
3
+ */
4
+
5
+ export class ExampleComponent {
6
+ static name = "ExampleComponent";
7
+ name = this.constructor.name;
8
+
9
+ paramA;
10
+ paramB;
11
+ paramC;
12
+
13
+ /**
14
+ * Example component constructor
15
+ * @param {string} paramA
16
+ * @param {number} paramB
17
+ * @param {boolean} [paramC = false]
18
+ */
19
+ constructor(paramA, paramB, paramC = false) {
20
+ this.paramA = paramA;
21
+ this.paramB = paramB;
22
+ this.paramC = paramC;
23
+ }
24
+
25
+ get foo() {
26
+ return "bar";
27
+ }
28
+
29
+ get paramAOrDefault() {
30
+ return this.paramC ? this.paramA : "default";
31
+ }
32
+
33
+ addOne() {
34
+ this.paramB += 1;
35
+ }
36
+ }
37
+
38
+ // * Required to generate code
39
+ export default ExampleComponent.name;
40
+
41
+ /**
42
+ * Editor component manifest
43
+ * * Required for the editor to display the component and generate code
44
+ * @type {EditorComponentManifest}
45
+ */
46
+ export const EDITOR_COMPONENT_MANIFEST = {
47
+ name: "Example",
48
+ description: "Example component description",
49
+ params: {
50
+ paramA: {
51
+ type: "string",
52
+ name: "Param A",
53
+ description: "Param A description",
54
+ example: "Example value",
55
+ },
56
+ paramB: {
57
+ type: "number",
58
+ name: "Param B",
59
+ description: "Param B description",
60
+ example: 3,
61
+ },
62
+ paramC: {
63
+ type: "boolean",
64
+ name: "Param C",
65
+ description: "Param C description",
66
+ example: true,
67
+ default: false,
68
+ // Not required because it has a default value
69
+ optional: true,
70
+ },
71
+ },
72
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/core").<%= appClass %>} <%= appClass %>
3
+ */
4
+
5
+ /**
6
+ * Actions that are executed after the application initialization
7
+ * @param {<%= appClass %>} app - Nanoforge <%= part %> instance
8
+ * @returns {Promise<void>}
9
+ */
10
+ export async function afterInit(app) {
11
+ // Actions after app initialization
12
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/core").<%= appClass %>} <%= appClass %>
3
+ * @typedef {import("@nanoforge-dev/ecs").Registry} Registry
4
+ */
5
+
6
+ /**
7
+ * Actions that are executed after the registry components, entities and systems initialization
8
+ * @param {<%= appClass %>} app - Nanoforge <%= part %> instance
9
+ * @param {Registry} registry - ECS registry instance
10
+ * @returns {Promise<void>}
11
+ */
12
+ export async function afterRegistryInit(app, registry) {
13
+ // Actions after registry components, entities and systems initialization
14
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/core").<%= appClass %>} <%= appClass %>
3
+ */
4
+
5
+ /**
6
+ * Actions that are executed when the application ended
7
+ * @param {<%= appClass %>} app - Nanoforge <%= part %> instance
8
+ * @returns {Promise<void>}
9
+ */
10
+ export async function afterRun(app) {
11
+ // Actions after app ended
12
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/core").<%= appClass %>} <%= appClass %>
3
+ */
4
+
5
+ /**
6
+ * Actions that are executed before the application initialization
7
+ * But are executed after base libraries addition
8
+ * @param {<%= appClass %>} app - Nanoforge <%= part %> instance
9
+ * @returns {Promise<void>}
10
+ */
11
+ export async function beforeInit(app) {
12
+ // Actions before app initialization
13
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/core").<%= appClass %>} <%= appClass %>
3
+ * @typedef {import("@nanoforge-dev/ecs").Registry} Registry
4
+ */
5
+
6
+ /**
7
+ * Actions that are executed before the registry components, entities and systems initialization
8
+ * @param {<%= appClass %>} app - Nanoforge <%= part %> instance
9
+ * @param {Registry} registry - ECS registry instance
10
+ * @returns {Promise<void>}
11
+ */
12
+ export async function beforeRegistryInit(app, registry) {
13
+ // Actions before registry components, entities and systems initialization
14
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/core").<%= appClass %>} <%= appClass %>
3
+ */
4
+
5
+ /**
6
+ * Actions that are executed before the application started
7
+ * @param {<%= appClass %>} app - Nanoforge <%= part %> instance
8
+ * @returns {Promise<void>}
9
+ */
10
+ export async function beforeRun(app) {
11
+ // Actions before app started
12
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @typedef {import("@nanoforge-dev/common").Context} Context
3
+ * @typedef {import("@nanoforge-dev/ecs").EditorSystemManifest} EditorSystemManifest
4
+ * @typedef {import("@nanoforge-dev/ecs").Registry} Registry
5
+ */
6
+
7
+ import { ExampleComponent } from "../components/example.component";
8
+
9
+ /**
10
+ * Example system
11
+ * This system end the game when paramB reaches 0 for any entity with ExampleComponent
12
+ * @param {Registry} registry - ECS registry instance
13
+ * @param {Context} ctx - Nanoforge <%= part %> instance
14
+ */
15
+ export const exampleSystem = (registry: Registry, ctx: Context) => {
16
+ const entities = registry.getZipper([ExampleComponent]);
17
+
18
+ entities.forEach((entity) => {
19
+ if (entity.ExampleComponent.paramA === "end") {
20
+ ctx.app.setIsRunning(false);
21
+ return;
22
+ }
23
+
24
+ if (entity.ExampleComponent.paramB === 0) entity.ExampleComponent.paramA = "end";
25
+
26
+ if (entity.ExampleComponent.paramB >= 0)
27
+ entity.ExampleComponent.paramB = entity.ExampleComponent.paramB - 1;
28
+ });
29
+ };
30
+
31
+ // * Required to generate code
32
+ export default exampleSystem.name;
33
+
34
+ /**
35
+ * Editor component manifest
36
+ * * Required for the editor to display the system and generate code
37
+ * @type {EditorSystemManifest}
38
+ */
39
+ export const EDITOR_SYSTEM_MANIFEST = {
40
+ name: "Example",
41
+ description:
42
+ "This system end the game when paramB reaches 0 for any entity with ExampleComponent",
43
+ dependencies: ["ExampleComponent"],
44
+ };