@vedangiitb/qwintly-core 1.3.16 → 1.3.17

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 (45) hide show
  1. package/dist/ai/prompts/codegen.prompt.d.ts.map +1 -1
  2. package/dist/ai/prompts/codegen.prompt.js +14 -12
  3. package/dist/ai/prompts/codegen.prompt.js.map +1 -1
  4. package/dist/ai/prompts/examples/codegen.examples.js +10 -10
  5. package/dist/ai/prompts/examples/codegen.examples.js.map +1 -1
  6. package/dist/ai/prompts/planner.prompt.d.ts.map +1 -1
  7. package/dist/ai/prompts/planner.prompt.js +9 -5
  8. package/dist/ai/prompts/planner.prompt.js.map +1 -1
  9. package/dist/ai/prompts/validator.prompt.d.ts.map +1 -1
  10. package/dist/ai/prompts/validator.prompt.js +9 -5
  11. package/dist/ai/prompts/validator.prompt.js.map +1 -1
  12. package/dist/ai/tools/helpers/pageConfigJson.helpers.d.ts.map +1 -1
  13. package/dist/ai/tools/helpers/pageConfigJson.helpers.js +15 -3
  14. package/dist/ai/tools/helpers/pageConfigJson.helpers.js.map +1 -1
  15. package/dist/ai/tools/implementations/createNewRoute.impl.js +1 -1
  16. package/dist/ai/tools/implementations/createNewRoute.impl.js.map +1 -1
  17. package/dist/ai/tools/implementations/factories.d.ts +18 -0
  18. package/dist/ai/tools/implementations/factories.d.ts.map +1 -1
  19. package/dist/ai/tools/implementations/factories.js +4 -0
  20. package/dist/ai/tools/implementations/factories.js.map +1 -1
  21. package/dist/ai/tools/implementations/insertElement.impl.js +1 -1
  22. package/dist/ai/tools/implementations/insertElement.impl.js.map +1 -1
  23. package/dist/ai/tools/implementations/updateGlobalStyles.impl.d.ts +22 -0
  24. package/dist/ai/tools/implementations/updateGlobalStyles.impl.d.ts.map +1 -0
  25. package/dist/ai/tools/implementations/updateGlobalStyles.impl.js +90 -0
  26. package/dist/ai/tools/implementations/updateGlobalStyles.impl.js.map +1 -0
  27. package/dist/ai/tools/schemas/insertElement.schema.js.map +1 -1
  28. package/dist/ai/tools/schemas/updateClassName.schema.js +1 -1
  29. package/dist/ai/tools/schemas/updateClassName.schema.js.map +1 -1
  30. package/dist/ai/tools/schemas/updateGlobalStyles.schema.d.ts +16 -0
  31. package/dist/ai/tools/schemas/updateGlobalStyles.schema.d.ts.map +1 -0
  32. package/dist/ai/tools/schemas/updateGlobalStyles.schema.js +16 -0
  33. package/dist/ai/tools/schemas/updateGlobalStyles.schema.js.map +1 -0
  34. package/dist/ai/tools/toolsets/codegenTools.d.ts.map +1 -1
  35. package/dist/ai/tools/toolsets/codegenTools.js +2 -0
  36. package/dist/ai/tools/toolsets/codegenTools.js.map +1 -1
  37. package/dist/tests/updateGlobalStyles.impl.test.d.ts +2 -0
  38. package/dist/tests/updateGlobalStyles.impl.test.d.ts.map +1 -0
  39. package/dist/tests/updateGlobalStyles.impl.test.js +133 -0
  40. package/dist/tests/updateGlobalStyles.impl.test.js.map +1 -0
  41. package/dist/types/styleConfig.d.ts +45 -0
  42. package/dist/types/styleConfig.d.ts.map +1 -0
  43. package/dist/types/styleConfig.js +113 -0
  44. package/dist/types/styleConfig.js.map +1 -0
  45. package/package.json +1 -1
