@vedangiitb/qwintly-core 1.3.9 → 1.3.10

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.
@@ -25,7 +25,7 @@ const DEFAULT_PAGE_CONFIG = (() => {
25
25
  ];
26
26
  // Validate uniqueness (and keep deterministic IDs).
27
27
  const ids = extractAllIds(elements);
28
- if (ids.size !== 2 || !ids.has("root") || !ids.has("title")) {
28
+ if (!ids.has("root")) {
29
29
  throw new Error("DEFAULT_PAGE_CONFIG ids must be stable and unique");
30
30
  }
31
31
  return JSON.stringify({ elements }, null, 2) + "\n";
@@ -1 +1 @@
1
- {"version":3,"file":"createNewRoute.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/createNewRoute.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { extractAllIds } from \"../helpers/elementid.helpers.js\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport {\n isSafeSegment,\n normalizeRouteSegments,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\ntype CreateNewRouteResult =\n | {\n success: true;\n route: string;\n created_files: string[];\n page_config_json: unknown;\n }\n | { success: false; error: string };\n\nconst PAGE_TSX_TEMPLATE = [\n 'import { RenderElement } from \"@/lib/renderer/RenderElement\";',\n 'import pageConfig from \"./pageConfig.json\";',\n 'import type { BuilderElement } from \"@/types/elements\";',\n \"\",\n \"export default function Page() {\",\n \" const config = pageConfig as { elements: BuilderElement[] };\",\n \" return config.elements.map((el) => <RenderElement key={el.id} el={el} />);\",\n \"}\",\n \"\",\n].join(\"\\n\");\n\nconst DEFAULT_PAGE_CONFIG = (() => {\n const elements: any[] = [\n {\n id: \"root\",\n type: \"div\",\n className: \"min-h-screen p-6\",\n props: {},\n },\n ];\n\n // Validate uniqueness (and keep deterministic IDs).\n const ids = extractAllIds(elements as any);\n if (ids.size !== 2 || !ids.has(\"root\") || !ids.has(\"title\")) {\n throw new Error(\"DEFAULT_PAGE_CONFIG ids must be stable and unique\");\n }\n\n return JSON.stringify({ elements }, null, 2) + \"\\n\";\n})();\n\nexport const createCreateNewRouteImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs: coreFs } = deps;\n\n return async (parentRoute: string, routeName: string) => {\n const parentSegments = normalizeRouteSegments(parentRoute);\n const routeSegment = String(routeName ?? \"\").trim();\n\n if (!isSafeSegment(routeSegment)) {\n return {\n success: false,\n error: \"Invalid route name\",\n } satisfies CreateNewRouteResult;\n }\n if (parentSegments.some((s) => !isSafeSegment(s))) {\n return {\n success: false,\n error: \"Invalid parent route\",\n } satisfies CreateNewRouteResult;\n }\n\n const appDir = toWorkspacePath(workspaceRoot, \"app\");\n const parentDir = path.join(appDir, ...parentSegments);\n const finalDir = path.join(parentDir, routeSegment);\n\n // Parent must exist (don't implicitly create arbitrary routes).\n try {\n const st = await coreFs.stat(parentDir);\n if (!st.isDirectory()) {\n return {\n success: false,\n error: \"Parent not a folder\",\n } satisfies CreateNewRouteResult;\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n return {\n success: false,\n error: \"Parent route missing\",\n } satisfies CreateNewRouteResult;\n }\n return {\n success: false,\n error: \"Parent check failed\",\n } satisfies CreateNewRouteResult;\n }\n\n // Route must not already exist.\n try {\n await coreFs.stat(finalDir);\n return {\n success: false,\n error: \"Route already exists\",\n } satisfies CreateNewRouteResult;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code && code !== \"ENOENT\") {\n return {\n success: false,\n error: \"Route check failed\",\n } satisfies CreateNewRouteResult;\n }\n }\n\n const tmpDir = path.join(\n parentDir,\n `.qwintly_route_tmp_${routeSegment}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n const rollback = async () => {\n // Rollback any partially-created temp output.\n try {\n await fs.rm(tmpDir, { recursive: true, force: true });\n } catch {\n // best-effort cleanup only\n }\n };\n\n try {\n await coreFs.mkdirp(tmpDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Temp folder create failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(path.join(tmpDir, \"page.tsx\"), PAGE_TSX_TEMPLATE);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write page.tsx failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(\n path.join(tmpDir, \"pageConfig.json\"),\n DEFAULT_PAGE_CONFIG,\n );\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write pageConfig failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n // Commit: move temp dir into place (best-effort atomic within same parent).\n await fs.rename(tmpDir, finalDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Finalize route failed\",\n } satisfies CreateNewRouteResult;\n }\n\n const routePath =\n \"/\" + [...parentSegments, routeSegment].filter(Boolean).join(\"/\");\n\n let pageConfigJson: unknown = null;\n try {\n pageConfigJson = JSON.parse(DEFAULT_PAGE_CONFIG);\n } catch {\n // shouldn't happen, but keep the tool robust\n pageConfigJson = { elements: [] };\n }\n\n return {\n success: true,\n route: routePath,\n created_files: [\n path\n .join(\"app\", ...parentSegments, routeSegment, \"page.tsx\")\n .replace(/\\\\/g, \"/\"),\n path\n .join(\"app\", ...parentSegments, routeSegment, \"pageConfig.json\")\n .replace(/\\\\/g, \"/\"),\n ],\n page_config_json: pageConfigJson,\n } satisfies CreateNewRouteResult;\n };\n};\n\nexport const DEFAULT_PAGE_CONFIG_JSON = DEFAULT_PAGE_CONFIG;\nexport const PAGE_TSX_TEMPLATE_STRING = PAGE_TSX_TEMPLATE;\n"]}
1
+ {"version":3,"file":"createNewRoute.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/createNewRoute.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { extractAllIds } from \"../helpers/elementid.helpers.js\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport {\n isSafeSegment,\n normalizeRouteSegments,\n} from \"../helpers/pageConfigJson.helpers.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\ntype CreateNewRouteResult =\n | {\n success: true;\n route: string;\n created_files: string[];\n page_config_json: unknown;\n }\n | { success: false; error: string };\n\nconst PAGE_TSX_TEMPLATE = [\n 'import { RenderElement } from \"@/lib/renderer/RenderElement\";',\n 'import pageConfig from \"./pageConfig.json\";',\n 'import type { BuilderElement } from \"@/types/elements\";',\n \"\",\n \"export default function Page() {\",\n \" const config = pageConfig as { elements: BuilderElement[] };\",\n \" return config.elements.map((el) => <RenderElement key={el.id} el={el} />);\",\n \"}\",\n \"\",\n].join(\"\\n\");\n\nconst DEFAULT_PAGE_CONFIG = (() => {\n const elements: any[] = [\n {\n id: \"root\",\n type: \"div\",\n className: \"min-h-screen p-6\",\n props: {},\n },\n ];\n\n // Validate uniqueness (and keep deterministic IDs).\n const ids = extractAllIds(elements as any);\n if (!ids.has(\"root\")) {\n throw new Error(\"DEFAULT_PAGE_CONFIG ids must be stable and unique\");\n }\n\n return JSON.stringify({ elements }, null, 2) + \"\\n\";\n})();\n\nexport const createCreateNewRouteImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs: coreFs } = deps;\n\n return async (parentRoute: string, routeName: string) => {\n const parentSegments = normalizeRouteSegments(parentRoute);\n const routeSegment = String(routeName ?? \"\").trim();\n\n if (!isSafeSegment(routeSegment)) {\n return {\n success: false,\n error: \"Invalid route name\",\n } satisfies CreateNewRouteResult;\n }\n if (parentSegments.some((s) => !isSafeSegment(s))) {\n return {\n success: false,\n error: \"Invalid parent route\",\n } satisfies CreateNewRouteResult;\n }\n\n const appDir = toWorkspacePath(workspaceRoot, \"app\");\n const parentDir = path.join(appDir, ...parentSegments);\n const finalDir = path.join(parentDir, routeSegment);\n\n // Parent must exist (don't implicitly create arbitrary routes).\n try {\n const st = await coreFs.stat(parentDir);\n if (!st.isDirectory()) {\n return {\n success: false,\n error: \"Parent not a folder\",\n } satisfies CreateNewRouteResult;\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") {\n return {\n success: false,\n error: \"Parent route missing\",\n } satisfies CreateNewRouteResult;\n }\n return {\n success: false,\n error: \"Parent check failed\",\n } satisfies CreateNewRouteResult;\n }\n\n // Route must not already exist.\n try {\n await coreFs.stat(finalDir);\n return {\n success: false,\n error: \"Route already exists\",\n } satisfies CreateNewRouteResult;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code && code !== \"ENOENT\") {\n return {\n success: false,\n error: \"Route check failed\",\n } satisfies CreateNewRouteResult;\n }\n }\n\n const tmpDir = path.join(\n parentDir,\n `.qwintly_route_tmp_${routeSegment}_${Date.now()}_${Math.random().toString(16).slice(2)}`,\n );\n\n const rollback = async () => {\n // Rollback any partially-created temp output.\n try {\n await fs.rm(tmpDir, { recursive: true, force: true });\n } catch {\n // best-effort cleanup only\n }\n };\n\n try {\n await coreFs.mkdirp(tmpDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Temp folder create failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(path.join(tmpDir, \"page.tsx\"), PAGE_TSX_TEMPLATE);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write page.tsx failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n await coreFs.writeFile(\n path.join(tmpDir, \"pageConfig.json\"),\n DEFAULT_PAGE_CONFIG,\n );\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Write pageConfig failed\",\n } satisfies CreateNewRouteResult;\n }\n\n try {\n // Commit: move temp dir into place (best-effort atomic within same parent).\n await fs.rename(tmpDir, finalDir);\n } catch (err) {\n await rollback();\n return {\n success: false,\n error: \"Finalize route failed\",\n } satisfies CreateNewRouteResult;\n }\n\n const routePath =\n \"/\" + [...parentSegments, routeSegment].filter(Boolean).join(\"/\");\n\n let pageConfigJson: unknown = null;\n try {\n pageConfigJson = JSON.parse(DEFAULT_PAGE_CONFIG);\n } catch {\n // shouldn't happen, but keep the tool robust\n pageConfigJson = { elements: [] };\n }\n\n return {\n success: true,\n route: routePath,\n created_files: [\n path\n .join(\"app\", ...parentSegments, routeSegment, \"page.tsx\")\n .replace(/\\\\/g, \"/\"),\n path\n .join(\"app\", ...parentSegments, routeSegment, \"pageConfig.json\")\n .replace(/\\\\/g, \"/\"),\n ],\n page_config_json: pageConfigJson,\n } satisfies CreateNewRouteResult;\n };\n};\n\nexport const DEFAULT_PAGE_CONFIG_JSON = DEFAULT_PAGE_CONFIG;\nexport const PAGE_TSX_TEMPLATE_STRING = PAGE_TSX_TEMPLATE;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vedangiitb/qwintly-core",
3
- "version": "1.3.9",
3
+ "version": "1.3.10",
4
4
  "description": "Qwintly Core",
5
5
  "homepage": "https://github.com/vedangiitb/qwintly-core#readme",
6
6
  "bugs": {