@nanoforge-dev/schematics 2.0.0 → 2.1.0
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.
- package/dist/collection.json +10 -0
- package/dist/libs/application/application.factory.js +4 -1
- package/dist/libs/application/application.factory.js.map +1 -1
- package/dist/libs/component/component.factory.d.ts +27 -0
- package/dist/libs/component/component.factory.js +50 -0
- package/dist/libs/component/component.factory.js.map +1 -0
- package/dist/libs/component/files/js/__fileName__.component.js +78 -0
- package/dist/libs/component/files/ts/__fileName__.component.ts +61 -0
- package/dist/libs/component/schema.json +30 -0
- package/dist/libs/docker/files/Dockerfile +1 -1
- package/dist/libs/part-base/files/js/__nanoforgeFolder__/client.save.json +1 -1
- package/dist/libs/part-base/files/js/__nanoforgeFolder__/server.save.json +1 -1
- package/dist/libs/part-base/files/js/__part__/components/example.component.js +29 -23
- package/dist/libs/part-base/files/js/__part__/systems/example.system.js +1 -1
- package/dist/libs/part-base/files/ts/__nanoforgeFolder__/client.save.json +1 -1
- package/dist/libs/part-base/files/ts/__nanoforgeFolder__/server.save.json +1 -1
- package/dist/libs/part-base/files/ts/__part__/components/example.component.ts +29 -23
- package/dist/libs/part-main/part-main.factory.js +29 -8
- package/dist/libs/part-main/part-main.factory.js.map +1 -1
- package/dist/libs/system/files/js/__fileName__.system.js +44 -0
- package/dist/libs/system/files/ts/__fileName__.system.ts +31 -0
- package/dist/libs/system/schema.json +30 -0
- package/dist/libs/system/system.factory.d.ts +27 -0
- package/dist/libs/system/system.factory.js +53 -0
- package/dist/libs/system/system.factory.js.map +1 -0
- package/package.json +1 -1
package/dist/collection.json
CHANGED
|
@@ -25,6 +25,16 @@
|
|
|
25
25
|
"factory": "./libs/docker/docker.factory#main",
|
|
26
26
|
"description": "Create a Dockerfile for the application.",
|
|
27
27
|
"schema": "./libs/docker/schema.json"
|
|
28
|
+
},
|
|
29
|
+
"component": {
|
|
30
|
+
"factory": "./libs/component/component.factory#main",
|
|
31
|
+
"description": "Create a NanoForge component.",
|
|
32
|
+
"schema": "./libs/component/schema.json"
|
|
33
|
+
},
|
|
34
|
+
"system": {
|
|
35
|
+
"factory": "./libs/system/system.factory#main",
|
|
36
|
+
"description": "Create a NanoForge system.",
|
|
37
|
+
"schema": "./libs/system/schema.json"
|
|
28
38
|
}
|
|
29
39
|
}
|
|
30
40
|
}
|
|
@@ -14,8 +14,11 @@ import {
|
|
|
14
14
|
import { firstValueFrom } from "rxjs";
|
|
15
15
|
|
|
16
16
|
// src/utils/formatting.ts
|
|
17
|
+
var toWords = /* @__PURE__ */ __name((str) => {
|
|
18
|
+
return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[-_]+/g, " ").trim().split(/\s+/).filter(Boolean);
|
|
19
|
+
}, "toWords");
|
|
17
20
|
var toKebabCase = /* @__PURE__ */ __name((str) => {
|
|
18
|
-
return str.
|
|
21
|
+
return toWords(str).map((word) => word.toLowerCase()).join("-");
|
|
19
22
|
}, "toKebabCase");
|
|
20
23
|
|
|
21
24
|
// src/utils/name.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/libs/application/application.factory.ts","../../../src/utils/formatting.ts","../../../src/utils/name.ts","../../../src/defaults.ts"],"sourcesContent":["import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type SchematicContext,\n type Source,\n type Tree,\n apply,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\nimport { firstValueFrom } from \"rxjs\";\n\nimport { toKebabCase } from \"@utils/formatting\";\nimport { resolvePackageName } from \"@utils/name\";\n\nimport {\n DEFAULT_APP_NAME,\n DEFAULT_AUTHOR,\n DEFAULT_DESCRIPTION,\n DEFAULT_LANGUAGE,\n DEFAULT_PACKAGE_MANAGER,\n DEFAULT_VERSION,\n} from \"~/defaults\";\n\nimport { type ApplicationOptions } from \"./application.options\";\nimport { type ApplicationSchema } from \"./application.schema\";\n\nconst transform = (schema: ApplicationSchema): ApplicationOptions => {\n const name = resolvePackageName(toKebabCase(schema.name?.toString() ?? DEFAULT_APP_NAME));\n\n return {\n name,\n version: schema.version ?? DEFAULT_VERSION,\n author: schema.author ?? DEFAULT_AUTHOR,\n description: schema.description ?? DEFAULT_DESCRIPTION,\n language: schema.language ?? DEFAULT_LANGUAGE,\n strict: schema.strict ?? true,\n lint: schema.lint ?? true,\n packageManager: schema.packageManager ?? DEFAULT_PACKAGE_MANAGER,\n server: schema.server ?? false,\n editor: schema.editor ?? false,\n };\n};\n\nconst generate = (options: ApplicationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n ...strings,\n ...options,\n }),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: ApplicationSchema): Rule => {\n const options = transform(schema);\n const path = schema.directory ?? options.name;\n\n return async (baseTree: Tree, context: SchematicContext) => {\n let tree = await mergeWith(generate(options, path))(baseTree, context);\n if (!tree) return tree;\n if (!(\"delete\" in tree)) {\n if (typeof tree === \"function\") return tree;\n tree = await firstValueFrom(tree);\n }\n\n if (!options.lint) {\n const basePath = join(\"/\" as Path, path);\n tree.delete(join(basePath, \"eslint.config.js\"));\n tree.delete(join(basePath, \"prettier.config.js\"));\n tree.delete(join(basePath, \".prettierignore\"));\n if (options.language === \"js\") tree.delete(join(basePath, \"jsconfig.json\"));\n }\n\n return tree;\n };\n};\n","
|
|
1
|
+
{"version":3,"sources":["../../../src/libs/application/application.factory.ts","../../../src/utils/formatting.ts","../../../src/utils/name.ts","../../../src/defaults.ts"],"sourcesContent":["import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type SchematicContext,\n type Source,\n type Tree,\n apply,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\nimport { firstValueFrom } from \"rxjs\";\n\nimport { toKebabCase } from \"@utils/formatting\";\nimport { resolvePackageName } from \"@utils/name\";\n\nimport {\n DEFAULT_APP_NAME,\n DEFAULT_AUTHOR,\n DEFAULT_DESCRIPTION,\n DEFAULT_LANGUAGE,\n DEFAULT_PACKAGE_MANAGER,\n DEFAULT_VERSION,\n} from \"~/defaults\";\n\nimport { type ApplicationOptions } from \"./application.options\";\nimport { type ApplicationSchema } from \"./application.schema\";\n\nconst transform = (schema: ApplicationSchema): ApplicationOptions => {\n const name = resolvePackageName(toKebabCase(schema.name?.toString() ?? DEFAULT_APP_NAME));\n\n return {\n name,\n version: schema.version ?? DEFAULT_VERSION,\n author: schema.author ?? DEFAULT_AUTHOR,\n description: schema.description ?? DEFAULT_DESCRIPTION,\n language: schema.language ?? DEFAULT_LANGUAGE,\n strict: schema.strict ?? true,\n lint: schema.lint ?? true,\n packageManager: schema.packageManager ?? DEFAULT_PACKAGE_MANAGER,\n server: schema.server ?? false,\n editor: schema.editor ?? false,\n };\n};\n\nconst generate = (options: ApplicationOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n ...strings,\n ...options,\n }),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: ApplicationSchema): Rule => {\n const options = transform(schema);\n const path = schema.directory ?? options.name;\n\n return async (baseTree: Tree, context: SchematicContext) => {\n let tree = await mergeWith(generate(options, path))(baseTree, context);\n if (!tree) return tree;\n if (!(\"delete\" in tree)) {\n if (typeof tree === \"function\") return tree;\n tree = await firstValueFrom(tree);\n }\n\n if (!options.lint) {\n const basePath = join(\"/\" as Path, path);\n tree.delete(join(basePath, \"eslint.config.js\"));\n tree.delete(join(basePath, \"prettier.config.js\"));\n tree.delete(join(basePath, \".prettierignore\"));\n if (options.language === \"js\") tree.delete(join(basePath, \"jsconfig.json\"));\n }\n\n return tree;\n };\n};\n","const toWords = (str: string): string[] => {\n return str\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n .replace(/[-_]+/g, \" \")\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n};\n\nexport const toKebabCase = (str: string): string => {\n return toWords(str)\n .map((word) => word.toLowerCase())\n .join(\"-\");\n};\n\nexport const toPascalCase = (str: string): string => {\n return toWords(str)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n};\n\nexport const toCamelCase = (str: string): string => {\n const words = toWords(str);\n return words\n .map((word, i) =>\n i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n )\n .join(\"\");\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","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\";\n"],"mappings":";;;;AAAA,SAAoB,MAAM,WAAW,eAAe;AACpD;AAAA,EAKE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;;;ACb/B,IAAM,UAAU,wBAAC,QAA0B;AACzC,SAAO,IACJ,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,yBAAyB,OAAO,EACxC,QAAQ,UAAU,GAAG,EACrB,KAAK,EACL,MAAM,KAAK,EACX,OAAO,OAAO;AACnB,GARgB;AAUT,IAAM,cAAc,wBAAC,QAAwB;AAClD,SAAO,QAAQ,GAAG,EACf,IAAI,CAAC,SAAS,KAAK,YAAY,CAAC,EAChC,KAAK,GAAG;AACb,GAJ2B;;;ACV3B,SAAS,UAAU,aAAa;AAEzB,IAAM,qBAAqB,wBAAC,SAAyB;AAC1D,QAAM,EAAE,MAAM,cAAc,KAAK,QAAQ,IAAI,MAAM,IAAI;AACvD,MAAI,iBAAiB,KAAK;AACxB,WAAO,SAAS,QAAQ,IAAI,CAAC;AAAA,EAC/B;AACA,MAAI,QAAQ,MAAM,SAAS,GAAG;AAC5B,WAAO,GAAG,OAAO,IAAI,YAAY;AAAA,EACnC;AACA,SAAO;AACT,GATkC;;;ACF3B,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,sBAAsB;AAC5B,IAAM,mBAAmB;AACzB,IAAM,0BAA0B;;;AHyBvC,IAAM,YAAY,wBAAC,WAAkD;AACnE,QAAM,OAAO,mBAAmB,YAAY,OAAO,MAAM,SAAS,KAAK,gBAAgB,CAAC;AAExF,SAAO;AAAA,IACL;AAAA,IACA,SAAS,OAAO,WAAW;AAAA,IAC3B,QAAQ,OAAO,UAAU;AAAA,IACzB,aAAa,OAAO,eAAe;AAAA,IACnC,UAAU,OAAO,YAAY;AAAA,IAC7B,QAAQ,OAAO,UAAU;AAAA,IACzB,MAAM,OAAO,QAAQ;AAAA,IACrB,gBAAgB,OAAO,kBAAkB;AAAA,IACzC,QAAQ,OAAO,UAAU;AAAA,IACzB,QAAQ,OAAO,UAAU;AAAA,EAC3B;AACF,GAfkB;AAiBlB,IAAM,WAAW,wBAAC,SAA6B,SAAyB;AACtE,SAAO,MAAM,IAAI,KAAK,WAAmB,QAAQ,QAAQ,CAAC,GAAG;AAAA,IAC3D,SAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,IACL,CAAC;AAAA,IACD,oBAAoB;AAAA,IACpB,KAAK,UAAU,IAAI,CAAC;AAAA,EACtB,CAAC;AACH,GATiB;AAWV,IAAM,OAAO,wBAAC,WAAoC;AACvD,QAAM,UAAU,UAAU,MAAM;AAChC,QAAM,OAAO,OAAO,aAAa,QAAQ;AAEzC,SAAO,OAAO,UAAgB,YAA8B;AAC1D,QAAI,OAAO,MAAM,UAAU,SAAS,SAAS,IAAI,CAAC,EAAE,UAAU,OAAO;AACrE,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,EAAE,YAAY,OAAO;AACvB,UAAI,OAAO,SAAS,WAAY,QAAO;AACvC,aAAO,MAAM,eAAe,IAAI;AAAA,IAClC;AAEA,QAAI,CAAC,QAAQ,MAAM;AACjB,YAAM,WAAW,KAAK,KAAa,IAAI;AACvC,WAAK,OAAO,KAAK,UAAU,kBAAkB,CAAC;AAC9C,WAAK,OAAO,KAAK,UAAU,oBAAoB,CAAC;AAChD,WAAK,OAAO,KAAK,UAAU,iBAAiB,CAAC;AAC7C,UAAI,QAAQ,aAAa,KAAM,MAAK,OAAO,KAAK,UAAU,eAAe,CAAC;AAAA,IAC5E;AAEA,WAAO;AAAA,EACT;AACF,GAtBoB;","names":[]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Rule } from '@angular-devkit/schematics';
|
|
2
|
+
|
|
3
|
+
interface ComponentSchema {
|
|
4
|
+
/**
|
|
5
|
+
* Component destination directory
|
|
6
|
+
*/
|
|
7
|
+
name: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Component destination directory
|
|
11
|
+
*/
|
|
12
|
+
directory: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The part of the application to generate
|
|
16
|
+
*/
|
|
17
|
+
part: "client" | "server";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* NanoForge Application language
|
|
21
|
+
*/
|
|
22
|
+
language: "js" | "ts";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare const main: (schema: ComponentSchema) => Rule;
|
|
26
|
+
|
|
27
|
+
export { main };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
|
|
4
|
+
// src/libs/component/component.factory.ts
|
|
5
|
+
import { join, normalize, strings } from "@angular-devkit/core";
|
|
6
|
+
import {
|
|
7
|
+
apply,
|
|
8
|
+
mergeWith,
|
|
9
|
+
move,
|
|
10
|
+
template,
|
|
11
|
+
url
|
|
12
|
+
} from "@angular-devkit/schematics";
|
|
13
|
+
|
|
14
|
+
// src/utils/formatting.ts
|
|
15
|
+
var toWords = /* @__PURE__ */ __name((str) => {
|
|
16
|
+
return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[-_]+/g, " ").trim().split(/\s+/).filter(Boolean);
|
|
17
|
+
}, "toWords");
|
|
18
|
+
var toKebabCase = /* @__PURE__ */ __name((str) => {
|
|
19
|
+
return toWords(str).map((word) => word.toLowerCase()).join("-");
|
|
20
|
+
}, "toKebabCase");
|
|
21
|
+
var toPascalCase = /* @__PURE__ */ __name((str) => {
|
|
22
|
+
return toWords(str).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
23
|
+
}, "toPascalCase");
|
|
24
|
+
|
|
25
|
+
// src/libs/component/component.factory.ts
|
|
26
|
+
var transform = /* @__PURE__ */ __name((schema) => {
|
|
27
|
+
return {
|
|
28
|
+
part: schema.part,
|
|
29
|
+
className: toPascalCase(schema.name),
|
|
30
|
+
fileName: toKebabCase(schema.name)
|
|
31
|
+
};
|
|
32
|
+
}, "transform");
|
|
33
|
+
var generate = /* @__PURE__ */ __name((options, path, language) => {
|
|
34
|
+
const rules = [
|
|
35
|
+
template({
|
|
36
|
+
...strings,
|
|
37
|
+
...options
|
|
38
|
+
}),
|
|
39
|
+
move(normalize(path))
|
|
40
|
+
];
|
|
41
|
+
return apply(url(join("./files", language)), rules);
|
|
42
|
+
}, "generate");
|
|
43
|
+
var main = /* @__PURE__ */ __name((schema) => {
|
|
44
|
+
const options = transform(schema);
|
|
45
|
+
return mergeWith(generate(options, schema.directory, schema.language));
|
|
46
|
+
}, "main");
|
|
47
|
+
export {
|
|
48
|
+
main
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=component.factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/libs/component/component.factory.ts","../../../src/utils/formatting.ts"],"sourcesContent":["import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n apply,\n mergeWith,\n move,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { toKebabCase, toPascalCase } from \"@utils/formatting\";\n\nimport { type ComponentOptions } from \"./component.options\";\nimport { type ComponentSchema } from \"./component.schema\";\n\nconst transform = (schema: ComponentSchema): ComponentOptions => {\n return {\n part: schema.part,\n className: toPascalCase(schema.name),\n fileName: toKebabCase(schema.name),\n };\n};\n\nconst generate = (options: ComponentOptions, path: string, language: \"ts\" | \"js\"): Source => {\n const rules = [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ];\n\n return apply(url(join(\"./files\" as Path, language)), rules);\n};\n\nexport const main = (schema: ComponentSchema): Rule => {\n const options = transform(schema);\n\n return mergeWith(generate(options, schema.directory, schema.language));\n};\n","const toWords = (str: string): string[] => {\n return str\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n .replace(/[-_]+/g, \" \")\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n};\n\nexport const toKebabCase = (str: string): string => {\n return toWords(str)\n .map((word) => word.toLowerCase())\n .join(\"-\");\n};\n\nexport const toPascalCase = (str: string): string => {\n return toWords(str)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n};\n\nexport const toCamelCase = (str: string): string => {\n const words = toWords(str);\n return words\n .map((word, i) =>\n i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n )\n .join(\"\");\n};\n"],"mappings":";;;;AAAA,SAAoB,MAAM,WAAW,eAAe;AACpD;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACTP,IAAM,UAAU,wBAAC,QAA0B;AACzC,SAAO,IACJ,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,yBAAyB,OAAO,EACxC,QAAQ,UAAU,GAAG,EACrB,KAAK,EACL,MAAM,KAAK,EACX,OAAO,OAAO;AACnB,GARgB;AAUT,IAAM,cAAc,wBAAC,QAAwB;AAClD,SAAO,QAAQ,GAAG,EACf,IAAI,CAAC,SAAS,KAAK,YAAY,CAAC,EAChC,KAAK,GAAG;AACb,GAJ2B;AAMpB,IAAM,eAAe,wBAAC,QAAwB;AACnD,SAAO,QAAQ,GAAG,EACf,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC,EACxE,KAAK,EAAE;AACZ,GAJ4B;;;ADA5B,IAAM,YAAY,wBAAC,WAA8C;AAC/D,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,WAAW,aAAa,OAAO,IAAI;AAAA,IACnC,UAAU,YAAY,OAAO,IAAI;AAAA,EACnC;AACF,GANkB;AAQlB,IAAM,WAAW,wBAAC,SAA2B,MAAc,aAAkC;AAC3F,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,IACL,CAAC;AAAA,IACD,KAAK,UAAU,IAAI,CAAC;AAAA,EACtB;AAEA,SAAO,MAAM,IAAI,KAAK,WAAmB,QAAQ,CAAC,GAAG,KAAK;AAC5D,GAViB;AAYV,IAAM,OAAO,wBAAC,WAAkC;AACrD,QAAM,UAAU,UAAU,MAAM;AAEhC,SAAO,UAAU,SAAS,SAAS,OAAO,WAAW,OAAO,QAAQ,CAAC;AACvE,GAJoB;","names":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("@nanoforge-dev/ecs-<%= part %>").EditorComponentManifest} EditorComponentManifest
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export class <%= className %>Component {
|
|
6
|
+
static name = "<%= className %>Component";
|
|
7
|
+
name = this.constructor.name;
|
|
8
|
+
|
|
9
|
+
paramA;
|
|
10
|
+
paramB;
|
|
11
|
+
paramC;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* <%= className %> 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 <%= className %>Component.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: "<%= className %>",
|
|
48
|
+
description: "<%= className %> component description",
|
|
49
|
+
params: [
|
|
50
|
+
[
|
|
51
|
+
{
|
|
52
|
+
type: "string",
|
|
53
|
+
name: "paramA",
|
|
54
|
+
description: "Param A description",
|
|
55
|
+
example: "Example value",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
{
|
|
60
|
+
type: "number",
|
|
61
|
+
name: "paramB",
|
|
62
|
+
description: "Param B description",
|
|
63
|
+
example: 3,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
{
|
|
68
|
+
type: "boolean",
|
|
69
|
+
name: "paramC",
|
|
70
|
+
description: "Param C description",
|
|
71
|
+
example: true,
|
|
72
|
+
default: false,
|
|
73
|
+
// Not required because it has a default value
|
|
74
|
+
optional: true,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
],
|
|
78
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type EditorComponentManifest } from "@nanoforge-dev/ecs-<%= part %>";
|
|
2
|
+
|
|
3
|
+
export class <%= className %>Component {
|
|
4
|
+
name = this.constructor.name;
|
|
5
|
+
|
|
6
|
+
constructor(
|
|
7
|
+
public paramA: string,
|
|
8
|
+
public paramB: number,
|
|
9
|
+
public paramC: boolean = false,
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
get foo() {
|
|
13
|
+
return "bar";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get paramAOrDefault() {
|
|
17
|
+
return this.paramC ? this.paramA : "default";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
addOne() {
|
|
21
|
+
this.paramB += 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// * Required to generate code
|
|
26
|
+
export default <%= className %>Component.name;
|
|
27
|
+
|
|
28
|
+
// * Required for the editor to display the component and generate code
|
|
29
|
+
export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
|
|
30
|
+
name: "<%= className %>",
|
|
31
|
+
description: "<%= className %> component description",
|
|
32
|
+
params: [
|
|
33
|
+
[
|
|
34
|
+
{
|
|
35
|
+
type: "string",
|
|
36
|
+
name: "paramA",
|
|
37
|
+
description: "Param A description",
|
|
38
|
+
example: "Example value",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
type: "number",
|
|
44
|
+
name: "paramB",
|
|
45
|
+
description: "Param B description",
|
|
46
|
+
example: 3,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
{
|
|
51
|
+
type: "boolean",
|
|
52
|
+
name: "paramC",
|
|
53
|
+
description: "Param C description",
|
|
54
|
+
example: true,
|
|
55
|
+
default: false,
|
|
56
|
+
// Not required because it has a default value
|
|
57
|
+
optional: true,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
],
|
|
61
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"$id": "SchematicsNanoForgeComponent",
|
|
4
|
+
"title": "NanoForge Component Options Schema",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "Component name",
|
|
10
|
+
"default": "example"
|
|
11
|
+
},
|
|
12
|
+
"directory": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Component destination directory",
|
|
15
|
+
"default": "."
|
|
16
|
+
},
|
|
17
|
+
"part": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": ["client", "server"],
|
|
20
|
+
"description": "The part of the application to generate"
|
|
21
|
+
},
|
|
22
|
+
"language": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["ts", "js"],
|
|
25
|
+
"description": "NanoForge application language",
|
|
26
|
+
"default": "ts"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"required": ["part"]
|
|
30
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<% if (packageManager === 'bun') { %>FROM oven/bun:1.3<% } else { %>FROM node:25-
|
|
1
|
+
<% if (packageManager === 'bun') { %>FROM oven/bun:1.3<% } else { %>FROM node:25-slim<% } %>
|
|
2
2
|
<% if (packageManager === 'pnpm') { %>
|
|
3
3
|
ENV PNPM_HOME="/pnpm"
|
|
4
4
|
ENV PATH="$PNPM_HOME:$PATH"
|
|
@@ -46,27 +46,33 @@ export default ExampleComponent.name;
|
|
|
46
46
|
export const EDITOR_COMPONENT_MANIFEST = {
|
|
47
47
|
name: "Example",
|
|
48
48
|
description: "Example component description",
|
|
49
|
-
params:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
49
|
+
params: [
|
|
50
|
+
[
|
|
51
|
+
{
|
|
52
|
+
type: "string",
|
|
53
|
+
name: "paramA",
|
|
54
|
+
description: "Param A description",
|
|
55
|
+
example: "Example value",
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
{
|
|
60
|
+
type: "number",
|
|
61
|
+
name: "paramB",
|
|
62
|
+
description: "Param B description",
|
|
63
|
+
example: 3,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
{
|
|
68
|
+
type: "boolean",
|
|
69
|
+
name: "paramC",
|
|
70
|
+
description: "Param C description",
|
|
71
|
+
example: true,
|
|
72
|
+
default: false,
|
|
73
|
+
// Not required because it has a default value
|
|
74
|
+
optional: true,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
],
|
|
72
78
|
};
|
|
@@ -12,7 +12,7 @@ import { ExampleComponent } from "../components/example.component";
|
|
|
12
12
|
* @param {Registry} registry - ECS registry instance
|
|
13
13
|
* @param {Context} ctx - Nanoforge <%= part %> instance
|
|
14
14
|
*/
|
|
15
|
-
export const exampleSystem = (registry
|
|
15
|
+
export const exampleSystem = (registry, ctx) => {
|
|
16
16
|
const entities = registry.getZipper([ExampleComponent]);
|
|
17
17
|
|
|
18
18
|
entities.forEach((entity) => {
|
|
@@ -29,27 +29,33 @@ export default ExampleComponent.name;
|
|
|
29
29
|
export const EDITOR_COMPONENT_MANIFEST: EditorComponentManifest = {
|
|
30
30
|
name: "Example",
|
|
31
31
|
description: "Example component description",
|
|
32
|
-
params:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
32
|
+
params: [
|
|
33
|
+
[
|
|
34
|
+
{
|
|
35
|
+
type: "string",
|
|
36
|
+
name: "paramA",
|
|
37
|
+
description: "Param A description",
|
|
38
|
+
example: "Example value",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
type: "number",
|
|
44
|
+
name: "paramB",
|
|
45
|
+
description: "Param B description",
|
|
46
|
+
example: 3,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
{
|
|
51
|
+
type: "boolean",
|
|
52
|
+
name: "paramC",
|
|
53
|
+
description: "Param C description",
|
|
54
|
+
example: true,
|
|
55
|
+
default: false,
|
|
56
|
+
// Not required because it has a default value
|
|
57
|
+
optional: true,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
],
|
|
55
61
|
};
|
|
@@ -32,6 +32,15 @@ var LIBS_FUNCTIONS_NAME = {
|
|
|
32
32
|
["sound" /* SOUND */]: "useSound"
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
// src/utils/main/main-utils.ts
|
|
36
|
+
var getStringParam = /* @__PURE__ */ __name((value) => {
|
|
37
|
+
if (typeof value === "string") return `"${value}"`;
|
|
38
|
+
if (typeof value === "number") return value.toString();
|
|
39
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
40
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
41
|
+
return "undefined";
|
|
42
|
+
}, "getStringParam");
|
|
43
|
+
|
|
35
44
|
// src/utils/main/main.generator.ts
|
|
36
45
|
var MainGenerator = class {
|
|
37
46
|
static {
|
|
@@ -114,8 +123,8 @@ var MainGenerator = class {
|
|
|
114
123
|
this.endSection();
|
|
115
124
|
return this;
|
|
116
125
|
}
|
|
117
|
-
generateEntities(entities) {
|
|
118
|
-
entities.forEach((entity, index) => this.generateEntity(entity, index));
|
|
126
|
+
generateEntities(components, entities) {
|
|
127
|
+
entities.forEach((entity, index) => this.generateEntity(components, entity, index));
|
|
119
128
|
return this;
|
|
120
129
|
}
|
|
121
130
|
generateSystems(systems) {
|
|
@@ -158,14 +167,26 @@ var MainGenerator = class {
|
|
|
158
167
|
this.endSection();
|
|
159
168
|
return this;
|
|
160
169
|
}
|
|
161
|
-
generateEntity(entity, entityIndex) {
|
|
170
|
+
generateEntity(components, entity, entityIndex) {
|
|
162
171
|
this.writeLine(`const ${entity.id} = registry.spawnEntity();`);
|
|
163
|
-
entity.components.forEach((
|
|
164
|
-
const
|
|
165
|
-
|
|
172
|
+
Object.entries(entity.components).forEach(([componentName, rawParams]) => {
|
|
173
|
+
const originalsParams = components.find(({ name }) => name === componentName)?.paramsNames;
|
|
174
|
+
if (!originalsParams)
|
|
175
|
+
throw new Error("Missing component in entity or inexistent saved component");
|
|
176
|
+
const params = !this.editor ? Object.values(originalsParams).map((ogParam) => {
|
|
177
|
+
return getStringParam(rawParams[ogParam]);
|
|
178
|
+
}) : Object.values(originalsParams).map((ogParam) => {
|
|
179
|
+
return `options.editor.save.entities[${entityIndex}].components["${componentName}"]["${ogParam}"]`;
|
|
180
|
+
});
|
|
181
|
+
this.writeLine(
|
|
182
|
+
`registry.addComponent(${entity.id}, new ${componentName}(${params.join(", ")}));`
|
|
166
183
|
);
|
|
167
|
-
this.writeLine(`registry.addComponent(${entity.id}, new ${name}(${params.join(", ")}));`);
|
|
168
184
|
});
|
|
185
|
+
if (this.editor) {
|
|
186
|
+
this.writeLine(
|
|
187
|
+
`registry.addComponent(${entity.id}, { name: "__RESERVED_entityId", entityId: "${entity.id}" });`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
169
190
|
this.endSection();
|
|
170
191
|
}
|
|
171
192
|
getInitFunction(name, type) {
|
|
@@ -195,7 +216,7 @@ var generateMain = /* @__PURE__ */ __name((options, save) => {
|
|
|
195
216
|
options.part
|
|
196
217
|
)
|
|
197
218
|
)).generateBaseImports(hasTypes).generateLibsImports(save.libraries).generateInitFunctionsImportsIfNeeded(initFunctions).generateComponentsImports(save.components).generateSystemsImports(save.systems).generateMainFunction(hasTypes, (generator) => {
|
|
198
|
-
generator.generateApp(isServer).generateLibsInstances(save.libraries).generateLibsInit(save.libraries).generateInitFunctionIfNeeded(initFunctions, "beforeInit" /* BEFORE_INIT */).generateAppInit().generateInitFunctionIfNeeded(initFunctions, "afterInit" /* AFTER_INIT */).generateRegistry(save.libraries).generateInitFunctionIfNeeded(initFunctions, "beforeRegistryInit" /* BEFORE_REGISTRY_INIT */).generateEntities(save.entities).generateSystems(save.systems).generateInitFunctionIfNeeded(initFunctions, "afterRegistryInit" /* AFTER_REGISTRY_INIT */).generateInitFunctionIfNeeded(initFunctions, "beforeRun" /* BEFORE_RUN */).generateAppRun(initFunctions).generateInitFunctionIfNeeded(initFunctions, "afterRun" /* AFTER_RUN */);
|
|
219
|
+
generator.generateApp(isServer).generateLibsInstances(save.libraries).generateLibsInit(save.libraries).generateInitFunctionIfNeeded(initFunctions, "beforeInit" /* BEFORE_INIT */).generateAppInit().generateInitFunctionIfNeeded(initFunctions, "afterInit" /* AFTER_INIT */).generateRegistry(save.libraries).generateInitFunctionIfNeeded(initFunctions, "beforeRegistryInit" /* BEFORE_REGISTRY_INIT */).generateEntities(save.components, save.entities).generateSystems(save.systems).generateInitFunctionIfNeeded(initFunctions, "afterRegistryInit" /* AFTER_REGISTRY_INIT */).generateInitFunctionIfNeeded(initFunctions, "beforeRun" /* BEFORE_RUN */).generateAppRun(initFunctions).generateInitFunctionIfNeeded(initFunctions, "afterRun" /* AFTER_RUN */);
|
|
199
220
|
}).toString();
|
|
200
221
|
}, "generateMain");
|
|
201
222
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/libs/part-main/part-main.factory.ts","../../../src/utils/main/main-functions.ts","../../../src/utils/path.ts","../../../src/utils/main/const.ts","../../../src/utils/main/main.generator.ts"],"sourcesContent":["import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n asSource,\n mergeWith,\n move,\n template,\n} from \"@angular-devkit/schematics\";\nimport * as fs from \"fs\";\n\nimport { generateMain } from \"@utils/main/main-functions\";\nimport { type Save } from \"@utils/main/save.type\";\n\nimport { type PartMainOptions } from \"./part-main.options\";\nimport { type PartMainSchema } from \"./part-main.schema\";\n\nconst transform = (schema: PartMainSchema): PartMainOptions => {\n void schema;\n\n return {};\n};\n\nconst generate = (options: PartMainOptions, path: string, schema: PartMainSchema): Source => {\n const rules = [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ];\n\n return apply(asSource(writeMain(schema, path)), rules);\n};\n\nconst getMainPath = (schema: PartMainSchema): string => {\n if (schema.outFile) return schema.outFile;\n if (schema.editor)\n return join(\".nanoforge/editor\" as Path, schema.part, `main.${schema.language}`);\n return join(schema.part as Path, `main.${schema.language}`);\n};\n\nconst writeMain = (schema: PartMainSchema, path: string) => {\n return (tree: Tree) => {\n const save = getSave(path, schema.part, schema.saveFile);\n\n const resPath = getMainPath(schema);\n\n const content = generateMain(schema, save);\n fs.rmSync(join(path as Path, resPath), { force: true });\n tree.create(resPath, content);\n return tree;\n };\n};\n\nconst getSave = (path: string, part: \"client\" | \"server\", saveFile?: string): Save => {\n return JSON.parse(\n fs.readFileSync(saveFile ?? join(path as Path, `.nanoforge/${part}.save.json`), \"utf-8\"),\n ) as Save;\n};\n\nexport const main = (schema: PartMainSchema): Rule => {\n const options = transform(schema);\n\n return mergeWith(generate(options, schema.directory, schema));\n};\n","import { join } from \"path\";\n\nimport { InitFunctionEnum } from \"@utils/main/enums\";\n\nimport { MainGenerator } from \"./main.generator\";\nimport { type Save } from \"./save.type\";\n\nexport interface MainOptions {\n part: \"client\" | \"server\";\n language: \"js\" | \"ts\";\n initFunctions: boolean;\n editor: boolean;\n outFile?: string;\n}\n\nexport const generateMain = (options: MainOptions, save: Save) => {\n const isServer = options.part === \"server\";\n const hasTypes = options.language === \"ts\";\n const initFunctions = options.initFunctions;\n\n return (\n !options.editor\n ? new MainGenerator()\n : new MainGenerator(\n true,\n join(\n \"../\".repeat(options.outFile ? options.outFile.split(\"/\").length - 1 : 3),\n options.part,\n ),\n )\n )\n .generateBaseImports(hasTypes)\n .generateLibsImports(save.libraries)\n .generateInitFunctionsImportsIfNeeded(initFunctions)\n .generateComponentsImports(save.components)\n .generateSystemsImports(save.systems)\n\n .generateMainFunction(hasTypes, (generator) => {\n generator\n .generateApp(isServer)\n\n .generateLibsInstances(save.libraries)\n .generateLibsInit(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_INIT)\n .generateAppInit()\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_INIT)\n\n .generateRegistry(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_REGISTRY_INIT)\n .generateEntities(save.entities)\n .generateSystems(save.systems)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_REGISTRY_INIT)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_RUN)\n .generateAppRun(initFunctions)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_RUN);\n })\n .toString();\n};\n","import { join } from \"path\";\n\nexport const joinRelative = (...paths: [string, ...string[]]): string => {\n const path = join(...paths);\n return path.startsWith(\"./\") || path.startsWith(\"../\") ? path : `./${path}`;\n};\n","import { SaveLibraryTypeEnum } from \"@utils/main/save.type\";\n\nexport const LIBS_FUNCTIONS_NAME: Record<SaveLibraryTypeEnum | string, string> = {\n [SaveLibraryTypeEnum.ASSET_MANAGER]: \"useAssetManager\",\n [SaveLibraryTypeEnum.COMPONENT_SYSTEM]: \"useComponentSystem\",\n [SaveLibraryTypeEnum.GRAPHICS]: \"useGraphics\",\n [SaveLibraryTypeEnum.INPUT]: \"useInput\",\n [SaveLibraryTypeEnum.NETWORK]: \"useNetwork\",\n [SaveLibraryTypeEnum.SOUND]: \"useSound\",\n};\n","import { InitFunctionEnum } from \"@utils/main/enums\";\nimport { joinRelative } from \"@utils/path\";\n\nimport { LIBS_FUNCTIONS_NAME } from \"./const\";\nimport {\n type SaveComponent,\n type SaveEntity,\n type SaveLibrary,\n SaveLibraryTypeEnum,\n type SaveSystem,\n} from \"./save.type\";\n\nexport class MainGenerator {\n private buffer = \"\";\n private indentation = 0;\n private readonly editor: boolean;\n private readonly pathToRoot: string;\n\n constructor(editor: boolean = false, pathToRoot: string = \"\") {\n this.editor = editor;\n this.pathToRoot = pathToRoot;\n }\n\n toString(): string {\n return this.buffer;\n }\n\n generateBaseImports(hasTypes: boolean): MainGenerator {\n if (this.editor) {\n if (hasTypes)\n this.writeLine(\n `import { type IEditorRunOptions, NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`,\n );\n else this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`);\n } else {\n if (hasTypes) this.writeLine(`import { type IRunOptions } from \"@nanoforge-dev/common\";`);\n this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core\";`);\n }\n\n this.endSection();\n return this;\n }\n\n generateLibsImports(libs: SaveLibrary[]): MainGenerator {\n return this.generateImports(libs, false);\n }\n\n generateComponentsImports(libs: SaveComponent[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateSystemsImports(libs: SaveSystem[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateMainFunction(hasTypes: boolean, cb: (generator: MainGenerator) => void): MainGenerator {\n if (this.editor)\n this.writeLine(\n `export async function main(options${hasTypes ? \": IEditorRunOptions\" : \"\"}) {`,\n );\n else this.writeLine(`export async function main(options${hasTypes ? \": IRunOptions\" : \"\"}) {`);\n this.indentation += 1;\n cb(this);\n this.indentation -= 1;\n this.writeLine(\"}\");\n return this;\n }\n\n generateApp(isServer: boolean): MainGenerator {\n this.writeLine(`const app = NanoforgeFactory.create${isServer ? \"Server\" : \"Client\"}();`);\n this.endSection();\n return this;\n }\n\n generateAppInit(): MainGenerator {\n this.writeLine(`await app.init(options);`);\n this.endSection();\n return this;\n }\n\n generateAppRun(hasInitFunctions: boolean): MainGenerator {\n this.writeLine(`await app.run();`);\n if (hasInitFunctions) this.endSection();\n return this;\n }\n\n generateLibsInstances(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, name }) => this.writeLine(`const ${id} = new ${name}();`));\n this.endSection();\n return this;\n }\n\n generateLibsInit(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, type }) => this.writeLine(this.getInitFunction(id, type)));\n this.endSection();\n return this;\n }\n\n generateRegistry(libs: SaveLibrary[]): MainGenerator {\n const libName =\n libs.find((lib) => lib.type === SaveLibraryTypeEnum.COMPONENT_SYSTEM)?.id ?? \"ecsLibrary\";\n this.writeLine(`const registry = ${libName}.registry;`);\n this.endSection();\n return this;\n }\n\n generateEntities(entities: SaveEntity[]): MainGenerator {\n entities.forEach((entity, index) => this.generateEntity(entity, index));\n return this;\n }\n\n generateSystems(systems: SaveSystem[]): MainGenerator {\n systems.forEach(({ name }) => this.writeLine(`registry.addSystem(${name});`));\n this.endSection();\n return this;\n }\n\n generateInitFunctionIfNeeded(needed: boolean, func: InitFunctionEnum): MainGenerator {\n if (needed) return this.generateInitFunction(func);\n return this;\n }\n\n generateInitFunctionsImportsIfNeeded(needed: boolean): MainGenerator {\n if (!needed) return this;\n return this.generateImports(\n [\n { name: \"afterInit\", path: \"./init/after-init\" },\n { name: \"afterRegistryInit\", path: \"./init/after-registry-init\" },\n { name: \"afterRun\", path: \"./init/after-run\" },\n { name: \"beforeInit\", path: \"./init/before-init\" },\n { name: \"beforeRegistryInit\", path: \"./init/before-registry-init\" },\n { name: \"beforeRun\", path: \"./init/before-run\" },\n ],\n true,\n );\n }\n\n private generateInitFunction(func: InitFunctionEnum): MainGenerator {\n const params = [\"app\"];\n if (\n [InitFunctionEnum.BEFORE_REGISTRY_INIT, InitFunctionEnum.AFTER_REGISTRY_INIT].includes(func)\n )\n params.push(\"registry\");\n this.writeLine(`await ${func}(${params.join(\", \")});`);\n if (func !== InitFunctionEnum.AFTER_RUN) this.endSection();\n return this;\n }\n\n private generateImports(els: { name: string; path: string }[], relative: boolean): MainGenerator {\n els\n .sort((a, b) => a.path.localeCompare(b.path))\n .forEach(({ name, path }) =>\n this.writeLine(\n `import { ${name} } from \"${relative ? joinRelative(this.pathToRoot, path) : path}\";`,\n ),\n );\n this.endSection();\n return this;\n }\n\n private generateEntity(entity: SaveEntity, entityIndex: number): void {\n this.writeLine(`const ${entity.id} = registry.spawnEntity();`);\n entity.components.forEach(({ name, params: rawParams }, componentIndex) => {\n const params = !this.editor\n ? rawParams\n : rawParams.map(\n (_param, index) =>\n `options.editor.save.entities[${entityIndex}].components[${componentIndex}].params[${index}]`,\n );\n this.writeLine(`registry.addComponent(${entity.id}, new ${name}(${params.join(\", \")}));`);\n });\n this.endSection();\n }\n\n private getInitFunction(name: string, type: SaveLibraryTypeEnum | string): string {\n const baseName = LIBS_FUNCTIONS_NAME[type];\n if (baseName) return `app.${baseName}(${name});`;\n return `app.use(Symbol(\"${type}\"), ${name});`;\n }\n\n private writeLine(text: string, indentation = true): void {\n const line = `${\" \".repeat(indentation ? this.indentation * 2 : 0)}${text}\\n`;\n this.buffer += line;\n }\n\n private endSection(): void {\n this.writeLine(\"\");\n }\n}\n"],"mappings":"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","names":["join","join","join","join"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/libs/part-main/part-main.factory.ts","../../../src/utils/main/main-functions.ts","../../../src/utils/path.ts","../../../src/utils/main/const.ts","../../../src/utils/main/main-utils.ts","../../../src/utils/main/main.generator.ts"],"sourcesContent":["import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n type Tree,\n apply,\n asSource,\n mergeWith,\n move,\n template,\n} from \"@angular-devkit/schematics\";\nimport * as fs from \"fs\";\n\nimport { generateMain } from \"@utils/main/main-functions\";\nimport { type Save } from \"@utils/main/save.type\";\n\nimport { type PartMainOptions } from \"./part-main.options\";\nimport { type PartMainSchema } from \"./part-main.schema\";\n\nconst transform = (schema: PartMainSchema): PartMainOptions => {\n void schema;\n\n return {};\n};\n\nconst generate = (options: PartMainOptions, path: string, schema: PartMainSchema): Source => {\n const rules = [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ];\n\n return apply(asSource(writeMain(schema, path)), rules);\n};\n\nconst getMainPath = (schema: PartMainSchema): string => {\n if (schema.outFile) return schema.outFile;\n if (schema.editor)\n return join(\".nanoforge/editor\" as Path, schema.part, `main.${schema.language}`);\n return join(schema.part as Path, `main.${schema.language}`);\n};\n\nconst writeMain = (schema: PartMainSchema, path: string) => {\n return (tree: Tree) => {\n const save = getSave(path, schema.part, schema.saveFile);\n\n const resPath = getMainPath(schema);\n\n const content = generateMain(schema, save);\n fs.rmSync(join(path as Path, resPath), { force: true });\n tree.create(resPath, content);\n return tree;\n };\n};\n\nconst getSave = (path: string, part: \"client\" | \"server\", saveFile?: string): Save => {\n return JSON.parse(\n fs.readFileSync(saveFile ?? join(path as Path, `.nanoforge/${part}.save.json`), \"utf-8\"),\n ) as Save;\n};\n\nexport const main = (schema: PartMainSchema): Rule => {\n const options = transform(schema);\n\n return mergeWith(generate(options, schema.directory, schema));\n};\n","import { join } from \"path\";\n\nimport { InitFunctionEnum } from \"@utils/main/enums\";\n\nimport { MainGenerator } from \"./main.generator\";\nimport { type Save } from \"./save.type\";\n\nexport interface MainOptions {\n part: \"client\" | \"server\";\n language: \"js\" | \"ts\";\n initFunctions: boolean;\n editor: boolean;\n outFile?: string;\n}\n\nexport const generateMain = (options: MainOptions, save: Save) => {\n const isServer = options.part === \"server\";\n const hasTypes = options.language === \"ts\";\n const initFunctions = options.initFunctions;\n\n return (\n !options.editor\n ? new MainGenerator()\n : new MainGenerator(\n true,\n join(\n \"../\".repeat(options.outFile ? options.outFile.split(\"/\").length - 1 : 3),\n options.part,\n ),\n )\n )\n .generateBaseImports(hasTypes)\n .generateLibsImports(save.libraries)\n .generateInitFunctionsImportsIfNeeded(initFunctions)\n .generateComponentsImports(save.components)\n .generateSystemsImports(save.systems)\n\n .generateMainFunction(hasTypes, (generator) => {\n generator\n .generateApp(isServer)\n\n .generateLibsInstances(save.libraries)\n .generateLibsInit(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_INIT)\n .generateAppInit()\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_INIT)\n\n .generateRegistry(save.libraries)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_REGISTRY_INIT)\n .generateEntities(save.components, save.entities)\n .generateSystems(save.systems)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_REGISTRY_INIT)\n\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.BEFORE_RUN)\n .generateAppRun(initFunctions)\n .generateInitFunctionIfNeeded(initFunctions, InitFunctionEnum.AFTER_RUN);\n })\n .toString();\n};\n","import { join } from \"path\";\n\nexport const joinRelative = (...paths: [string, ...string[]]): string => {\n const path = join(...paths);\n return path.startsWith(\"./\") || path.startsWith(\"../\") ? path : `./${path}`;\n};\n","import { SaveLibraryTypeEnum } from \"@utils/main/save.type\";\n\nexport const LIBS_FUNCTIONS_NAME: Record<SaveLibraryTypeEnum | string, string> = {\n [SaveLibraryTypeEnum.ASSET_MANAGER]: \"useAssetManager\",\n [SaveLibraryTypeEnum.COMPONENT_SYSTEM]: \"useComponentSystem\",\n [SaveLibraryTypeEnum.GRAPHICS]: \"useGraphics\",\n [SaveLibraryTypeEnum.INPUT]: \"useInput\",\n [SaveLibraryTypeEnum.NETWORK]: \"useNetwork\",\n [SaveLibraryTypeEnum.SOUND]: \"useSound\",\n};\n","export const getStringParam = (value: any): string => {\n if (typeof value === \"string\") return `\"${value}\"`;\n if (typeof value === \"number\") return value.toString();\n if (typeof value === \"boolean\") return value ? \"true\" : \"false\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return \"undefined\";\n};\n","import { joinRelative } from \"@utils/path\";\n\nimport { LIBS_FUNCTIONS_NAME } from \"./const\";\nimport { InitFunctionEnum } from \"./enums\";\nimport { getStringParam } from \"./main-utils\";\nimport {\n type SaveComponent,\n type SaveEntity,\n type SaveLibrary,\n SaveLibraryTypeEnum,\n type SaveSystem,\n} from \"./save.type\";\n\nexport class MainGenerator {\n private buffer = \"\";\n private indentation = 0;\n private readonly editor: boolean;\n private readonly pathToRoot: string;\n\n constructor(editor: boolean = false, pathToRoot: string = \"\") {\n this.editor = editor;\n this.pathToRoot = pathToRoot;\n }\n\n toString(): string {\n return this.buffer;\n }\n\n generateBaseImports(hasTypes: boolean): MainGenerator {\n if (this.editor) {\n if (hasTypes)\n this.writeLine(\n `import { type IEditorRunOptions, NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`,\n );\n else this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core-editor\";`);\n } else {\n if (hasTypes) this.writeLine(`import { type IRunOptions } from \"@nanoforge-dev/common\";`);\n this.writeLine(`import { NanoforgeFactory } from \"@nanoforge-dev/core\";`);\n }\n\n this.endSection();\n return this;\n }\n\n generateLibsImports(libs: SaveLibrary[]): MainGenerator {\n return this.generateImports(libs, false);\n }\n\n generateComponentsImports(libs: SaveComponent[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateSystemsImports(libs: SaveSystem[]): MainGenerator {\n return this.generateImports(libs, true);\n }\n\n generateMainFunction(hasTypes: boolean, cb: (generator: MainGenerator) => void): MainGenerator {\n if (this.editor)\n this.writeLine(\n `export async function main(options${hasTypes ? \": IEditorRunOptions\" : \"\"}) {`,\n );\n else this.writeLine(`export async function main(options${hasTypes ? \": IRunOptions\" : \"\"}) {`);\n this.indentation += 1;\n cb(this);\n this.indentation -= 1;\n this.writeLine(\"}\");\n return this;\n }\n\n generateApp(isServer: boolean): MainGenerator {\n this.writeLine(`const app = NanoforgeFactory.create${isServer ? \"Server\" : \"Client\"}();`);\n this.endSection();\n return this;\n }\n\n generateAppInit(): MainGenerator {\n this.writeLine(`await app.init(options);`);\n this.endSection();\n return this;\n }\n\n generateAppRun(hasInitFunctions: boolean): MainGenerator {\n this.writeLine(`await app.run();`);\n if (hasInitFunctions) this.endSection();\n return this;\n }\n\n generateLibsInstances(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, name }) => this.writeLine(`const ${id} = new ${name}();`));\n this.endSection();\n return this;\n }\n\n generateLibsInit(libs: SaveLibrary[]): MainGenerator {\n libs.forEach(({ id, type }) => this.writeLine(this.getInitFunction(id, type)));\n this.endSection();\n return this;\n }\n\n generateRegistry(libs: SaveLibrary[]): MainGenerator {\n const libName =\n libs.find((lib) => lib.type === SaveLibraryTypeEnum.COMPONENT_SYSTEM)?.id ?? \"ecsLibrary\";\n this.writeLine(`const registry = ${libName}.registry;`);\n this.endSection();\n return this;\n }\n\n generateEntities(components: SaveComponent[], entities: SaveEntity[]): MainGenerator {\n entities.forEach((entity, index) => this.generateEntity(components, entity, index));\n return this;\n }\n\n generateSystems(systems: SaveSystem[]): MainGenerator {\n systems.forEach(({ name }) => this.writeLine(`registry.addSystem(${name});`));\n this.endSection();\n return this;\n }\n\n generateInitFunctionIfNeeded(needed: boolean, func: InitFunctionEnum): MainGenerator {\n if (needed) return this.generateInitFunction(func);\n return this;\n }\n\n generateInitFunctionsImportsIfNeeded(needed: boolean): MainGenerator {\n if (!needed) return this;\n return this.generateImports(\n [\n { name: \"afterInit\", path: \"./init/after-init\" },\n { name: \"afterRegistryInit\", path: \"./init/after-registry-init\" },\n { name: \"afterRun\", path: \"./init/after-run\" },\n { name: \"beforeInit\", path: \"./init/before-init\" },\n { name: \"beforeRegistryInit\", path: \"./init/before-registry-init\" },\n { name: \"beforeRun\", path: \"./init/before-run\" },\n ],\n true,\n );\n }\n\n private generateInitFunction(func: InitFunctionEnum): MainGenerator {\n const params = [\"app\"];\n if (\n [InitFunctionEnum.BEFORE_REGISTRY_INIT, InitFunctionEnum.AFTER_REGISTRY_INIT].includes(func)\n )\n params.push(\"registry\");\n this.writeLine(`await ${func}(${params.join(\", \")});`);\n if (func !== InitFunctionEnum.AFTER_RUN) this.endSection();\n return this;\n }\n\n private generateImports(els: { name: string; path: string }[], relative: boolean): MainGenerator {\n els\n .sort((a, b) => a.path.localeCompare(b.path))\n .forEach(({ name, path }) =>\n this.writeLine(\n `import { ${name} } from \"${relative ? joinRelative(this.pathToRoot, path) : path}\";`,\n ),\n );\n this.endSection();\n return this;\n }\n\n private generateEntity(\n components: SaveComponent[],\n entity: SaveEntity,\n entityIndex: number,\n ): void {\n this.writeLine(`const ${entity.id} = registry.spawnEntity();`);\n Object.entries(entity.components).forEach(([componentName, rawParams]) => {\n const originalsParams = components.find(({ name }) => name === componentName)?.paramsNames;\n if (!originalsParams)\n throw new Error(\"Missing component in entity or inexistent saved component\");\n const params: string[] = !this.editor\n ? Object.values(originalsParams).map((ogParam) => {\n return getStringParam(rawParams[ogParam]);\n })\n : Object.values(originalsParams).map((ogParam) => {\n return `options.editor.save.entities[${entityIndex}].components[\"${componentName}\"][\"${ogParam}\"]`;\n });\n this.writeLine(\n `registry.addComponent(${entity.id}, new ${componentName}(${params.join(\", \")}));`,\n );\n });\n if (this.editor) {\n this.writeLine(\n `registry.addComponent(${entity.id}, { name: \"__RESERVED_entityId\", entityId: \"${entity.id}\" });`,\n );\n }\n this.endSection();\n }\n\n private getInitFunction(name: string, type: SaveLibraryTypeEnum | string): string {\n const baseName = LIBS_FUNCTIONS_NAME[type];\n if (baseName) return `app.${baseName}(${name});`;\n return `app.use(Symbol(\"${type}\"), ${name});`;\n }\n\n private writeLine(text: string, indentation = true): void {\n const line = `${\" \".repeat(indentation ? this.indentation * 2 : 0)}${text}\\n`;\n this.buffer += line;\n }\n\n private endSection(): void {\n this.writeLine(\"\");\n }\n}\n"],"mappings":"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","names":["join","join","join","join"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("@nanoforge-dev/common").Context} Context
|
|
3
|
+
* @typedef {import("@nanoforge-dev/ecs-<%= part %>").EditorSystemManifest} EditorSystemManifest
|
|
4
|
+
* @typedef {import("@nanoforge-dev/ecs-<%= part %>").Registry} Registry
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ExampleComponent } from "../components/example.component";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* <%= functionName %> 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 <%= functionName %>System = (registry, ctx) => {
|
|
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 <%= functionName %>System.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: "<%= functionName %>",
|
|
41
|
+
description:
|
|
42
|
+
"This system end the game when paramB reaches 0 for any entity with ExampleComponent",
|
|
43
|
+
dependencies: ["ExampleComponent"],
|
|
44
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Context } from "@nanoforge-dev/common";
|
|
2
|
+
import { type EditorSystemManifest, type Registry } from "@nanoforge-dev/ecs-<%= part %>";
|
|
3
|
+
|
|
4
|
+
import { ExampleComponent } from "../components/example.component";
|
|
5
|
+
|
|
6
|
+
export const <%= functionName %>System = (registry: Registry, ctx: Context) => {
|
|
7
|
+
const entities = registry.getZipper([ExampleComponent]);
|
|
8
|
+
|
|
9
|
+
entities.forEach((entity) => {
|
|
10
|
+
if (entity.ExampleComponent.paramA === "end") {
|
|
11
|
+
ctx.app.setIsRunning(false);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (entity.ExampleComponent.paramB === 0) entity.ExampleComponent.paramA = "end";
|
|
16
|
+
|
|
17
|
+
if (entity.ExampleComponent.paramB >= 0)
|
|
18
|
+
entity.ExampleComponent.paramB = entity.ExampleComponent.paramB - 1;
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// * Required to generate code
|
|
23
|
+
export default <%= functionName %>System.name;
|
|
24
|
+
|
|
25
|
+
// * Required for the editor to display the system and generate code
|
|
26
|
+
export const EDITOR_SYSTEM_MANIFEST: EditorSystemManifest = {
|
|
27
|
+
name: "<%= functionName %>",
|
|
28
|
+
description:
|
|
29
|
+
"This system end the game when paramB reaches 0 for any entity with ExampleComponent",
|
|
30
|
+
dependencies: ["ExampleComponent"],
|
|
31
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"$id": "SchematicsNanoForgeSystem",
|
|
4
|
+
"title": "NanoForge System Options Schema",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "System name",
|
|
10
|
+
"default": "example"
|
|
11
|
+
},
|
|
12
|
+
"directory": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "System destination directory",
|
|
15
|
+
"default": "."
|
|
16
|
+
},
|
|
17
|
+
"part": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": ["client", "server"],
|
|
20
|
+
"description": "The part of the application to generate"
|
|
21
|
+
},
|
|
22
|
+
"language": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": ["ts", "js"],
|
|
25
|
+
"description": "NanoForge application language",
|
|
26
|
+
"default": "ts"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"required": ["part"]
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Rule } from '@angular-devkit/schematics';
|
|
2
|
+
|
|
3
|
+
interface SystemSchema {
|
|
4
|
+
/**
|
|
5
|
+
* System destination directory
|
|
6
|
+
*/
|
|
7
|
+
name: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* System destination directory
|
|
11
|
+
*/
|
|
12
|
+
directory: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The part of the application to generate
|
|
16
|
+
*/
|
|
17
|
+
part: "client" | "server";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* NanoForge Application language
|
|
21
|
+
*/
|
|
22
|
+
language: "js" | "ts";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare const main: (schema: SystemSchema) => Rule;
|
|
26
|
+
|
|
27
|
+
export { main };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
|
|
4
|
+
// src/libs/system/system.factory.ts
|
|
5
|
+
import { join, normalize, strings } from "@angular-devkit/core";
|
|
6
|
+
import {
|
|
7
|
+
apply,
|
|
8
|
+
mergeWith,
|
|
9
|
+
move,
|
|
10
|
+
template,
|
|
11
|
+
url
|
|
12
|
+
} from "@angular-devkit/schematics";
|
|
13
|
+
|
|
14
|
+
// src/utils/formatting.ts
|
|
15
|
+
var toWords = /* @__PURE__ */ __name((str) => {
|
|
16
|
+
return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/[-_]+/g, " ").trim().split(/\s+/).filter(Boolean);
|
|
17
|
+
}, "toWords");
|
|
18
|
+
var toKebabCase = /* @__PURE__ */ __name((str) => {
|
|
19
|
+
return toWords(str).map((word) => word.toLowerCase()).join("-");
|
|
20
|
+
}, "toKebabCase");
|
|
21
|
+
var toCamelCase = /* @__PURE__ */ __name((str) => {
|
|
22
|
+
const words = toWords(str);
|
|
23
|
+
return words.map(
|
|
24
|
+
(word, i) => i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
|
25
|
+
).join("");
|
|
26
|
+
}, "toCamelCase");
|
|
27
|
+
|
|
28
|
+
// src/libs/system/system.factory.ts
|
|
29
|
+
var transform = /* @__PURE__ */ __name((schema) => {
|
|
30
|
+
return {
|
|
31
|
+
part: schema.part,
|
|
32
|
+
functionName: toCamelCase(schema.name),
|
|
33
|
+
fileName: toKebabCase(schema.name)
|
|
34
|
+
};
|
|
35
|
+
}, "transform");
|
|
36
|
+
var generate = /* @__PURE__ */ __name((options, path, language) => {
|
|
37
|
+
const rules = [
|
|
38
|
+
template({
|
|
39
|
+
...strings,
|
|
40
|
+
...options
|
|
41
|
+
}),
|
|
42
|
+
move(normalize(path))
|
|
43
|
+
];
|
|
44
|
+
return apply(url(join("./files", language)), rules);
|
|
45
|
+
}, "generate");
|
|
46
|
+
var main = /* @__PURE__ */ __name((schema) => {
|
|
47
|
+
const options = transform(schema);
|
|
48
|
+
return mergeWith(generate(options, schema.directory, schema.language));
|
|
49
|
+
}, "main");
|
|
50
|
+
export {
|
|
51
|
+
main
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=system.factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/libs/system/system.factory.ts","../../../src/utils/formatting.ts"],"sourcesContent":["import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n apply,\n mergeWith,\n move,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { toCamelCase, toKebabCase } from \"@utils/formatting\";\n\nimport { type SystemOptions } from \"./system.options\";\nimport { type SystemSchema } from \"./system.schema\";\n\nconst transform = (schema: SystemSchema): SystemOptions => {\n return {\n part: schema.part,\n functionName: toCamelCase(schema.name),\n fileName: toKebabCase(schema.name),\n };\n};\n\nconst generate = (options: SystemOptions, path: string, language: \"ts\" | \"js\"): Source => {\n const rules = [\n template({\n ...strings,\n ...options,\n }),\n move(normalize(path)),\n ];\n\n return apply(url(join(\"./files\" as Path, language)), rules);\n};\n\nexport const main = (schema: SystemSchema): Rule => {\n const options = transform(schema);\n\n return mergeWith(generate(options, schema.directory, schema.language));\n};\n","const toWords = (str: string): string[] => {\n return str\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\n .replace(/[-_]+/g, \" \")\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n};\n\nexport const toKebabCase = (str: string): string => {\n return toWords(str)\n .map((word) => word.toLowerCase())\n .join(\"-\");\n};\n\nexport const toPascalCase = (str: string): string => {\n return toWords(str)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n};\n\nexport const toCamelCase = (str: string): string => {\n const words = toWords(str);\n return words\n .map((word, i) =>\n i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(),\n )\n .join(\"\");\n};\n"],"mappings":";;;;AAAA,SAAoB,MAAM,WAAW,eAAe;AACpD;AAAA,EAGE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACTP,IAAM,UAAU,wBAAC,QAA0B;AACzC,SAAO,IACJ,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,yBAAyB,OAAO,EACxC,QAAQ,UAAU,GAAG,EACrB,KAAK,EACL,MAAM,KAAK,EACX,OAAO,OAAO;AACnB,GARgB;AAUT,IAAM,cAAc,wBAAC,QAAwB;AAClD,SAAO,QAAQ,GAAG,EACf,IAAI,CAAC,SAAS,KAAK,YAAY,CAAC,EAChC,KAAK,GAAG;AACb,GAJ2B;AAYpB,IAAM,cAAc,wBAAC,QAAwB;AAClD,QAAM,QAAQ,QAAQ,GAAG;AACzB,SAAO,MACJ;AAAA,IAAI,CAAC,MAAM,MACV,MAAM,IAAI,KAAK,YAAY,IAAI,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY;AAAA,EAC1F,EACC,KAAK,EAAE;AACZ,GAP2B;;;ADN3B,IAAM,YAAY,wBAAC,WAAwC;AACzD,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,cAAc,YAAY,OAAO,IAAI;AAAA,IACrC,UAAU,YAAY,OAAO,IAAI;AAAA,EACnC;AACF,GANkB;AAQlB,IAAM,WAAW,wBAAC,SAAwB,MAAc,aAAkC;AACxF,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,IACL,CAAC;AAAA,IACD,KAAK,UAAU,IAAI,CAAC;AAAA,EACtB;AAEA,SAAO,MAAM,IAAI,KAAK,WAAmB,QAAQ,CAAC,GAAG,KAAK;AAC5D,GAViB;AAYV,IAAM,OAAO,wBAAC,WAA+B;AAClD,QAAM,UAAU,UAAU,MAAM;AAEhC,SAAO,UAAU,SAAS,SAAS,OAAO,WAAW,OAAO,QAAQ,CAAC;AACvE,GAJoB;","names":[]}
|