@vedangiitb/qwintly-core 1.3.9 → 1.3.11
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/ai/prompts/codegen.prompt.d.ts.map +1 -1
- package/dist/ai/prompts/codegen.prompt.js +6 -5
- package/dist/ai/prompts/codegen.prompt.js.map +1 -1
- package/dist/ai/tools/implementations/createNewRoute.impl.js +1 -1
- package/dist/ai/tools/implementations/createNewRoute.impl.js.map +1 -1
- package/dist/ai/tools/schemas/insertElement.schema.d.ts +1 -0
- package/dist/ai/tools/schemas/insertElement.schema.d.ts.map +1 -1
- package/dist/ai/tools/schemas/insertElement.schema.js +2 -1
- package/dist/ai/tools/schemas/insertElement.schema.js.map +1 -1
- package/dist/ai/tools/validators/builderElement.zod.d.ts.map +1 -1
- package/dist/ai/tools/validators/builderElement.zod.js +21 -2
- package/dist/ai/tools/validators/builderElement.zod.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQvE,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,GAAG,CAAC;IACV,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,uBAAuB,
|
|
1
|
+
{"version":3,"file":"codegen.prompt.d.ts","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAQvE,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,GAAG,CAAC;IACV,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,uBAAuB,WAqE5D,CAAC"}
|
|
@@ -26,11 +26,12 @@ export const codegenPrompt = (params) => {
|
|
|
26
26
|
- update_props: Update props
|
|
27
27
|
- submit_codegen_done: Finish task
|
|
28
28
|
|
|
29
|
-
Rules:
|
|
30
|
-
- One insert_element per tree (include children inline) unless depth blocks it.
|
|
31
|
-
- Create missing routes with create_new_route.
|
|
32
|
-
-
|
|
33
|
-
-
|
|
29
|
+
Rules:
|
|
30
|
+
- One insert_element per tree (include children inline) unless depth blocks it.
|
|
31
|
+
- Create missing routes with create_new_route.
|
|
32
|
+
- For any tool arg named route, always use URL paths with forward slashes (e.g. '/', '/pricing'); never use '\\' or filesystem paths like 'app/pricing'.
|
|
33
|
+
- image src auto-generated from alt
|
|
34
|
+
- lucide-react icons only
|
|
34
35
|
`.trim());
|
|
35
36
|
const projectConfiguration = mdSection("Project Config", [
|
|
36
37
|
jsonBlock("framework", codegenIndex.projectConfigs.frameworkConfig),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,SAAS,EACT,SAAS,EACT,gBAAgB,GACjB,MAAM,iCAAiC,CAAC;AASzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAA+B,EAAE,EAAE;IAC/D,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEtE,MAAM,MAAM,GAAG;;;;;;;;;MASX,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC;GAC5C,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,QAAQ,GAAG,SAAS,CACxB,mBAAmB,EACnB,SAAS,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,CAChC,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,EACP
|
|
1
|
+
{"version":3,"file":"codegen.prompt.js","sourceRoot":"","sources":["../../../src/ai/prompts/codegen.prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EACL,SAAS,EACT,SAAS,EACT,gBAAgB,GACjB,MAAM,iCAAiC,CAAC;AASzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAA+B,EAAE,EAAE;IAC/D,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEtE,MAAM,MAAM,GAAG;;;;;;;;;MASX,gBAAgB,CAAC,YAAY,EAAE,SAAS,CAAC;GAC5C,CAAC,IAAI,EAAE,CAAC;IAET,MAAM,QAAQ,GAAG,SAAS,CACxB,mBAAmB,EACnB,SAAS,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,CAChC,CAAC;IAEF,MAAM,SAAS,GAAG,SAAS,CACzB,OAAO,EACP;;;;;;;;;;;;;;;;;;KAkBC,CAAC,IAAI,EAAE,CACT,CAAC;IAEF,MAAM,oBAAoB,GAAG,SAAS,CACpC,gBAAgB,EAChB;QACE,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC;QAEnE,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,cAAc,CAAC,aAAa,CAAC;QAE/D,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,cAAc,CAAC,eAAe,CAAC;KACpE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,OAAO,GAAG,SAAS,CACvB,kBAAkB,EAClB,SAAS,CAAC,SAAS,EAAE,gBAAgB,IAAI,EAAE,CAAC,CAC7C,CAAC;IAEF,MAAM,QAAQ,GAAG;QACf,MAAM;QACN,QAAQ;QACR,SAAS;QACT,oBAAoB;QACpB,OAAO;QACP,eAAe;KAChB,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC,CAAC","sourcesContent":["import { CodegenIndex, CollectedContext } from \"../../types/public.js\";\r\nimport { codegenExamples } from \"./examples/codegen.examples.js\";\r\nimport {\r\n jsonBlock,\r\n mdSection,\r\n projectStateNote,\r\n} from \"./helpers/promptParts.helper.js\";\r\n\r\nexport type CodegenNodePromptParams = {\r\n task: any;\r\n codegenIndex: CodegenIndex;\r\n collectedContext: CollectedContext;\r\n isNewProject: boolean;\r\n};\r\n\r\nexport const codegenPrompt = (params: CodegenNodePromptParams) => {\r\n const { task, codegenIndex, collectedContext, isNewProject } = params;\r\n\r\n const system = `\r\n You are a senior software engineer implementing tasks in an existing codebase.\r\n\r\n Rules:\r\n - Implement ONLY the requested task.\r\n - Prefer incremental edits over rewrites.\r\n - Be concise and deterministic.\r\n - Do not output code directly; use tools.\r\n\r\n ${projectStateNote(isNewProject, \"codegen\")}\r\n `.trim();\r\n\r\n const taskInfo = mdSection(\r\n \"Task to implement\",\r\n jsonBlock(\"task\", task ?? null),\r\n );\r\n\r\n const toolsInfo = mdSection(\r\n \"Tools\",\r\n `\r\n Available tools:\r\n\r\n - read_file: Read file\r\n - list_dir: List directory\r\n - create_new_route: Create route with page.tsx + pageConfig.json\r\n - insert_element: Insert element tree\r\n - delete_element: Delete element\r\n - update_classname: Update className\r\n - update_props: Update props\r\n - submit_codegen_done: Finish task\r\n\r\n Rules:\n - One insert_element per tree (include children inline) unless depth blocks it.\n - Create missing routes with create_new_route.\n - For any tool arg named route, always use URL paths with forward slashes (e.g. '/', '/pricing'); never use '\\\\' or filesystem paths like 'app/pricing'.\n - image src auto-generated from alt\n - lucide-react icons only\n `.trim(),\n );\n\r\n const projectConfiguration = mdSection(\r\n \"Project Config\",\r\n [\r\n jsonBlock(\"framework\", codegenIndex.projectConfigs.frameworkConfig),\r\n\r\n jsonBlock(\"runtime\", codegenIndex.projectConfigs.runtimeConfig),\r\n\r\n jsonBlock(\"rendering\", codegenIndex.projectConfigs.renderingConfig),\r\n ].join(\"\\n\"),\r\n );\r\n\r\n const context = mdSection(\r\n \"Relevant Context\",\r\n jsonBlock(\"context\", collectedContext ?? {}),\r\n );\r\n\r\n const sections = [\r\n system,\r\n taskInfo,\r\n toolsInfo,\r\n projectConfiguration,\r\n context,\r\n codegenExamples,\r\n ];\r\n\r\n return sections.join(\"\\n\\n---\\n\\n\");\r\n};\r\n"]}
|
|
@@ -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 (
|
|
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":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EACL,aAAa,EACb,sBAAsB,GACvB,MAAM,sCAAsC,CAAC;AAY9C,MAAM,iBAAiB,GAAG;IACxB,+DAA+D;IAC/D,6CAA6C;IAC7C,yDAAyD;IACzD,EAAE;IACF,kCAAkC;IAClC,gEAAgE;IAChE,8EAA8E;IAC9E,GAAG;IACH,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE;IAChC,MAAM,QAAQ,GAAU;QACtB;YACE,EAAE,EAAE,MAAM;YACV,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,kBAAkB;YAC7B,KAAK,EAAE,EAAE;SACV;KACF,CAAC;IAEF,oDAAoD;IACpD,MAAM,GAAG,GAAG,aAAa,CAAC,QAAe,CAAC,CAAC;IAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AACtD,CAAC,CAAC,EAAE,CAAC;AAEL,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,IAAmB,EAAE,EAAE;IAC9D,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE3C,OAAO,KAAK,EAAE,WAAmB,EAAE,SAAiB,EAAE,EAAE;QACtD,MAAM,cAAc,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAEpD,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;YACjC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,oBAAoB;aACG,CAAC;QACnC,CAAC;QACD,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,sBAAsB;aACC,CAAC;QACnC,CAAC;QAED,MAAM,MAAM,GAAG,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAEpD,gEAAgE;QAChE,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;gBACtB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,qBAAqB;iBACE,CAAC;YACnC,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAAoC,EAAE,IAAI,CAAC;YACzD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,sBAAsB;iBACC,CAAC;YACnC,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,qBAAqB;aACE,CAAC;QACnC,CAAC;QAED,gCAAgC;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,sBAAsB;aACC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAAoC,EAAE,IAAI,CAAC;YACzD,IAAI,IAAI,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,oBAAoB;iBACG,CAAC;YACnC,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CACtB,SAAS,EACT,sBAAsB,YAAY,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAC1F,CAAC;QAEF,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,8CAA8C;YAC9C,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,2BAA2B;aACJ,CAAC;QACnC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,uBAAuB;aACA,CAAC;QACnC,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CACpB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACpC,mBAAmB,CACpB,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,yBAAyB;aACF,CAAC;QACnC,CAAC;QAED,IAAI,CAAC;YACH,4EAA4E;YAC5E,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,uBAAuB;aACA,CAAC;QACnC,CAAC;QAED,MAAM,SAAS,GACb,GAAG,GAAG,CAAC,GAAG,cAAc,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpE,IAAI,cAAc,GAAY,IAAI,CAAC;QACnC,IAAI,CAAC;YACH,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;YAC7C,cAAc,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACpC,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,SAAS;YAChB,aAAa,EAAE;gBACb,IAAI;qBACD,IAAI,CAAC,KAAK,EAAE,GAAG,cAAc,EAAE,YAAY,EAAE,UAAU,CAAC;qBACxD,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;gBACtB,IAAI;qBACD,IAAI,CAAC,KAAK,EAAE,GAAG,cAAc,EAAE,YAAY,EAAE,iBAAiB,CAAC;qBAC/D,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;aACvB;YACD,gBAAgB,EAAE,cAAc;SACF,CAAC;IACnC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,mBAAmB,CAAC;AAC5D,MAAM,CAAC,MAAM,wBAAwB,GAAG,iBAAiB,CAAC","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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insertElement.schema.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,aAAa,8FAUhB,CAAC;AA0HX,eAAO,MAAM,oBAAoB,EAAE,GAAkC,CAAC;AAEtE,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"insertElement.schema.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,aAAa,8FAUhB,CAAC;AA0HX,eAAO,MAAM,oBAAoB,EAAE,GAAkC,CAAC;AAEtE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;CAwB/B,CAAC"}
|
|
@@ -125,7 +125,8 @@ export const InsertElementSchema = {
|
|
|
125
125
|
properties: {
|
|
126
126
|
route: {
|
|
127
127
|
type: Type.STRING,
|
|
128
|
-
|
|
128
|
+
pattern: "^/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?$",
|
|
129
|
+
description: "The route to insert the element at. Use URL paths with forward slashes only. Examples: '/', '/about', '/pricing'. Never send Windows-style backslashes (e.g. '\\\\') or filesystem paths like 'app/pricing'. Never send empty string.",
|
|
129
130
|
},
|
|
130
131
|
parent_id: {
|
|
131
132
|
type: Type.STRING,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insertElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"insertElement.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/insertElement.schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const ELEMENT_TYPES = [\r\n \"fragment\",\r\n \"div\",\r\n \"text\",\r\n \"image\",\r\n \"button\",\r\n \"input\",\r\n \"textarea\",\r\n \"link\",\r\n \"icon\",\r\n] as const;\r\n\r\nconst OnClickActionSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n kind: {\r\n type: Type.STRING,\r\n enum: [\"route\", \"back\", \"reload\", \"external\"],\r\n description:\r\n \"What happens when the element is clicked. 'route' navigates within the app, 'external' opens a URL, 'back' goes back, 'reload' refreshes.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description:\r\n \"URL to navigate to (used for kind='route' and kind='external').\",\r\n },\r\n replace: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='route': replace history instead of pushing.\",\r\n },\r\n newTab: {\r\n type: Type.BOOLEAN,\r\n description: \"For kind='external': open link in a new tab.\",\r\n },\r\n },\r\n required: [\"kind\"],\r\n};\r\n\r\nconst BuilderElementPropsSchema = {\r\n type: Type.OBJECT,\r\n properties: {\r\n onClick: OnClickActionSchema,\r\n text: {\r\n type: Type.STRING,\r\n description:\r\n \"Text content used by 'text' (<p>), 'button' (label), and as a fallback for 'link' when it has no children.\",\r\n },\r\n href: {\r\n type: Type.STRING,\r\n description: \"For 'link': the href attribute (defaults to '#').\",\r\n },\r\n placeholder: {\r\n type: Type.STRING,\r\n description: \"For 'input' and 'textarea': placeholder shown when empty.\",\r\n },\r\n alt: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'image': alt text for accessibility AND the query used to fetch a suitable Unsplash image (src is auto-resolved from alt).\",\r\n },\r\n target: {\r\n type: Type.STRING,\r\n description: \"For 'link': target attribute (e.g. '_blank').\",\r\n },\r\n rel: {\r\n type: Type.STRING,\r\n description: \"For 'link': rel attribute (e.g. 'noreferrer').\",\r\n },\r\n value: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input' and 'textarea': default value (maps to defaultValue).\",\r\n },\r\n type: {\r\n type: Type.STRING,\r\n description:\r\n \"For 'input': input type (e.g. 'text', 'email', 'password'). Defaults to 'text'.\",\r\n },\r\n\r\n // icon\r\n name: {\r\n type: Type.STRING,\r\n description: \"For 'icon': Lucide icon name (e.g. 'ArrowRight', 'Menu').\",\r\n },\r\n size: { type: Type.NUMBER, description: \"For 'icon': size in px.\" },\r\n color: { type: Type.STRING, description: \"For 'icon': stroke color.\" },\r\n strokeWidth: {\r\n type: Type.NUMBER,\r\n description: \"For 'icon': stroke width.\",\r\n },\r\n },\r\n};\r\n\r\n// NOTE: Gemini tool `parameters` schemas reject `$ref`, so true recursion isn't available here.\r\n// We unroll nesting to a reasonable max depth; for deeper trees, insert in multiple steps.\r\nconst buildBuilderElementSchema = (depth: number): any => {\r\n return {\r\n type: Type.OBJECT,\r\n properties: {\r\n type: {\r\n type: Type.STRING,\r\n enum: ELEMENT_TYPES,\r\n description:\r\n \"Element type to render. Use 'text' for <p>, 'image' forn <img>, 'link' for <a>, 'icon' for Lucide icon, 'fragment' renders children only\",\r\n },\r\n className: {\r\n type: Type.STRING,\r\n description: \"Tailwind CSS className (Tailwind only)\",\r\n },\r\n visible: {\r\n type: Type.BOOLEAN,\r\n description: \"Visibility flag\",\r\n },\r\n props: BuilderElementPropsSchema,\r\n children: {\r\n type: Type.ARRAY,\r\n description:\r\n \"Child elements. Each child can itself have children (children[].children[]...)\",\r\n items:\r\n depth > 0\r\n ? buildBuilderElementSchema(depth - 1)\r\n : {\r\n type: Type.OBJECT,\r\n description:\r\n \"Max depth reached. Insert deeper children separately using the returned inserted_id as parent_id\",\r\n },\r\n },\r\n },\r\n required: [\"type\"],\r\n };\r\n};\r\n\r\nexport const BuilderElementSchema: any = buildBuilderElementSchema(4);\r\n\r\nexport const InsertElementSchema = {\n name: \"insert_element\",\n description:\n \"Inserts element code. Use element.children to create nested UI. Each child is another BuilderElement and can itself have children.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\n pattern: \"^/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?$\",\n description:\n \"The route to insert the element at. Use URL paths with forward slashes only. Examples: '/', '/about', '/pricing'. Never send Windows-style backslashes (e.g. '\\\\\\\\') or filesystem paths like 'app/pricing'. Never send empty string.\",\n },\n parent_id: {\n type: Type.STRING,\n description: \"The parent id to insert the element at.\",\n },\n element: {\r\n ...BuilderElementSchema,\r\n description: \"The element to insert.\",\r\n },\r\n },\r\n required: [\"route\", \"parent_id\", \"element\"],\r\n },\r\n};\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builderElement.zod.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa,8FAUhB,CAAC;
|
|
1
|
+
{"version":3,"file":"builderElement.zod.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa,8FAUhB,CAAC;AAUX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;2BAmB3B,CAAC;AAEH,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAuB3C,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;iBAU/B,CAAC"}
|
|
@@ -10,10 +10,24 @@ export const ELEMENT_TYPES = [
|
|
|
10
10
|
"link",
|
|
11
11
|
"icon",
|
|
12
12
|
];
|
|
13
|
+
const isInternalRoutePath = (value) => {
|
|
14
|
+
const s = String(value ?? "").trim();
|
|
15
|
+
if (!s)
|
|
16
|
+
return false;
|
|
17
|
+
if (s.includes("\\"))
|
|
18
|
+
return false;
|
|
19
|
+
// Allow "/" or "/a" or "/a/b-c_d"
|
|
20
|
+
return /^\/(?:[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*)?$/.test(s);
|
|
21
|
+
};
|
|
13
22
|
export const OnClickActionZod = z.discriminatedUnion("kind", [
|
|
14
23
|
z.object({
|
|
15
24
|
kind: z.literal("route"),
|
|
16
|
-
href: z
|
|
25
|
+
href: z
|
|
26
|
+
.string()
|
|
27
|
+
.min(1)
|
|
28
|
+
.refine(isInternalRoutePath, {
|
|
29
|
+
message: "href must be an internal route path like '/' or '/pricing' (forward slashes only; no backslashes)",
|
|
30
|
+
}),
|
|
17
31
|
replace: z.boolean().optional(),
|
|
18
32
|
}),
|
|
19
33
|
z.object({ kind: z.literal("back") }),
|
|
@@ -49,7 +63,12 @@ export const BuilderElementZod = z.object({
|
|
|
49
63
|
children: z.array(z.lazy(() => BuilderElementZod)).optional(),
|
|
50
64
|
});
|
|
51
65
|
export const InsertElementArgsZod = z.object({
|
|
52
|
-
route: z
|
|
66
|
+
route: z
|
|
67
|
+
.string()
|
|
68
|
+
.min(1)
|
|
69
|
+
.refine(isInternalRoutePath, {
|
|
70
|
+
message: "route must be like '/' or '/about' (forward slashes only; no backslashes)",
|
|
71
|
+
}),
|
|
53
72
|
parent_id: z.string().min(1),
|
|
54
73
|
element: BuilderElementZod,
|
|
55
74
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builderElement.zod.js","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,UAAU;IACV,KAAK;IACL,MAAM;IACN,OAAO;IACP,QAAQ;IACR,OAAO;IACP,UAAU;IACV,MAAM;IACN,MAAM;CACE,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC3D,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QACxB,IAAI,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"builderElement.zod.js","sourceRoot":"","sources":["../../../../src/ai/tools/validators/builderElement.zod.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nexport const ELEMENT_TYPES = [\n \"fragment\",\n \"div\",\n \"text\",\n \"image\",\n \"button\",\n \"input\",\n \"textarea\",\n \"link\",\n \"icon\",\n] as const;\n\nconst isInternalRoutePath = (value: string) => {\n const s = String(value ?? \"\").trim();\n if (!s) return false;\n if (s.includes(\"\\\\\")) return false;\n // Allow \"/\" or \"/a\" or \"/a/b-c_d\"\n return /^\\/(?:[A-Za-z0-9_-]+(?:\\/[A-Za-z0-9_-]+)*)?$/.test(s);\n};\n\nexport const OnClickActionZod = z.discriminatedUnion(\"kind\", [\n z.object({\n kind: z.literal(\"route\"),\n href: z\n .string()\n .min(1)\n .refine(isInternalRoutePath, {\n message:\n \"href must be an internal route path like '/' or '/pricing' (forward slashes only; no backslashes)\",\n }),\n replace: z.boolean().optional(),\n }),\n z.object({ kind: z.literal(\"back\") }),\n z.object({ kind: z.literal(\"reload\") }),\n z.object({\n kind: z.literal(\"external\"),\n href: z.string().min(1),\n newTab: z.boolean().optional(),\n }),\n]);\n\nexport const BuilderElementZod: z.ZodType<any> = z.object({\n type: z.enum(ELEMENT_TYPES),\n className: z.string().optional(),\n visible: z.boolean().optional(),\n props: z\n .object({\n onClick: OnClickActionZod.optional(),\n text: z.string().optional(),\n href: z.string().optional(),\n placeholder: z.string().optional(),\n alt: z.string().optional(),\n target: z.string().optional(),\n rel: z.string().optional(),\n value: z.string().optional(),\n type: z.string().optional(),\n name: z.string().optional(),\n size: z.number().optional(),\n color: z.string().optional(),\n strokeWidth: z.number().optional(),\n })\n .passthrough()\n .optional(),\n children: z.array(z.lazy(() => BuilderElementZod)).optional(),\n});\n\nexport const InsertElementArgsZod = z.object({\n route: z\n .string()\n .min(1)\n .refine(isInternalRoutePath, {\n message:\n \"route must be like '/' or '/about' (forward slashes only; no backslashes)\",\n }),\n parent_id: z.string().min(1),\n element: BuilderElementZod,\n});\n"]}
|