@@ -0,0 +1,90 @@
1
+ import path from "node:path";
2
+ import { toWorkspacePath } from "../helpers/fileSystem.helpers.js";
3
+ import { writeFileAtomic } from "../helpers/pageConfigJson.helpers.js";
4
+ import { assertStyleConfig, defaultStyleConfigJson, STYLE_TOKEN_KEYS, } from "../../../types/styleConfig.js";
5
+ const STYLE_CONFIG_REL_PATH = path.posix.join("app", "styleConfig.json");
6
+ const parseStyleConfigOrDefault = (raw) => {
7
+ try {
8
+ const parsed = JSON.parse(String(raw ?? ""));
9
+ return assertStyleConfig(parsed);
10
+ }
11
+ catch {
12
+ return assertStyleConfig(defaultStyleConfigJson);
13
+ }
14
+ };
15
+ const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
16
+ export const createUpdateGlobalStylesImpl = (deps) => {
17
+ const { workspaceRoot, fs } = deps;
18
+ return async (args) => {
19
+ const tokensPatch = args?.tokens;
20
+ if (!isPlainObject(tokensPatch)) {
21
+ return { success: false, error: "invalid tokens" };
22
+ }
23
+ const allowedKeys = new Set(STYLE_TOKEN_KEYS);
24
+ const patchKeys = Object.keys(tokensPatch);
25
+ const unknownKeys = patchKeys.filter((k) => !allowedKeys.has(k));
26
+ if (unknownKeys.length > 0) {
27
+ return {
28
+ success: false,
29
+ error: `unknown token keys: ${unknownKeys.sort().join(", ")}`,
30
+ };
31
+ }
32
+ const configPath = toWorkspacePath(workspaceRoot, STYLE_CONFIG_REL_PATH);
33
+ let beforeConfig;
34
+ let existed = true;
35
+ try {
36
+ const raw = await fs.readFile(configPath);
37
+ beforeConfig = parseStyleConfigOrDefault(raw);
38
+ }
39
+ catch (err) {
40
+ const code = err?.code;
41
+ if (code !== "ENOENT") {
42
+ return {
43
+ success: false,
44
+ error: err instanceof Error ? err.message : String(err),
45
+ };
46
+ }
47
+ existed = false;
48
+ beforeConfig = assertStyleConfig(defaultStyleConfigJson);
49
+ }
50
+ const merged = {
51
+ version: beforeConfig.version,
52
+ tokens: {
53
+ ...beforeConfig.tokens,
54
+ ...tokensPatch,
55
+ },
56
+ };
57
+ let validated;
58
+ try {
59
+ validated = assertStyleConfig(merged);
60
+ }
61
+ catch (err) {
62
+ return {
63
+ success: false,
64
+ error: err instanceof Error ? err.message : String(err),
65
+ };
66
+ }
67
+ const nextVersion = Number.isFinite(validated.version)
68
+ ? validated.version + 1
69
+ : 1;
70
+ const afterConfig = { ...validated, version: nextVersion };
71
+ const after = JSON.stringify(afterConfig, null, 2) + "\n";
72
+ try {
73
+ await writeFileAtomic(configPath, after);
74
+ return {
75
+ success: true,
76
+ changed: true,
77
+ file: STYLE_CONFIG_REL_PATH,
78
+ version: nextVersion,
79
+ created: !existed,
80
+ };
81
+ }
82
+ catch (err) {
83
+ return {
84
+ success: false,
85
+ error: err instanceof Error ? err.message : String(err),
86
+ };
87
+ }
88
+ };
89
+ };
90
+ //# sourceMappingURL=updateGlobalStyles.impl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateGlobalStyles.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateGlobalStyles.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport { writeFileAtomic } from \"../helpers/pageConfigJson.helpers.js\";\nimport {\n assertStyleConfig,\n defaultStyleConfigJson,\n STYLE_TOKEN_KEYS,\n type StyleConfig,\n type StyleTokenKey,\n} from \"../../../types/styleConfig.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\ntype UpdateGlobalStylesArgs = {\n tokens: Partial<Record<StyleTokenKey, string>>;\n};\n\nconst STYLE_CONFIG_REL_PATH = path.posix.join(\"app\", \"styleConfig.json\");\n\nconst parseStyleConfigOrDefault = (raw: string): StyleConfig => {\n try {\n const parsed = JSON.parse(String(raw ?? \"\"));\n return assertStyleConfig(parsed);\n } catch {\n return assertStyleConfig(defaultStyleConfigJson);\n }\n};\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nexport const createUpdateGlobalStylesImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (args: UpdateGlobalStylesArgs) => {\n const tokensPatch = (args as any)?.tokens;\n if (!isPlainObject(tokensPatch)) {\n return { success: false, error: \"invalid tokens\" };\n }\n\n const allowedKeys = new Set<string>(STYLE_TOKEN_KEYS as unknown as string[]);\n const patchKeys = Object.keys(tokensPatch);\n const unknownKeys = patchKeys.filter((k) => !allowedKeys.has(k));\n if (unknownKeys.length > 0) {\n return {\n success: false,\n error: `unknown token keys: ${unknownKeys.sort().join(\", \")}`,\n };\n }\n\n const configPath = toWorkspacePath(workspaceRoot, STYLE_CONFIG_REL_PATH);\n\n let beforeConfig: StyleConfig;\n let existed = true;\n try {\n const raw = await fs.readFile(configPath);\n beforeConfig = parseStyleConfigOrDefault(raw);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code !== \"ENOENT\") {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n existed = false;\n beforeConfig = assertStyleConfig(defaultStyleConfigJson);\n }\n\n const merged: StyleConfig = {\n version: beforeConfig.version,\n tokens: {\n ...beforeConfig.tokens,\n ...(tokensPatch as Partial<Record<StyleTokenKey, string>>),\n } as any,\n };\n\n let validated: StyleConfig;\n try {\n validated = assertStyleConfig(merged);\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n\n const nextVersion = Number.isFinite(validated.version)\n ? validated.version + 1\n : 1;\n const afterConfig: StyleConfig = { ...validated, version: nextVersion };\n\n const after = JSON.stringify(afterConfig, null, 2) + \"\\n\";\n try {\n await writeFileAtomic(configPath, after);\n return {\n success: true,\n changed: true,\n file: STYLE_CONFIG_REL_PATH,\n version: nextVersion,\n created: !existed,\n };\n } catch (err) {\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n };\n};\n\n"]}
@@ -1 +1 @@
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
+ {"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 = {\r\n name: \"insert_element\",\r\n description:\r\n \"Inserts element code. Use element.children to create nested UI. Each child is another BuilderElement and can itself have children.\",\r\n parameters: {\r\n type: Type.OBJECT,\r\n properties: {\r\n route: {\r\n type: Type.STRING,\r\n pattern: \"^/(?:[A-Za-z0-9_-]+(?:/[A-Za-z0-9_-]+)*)?$\",\r\n description:\r\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.\",\r\n },\r\n parent_id: {\r\n type: Type.STRING,\r\n description: \"The parent id to insert the element at.\",\r\n },\r\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,7 +1,7 @@
1
1
  import { Type } from "@google/genai";
2
2
  export const UpdateClassNameSchema = {
3
3
  name: "update_classname",
4
- description: "Updates className (only tailwind classes allowed). Give complete className.",
4
+ description: "Updates className (only tailwind classes allowed). Give complete className. Prefer semantic token classes (bg-background, text-foreground, border-border, ring-ring, etc.); use update_global_styles to change global tokens.",
5
5
  parameters: {
6
6
  type: Type.OBJECT,
7
7
  properties: {
@@ -1 +1 @@
1
- {"version":3,"file":"updateClassName.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateClassName.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,6EAA6E;IAC/E,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,mEAAmE;aACtE;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;YACD,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC;KAC/C;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const UpdateClassNameSchema = {\r\n name: \"update_classname\",\r\n description:\r\n \"Updates className (only tailwind classes allowed). Give complete className.\",\r\n parameters: {\r\n type: Type.OBJECT,\r\n properties: {\r\n route: {\r\n type: Type.STRING,\r\n description:\r\n \"The route to update the element at. Example. '/' or '/about' etc.\",\r\n },\r\n element_id: {\r\n type: Type.STRING,\r\n description: \"The id of the element to be updated.\",\r\n },\r\n className: { type: Type.STRING },\r\n },\r\n required: [\"route\", \"element_id\", \"className\"],\r\n },\r\n};\r\n"]}
1
+ {"version":3,"file":"updateClassName.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateClassName.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,+NAA+N;IACjO,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,mEAAmE;aACtE;YACD,UAAU,EAAE;gBACV,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,sCAAsC;aACpD;YACD,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE;SACjC;QACD,QAAQ,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC;KAC/C;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\r\n\r\nexport const UpdateClassNameSchema = {\n name: \"update_classname\",\n description:\n \"Updates className (only tailwind classes allowed). Give complete className. Prefer semantic token classes (bg-background, text-foreground, border-border, ring-ring, etc.); use update_global_styles to change global tokens.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n route: {\n type: Type.STRING,\r\n description:\r\n \"The route to update the element at. Example. '/' or '/about' etc.\",\r\n },\r\n element_id: {\r\n type: Type.STRING,\r\n description: \"The id of the element to be updated.\",\r\n },\r\n className: { type: Type.STRING },\r\n },\r\n required: [\"route\", \"element_id\", \"className\"],\r\n },\r\n};\r\n"]}
@@ -0,0 +1,16 @@
1
+ import { Type } from "@google/genai";
2
+ export declare const UpdateGlobalStylesSchema: {
3
+ name: string;
4
+ description: string;
5
+ parameters: {
6
+ type: Type;
7
+ properties: {
8
+ tokens: {
9
+ type: Type;
10
+ description: string;
11
+ };
12
+ };
13
+ required: string[];
14
+ };
15
+ };
16
+ //# sourceMappingURL=updateGlobalStyles.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateGlobalStyles.schema.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateGlobalStyles.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;CAepC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { Type } from "@google/genai";
2
+ export const UpdateGlobalStylesSchema = {
3
+ name: "update_global_styles",
4
+ description: "Updates global design tokens in app/styleConfig.json. Use this to change theme colors/radius used by semantic Tailwind classes like bg-background and text-foreground.",
5
+ parameters: {
6
+ type: Type.OBJECT,
7
+ properties: {
8
+ tokens: {
9
+ type: Type.OBJECT,
10
+ description: "Partial tokens patch. Keys must be one of the StyleTokenKey values (see types/styleConfig.ts). Values must be non-empty safe CSS strings. Unknown keys are rejected.",
11
+ },
12
+ },
13
+ required: ["tokens"],
14
+ },
15
+ };
16
+ //# sourceMappingURL=updateGlobalStyles.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateGlobalStyles.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/updateGlobalStyles.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACT,wKAAwK;IAC1K,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EACT,sKAAsK;aACzK;SACF;QACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;KACrB;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\n\nexport const UpdateGlobalStylesSchema = {\n name: \"update_global_styles\",\n description:\n \"Updates global design tokens in app/styleConfig.json. Use this to change theme colors/radius used by semantic Tailwind classes like bg-background and text-foreground.\",\n parameters: {\n type: Type.OBJECT,\n properties: {\n tokens: {\n type: Type.OBJECT,\n description:\n \"Partial tokens patch. Keys must be one of the StyleTokenKey values (see types/styleConfig.ts). Values must be non-empty safe CSS strings. Unknown keys are rejected.\",\n },\n },\n required: [\"tokens\"],\n },\n};\n\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"codegenTools.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAUrC,eAAO,MAAM,YAAY,QAAO,IAAI,EAenC,CAAC"}
1
+ {"version":3,"file":"codegenTools.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAWrC,eAAO,MAAM,YAAY,QAAO,IAAI,EAgBnC,CAAC"}
@@ -6,11 +6,13 @@ import { DeleteElementSchema } from "../schemas/deleteElement.schema.js";
6
6
  import { InsertElementSchema } from "../schemas/insertElement.schema.js";
7
7
  import { UpdateClassNameSchema } from "../schemas/updateClassName.schema.js";
8
8
  import { UpdatePropsSchema } from "../schemas/updateProps.schema.js";
9
+ import { UpdateGlobalStylesSchema } from "../schemas/updateGlobalStyles.schema.js";
9
10
  export const codegenTools = () => {
10
11
  return [
11
12
  {
12
13
  functionDeclarations: [
13
14
  ReadFileSchema,
15
+ UpdateGlobalStylesSchema,
14
16
  CreateNewRouteSchema,
15
17
  InsertElementSchema,
16
18
  DeleteElementSchema,
@@ -1 +1 @@
1
- {"version":3,"file":"codegenTools.js","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAErE,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,OAAO;QACL;YACE,oBAAoB,EAAE;gBACpB,cAAc;gBACd,oBAAoB;gBACpB,mBAAmB;gBACnB,mBAAmB;gBACnB,qBAAqB;gBACrB,iBAAiB;gBACjB,aAAa;gBACb,uBAAuB;aACxB;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Tool } from \"@google/genai\";\nimport { ReadFileSchema } from \"../schemas/readFile.schema.js\";\nimport { SubmitCodegenDoneSchema } from \"../schemas/submitCodegenDone.schema.js\";\nimport { ListDirSchema } from \"../schemas/listDir.schema.js\";\nimport { CreateNewRouteSchema } from \"../schemas/createNewRoute.schema.js\";\nimport { DeleteElementSchema } from \"../schemas/deleteElement.schema.js\";\nimport { InsertElementSchema } from \"../schemas/insertElement.schema.js\";\nimport { UpdateClassNameSchema } from \"../schemas/updateClassName.schema.js\";\nimport { UpdatePropsSchema } from \"../schemas/updateProps.schema.js\";\n\nexport const codegenTools = (): Tool[] => {\n return [\n {\n functionDeclarations: [\n ReadFileSchema,\n CreateNewRouteSchema,\n InsertElementSchema,\n DeleteElementSchema,\n UpdateClassNameSchema,\n UpdatePropsSchema,\n ListDirSchema,\n SubmitCodegenDoneSchema,\n ],\n },\n ];\n};\n"]}
1
+ {"version":3,"file":"codegenTools.js","sourceRoot":"","sources":["../../../../src/ai/tools/toolsets/codegenTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AAEnF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,OAAO;QACL;YACE,oBAAoB,EAAE;gBACpB,cAAc;gBACd,wBAAwB;gBACxB,oBAAoB;gBACpB,mBAAmB;gBACnB,mBAAmB;gBACnB,qBAAqB;gBACrB,iBAAiB;gBACjB,aAAa;gBACb,uBAAuB;aACxB;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Tool } from \"@google/genai\";\nimport { ReadFileSchema } from \"../schemas/readFile.schema.js\";\nimport { SubmitCodegenDoneSchema } from \"../schemas/submitCodegenDone.schema.js\";\nimport { ListDirSchema } from \"../schemas/listDir.schema.js\";\nimport { CreateNewRouteSchema } from \"../schemas/createNewRoute.schema.js\";\nimport { DeleteElementSchema } from \"../schemas/deleteElement.schema.js\";\nimport { InsertElementSchema } from \"../schemas/insertElement.schema.js\";\nimport { UpdateClassNameSchema } from \"../schemas/updateClassName.schema.js\";\nimport { UpdatePropsSchema } from \"../schemas/updateProps.schema.js\";\nimport { UpdateGlobalStylesSchema } from \"../schemas/updateGlobalStyles.schema.js\";\n\nexport const codegenTools = (): Tool[] => {\n return [\n {\n functionDeclarations: [\n ReadFileSchema,\n UpdateGlobalStylesSchema,\n CreateNewRouteSchema,\n InsertElementSchema,\n DeleteElementSchema,\n UpdateClassNameSchema,\n UpdatePropsSchema,\n ListDirSchema,\n SubmitCodegenDoneSchema,\n ],\n },\n ];\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=updateGlobalStyles.impl.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateGlobalStyles.impl.test.d.ts","sourceRoot":"","sources":["../../src/tests/updateGlobalStyles.impl.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,133 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import path from "node:path";
4
+ import os from "node:os";
5
+ import fs from "node:fs/promises";
6
+ import { createUpdateGlobalStylesImpl, } from "../ai/tools/implementations/updateGlobalStyles.impl.js";
7
+ const makeRealFs = (overrides) => {
8
+ return {
9
+ readFile: async (absolutePath) => fs.readFile(absolutePath, "utf-8"),
10
+ writeFile: async (absolutePath, content) => fs.writeFile(absolutePath, content ?? "", "utf-8"),
11
+ mkdirp: async (absoluteDir) => {
12
+ await fs.mkdir(absoluteDir, { recursive: true });
13
+ },
14
+ rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),
15
+ stat: async (absolutePath) => fs.stat(absolutePath),
16
+ safeReadDir: async (absoluteDir) => fs.readdir(absoluteDir, { withFileTypes: true }),
17
+ ...(overrides ?? {}),
18
+ };
19
+ };
20
+ const readStyleConfig = async (workspaceRoot) => {
21
+ const raw = await fs.readFile(path.join(workspaceRoot, "app", "styleConfig.json"), "utf-8");
22
+ return JSON.parse(raw);
23
+ };
24
+ test("update_global_styles: merges tokens and bumps version", async () => {
25
+ const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qwintly-core-"));
26
+ try {
27
+ await fs.mkdir(path.join(workspaceRoot, "app"), { recursive: true });
28
+ await fs.writeFile(path.join(workspaceRoot, "app", "styleConfig.json"), JSON.stringify({
29
+ version: 10,
30
+ tokens: {
31
+ radius: "1rem",
32
+ background: "oklch(0.9 0.02 80.2)",
33
+ foreground: "oklch(0.2 0.03 255.4)",
34
+ card: "oklch(0.995 0.004 80.2)",
35
+ cardForeground: "oklch(0.2 0.03 255.4)",
36
+ popover: "oklch(0.995 0.004 80.2)",
37
+ popoverForeground: "oklch(0.2 0.03 255.4)",
38
+ primary: "oklch(0.62 0.16 199.4)",
39
+ primaryForeground: "oklch(0.985 0.008 80.2)",
40
+ secondary: "oklch(0.94 0.02 83.1)",
41
+ secondaryForeground: "oklch(0.22 0.04 258.2)",
42
+ muted: "oklch(0.95 0.01 85.6)",
43
+ mutedForeground: "oklch(0.46 0.04 257.6)",
44
+ accent: "oklch(0.9 0.06 78.4)",
45
+ accentForeground: "oklch(0.22 0.04 258.2)",
46
+ destructive: "oklch(0.57 0.21 25.6)",
47
+ border: "oklch(0.89 0.02 82.5)",
48
+ input: "oklch(0.92 0.02 82.5)",
49
+ ring: "oklch(0.62 0.16 199.4)",
50
+ chart1: "oklch(0.62 0.16 199.4)",
51
+ chart2: "oklch(0.66 0.14 143.6)",
52
+ chart3: "oklch(0.52 0.12 297.6)",
53
+ chart4: "oklch(0.74 0.16 79.3)",
54
+ chart5: "oklch(0.62 0.18 24.8)",
55
+ sidebar: "oklch(0.975 0.01 82.5)",
56
+ sidebarForeground: "oklch(0.2 0.03 255.4)",
57
+ sidebarPrimary: "oklch(0.62 0.16 199.4)",
58
+ sidebarPrimaryForeground: "oklch(0.985 0.008 80.2)",
59
+ sidebarAccent: "oklch(0.94 0.02 83.1)",
60
+ sidebarAccentForeground: "oklch(0.22 0.04 258.2)",
61
+ sidebarBorder: "oklch(0.89 0.02 82.5)",
62
+ sidebarRing: "oklch(0.62 0.16 199.4)",
63
+ },
64
+ }, null, 2) + "\n", "utf-8");
65
+ const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() });
66
+ const res = await impl({ tokens: { background: "oklch(0.88 0.02 80.2)" } });
67
+ assert.equal(res?.success, true);
68
+ assert.equal(res?.version, 11);
69
+ const stored = await readStyleConfig(workspaceRoot);
70
+ assert.equal(stored.version, 11);
71
+ assert.equal(stored.tokens.background, "oklch(0.88 0.02 80.2)");
72
+ }
73
+ finally {
74
+ await fs.rm(workspaceRoot, { recursive: true, force: true });
75
+ }
76
+ });
77
+ test("update_global_styles: missing file => creates defaults and applies patch", async () => {
78
+ const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qwintly-core-"));
79
+ try {
80
+ await fs.mkdir(path.join(workspaceRoot, "app"), { recursive: true });
81
+ const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() });
82
+ const res = await impl({ tokens: { radius: "0.5rem" } });
83
+ assert.equal(res?.success, true);
84
+ assert.equal(res?.created, true);
85
+ const stored = await readStyleConfig(workspaceRoot);
86
+ assert.equal(stored.tokens.radius, "0.5rem");
87
+ assert.equal(stored.version, 2);
88
+ }
89
+ finally {
90
+ await fs.rm(workspaceRoot, { recursive: true, force: true });
91
+ }
92
+ });
93
+ test("update_global_styles: invalid JSON => recreates defaults then applies patch", async () => {
94
+ const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qwintly-core-"));
95
+ try {
96
+ await fs.mkdir(path.join(workspaceRoot, "app"), { recursive: true });
97
+ await fs.writeFile(path.join(workspaceRoot, "app", "styleConfig.json"), "{", "utf-8");
98
+ const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() });
99
+ const res = await impl({ tokens: { border: "oklch(0.5 0.02 82.5)" } });
100
+ assert.equal(res?.success, true);
101
+ const stored = await readStyleConfig(workspaceRoot);
102
+ assert.equal(stored.tokens.border, "oklch(0.5 0.02 82.5)");
103
+ assert.equal(stored.version, 2);
104
+ }
105
+ finally {
106
+ await fs.rm(workspaceRoot, { recursive: true, force: true });
107
+ }
108
+ });
109
+ test("update_global_styles: unknown token key is rejected", async () => {
110
+ const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qwintly-core-"));
111
+ try {
112
+ await fs.mkdir(path.join(workspaceRoot, "app"), { recursive: true });
113
+ const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() });
114
+ const res = await impl({ tokens: { notAKey: "oklch(0.1 0 0)" } });
115
+ assert.equal(res?.success, false);
116
+ }
117
+ finally {
118
+ await fs.rm(workspaceRoot, { recursive: true, force: true });
119
+ }
120
+ });
121
+ test("update_global_styles: unsafe/empty token value is rejected", async () => {
122
+ const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qwintly-core-"));
123
+ try {
124
+ await fs.mkdir(path.join(workspaceRoot, "app"), { recursive: true });
125
+ const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() });
126
+ const res = await impl({ tokens: { background: "" } });
127
+ assert.equal(res?.success, false);
128
+ }
129
+ finally {
130
+ await fs.rm(workspaceRoot, { recursive: true, force: true });
131
+ }
132
+ });
133
+ //# sourceMappingURL=updateGlobalStyles.impl.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateGlobalStyles.impl.test.js","sourceRoot":"","sources":["../../src/tests/updateGlobalStyles.impl.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport test from \"node:test\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport fs from \"node:fs/promises\";\nimport {\n createUpdateGlobalStylesImpl,\n} from \"../ai/tools/implementations/updateGlobalStyles.impl.js\";\n\ntype CoreFs = Parameters<typeof createUpdateGlobalStylesImpl>[0][\"fs\"];\n\nconst makeRealFs = (overrides?: Partial<CoreFs>): CoreFs => {\n return {\n readFile: async (absolutePath) => fs.readFile(absolutePath, \"utf-8\"),\n writeFile: async (absolutePath, content) =>\n fs.writeFile(absolutePath, content ?? \"\", \"utf-8\"),\n mkdirp: async (absoluteDir) => {\n await fs.mkdir(absoluteDir, { recursive: true });\n },\n rmFile: async (absolutePath) => fs.rm(absolutePath, { force: true }),\n stat: async (absolutePath) => fs.stat(absolutePath),\n safeReadDir: async (absoluteDir) =>\n fs.readdir(absoluteDir, { withFileTypes: true }),\n ...(overrides ?? {}),\n };\n};\n\nconst readStyleConfig = async (workspaceRoot: string) => {\n const raw = await fs.readFile(\n path.join(workspaceRoot, \"app\", \"styleConfig.json\"),\n \"utf-8\",\n );\n return JSON.parse(raw) as any;\n};\n\ntest(\"update_global_styles: merges tokens and bumps version\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n await fs.writeFile(\n path.join(workspaceRoot, \"app\", \"styleConfig.json\"),\n JSON.stringify(\n {\n version: 10,\n tokens: {\n radius: \"1rem\",\n background: \"oklch(0.9 0.02 80.2)\",\n foreground: \"oklch(0.2 0.03 255.4)\",\n card: \"oklch(0.995 0.004 80.2)\",\n cardForeground: \"oklch(0.2 0.03 255.4)\",\n popover: \"oklch(0.995 0.004 80.2)\",\n popoverForeground: \"oklch(0.2 0.03 255.4)\",\n primary: \"oklch(0.62 0.16 199.4)\",\n primaryForeground: \"oklch(0.985 0.008 80.2)\",\n secondary: \"oklch(0.94 0.02 83.1)\",\n secondaryForeground: \"oklch(0.22 0.04 258.2)\",\n muted: \"oklch(0.95 0.01 85.6)\",\n mutedForeground: \"oklch(0.46 0.04 257.6)\",\n accent: \"oklch(0.9 0.06 78.4)\",\n accentForeground: \"oklch(0.22 0.04 258.2)\",\n destructive: \"oklch(0.57 0.21 25.6)\",\n border: \"oklch(0.89 0.02 82.5)\",\n input: \"oklch(0.92 0.02 82.5)\",\n ring: \"oklch(0.62 0.16 199.4)\",\n chart1: \"oklch(0.62 0.16 199.4)\",\n chart2: \"oklch(0.66 0.14 143.6)\",\n chart3: \"oklch(0.52 0.12 297.6)\",\n chart4: \"oklch(0.74 0.16 79.3)\",\n chart5: \"oklch(0.62 0.18 24.8)\",\n sidebar: \"oklch(0.975 0.01 82.5)\",\n sidebarForeground: \"oklch(0.2 0.03 255.4)\",\n sidebarPrimary: \"oklch(0.62 0.16 199.4)\",\n sidebarPrimaryForeground: \"oklch(0.985 0.008 80.2)\",\n sidebarAccent: \"oklch(0.94 0.02 83.1)\",\n sidebarAccentForeground: \"oklch(0.22 0.04 258.2)\",\n sidebarBorder: \"oklch(0.89 0.02 82.5)\",\n sidebarRing: \"oklch(0.62 0.16 199.4)\",\n },\n },\n null,\n 2,\n ) + \"\\n\",\n \"utf-8\",\n );\n\n const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() } as any);\n const res = await impl({ tokens: { background: \"oklch(0.88 0.02 80.2)\" } });\n assert.equal((res as any)?.success, true);\n assert.equal((res as any)?.version, 11);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.version, 11);\n assert.equal(stored.tokens.background, \"oklch(0.88 0.02 80.2)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: missing file => creates defaults and applies patch\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() } as any);\n const res = await impl({ tokens: { radius: \"0.5rem\" } });\n assert.equal((res as any)?.success, true);\n assert.equal((res as any)?.created, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.radius, \"0.5rem\");\n assert.equal(stored.version, 2);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: invalid JSON => recreates defaults then applies patch\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n await fs.writeFile(\n path.join(workspaceRoot, \"app\", \"styleConfig.json\"),\n \"{\",\n \"utf-8\",\n );\n const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() } as any);\n const res = await impl({ tokens: { border: \"oklch(0.5 0.02 82.5)\" } });\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.border, \"oklch(0.5 0.02 82.5)\");\n assert.equal(stored.version, 2);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: unknown token key is rejected\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() } as any);\n const res = await impl({ tokens: { notAKey: \"oklch(0.1 0 0)\" } as any });\n assert.equal((res as any)?.success, false);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: unsafe/empty token value is rejected\", async () => {\n const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"qwintly-core-\"));\n try {\n await fs.mkdir(path.join(workspaceRoot, \"app\"), { recursive: true });\n const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() } as any);\n const res = await impl({ tokens: { background: \"\" } });\n assert.equal((res as any)?.success, false);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\n"]}
@@ -0,0 +1,45 @@
1
+ export declare const STYLE_TOKEN_KEYS: readonly ["radius", "background", "foreground", "card", "cardForeground", "popover", "popoverForeground", "primary", "primaryForeground", "secondary", "secondaryForeground", "muted", "mutedForeground", "accent", "accentForeground", "destructive", "border", "input", "ring", "chart1", "chart2", "chart3", "chart4", "chart5", "sidebar", "sidebarForeground", "sidebarPrimary", "sidebarPrimaryForeground", "sidebarAccent", "sidebarAccentForeground", "sidebarBorder", "sidebarRing"];
2
+ export type StyleTokenKey = (typeof STYLE_TOKEN_KEYS)[number];
3
+ export type StyleConfig = {
4
+ version: number;
5
+ tokens: Record<StyleTokenKey, string>;
6
+ };
7
+ export declare function assertStyleConfig(config: unknown): StyleConfig;
8
+ export declare const defaultStyleConfigJson: {
9
+ version: number;
10
+ tokens: {
11
+ radius: string;
12
+ background: string;
13
+ foreground: string;
14
+ card: string;
15
+ cardForeground: string;
16
+ popover: string;
17
+ popoverForeground: string;
18
+ primary: string;
19
+ primaryForeground: string;
20
+ secondary: string;
21
+ secondaryForeground: string;
22
+ muted: string;
23
+ mutedForeground: string;
24
+ accent: string;
25
+ accentForeground: string;
26
+ destructive: string;
27
+ border: string;
28
+ input: string;
29
+ ring: string;
30
+ chart1: string;
31
+ chart2: string;
32
+ chart3: string;
33
+ chart4: string;
34
+ chart5: string;
35
+ sidebar: string;
36
+ sidebarForeground: string;
37
+ sidebarPrimary: string;
38
+ sidebarPrimaryForeground: string;
39
+ sidebarAccent: string;
40
+ sidebarAccentForeground: string;
41
+ sidebarBorder: string;
42
+ sidebarRing: string;
43
+ };
44
+ };
45
+ //# sourceMappingURL=styleConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styleConfig.d.ts","sourceRoot":"","sources":["../../src/types/styleConfig.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,+dAiCnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;CACvC,CAAC;AAoBF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,WAAW,CAkC9D;AAED,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoClC,CAAC"}
@@ -0,0 +1,113 @@
1
+ export const STYLE_TOKEN_KEYS = [
2
+ "radius",
3
+ "background",
4
+ "foreground",
5
+ "card",
6
+ "cardForeground",
7
+ "popover",
8
+ "popoverForeground",
9
+ "primary",
10
+ "primaryForeground",
11
+ "secondary",
12
+ "secondaryForeground",
13
+ "muted",
14
+ "mutedForeground",
15
+ "accent",
16
+ "accentForeground",
17
+ "destructive",
18
+ "border",
19
+ "input",
20
+ "ring",
21
+ "chart1",
22
+ "chart2",
23
+ "chart3",
24
+ "chart4",
25
+ "chart5",
26
+ "sidebar",
27
+ "sidebarForeground",
28
+ "sidebarPrimary",
29
+ "sidebarPrimaryForeground",
30
+ "sidebarAccent",
31
+ "sidebarAccentForeground",
32
+ "sidebarBorder",
33
+ "sidebarRing",
34
+ ];
35
+ function isPlainObject(value) {
36
+ return typeof value === "object" && value !== null && !Array.isArray(value);
37
+ }
38
+ function assertSafeCssValue(key, value) {
39
+ if (!value.trim()) {
40
+ throw new Error(`styleConfig.tokens.${key} must be a non-empty string`);
41
+ }
42
+ if (value.includes("<") || value.includes(">")) {
43
+ throw new Error(`styleConfig.tokens.${key} contains forbidden characters`);
44
+ }
45
+ if (value.toLowerCase().includes("</style")) {
46
+ throw new Error(`styleConfig.tokens.${key} contains a forbidden substring ("</style")`);
47
+ }
48
+ }
49
+ export function assertStyleConfig(config) {
50
+ if (!isPlainObject(config))
51
+ throw new Error("styleConfig must be an object");
52
+ const version = config.version;
53
+ if (typeof version !== "number" || !Number.isFinite(version)) {
54
+ throw new Error("styleConfig.version must be a finite number");
55
+ }
56
+ const tokens = config.tokens;
57
+ if (!isPlainObject(tokens))
58
+ throw new Error("styleConfig.tokens must be an object");
59
+ const resolvedTokens = {};
60
+ for (const key of STYLE_TOKEN_KEYS) {
61
+ const rawValue = tokens[key];
62
+ if (typeof rawValue !== "string") {
63
+ throw new Error(`styleConfig.tokens.${key} must be a string`);
64
+ }
65
+ assertSafeCssValue(key, rawValue);
66
+ resolvedTokens[key] = rawValue;
67
+ }
68
+ const extraKeys = Object.keys(tokens).filter((k) => !STYLE_TOKEN_KEYS.includes(k));
69
+ if (extraKeys.length) {
70
+ throw new Error(`styleConfig.tokens contains unknown keys: ${extraKeys
71
+ .sort()
72
+ .join(", ")}`);
73
+ }
74
+ return { version, tokens: resolvedTokens };
75
+ }
76
+ export const defaultStyleConfigJson = {
77
+ version: 1,
78
+ tokens: {
79
+ radius: "0.85rem",
80
+ background: "oklch(0.985 0.008 80.2)",
81
+ foreground: "oklch(0.2 0.03 255.4)",
82
+ card: "oklch(0.995 0.004 80.2)",
83
+ cardForeground: "oklch(0.2 0.03 255.4)",
84
+ popover: "oklch(0.995 0.004 80.2)",
85
+ popoverForeground: "oklch(0.2 0.03 255.4)",
86
+ primary: "oklch(0.62 0.16 199.4)",
87
+ primaryForeground: "oklch(0.985 0.008 80.2)",
88
+ secondary: "oklch(0.94 0.02 83.1)",
89
+ secondaryForeground: "oklch(0.22 0.04 258.2)",
90
+ muted: "oklch(0.95 0.01 85.6)",
91
+ mutedForeground: "oklch(0.46 0.04 257.6)",
92
+ accent: "oklch(0.9 0.06 78.4)",
93
+ accentForeground: "oklch(0.22 0.04 258.2)",
94
+ destructive: "oklch(0.57 0.21 25.6)",
95
+ border: "oklch(0.89 0.02 82.5)",
96
+ input: "oklch(0.92 0.02 82.5)",
97
+ ring: "oklch(0.62 0.16 199.4)",
98
+ chart1: "oklch(0.62 0.16 199.4)",
99
+ chart2: "oklch(0.66 0.14 143.6)",
100
+ chart3: "oklch(0.52 0.12 297.6)",
101
+ chart4: "oklch(0.74 0.16 79.3)",
102
+ chart5: "oklch(0.62 0.18 24.8)",
103
+ sidebar: "oklch(0.975 0.01 82.5)",
104
+ sidebarForeground: "oklch(0.2 0.03 255.4)",
105
+ sidebarPrimary: "oklch(0.62 0.16 199.4)",
106
+ sidebarPrimaryForeground: "oklch(0.985 0.008 80.2)",
107
+ sidebarAccent: "oklch(0.94 0.02 83.1)",
108
+ sidebarAccentForeground: "oklch(0.22 0.04 258.2)",
109
+ sidebarBorder: "oklch(0.89 0.02 82.5)",
110
+ sidebarRing: "oklch(0.62 0.16 199.4)",
111
+ },
112
+ };
113
+ //# sourceMappingURL=styleConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styleConfig.js","sourceRoot":"","sources":["../../src/types/styleConfig.ts"],"names":[],"mappings":"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","sourcesContent":["export const STYLE_TOKEN_KEYS = [\n \"radius\",\n \"background\",\n \"foreground\",\n \"card\",\n \"cardForeground\",\n \"popover\",\n \"popoverForeground\",\n \"primary\",\n \"primaryForeground\",\n \"secondary\",\n \"secondaryForeground\",\n \"muted\",\n \"mutedForeground\",\n \"accent\",\n \"accentForeground\",\n \"destructive\",\n \"border\",\n \"input\",\n \"ring\",\n \"chart1\",\n \"chart2\",\n \"chart3\",\n \"chart4\",\n \"chart5\",\n \"sidebar\",\n \"sidebarForeground\",\n \"sidebarPrimary\",\n \"sidebarPrimaryForeground\",\n \"sidebarAccent\",\n \"sidebarAccentForeground\",\n \"sidebarBorder\",\n \"sidebarRing\",\n] as const;\n\nexport type StyleTokenKey = (typeof STYLE_TOKEN_KEYS)[number];\n\nexport type StyleConfig = {\n version: number;\n tokens: Record<StyleTokenKey, string>;\n};\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction assertSafeCssValue(key: string, value: string) {\n if (!value.trim()) {\n throw new Error(`styleConfig.tokens.${key} must be a non-empty string`);\n }\n if (value.includes(\"<\") || value.includes(\">\")) {\n throw new Error(`styleConfig.tokens.${key} contains forbidden characters`);\n }\n if (value.toLowerCase().includes(\"</style\")) {\n throw new Error(\n `styleConfig.tokens.${key} contains a forbidden substring (\"</style\")`,\n );\n }\n}\n\nexport function assertStyleConfig(config: unknown): StyleConfig {\n if (!isPlainObject(config)) throw new Error(\"styleConfig must be an object\");\n\n const version = config.version;\n if (typeof version !== \"number\" || !Number.isFinite(version)) {\n throw new Error(\"styleConfig.version must be a finite number\");\n }\n\n const tokens = (config as Record<string, unknown>).tokens;\n if (!isPlainObject(tokens))\n throw new Error(\"styleConfig.tokens must be an object\");\n\n const resolvedTokens = {} as Record<StyleTokenKey, string>;\n for (const key of STYLE_TOKEN_KEYS) {\n const rawValue = (tokens as Record<string, unknown>)[key];\n if (typeof rawValue !== \"string\") {\n throw new Error(`styleConfig.tokens.${key} must be a string`);\n }\n assertSafeCssValue(key, rawValue);\n resolvedTokens[key] = rawValue;\n }\n\n const extraKeys = Object.keys(tokens).filter(\n (k) => !(STYLE_TOKEN_KEYS as readonly string[]).includes(k),\n );\n if (extraKeys.length) {\n throw new Error(\n `styleConfig.tokens contains unknown keys: ${extraKeys\n .sort()\n .join(\", \")}`,\n );\n }\n\n return { version, tokens: resolvedTokens };\n}\n\nexport const defaultStyleConfigJson = {\n version: 1,\n tokens: {\n radius: \"0.85rem\",\n background: \"oklch(0.985 0.008 80.2)\",\n foreground: \"oklch(0.2 0.03 255.4)\",\n card: \"oklch(0.995 0.004 80.2)\",\n cardForeground: \"oklch(0.2 0.03 255.4)\",\n popover: \"oklch(0.995 0.004 80.2)\",\n popoverForeground: \"oklch(0.2 0.03 255.4)\",\n primary: \"oklch(0.62 0.16 199.4)\",\n primaryForeground: \"oklch(0.985 0.008 80.2)\",\n secondary: \"oklch(0.94 0.02 83.1)\",\n secondaryForeground: \"oklch(0.22 0.04 258.2)\",\n muted: \"oklch(0.95 0.01 85.6)\",\n mutedForeground: \"oklch(0.46 0.04 257.6)\",\n accent: \"oklch(0.9 0.06 78.4)\",\n accentForeground: \"oklch(0.22 0.04 258.2)\",\n destructive: \"oklch(0.57 0.21 25.6)\",\n border: \"oklch(0.89 0.02 82.5)\",\n input: \"oklch(0.92 0.02 82.5)\",\n ring: \"oklch(0.62 0.16 199.4)\",\n chart1: \"oklch(0.62 0.16 199.4)\",\n chart2: \"oklch(0.66 0.14 143.6)\",\n chart3: \"oklch(0.52 0.12 297.6)\",\n chart4: \"oklch(0.74 0.16 79.3)\",\n chart5: \"oklch(0.62 0.18 24.8)\",\n sidebar: \"oklch(0.975 0.01 82.5)\",\n sidebarForeground: \"oklch(0.2 0.03 255.4)\",\n sidebarPrimary: \"oklch(0.62 0.16 199.4)\",\n sidebarPrimaryForeground: \"oklch(0.985 0.008 80.2)\",\n sidebarAccent: \"oklch(0.94 0.02 83.1)\",\n sidebarAccentForeground: \"oklch(0.22 0.04 258.2)\",\n sidebarBorder: \"oklch(0.89 0.02 82.5)\",\n sidebarRing: \"oklch(0.62 0.16 199.4)\",\n },\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vedangiitb/qwintly-core",
3
- "version": "1.3.16",
3
+ "version": "1.3.17",
4
4
  "description": "Qwintly Core",
5
5
  "homepage": "https://github.com/vedangiitb/qwintly-core#readme",
6
6
  "bugs": {