@nanoforge-dev/schematics 2.3.0 → 2.3.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 (25) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/libs/project/files/js/nanoforge.config.js +1 -1
  3. package/dist/libs/project/files/js/package.json.template +8 -3
  4. package/dist/libs/project/files/js/src/components/drawable-circle-2d.component.js +1 -1
  5. package/dist/libs/project/files/js/src/main.js +2 -2
  6. package/dist/libs/project/files/js/src/systems/draw-2d.system.js +1 -1
  7. package/dist/libs/project/files/js/src/systems/move-2d.system.js +1 -1
  8. package/dist/libs/project/files/js/src/systems/position-sync.system.js +1 -1
  9. package/dist/libs/project/files/ts/nanoforge.config.ts +1 -1
  10. package/dist/libs/project/files/ts/package.json.template +8 -3
  11. package/dist/libs/project/files/ts/src/components/drawable-circle-2d.component.ts +1 -1
  12. package/dist/libs/project/files/ts/src/main.ts +2 -1
  13. package/dist/libs/project/files/ts/src/systems/draw-2d.system.ts +1 -1
  14. package/dist/libs/project/files/ts/src/systems/move-2d.system.ts +1 -1
  15. package/dist/libs/project/files/ts/src/systems/position-sync.system.ts +1 -1
  16. package/dist/libs/project/project.factory.d.ts.map +1 -1
  17. package/dist/libs/project/project.factory.js +9 -4
  18. package/dist/libs/project/project.factory.js.map +1 -1
  19. package/dist/libs/workspace/files/js/nanoforge.config.js +1 -1
  20. package/dist/libs/workspace/files/js/package.json.template +1 -1
  21. package/dist/libs/workspace/files/ts/nanoforge.config.ts +1 -1
  22. package/dist/libs/workspace/files/ts/package.json.template +1 -1
  23. package/dist/libs/workspace/workspace.factory.js +2 -2
  24. package/dist/libs/workspace/workspace.factory.js.map +1 -1
  25. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ # [2.3.1](https://github.com/NanoForge-dev/CLI/compare/2.3.0...2.3.1) - (2026-09-25)
6
+
5
7
  # [2.3.0](https://github.com/NanoForge-dev/CLI/compare/1.6.2...2.3.0) - (2026-09-24)
6
8
 
7
9
  > `@nanoforge-dev/schematics` now lives in the CLI monorepo (`libs/schematics`) and is released
@@ -1,4 +1,4 @@
1
- import { defineConfig } from "nanoforge/config";
1
+ import { defineConfig } from "@nanoforge-dev/config";
2
2
 
3
3
  export default defineConfig({
4
4
  type: "<%= part %>",
@@ -10,11 +10,16 @@
10
10
  "@nanoforge-dev/network": "<%= networkVersion %>"
11
11
  },<% } %>
12
12
  "devDependencies": {
13
- "@nanoforge-dev/ecs": "<%= ecsVersion %>",<% if (part === "client") { %>
13
+ "@nanoforge-dev/asset": "<%= engineVersion %>",
14
+ "@nanoforge-dev/cli": "<%= cliVersion %>",
15
+ "@nanoforge-dev/common": "<%= engineVersion %>",
16
+ "@nanoforge-dev/core": "<%= engineVersion %>",
17
+ "@nanoforge-dev/config": "<%= engineVersion %>",
18
+ "@nanoforge-dev/ecs": "<%= ecsVersion %>"<% if (part === "client") { %>,
19
+ "@nanoforge-dev/env": "<%= engineVersion %>",
14
20
  "@nanoforge-dev/graphics-2d": "<%= graphics2dVersion %>",
15
21
  "@nanoforge-dev/input": "<%= inputVersion %>",
16
- "@nanoforge-dev/network": "<%= networkVersion %>",<% } %>
17
- "nanoforge": "<%= nanoforgeVersion %>"
22
+ "@nanoforge-dev/network": "<%= networkVersion %>"<% } %>
18
23
  },<% if (packageManager === "npm" && allowBuilds.length > 0) { %>
19
24
  "allowScripts": {<% allowBuilds.forEach(function (pkg, i) { %>
20
25
  "<%= pkg %>": true<% if (i < allowBuilds.length - 1) { %>,<% } %><% }); %>
@@ -1,7 +1,7 @@
1
1
  /**
2
+ * @typedef {import("@nanoforge-dev/common").NfFile} NfFile
2
3
  * @typedef {import("@nanoforge-dev/ecs").EditorComponentManifest} EditorComponentManifest
3
4
  * @typedef {import("@nanoforge-dev/graphics-2d").Layer} Layer
4
- * @typedef {import("nanoforge").NfFile} NfFile
5
5
  */
6
6
 
7
7
  import { Circle } from "@nanoforge-dev/graphics-2d";
@@ -1,4 +1,4 @@
1
- import { NanoforgeFactory } from "nanoforge";
1
+ import { NanoforgeFactory } from "@nanoforge-dev/core";
2
2
  import { EcsLibrary } from "@nanoforge-dev/ecs/<%= part %>";<% if (part === "client") { %>
3
3
  import { Graphics2DLibrary } from "@nanoforge-dev/graphics-2d";
4
4
  import { InputLibrary } from "@nanoforge-dev/input";<% } %>
@@ -11,7 +11,7 @@ import { positionSync } from "./systems/position-sync.system";<% } %><% } else {
11
11
  import { move2D } from "./systems/move-2d.system";<% } %>
12
12
 
13
13
  /**
14
- * @param {import("nanoforge").<%= part === "client" ? "ClientRunOptions" : "ServerRunOptions" %>} options
14
+ * @param {import("@nanoforge-dev/common").<%= part === "client" ? "ClientRunOptions" : "ServerRunOptions" %>} options
15
15
  * @returns {Promise<void>}
16
16
  */
17
17
  export const main = async (options) => {
@@ -1,7 +1,7 @@
1
1
  /**
2
+ * @typedef {import("@nanoforge-dev/common").Context} Context
2
3
  * @typedef {import("@nanoforge-dev/ecs").EditorSystemManifest} EditorSystemManifest
3
4
  * @typedef {import("@nanoforge-dev/ecs").Registry} Registry
4
- * @typedef {import("nanoforge").Context} Context
5
5
  */
6
6
 
7
7
  import { DrawableCircle2D } from "../components/drawable-circle-2d.component";
@@ -1,7 +1,7 @@
1
1
  /**
2
+ * @typedef {import("@nanoforge-dev/common").Context} Context
2
3
  * @typedef {import("@nanoforge-dev/ecs").EditorSystemManifest} EditorSystemManifest
3
4
  * @typedef {import("@nanoforge-dev/ecs").Registry} Registry
4
- * @typedef {import("nanoforge").Context} Context
5
5
  */
6
6
 
7
7
  import { Position2D } from "../components/position-2d.component";
@@ -1,7 +1,7 @@
1
1
  /**
2
+ * @typedef {import("@nanoforge-dev/common").Context} Context
2
3
  * @typedef {import("@nanoforge-dev/ecs").EditorSystemManifest} EditorSystemManifest
3
4
  * @typedef {import("@nanoforge-dev/ecs").Registry} Registry
4
- * @typedef {import("nanoforge").Context} Context
5
5
  */
6
6
 
7
7
  import { Position2D } from "../components/position-2d.component";
@@ -1,4 +1,4 @@
1
- import { defineConfig } from "nanoforge/config";
1
+ import { defineConfig } from "@nanoforge-dev/config";
2
2
 
3
3
  export default defineConfig({
4
4
  type: "<%= part %>",
@@ -10,11 +10,16 @@
10
10
  "@nanoforge-dev/network": "<%= networkVersion %>"
11
11
  },<% } %>
12
12
  "devDependencies": {
13
- "@nanoforge-dev/ecs": "<%= ecsVersion %>",<% if (part === "client") { %>
13
+ "@nanoforge-dev/asset": "<%= engineVersion %>",
14
+ "@nanoforge-dev/cli": "<%= cliVersion %>",
15
+ "@nanoforge-dev/common": "<%= engineVersion %>",
16
+ "@nanoforge-dev/core": "<%= engineVersion %>",
17
+ "@nanoforge-dev/config": "<%= engineVersion %>",
18
+ "@nanoforge-dev/ecs": "<%= ecsVersion %>"<% if (part === "client") { %>,
19
+ "@nanoforge-dev/env": "<%= engineVersion %>",
14
20
  "@nanoforge-dev/graphics-2d": "<%= graphics2dVersion %>",
15
21
  "@nanoforge-dev/input": "<%= inputVersion %>",
16
- "@nanoforge-dev/network": "<%= networkVersion %>",<% } %>
17
- "nanoforge": "<%= nanoforgeVersion %>"
22
+ "@nanoforge-dev/network": "<%= networkVersion %>"<% } %>
18
23
  },<% if (packageManager === "npm" && allowBuilds.length > 0) { %>
19
24
  "allowScripts": {<% allowBuilds.forEach(function (pkg, i) { %>
20
25
  "<%= pkg %>": true<% if (i < allowBuilds.length - 1) { %>,<% } %><% }); %>
@@ -1,6 +1,6 @@
1
+ import type { NfFile } from "@nanoforge-dev/common";
1
2
  import type { EditorComponentManifest } from "@nanoforge-dev/ecs";
2
3
  import { Circle, type Layer } from "@nanoforge-dev/graphics-2d";
3
- import type { NfFile } from "nanoforge";
4
4
 
5
5
  export class DrawableCircle2D {
6
6
  public readonly name: string = this.constructor.name;
@@ -1,4 +1,5 @@
1
- import { NanoforgeFactory, type <%= part === "client" ? "ClientRunOptions" : "ServerRunOptions" %> } from "nanoforge";
1
+ import { type <%= part === "client" ? "ClientRunOptions" : "ServerRunOptions" %> } from "@nanoforge-dev/common";
2
+ import { NanoforgeFactory } from "@nanoforge-dev/core";
2
3
  import { EcsLibrary } from "@nanoforge-dev/ecs/<%= part %>";<% if (part === "client") { %>
3
4
  import { Graphics2DLibrary } from "@nanoforge-dev/graphics-2d";
4
5
  import { InputLibrary } from "@nanoforge-dev/input";<% } %>
@@ -1,5 +1,5 @@
1
+ import type { Context } from "@nanoforge-dev/common";
1
2
  import type { EditorSystemManifest, Registry } from "@nanoforge-dev/ecs";
2
- import { type Context } from "nanoforge";
3
3
 
4
4
  import { DrawableCircle2D } from "../components/drawable-circle-2d.component";
5
5
  import { Position2D } from "../components/position-2d.component";
@@ -1,5 +1,5 @@
1
+ import type { Context } from "@nanoforge-dev/common";
1
2
  import type { EditorSystemManifest, Registry } from "@nanoforge-dev/ecs";
2
- import { type Context } from "nanoforge";
3
3
 
4
4
  import { Position2D } from "../components/position-2d.component";
5
5
 
@@ -1,5 +1,5 @@
1
+ import type { Context } from "@nanoforge-dev/common";
1
2
  import type { EditorSystemManifest, Registry } from "@nanoforge-dev/ecs";
2
- import { type Context } from "nanoforge";
3
3
 
4
4
  import { Position2D } from "../components/position-2d.component";
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"project.factory.d.ts","names":[],"sources":["../../../src/libs/project/project.schema.d.ts","../../../src/libs/project/project.factory.ts"],"mappings":";;UAAiB;;;;EAIf;;;;;;EAOA;;;;;;;EAQA;;;;;;EAOA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;;EAMA;;;;;;;EAQA;;;;EAKA;;;;qBC6DW,OAAQ,QAAQ,kBAAgB"}
1
+ {"version":3,"file":"project.factory.d.ts","names":[],"sources":["../../../src/libs/project/project.schema.d.ts","../../../src/libs/project/project.factory.ts"],"mappings":";;UAAiB;;;;EAIf;;;;;;EAOA;;;;;;;EAQA;;;;;;EAOA;;;;EAKA;;;;EAKA;;;;EAKA;;;;EAKA;;;;;EAMA;;;;;;;EAQA;;;;EAKA;;;;qBCmEW,OAAQ,QAAQ,kBAAgB"}
@@ -7,6 +7,8 @@ const toWords = (str) => {
7
7
  const toKebabCase = (str) => {
8
8
  return toWords(str).map((word) => word.toLowerCase()).join("-");
9
9
  };
10
+ /** Fallback used when the registry lookup for `@nanoforge-dev/cli` fails. */
11
+ const DEFAULT_CLI_DEPENDENCY_VERSION = "latest";
10
12
  //#endregion
11
13
  //#region src/utils/registry.ts
12
14
  const REGISTRY_URL = "https://registry.npmjs.org";
@@ -50,8 +52,9 @@ const fetchTrustedVersion = async (packageName, fallback, options = {}) => {
50
52
  //#region src/libs/project/project.factory.ts
51
53
  const resolveDepVersions = async (part) => {
52
54
  const isClient = part === "client";
53
- const [nanoforge, ecs, network, graphics2d, input] = await Promise.all([
54
- fetchTrustedVersion("nanoforge", "^2"),
55
+ const [engine, cli, ecs, network, graphics2d, input] = await Promise.all([
56
+ fetchTrustedVersion("@nanoforge-dev/core", "^2"),
57
+ fetchTrustedVersion("@nanoforge-dev/cli", DEFAULT_CLI_DEPENDENCY_VERSION),
55
58
  fetchTrustedVersion("@nanoforge-dev/ecs", "^2"),
56
59
  fetchTrustedVersion("@nanoforge-dev/network", "^2"),
57
60
  isClient ? fetchTrustedVersion("@nanoforge-dev/graphics-2d", "^2") : "^2",
@@ -62,7 +65,8 @@ const resolveDepVersions = async (part) => {
62
65
  graphics2d,
63
66
  input,
64
67
  network,
65
- nanoforge
68
+ engine,
69
+ cli
66
70
  };
67
71
  };
68
72
  const transform = async (schema) => {
@@ -83,7 +87,8 @@ const transform = async (schema) => {
83
87
  graphics2dVersion: depVersions.graphics2d,
84
88
  inputVersion: depVersions.input,
85
89
  networkVersion: depVersions.network,
86
- nanoforgeVersion: depVersions.nanoforge,
90
+ engineVersion: depVersions.engine,
91
+ cliVersion: depVersions.cli,
87
92
  hasServer: schema.hasServer,
88
93
  docker: schema.docker ?? false,
89
94
  editor: schema.editor ?? false,
@@ -1 +1 @@
1
- {"version":3,"file":"project.factory.js","names":[],"sources":["../../../src/utils/formatting.ts","../../../src/defaults.ts","../../../src/utils/registry.ts","../../../src/libs/project/project.factory.ts"],"sourcesContent":["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","export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\nexport const DEFAULT_NANOFORGE_DEPENDENCY_VERSION = \"^2\";\nexport const DEFAULT_ENGINE_VERSION = \"^2\";\n\n/** Fallback used when the registry lookup for `@nanoforge-dev/cli` fails. */\nexport const DEFAULT_CLI_DEPENDENCY_VERSION = \"latest\";\n\n/**\n * Fallback used when the registry lookup for `typescript` fails. A specific\n * version, not a range — non-nanoforge packages are pinned exactly.\n */\nexport const DEFAULT_TYPESCRIPT_VERSION = \"6.0.3\";\n\n/**\n * Mirrors pnpm's own `minimumReleaseAge` supply-chain protection: when\n * resolving a pinned dependency version at generation time, only consider\n * versions published at least this long ago, so a freshly (and potentially\n * maliciously) published release isn't picked up immediately.\n */\nexport const MIN_RELEASE_AGE_HOURS = 48;\n","import { MIN_RELEASE_AGE_HOURS } from \"~/defaults\";\n\nconst REGISTRY_URL = \"https://registry.npmjs.org\";\nconst DEFAULT_TIMEOUT_MS = 3000;\n\nconst RELEASE_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/;\n\nconst compareVersions = (a: string, b: string): number => {\n const partsA = a.split(\".\").map(Number);\n const partsB = b.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) {\n const diff = (partsA[i] ?? 0) - (partsB[i] ?? 0);\n if (diff !== 0) {\n return diff;\n }\n }\n return 0;\n};\n\nexport interface FetchTrustedVersionOptions {\n /**\n * Only consider versions published at least this many hours ago, mirroring\n * pnpm's `minimumReleaseAge` supply-chain protection for a freshly\n * published (and potentially compromised) release.\n * @default MIN_RELEASE_AGE_HOURS\n */\n minAgeHours?: number;\n\n /**\n * Restrict candidates to this major version (e.g. `6` only considers\n * `6.x.x`). Useful to avoid silently jumping a generated project onto a\n * new major release.\n */\n major?: number;\n\n /** Network timeout in milliseconds. @default 3000 */\n timeoutMs?: number;\n}\n\n/**\n * Resolves the newest published version of an npm package that is at least\n * `minAgeHours` old, so freshly (and potentially maliciously) published\n * versions aren't picked up immediately. Falls back to `fallback` on any\n * network error, timeout, missing package, or when no version satisfies the\n * constraints, so callers never have to handle a rejected promise.\n */\nexport const fetchTrustedVersion = async (\n packageName: string,\n fallback: string,\n options: FetchTrustedVersionOptions = {},\n): Promise<string> => {\n const { minAgeHours = MIN_RELEASE_AGE_HOURS, major, timeoutMs = DEFAULT_TIMEOUT_MS } = options;\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(`${REGISTRY_URL}/${encodeURIComponent(packageName)}`, {\n signal: controller.signal,\n });\n if (!response.ok) {\n return fallback;\n }\n\n const data = (await response.json()) as { time?: Record<string, string> };\n const time = data.time;\n if (!time) {\n return fallback;\n }\n\n const cutoff = Date.now() - minAgeHours * 60 * 60 * 1000;\n const eligible = Object.entries(time)\n .filter(([version]) => RELEASE_VERSION_PATTERN.test(version))\n .filter(([version]) => major === undefined || Number(version.split(\".\")[0]) === major)\n .filter(([, publishedAt]) => new Date(publishedAt).getTime() <= cutoff)\n .map(([version]) => version)\n .sort(compareVersions);\n\n return eligible.at(-1) ? `^${eligible.at(-1)}` : fallback;\n } catch {\n return fallback;\n } finally {\n clearTimeout(timeout);\n }\n};\n\n/**\n * Resolves several packages' trusted versions in parallel. Keys of `specs`\n * are the package name to query the registry for; values are the fallback\n * to use if that lookup fails. Returns a map from the *same* keys to the\n * resolved (or fallback) version — typed so callers don't get `| undefined`\n * back for a key they just passed in.\n */\nexport const fetchTrustedVersions = async <\n T extends Record<string, { fallback: string; major?: number }>,\n>(\n specs: T,\n): Promise<{ [K in keyof T]: string }> => {\n const entries = await Promise.all(\n Object.entries(specs).map(async ([packageName, { fallback, major }]) => {\n const version = await fetchTrustedVersion(packageName, fallback, { major });\n return [packageName, version] as const;\n }),\n );\n return Object.fromEntries(entries) as { [K in keyof T]: string };\n};\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n apply,\n filter,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { toKebabCase } from \"@utils/formatting\";\nimport { fetchTrustedVersion } from \"@utils/registry\";\n\nimport {\n DEFAULT_APP_NAME,\n DEFAULT_LANGUAGE,\n DEFAULT_NANOFORGE_DEPENDENCY_VERSION,\n DEFAULT_PACKAGE_MANAGER,\n} from \"~/defaults\";\n\nimport { type ProjectOptions } from \"./project.options\";\nimport { type ProjectSchema } from \"./project.schema\";\n\ninterface DepVersions {\n ecs: string;\n graphics2d: string;\n input: string;\n network: string;\n nanoforge: string;\n}\n\nconst resolveDepVersions = async (part: ProjectSchema[\"part\"]): Promise<DepVersions> => {\n const isClient = part === \"client\";\n\n const [nanoforge, ecs, network, graphics2d, input] = await Promise.all([\n fetchTrustedVersion(\"nanoforge\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION),\n fetchTrustedVersion(\"@nanoforge-dev/ecs\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION),\n fetchTrustedVersion(\"@nanoforge-dev/network\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION),\n isClient\n ? fetchTrustedVersion(\"@nanoforge-dev/graphics-2d\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION)\n : DEFAULT_NANOFORGE_DEPENDENCY_VERSION,\n isClient\n ? fetchTrustedVersion(\"@nanoforge-dev/input\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION)\n : DEFAULT_NANOFORGE_DEPENDENCY_VERSION,\n ]);\n\n return {\n ecs,\n graphics2d,\n input,\n network,\n nanoforge,\n };\n};\n\nconst transform = async (schema: ProjectSchema): Promise<ProjectOptions> => {\n const packageManager = schema.packageManager ?? DEFAULT_PACKAGE_MANAGER;\n const workspace = schema.workspace ?? true;\n const depVersions = await resolveDepVersions(schema.part);\n\n const name = schema.name ?? schema.part;\n const packageName = schema.workspaceName\n ? `${toKebabCase(schema.workspaceName)}-${toKebabCase(name)}`\n : toKebabCase(schema.name ?? DEFAULT_APP_NAME);\n\n return {\n part: schema.part,\n appClass: schema.part === \"client\" ? \"NanoforgeClient\" : \"NanoforgeServer\",\n packageName,\n language: schema.language ?? DEFAULT_LANGUAGE,\n strict: schema.strict ?? true,\n packageManager,\n workspace,\n ecsVersion: depVersions.ecs,\n graphics2dVersion: depVersions.graphics2d,\n inputVersion: depVersions.input,\n networkVersion: depVersions.network,\n nanoforgeVersion: depVersions.nanoforge,\n hasServer: schema.hasServer,\n docker: schema.docker ?? false,\n editor: schema.editor ?? false,\n allowBuilds: workspace ? [] : [\"bun\"],\n };\n};\n\nconst generate = (options: ProjectOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n dot: \".\",\n ...strings,\n ...options,\n }),\n filter(\n (path) =>\n (options.docker && !options.workspace) ||\n ![\"Dockerfile\", \".dockerignore\"].includes(path.split(\"/\").at(-1) ?? \"\"),\n ),\n filter(\n (path) =>\n (options.packageManager === \"pnpm\" && options.allowBuilds.length > 0) ||\n !(path.split(\"/\").at(-1) ?? \"\").startsWith(\"pnpm-workspace.yaml\"),\n ),\n filter((path) => {\n const filename = path.split(\"/\").at(-1) ?? \"\";\n if (\n filename.startsWith(\"drawable-circle-2d.component\") ||\n filename.startsWith(\"draw-2d.system\")\n ) {\n return options.part === \"client\";\n }\n if (filename.startsWith(\"move-2d.system\")) {\n return options.part === \"server\";\n }\n if (filename.startsWith(\"position-sync.system\")) {\n return options.part === \"client\" && options.hasServer;\n }\n return true;\n }),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: ProjectSchema): Rule => {\n return async () => {\n const options = await transform(schema);\n\n return mergeWith(generate(options, schema.directory));\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"project.factory.js","names":[],"sources":["../../../src/utils/formatting.ts","../../../src/defaults.ts","../../../src/utils/registry.ts","../../../src/libs/project/project.factory.ts"],"sourcesContent":["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","export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\nexport const DEFAULT_NANOFORGE_DEPENDENCY_VERSION = \"^2\";\nexport const DEFAULT_ENGINE_VERSION = \"^2\";\n\n/** Fallback used when the registry lookup for `@nanoforge-dev/cli` fails. */\nexport const DEFAULT_CLI_DEPENDENCY_VERSION = \"latest\";\n\n/**\n * Fallback used when the registry lookup for `typescript` fails. A specific\n * version, not a range — non-nanoforge packages are pinned exactly.\n */\nexport const DEFAULT_TYPESCRIPT_VERSION = \"6.0.3\";\n\n/**\n * Mirrors pnpm's own `minimumReleaseAge` supply-chain protection: when\n * resolving a pinned dependency version at generation time, only consider\n * versions published at least this long ago, so a freshly (and potentially\n * maliciously) published release isn't picked up immediately.\n */\nexport const MIN_RELEASE_AGE_HOURS = 48;\n","import { MIN_RELEASE_AGE_HOURS } from \"~/defaults\";\n\nconst REGISTRY_URL = \"https://registry.npmjs.org\";\nconst DEFAULT_TIMEOUT_MS = 3000;\n\nconst RELEASE_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/;\n\nconst compareVersions = (a: string, b: string): number => {\n const partsA = a.split(\".\").map(Number);\n const partsB = b.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) {\n const diff = (partsA[i] ?? 0) - (partsB[i] ?? 0);\n if (diff !== 0) {\n return diff;\n }\n }\n return 0;\n};\n\nexport interface FetchTrustedVersionOptions {\n /**\n * Only consider versions published at least this many hours ago, mirroring\n * pnpm's `minimumReleaseAge` supply-chain protection for a freshly\n * published (and potentially compromised) release.\n * @default MIN_RELEASE_AGE_HOURS\n */\n minAgeHours?: number;\n\n /**\n * Restrict candidates to this major version (e.g. `6` only considers\n * `6.x.x`). Useful to avoid silently jumping a generated project onto a\n * new major release.\n */\n major?: number;\n\n /** Network timeout in milliseconds. @default 3000 */\n timeoutMs?: number;\n}\n\n/**\n * Resolves the newest published version of an npm package that is at least\n * `minAgeHours` old, so freshly (and potentially maliciously) published\n * versions aren't picked up immediately. Falls back to `fallback` on any\n * network error, timeout, missing package, or when no version satisfies the\n * constraints, so callers never have to handle a rejected promise.\n */\nexport const fetchTrustedVersion = async (\n packageName: string,\n fallback: string,\n options: FetchTrustedVersionOptions = {},\n): Promise<string> => {\n const { minAgeHours = MIN_RELEASE_AGE_HOURS, major, timeoutMs = DEFAULT_TIMEOUT_MS } = options;\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(`${REGISTRY_URL}/${encodeURIComponent(packageName)}`, {\n signal: controller.signal,\n });\n if (!response.ok) {\n return fallback;\n }\n\n const data = (await response.json()) as { time?: Record<string, string> };\n const time = data.time;\n if (!time) {\n return fallback;\n }\n\n const cutoff = Date.now() - minAgeHours * 60 * 60 * 1000;\n const eligible = Object.entries(time)\n .filter(([version]) => RELEASE_VERSION_PATTERN.test(version))\n .filter(([version]) => major === undefined || Number(version.split(\".\")[0]) === major)\n .filter(([, publishedAt]) => new Date(publishedAt).getTime() <= cutoff)\n .map(([version]) => version)\n .sort(compareVersions);\n\n return eligible.at(-1) ? `^${eligible.at(-1)}` : fallback;\n } catch {\n return fallback;\n } finally {\n clearTimeout(timeout);\n }\n};\n\n/**\n * Resolves several packages' trusted versions in parallel. Keys of `specs`\n * are the package name to query the registry for; values are the fallback\n * to use if that lookup fails. Returns a map from the *same* keys to the\n * resolved (or fallback) version — typed so callers don't get `| undefined`\n * back for a key they just passed in.\n */\nexport const fetchTrustedVersions = async <\n T extends Record<string, { fallback: string; major?: number }>,\n>(\n specs: T,\n): Promise<{ [K in keyof T]: string }> => {\n const entries = await Promise.all(\n Object.entries(specs).map(async ([packageName, { fallback, major }]) => {\n const version = await fetchTrustedVersion(packageName, fallback, { major });\n return [packageName, version] as const;\n }),\n );\n return Object.fromEntries(entries) as { [K in keyof T]: string };\n};\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n apply,\n filter,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { toKebabCase } from \"@utils/formatting\";\nimport { fetchTrustedVersion } from \"@utils/registry\";\n\nimport {\n DEFAULT_APP_NAME,\n DEFAULT_CLI_DEPENDENCY_VERSION,\n DEFAULT_ENGINE_VERSION,\n DEFAULT_LANGUAGE,\n DEFAULT_NANOFORGE_DEPENDENCY_VERSION,\n DEFAULT_PACKAGE_MANAGER,\n} from \"~/defaults\";\n\nimport { type ProjectOptions } from \"./project.options\";\nimport { type ProjectSchema } from \"./project.schema\";\n\ninterface DepVersions {\n ecs: string;\n graphics2d: string;\n input: string;\n network: string;\n engine: string;\n cli: string;\n}\n\nconst resolveDepVersions = async (part: ProjectSchema[\"part\"]): Promise<DepVersions> => {\n const isClient = part === \"client\";\n\n const [engine, cli, ecs, network, graphics2d, input] = await Promise.all([\n fetchTrustedVersion(\"@nanoforge-dev/core\", DEFAULT_ENGINE_VERSION),\n fetchTrustedVersion(\"@nanoforge-dev/cli\", DEFAULT_CLI_DEPENDENCY_VERSION),\n fetchTrustedVersion(\"@nanoforge-dev/ecs\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION),\n fetchTrustedVersion(\"@nanoforge-dev/network\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION),\n isClient\n ? fetchTrustedVersion(\"@nanoforge-dev/graphics-2d\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION)\n : DEFAULT_NANOFORGE_DEPENDENCY_VERSION,\n isClient\n ? fetchTrustedVersion(\"@nanoforge-dev/input\", DEFAULT_NANOFORGE_DEPENDENCY_VERSION)\n : DEFAULT_NANOFORGE_DEPENDENCY_VERSION,\n ]);\n\n return {\n ecs,\n graphics2d,\n input,\n network,\n engine,\n cli,\n };\n};\n\nconst transform = async (schema: ProjectSchema): Promise<ProjectOptions> => {\n const packageManager = schema.packageManager ?? DEFAULT_PACKAGE_MANAGER;\n const workspace = schema.workspace ?? true;\n const depVersions = await resolveDepVersions(schema.part);\n\n const name = schema.name ?? schema.part;\n const packageName = schema.workspaceName\n ? `${toKebabCase(schema.workspaceName)}-${toKebabCase(name)}`\n : toKebabCase(schema.name ?? DEFAULT_APP_NAME);\n\n return {\n part: schema.part,\n appClass: schema.part === \"client\" ? \"NanoforgeClient\" : \"NanoforgeServer\",\n packageName,\n language: schema.language ?? DEFAULT_LANGUAGE,\n strict: schema.strict ?? true,\n packageManager,\n workspace,\n ecsVersion: depVersions.ecs,\n graphics2dVersion: depVersions.graphics2d,\n inputVersion: depVersions.input,\n networkVersion: depVersions.network,\n engineVersion: depVersions.engine,\n cliVersion: depVersions.cli,\n hasServer: schema.hasServer,\n docker: schema.docker ?? false,\n editor: schema.editor ?? false,\n allowBuilds: workspace ? [] : [\"bun\"],\n };\n};\n\nconst generate = (options: ProjectOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n dot: \".\",\n ...strings,\n ...options,\n }),\n filter(\n (path) =>\n (options.docker && !options.workspace) ||\n ![\"Dockerfile\", \".dockerignore\"].includes(path.split(\"/\").at(-1) ?? \"\"),\n ),\n filter(\n (path) =>\n (options.packageManager === \"pnpm\" && options.allowBuilds.length > 0) ||\n !(path.split(\"/\").at(-1) ?? \"\").startsWith(\"pnpm-workspace.yaml\"),\n ),\n filter((path) => {\n const filename = path.split(\"/\").at(-1) ?? \"\";\n if (\n filename.startsWith(\"drawable-circle-2d.component\") ||\n filename.startsWith(\"draw-2d.system\")\n ) {\n return options.part === \"client\";\n }\n if (filename.startsWith(\"move-2d.system\")) {\n return options.part === \"server\";\n }\n if (filename.startsWith(\"position-sync.system\")) {\n return options.part === \"client\" && options.hasServer;\n }\n return true;\n }),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: ProjectSchema): Rule => {\n return async () => {\n const options = await transform(schema);\n\n return mergeWith(generate(options, schema.directory));\n };\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { defineConfig } from "nanoforge/config";
1
+ import { defineConfig } from "@nanoforge-dev/config";
2
2
 
3
3
  export default defineConfig({
4
4
  type: "workspace",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "devDependencies": {
10
10
  "@nanoforge-dev/cli": "<%= cliVersion %>",
11
- "nanoforge": "<%= engineVersion %>"
11
+ "@nanoforge-dev/config": "<%= engineVersion %>"
12
12
  },<% if (packageManager !== "pnpm") { %>
13
13
  "workspaces": ["apps/*"],<% } %><% if (packageManager === "npm" && allowBuilds.length > 0) { %>
14
14
  "allowScripts": {<% allowBuilds.forEach(function (pkg, i) { %>
@@ -1,4 +1,4 @@
1
- import { defineConfig } from "nanoforge/config";
1
+ import { defineConfig } from "@nanoforge-dev/config";
2
2
 
3
3
  export default defineConfig({
4
4
  type: "workspace",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "devDependencies": {
10
10
  "@nanoforge-dev/cli": "<%= cliVersion %>",
11
- "nanoforge": "<%= engineVersion %>",
11
+ "@nanoforge-dev/config": "<%= engineVersion %>",
12
12
  "typescript": "<%= typescriptVersion %>"
13
13
  },<% if (packageManager !== "pnpm") { %>
14
14
  "workspaces": ["apps/*"],<% } %><% if (packageManager === "npm" && allowBuilds.length > 0) { %>
@@ -72,7 +72,7 @@ const transform = async (schema) => {
72
72
  const packageManager = schema.packageManager ?? "npm";
73
73
  const versions = await fetchTrustedVersions({
74
74
  "@nanoforge-dev/cli": { fallback: DEFAULT_CLI_DEPENDENCY_VERSION },
75
- nanoforge: { fallback: "^2" },
75
+ "@nanoforge-dev/core": { fallback: "^2" },
76
76
  typescript: {
77
77
  fallback: DEFAULT_TYPESCRIPT_VERSION,
78
78
  major: 6
@@ -80,7 +80,7 @@ const transform = async (schema) => {
80
80
  });
81
81
  return {
82
82
  name: schema.name,
83
- engineVersion: versions.nanoforge,
83
+ engineVersion: versions["@nanoforge-dev/core"],
84
84
  cliVersion: versions["@nanoforge-dev/cli"],
85
85
  typescriptVersion: versions.typescript,
86
86
  language: schema.language,
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.factory.js","names":[],"sources":["../../../src/defaults.ts","../../../src/utils/registry.ts","../../../src/libs/workspace/workspace.factory.ts"],"sourcesContent":["export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\nexport const DEFAULT_NANOFORGE_DEPENDENCY_VERSION = \"^2\";\nexport const DEFAULT_ENGINE_VERSION = \"^2\";\n\n/** Fallback used when the registry lookup for `@nanoforge-dev/cli` fails. */\nexport const DEFAULT_CLI_DEPENDENCY_VERSION = \"latest\";\n\n/**\n * Fallback used when the registry lookup for `typescript` fails. A specific\n * version, not a range — non-nanoforge packages are pinned exactly.\n */\nexport const DEFAULT_TYPESCRIPT_VERSION = \"6.0.3\";\n\n/**\n * Mirrors pnpm's own `minimumReleaseAge` supply-chain protection: when\n * resolving a pinned dependency version at generation time, only consider\n * versions published at least this long ago, so a freshly (and potentially\n * maliciously) published release isn't picked up immediately.\n */\nexport const MIN_RELEASE_AGE_HOURS = 48;\n","import { MIN_RELEASE_AGE_HOURS } from \"~/defaults\";\n\nconst REGISTRY_URL = \"https://registry.npmjs.org\";\nconst DEFAULT_TIMEOUT_MS = 3000;\n\nconst RELEASE_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/;\n\nconst compareVersions = (a: string, b: string): number => {\n const partsA = a.split(\".\").map(Number);\n const partsB = b.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) {\n const diff = (partsA[i] ?? 0) - (partsB[i] ?? 0);\n if (diff !== 0) {\n return diff;\n }\n }\n return 0;\n};\n\nexport interface FetchTrustedVersionOptions {\n /**\n * Only consider versions published at least this many hours ago, mirroring\n * pnpm's `minimumReleaseAge` supply-chain protection for a freshly\n * published (and potentially compromised) release.\n * @default MIN_RELEASE_AGE_HOURS\n */\n minAgeHours?: number;\n\n /**\n * Restrict candidates to this major version (e.g. `6` only considers\n * `6.x.x`). Useful to avoid silently jumping a generated project onto a\n * new major release.\n */\n major?: number;\n\n /** Network timeout in milliseconds. @default 3000 */\n timeoutMs?: number;\n}\n\n/**\n * Resolves the newest published version of an npm package that is at least\n * `minAgeHours` old, so freshly (and potentially maliciously) published\n * versions aren't picked up immediately. Falls back to `fallback` on any\n * network error, timeout, missing package, or when no version satisfies the\n * constraints, so callers never have to handle a rejected promise.\n */\nexport const fetchTrustedVersion = async (\n packageName: string,\n fallback: string,\n options: FetchTrustedVersionOptions = {},\n): Promise<string> => {\n const { minAgeHours = MIN_RELEASE_AGE_HOURS, major, timeoutMs = DEFAULT_TIMEOUT_MS } = options;\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(`${REGISTRY_URL}/${encodeURIComponent(packageName)}`, {\n signal: controller.signal,\n });\n if (!response.ok) {\n return fallback;\n }\n\n const data = (await response.json()) as { time?: Record<string, string> };\n const time = data.time;\n if (!time) {\n return fallback;\n }\n\n const cutoff = Date.now() - minAgeHours * 60 * 60 * 1000;\n const eligible = Object.entries(time)\n .filter(([version]) => RELEASE_VERSION_PATTERN.test(version))\n .filter(([version]) => major === undefined || Number(version.split(\".\")[0]) === major)\n .filter(([, publishedAt]) => new Date(publishedAt).getTime() <= cutoff)\n .map(([version]) => version)\n .sort(compareVersions);\n\n return eligible.at(-1) ? `^${eligible.at(-1)}` : fallback;\n } catch {\n return fallback;\n } finally {\n clearTimeout(timeout);\n }\n};\n\n/**\n * Resolves several packages' trusted versions in parallel. Keys of `specs`\n * are the package name to query the registry for; values are the fallback\n * to use if that lookup fails. Returns a map from the *same* keys to the\n * resolved (or fallback) version — typed so callers don't get `| undefined`\n * back for a key they just passed in.\n */\nexport const fetchTrustedVersions = async <\n T extends Record<string, { fallback: string; major?: number }>,\n>(\n specs: T,\n): Promise<{ [K in keyof T]: string }> => {\n const entries = await Promise.all(\n Object.entries(specs).map(async ([packageName, { fallback, major }]) => {\n const version = await fetchTrustedVersion(packageName, fallback, { major });\n return [packageName, version] as const;\n }),\n );\n return Object.fromEntries(entries) as { [K in keyof T]: string };\n};\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n apply,\n filter,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { fetchTrustedVersions } from \"@utils/registry\";\n\nimport {\n DEFAULT_CLI_DEPENDENCY_VERSION,\n DEFAULT_ENGINE_VERSION,\n DEFAULT_PACKAGE_MANAGER,\n DEFAULT_TYPESCRIPT_VERSION,\n} from \"~/defaults\";\n\nimport { type WorkspaceOptions } from \"./workspace.options\";\nimport { type WorkspaceSchema } from \"./workspace.schema\";\n\n/**\n * bun ships as a postinstall-driven binary download (its own package.json\n * declares `\"postinstall\": \"node install.js\"`), and @nanoforge-dev/cli\n * depends on it unconditionally, so every generated workspace needs it\n * approved to run its build script regardless of what the caller passes.\n */\nconst ALWAYS_ALLOWED_BUILDS = [\"bun\"];\n\nconst transform = async (schema: WorkspaceSchema): Promise<WorkspaceOptions> => {\n const packageManager = schema.packageManager ?? DEFAULT_PACKAGE_MANAGER;\n\n const versions = await fetchTrustedVersions({\n \"@nanoforge-dev/cli\": { fallback: DEFAULT_CLI_DEPENDENCY_VERSION },\n nanoforge: { fallback: DEFAULT_ENGINE_VERSION },\n typescript: { fallback: DEFAULT_TYPESCRIPT_VERSION, major: 6 },\n });\n\n return {\n name: schema.name,\n engineVersion: versions.nanoforge,\n cliVersion: versions[\"@nanoforge-dev/cli\"],\n typescriptVersion: versions.typescript,\n language: schema.language,\n strict: schema.strict,\n packageManager,\n allowBuilds: Array.from(new Set([...ALWAYS_ALLOWED_BUILDS, ...(schema.allowBuilds ?? [])])),\n docker: schema.docker ?? false,\n };\n};\n\nconst generate = (options: WorkspaceOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n dot: \".\",\n ...strings,\n ...options,\n }),\n filter(\n (path) =>\n options.packageManager === \"pnpm\" ||\n !(path.split(\"/\").at(-1) ?? \"\").startsWith(\"pnpm-workspace.yaml\"),\n ),\n filter(\n (path) =>\n options.docker || ![\"Dockerfile\", \".dockerignore\"].includes(path.split(\"/\").at(-1) ?? \"\"),\n ),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: WorkspaceSchema): Rule => {\n return async () => {\n const options = await transform(schema);\n const path = schema.directory ?? options.name;\n\n return mergeWith(generate(options, path));\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"workspace.factory.js","names":[],"sources":["../../../src/defaults.ts","../../../src/utils/registry.ts","../../../src/libs/workspace/workspace.factory.ts"],"sourcesContent":["export const DEFAULT_APP_NAME = \"nanoforge-app\";\nexport const DEFAULT_LANGUAGE = \"ts\";\nexport const DEFAULT_PACKAGE_MANAGER = \"npm\";\nexport const DEFAULT_NANOFORGE_DEPENDENCY_VERSION = \"^2\";\nexport const DEFAULT_ENGINE_VERSION = \"^2\";\n\n/** Fallback used when the registry lookup for `@nanoforge-dev/cli` fails. */\nexport const DEFAULT_CLI_DEPENDENCY_VERSION = \"latest\";\n\n/**\n * Fallback used when the registry lookup for `typescript` fails. A specific\n * version, not a range — non-nanoforge packages are pinned exactly.\n */\nexport const DEFAULT_TYPESCRIPT_VERSION = \"6.0.3\";\n\n/**\n * Mirrors pnpm's own `minimumReleaseAge` supply-chain protection: when\n * resolving a pinned dependency version at generation time, only consider\n * versions published at least this long ago, so a freshly (and potentially\n * maliciously) published release isn't picked up immediately.\n */\nexport const MIN_RELEASE_AGE_HOURS = 48;\n","import { MIN_RELEASE_AGE_HOURS } from \"~/defaults\";\n\nconst REGISTRY_URL = \"https://registry.npmjs.org\";\nconst DEFAULT_TIMEOUT_MS = 3000;\n\nconst RELEASE_VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/;\n\nconst compareVersions = (a: string, b: string): number => {\n const partsA = a.split(\".\").map(Number);\n const partsB = b.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) {\n const diff = (partsA[i] ?? 0) - (partsB[i] ?? 0);\n if (diff !== 0) {\n return diff;\n }\n }\n return 0;\n};\n\nexport interface FetchTrustedVersionOptions {\n /**\n * Only consider versions published at least this many hours ago, mirroring\n * pnpm's `minimumReleaseAge` supply-chain protection for a freshly\n * published (and potentially compromised) release.\n * @default MIN_RELEASE_AGE_HOURS\n */\n minAgeHours?: number;\n\n /**\n * Restrict candidates to this major version (e.g. `6` only considers\n * `6.x.x`). Useful to avoid silently jumping a generated project onto a\n * new major release.\n */\n major?: number;\n\n /** Network timeout in milliseconds. @default 3000 */\n timeoutMs?: number;\n}\n\n/**\n * Resolves the newest published version of an npm package that is at least\n * `minAgeHours` old, so freshly (and potentially maliciously) published\n * versions aren't picked up immediately. Falls back to `fallback` on any\n * network error, timeout, missing package, or when no version satisfies the\n * constraints, so callers never have to handle a rejected promise.\n */\nexport const fetchTrustedVersion = async (\n packageName: string,\n fallback: string,\n options: FetchTrustedVersionOptions = {},\n): Promise<string> => {\n const { minAgeHours = MIN_RELEASE_AGE_HOURS, major, timeoutMs = DEFAULT_TIMEOUT_MS } = options;\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(`${REGISTRY_URL}/${encodeURIComponent(packageName)}`, {\n signal: controller.signal,\n });\n if (!response.ok) {\n return fallback;\n }\n\n const data = (await response.json()) as { time?: Record<string, string> };\n const time = data.time;\n if (!time) {\n return fallback;\n }\n\n const cutoff = Date.now() - minAgeHours * 60 * 60 * 1000;\n const eligible = Object.entries(time)\n .filter(([version]) => RELEASE_VERSION_PATTERN.test(version))\n .filter(([version]) => major === undefined || Number(version.split(\".\")[0]) === major)\n .filter(([, publishedAt]) => new Date(publishedAt).getTime() <= cutoff)\n .map(([version]) => version)\n .sort(compareVersions);\n\n return eligible.at(-1) ? `^${eligible.at(-1)}` : fallback;\n } catch {\n return fallback;\n } finally {\n clearTimeout(timeout);\n }\n};\n\n/**\n * Resolves several packages' trusted versions in parallel. Keys of `specs`\n * are the package name to query the registry for; values are the fallback\n * to use if that lookup fails. Returns a map from the *same* keys to the\n * resolved (or fallback) version — typed so callers don't get `| undefined`\n * back for a key they just passed in.\n */\nexport const fetchTrustedVersions = async <\n T extends Record<string, { fallback: string; major?: number }>,\n>(\n specs: T,\n): Promise<{ [K in keyof T]: string }> => {\n const entries = await Promise.all(\n Object.entries(specs).map(async ([packageName, { fallback, major }]) => {\n const version = await fetchTrustedVersion(packageName, fallback, { major });\n return [packageName, version] as const;\n }),\n );\n return Object.fromEntries(entries) as { [K in keyof T]: string };\n};\n","import { type Path, join, normalize, strings } from \"@angular-devkit/core\";\nimport {\n type Rule,\n type Source,\n apply,\n filter,\n mergeWith,\n move,\n renameTemplateFiles,\n template,\n url,\n} from \"@angular-devkit/schematics\";\n\nimport { fetchTrustedVersions } from \"@utils/registry\";\n\nimport {\n DEFAULT_CLI_DEPENDENCY_VERSION,\n DEFAULT_ENGINE_VERSION,\n DEFAULT_PACKAGE_MANAGER,\n DEFAULT_TYPESCRIPT_VERSION,\n} from \"~/defaults\";\n\nimport { type WorkspaceOptions } from \"./workspace.options\";\nimport { type WorkspaceSchema } from \"./workspace.schema\";\n\n/**\n * bun ships as a postinstall-driven binary download (its own package.json\n * declares `\"postinstall\": \"node install.js\"`), and @nanoforge-dev/cli\n * depends on it unconditionally, so every generated workspace needs it\n * approved to run its build script regardless of what the caller passes.\n */\nconst ALWAYS_ALLOWED_BUILDS = [\"bun\"];\n\nconst transform = async (schema: WorkspaceSchema): Promise<WorkspaceOptions> => {\n const packageManager = schema.packageManager ?? DEFAULT_PACKAGE_MANAGER;\n\n const versions = await fetchTrustedVersions({\n \"@nanoforge-dev/cli\": { fallback: DEFAULT_CLI_DEPENDENCY_VERSION },\n \"@nanoforge-dev/core\": { fallback: DEFAULT_ENGINE_VERSION },\n typescript: { fallback: DEFAULT_TYPESCRIPT_VERSION, major: 6 },\n });\n\n return {\n name: schema.name,\n engineVersion: versions[\"@nanoforge-dev/core\"],\n cliVersion: versions[\"@nanoforge-dev/cli\"],\n typescriptVersion: versions.typescript,\n language: schema.language,\n strict: schema.strict,\n packageManager,\n allowBuilds: Array.from(new Set([...ALWAYS_ALLOWED_BUILDS, ...(schema.allowBuilds ?? [])])),\n docker: schema.docker ?? false,\n };\n};\n\nconst generate = (options: WorkspaceOptions, path: string): Source => {\n return apply(url(join(\"./files\" as Path, options.language)), [\n template({\n dot: \".\",\n ...strings,\n ...options,\n }),\n filter(\n (path) =>\n options.packageManager === \"pnpm\" ||\n !(path.split(\"/\").at(-1) ?? \"\").startsWith(\"pnpm-workspace.yaml\"),\n ),\n filter(\n (path) =>\n options.docker || ![\"Dockerfile\", \".dockerignore\"].includes(path.split(\"/\").at(-1) ?? \"\"),\n ),\n renameTemplateFiles(),\n move(normalize(path)),\n ]);\n};\n\nexport const main = (schema: WorkspaceSchema): Rule => {\n return async () => {\n const options = await transform(schema);\n const path = schema.directory ?? options.name;\n\n return mergeWith(generate(options, path));\n };\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@nanoforge-dev/schematics",
4
- "version": "2.3.0",
4
+ "version": "2.3.1",
5
5
  "description": "NanoForge Schematics",
6
6
  "keywords": [
7
7
  "nanoforge",