@vedangiitb/qwintly-core 1.3.28 → 1.3.29
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/tools/implementations/updateGlobalStyles.impl.d.ts.map +1 -1
- package/dist/ai/tools/implementations/updateGlobalStyles.impl.js +28 -0
- package/dist/ai/tools/implementations/updateGlobalStyles.impl.js.map +1 -1
- package/dist/tests/updateGlobalStyles.impl.test.js +29 -0
- package/dist/tests/updateGlobalStyles.impl.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateGlobalStyles.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateGlobalStyles.impl.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"updateGlobalStyles.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/updateGlobalStyles.impl.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA+ExD,eAAO,MAAM,4BAA4B,GAAI,MAAM,aAAa,MAGhD,SAAS,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoF/B,CAAC"}
|
|
@@ -26,6 +26,34 @@ const extractAllValidTokens = (value) => {
|
|
|
26
26
|
const out = {};
|
|
27
27
|
const visited = new WeakSet();
|
|
28
28
|
const traverse = (val) => {
|
|
29
|
+
if (typeof val === "string") {
|
|
30
|
+
const trimmedVal = val.trim();
|
|
31
|
+
if (!trimmedVal)
|
|
32
|
+
return;
|
|
33
|
+
// Try to parse string as JSON first
|
|
34
|
+
try {
|
|
35
|
+
const parsed = JSON.parse(trimmedVal);
|
|
36
|
+
traverse(parsed);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
catch { }
|
|
40
|
+
// If it's a string and not valid JSON, try to extract key-value patterns (e.g. key: "value", "key": 'value', etc.)
|
|
41
|
+
const regex = /(?:["']?([a-zA-Z0-9_-]+)["']?\s*:\s*["']([^"']+)["'])/g;
|
|
42
|
+
let match;
|
|
43
|
+
let foundAny = false;
|
|
44
|
+
while ((match = regex.exec(trimmedVal)) !== null) {
|
|
45
|
+
const [, k, v] = match;
|
|
46
|
+
if (allowed.has(k) && isSafeCssValue(v)) {
|
|
47
|
+
out[k] = v.trim();
|
|
48
|
+
foundAny = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (foundAny)
|
|
52
|
+
return;
|
|
53
|
+
// As a last resort, if the string itself is a safe value and allowed keys can be matched elsewhere,
|
|
54
|
+
// or if we want to handle a plain string value, but without a key we can't map it.
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
29
57
|
if (typeof val !== "object" || val === null)
|
|
30
58
|
return;
|
|
31
59
|
if (visited.has(val))
|
|
@@ -1 +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 type StyleConfig,\n type StyleTokenKey,\n STYLE_TOKEN_KEYS,\n} from \"../../../types/styleConfig.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\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 isSafeCssValue = (value: string): boolean => {\n if (!value.trim()) return false;\n if (value.includes(\"<\") || value.includes(\">\")) return false;\n if (value.toLowerCase().includes(\"</style\")) return false;\n return true;\n};\n\nconst extractAllValidTokens = (value: unknown): Partial<Record<StyleTokenKey, string>> => {\n const allowed = new Set<string>(STYLE_TOKEN_KEYS as unknown as string[]);\n const out: Record<string, string> = {};\n const visited = new WeakSet<object>();\n\n const traverse = (val: unknown) => {\n if (typeof val !== \"object\" || val === null) return;\n if (visited.has(val)) return;\n visited.add(val);\n\n if (Array.isArray(val)) {\n for (const item of val) {\n traverse(item);\n }\n return;\n }\n\n for (const [k, v] of Object.entries(val)) {\n if (allowed.has(k) && typeof v === \"string\" && isSafeCssValue(v)) {\n out[k] = v.trim();\n } else {\n traverse(v);\n }\n }\n };\n\n traverse(value);\n return out as any;\n};\n\nexport const createUpdateGlobalStylesImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (rawArgs: unknown) => {\n const normalizedArgs: unknown = (() => {\n if (typeof rawArgs !== \"string\") return rawArgs;\n try {\n return JSON.parse(rawArgs);\n } catch {\n return rawArgs;\n }\n })();\n\n const tokensPatch = extractAllValidTokens(normalizedArgs);\n\n if (Object.keys(tokensPatch).length === 0) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: {\n formErrors: [\"must include at least one token key/value\"],\n fieldErrors: {},\n },\n note: \"update_global_styles requires at least one valid token key/value (e.g. { primary: \\\"oklch(...)\\\" }).\",\n };\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"]}
|
|
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 type StyleConfig,\n type StyleTokenKey,\n STYLE_TOKEN_KEYS,\n} from \"../../../types/styleConfig.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\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 isSafeCssValue = (value: string): boolean => {\n if (!value.trim()) return false;\n if (value.includes(\"<\") || value.includes(\">\")) return false;\n if (value.toLowerCase().includes(\"</style\")) return false;\n return true;\n};\n\nconst extractAllValidTokens = (value: unknown): Partial<Record<StyleTokenKey, string>> => {\n const allowed = new Set<string>(STYLE_TOKEN_KEYS as unknown as string[]);\n const out: Record<string, string> = {};\n const visited = new WeakSet<object>();\n\n const traverse = (val: unknown) => {\n if (typeof val === \"string\") {\n const trimmedVal = val.trim();\n if (!trimmedVal) return;\n\n // Try to parse string as JSON first\n try {\n const parsed = JSON.parse(trimmedVal);\n traverse(parsed);\n return;\n } catch {}\n\n // If it's a string and not valid JSON, try to extract key-value patterns (e.g. key: \"value\", \"key\": 'value', etc.)\n const regex = /(?:[\"']?([a-zA-Z0-9_-]+)[\"']?\\s*:\\s*[\"']([^\"']+)[\"'])/g;\n let match;\n let foundAny = false;\n while ((match = regex.exec(trimmedVal)) !== null) {\n const [, k, v] = match;\n if (allowed.has(k) && isSafeCssValue(v)) {\n out[k] = v.trim();\n foundAny = true;\n }\n }\n if (foundAny) return;\n\n // As a last resort, if the string itself is a safe value and allowed keys can be matched elsewhere,\n // or if we want to handle a plain string value, but without a key we can't map it.\n return;\n }\n\n if (typeof val !== \"object\" || val === null) return;\n if (visited.has(val)) return;\n visited.add(val);\n\n if (Array.isArray(val)) {\n for (const item of val) {\n traverse(item);\n }\n return;\n }\n\n for (const [k, v] of Object.entries(val)) {\n if (allowed.has(k) && typeof v === \"string\" && isSafeCssValue(v)) {\n out[k] = v.trim();\n } else {\n traverse(v);\n }\n }\n };\n\n traverse(value);\n return out as any;\n};\n\nexport const createUpdateGlobalStylesImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (rawArgs: unknown) => {\n const normalizedArgs: unknown = (() => {\n if (typeof rawArgs !== \"string\") return rawArgs;\n try {\n return JSON.parse(rawArgs);\n } catch {\n return rawArgs;\n }\n })();\n\n const tokensPatch = extractAllValidTokens(normalizedArgs);\n\n if (Object.keys(tokensPatch).length === 0) {\n return {\n success: false,\n error: \"invalid args\",\n error_detail: {\n formErrors: [\"must include at least one token key/value\"],\n fieldErrors: {},\n },\n note: \"update_global_styles requires at least one valid token key/value (e.g. { primary: \\\"oklch(...)\\\" }).\",\n };\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"]}
|
|
@@ -280,4 +280,33 @@ test("update_global_styles: handles heavily nested/wrapped SDK responses", async
|
|
|
280
280
|
await fs.rm(workspaceRoot, { recursive: true, force: true });
|
|
281
281
|
}
|
|
282
282
|
});
|
|
283
|
+
test("update_global_styles: accepts malformed/unquoted JS object string", async () => {
|
|
284
|
+
const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qwintly-core-"));
|
|
285
|
+
try {
|
|
286
|
+
await fs.mkdir(path.join(workspaceRoot, "app"), { recursive: true });
|
|
287
|
+
const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() });
|
|
288
|
+
// JS object literal format (invalid standard JSON)
|
|
289
|
+
const res = await impl("{ primary: 'oklch(0.6, 0.2, 260)' }");
|
|
290
|
+
assert.equal(res?.success, true);
|
|
291
|
+
const stored = await readStyleConfig(workspaceRoot);
|
|
292
|
+
assert.equal(stored.tokens.primary, "oklch(0.6, 0.2, 260)");
|
|
293
|
+
}
|
|
294
|
+
finally {
|
|
295
|
+
await fs.rm(workspaceRoot, { recursive: true, force: true });
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
test("update_global_styles: accepts single valid key/value", async () => {
|
|
299
|
+
const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "qwintly-core-"));
|
|
300
|
+
try {
|
|
301
|
+
await fs.mkdir(path.join(workspaceRoot, "app"), { recursive: true });
|
|
302
|
+
const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() });
|
|
303
|
+
const res = await impl({ primary: "oklch(0.6, 0.2, 260)" });
|
|
304
|
+
assert.equal(res?.success, true);
|
|
305
|
+
const stored = await readStyleConfig(workspaceRoot);
|
|
306
|
+
assert.equal(stored.tokens.primary, "oklch(0.6, 0.2, 260)");
|
|
307
|
+
}
|
|
308
|
+
finally {
|
|
309
|
+
await fs.rm(workspaceRoot, { recursive: true, force: true });
|
|
310
|
+
}
|
|
311
|
+
});
|
|
283
312
|
//# sourceMappingURL=updateGlobalStyles.impl.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateGlobalStyles.impl.test.js","sourceRoot":"","sources":["../../src/tests/updateGlobalStyles.impl.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EACL,4BAA4B,GAC7B,MAAM,wDAAwD,CAAC;AAIhE,MAAM,UAAU,GAAG,CAAC,SAA2B,EAAU,EAAE;IACzD,OAAO;QACL,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;QACpE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,CACzC,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,IAAI,EAAE,EAAE,OAAO,CAAC;QACpD,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE;YAC5B,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACpE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC;QACnD,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CACjC,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QAClD,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;KACrB,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,EAAE,aAAqB,EAAE,EAAE;IACtD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAC3B,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,kBAAkB,CAAC,EACnD,OAAO,CACR,CAAC;IACF,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAQ,CAAC;AAChC,CAAC,CAAC;AAEF,IAAI,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;IACvE,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,kBAAkB,CAAC,EACnD,IAAI,CAAC,SAAS,CACZ;YACE,OAAO,EAAE,EAAE;YACX,MAAM,EAAE;gBACN,MAAM,EAAE,MAAM;gBACd,UAAU,EAAE,sBAAsB;gBAClC,UAAU,EAAE,uBAAuB;gBACnC,IAAI,EAAE,yBAAyB;gBAC/B,cAAc,EAAE,uBAAuB;gBACvC,OAAO,EAAE,yBAAyB;gBAClC,iBAAiB,EAAE,uBAAuB;gBAC1C,OAAO,EAAE,wBAAwB;gBACjC,iBAAiB,EAAE,yBAAyB;gBAC5C,SAAS,EAAE,uBAAuB;gBAClC,mBAAmB,EAAE,wBAAwB;gBAC7C,KAAK,EAAE,uBAAuB;gBAC9B,eAAe,EAAE,wBAAwB;gBACzC,MAAM,EAAE,sBAAsB;gBAC9B,gBAAgB,EAAE,wBAAwB;gBAC1C,WAAW,EAAE,uBAAuB;gBACpC,MAAM,EAAE,uBAAuB;gBAC/B,KAAK,EAAE,uBAAuB;gBAC9B,IAAI,EAAE,wBAAwB;gBAC9B,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,uBAAuB;gBAC/B,MAAM,EAAE,uBAAuB;gBAC/B,OAAO,EAAE,wBAAwB;gBACjC,iBAAiB,EAAE,uBAAuB;gBAC1C,cAAc,EAAE,wBAAwB;gBACxC,wBAAwB,EAAE,yBAAyB;gBACnD,aAAa,EAAE,uBAAuB;gBACtC,uBAAuB,EAAE,wBAAwB;gBACjD,aAAa,EAAE,uBAAuB;gBACtC,WAAW,EAAE,wBAAwB;aACtC;SACF,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,EACR,OAAO,CACR,CAAC;QAEF,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,UAAU,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;IAClE,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;IAC1F,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;IAC7F,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,kBAAkB,CAAC,EACnD,GAAG,EACH,OAAO,CACR,CAAC;QACF,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;IACrE,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAS,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;IAC5E,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3C,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;IACtE,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,kBAAkB,CAAC,EACnD,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,EAC7D,OAAO,CACR,CAAC;QAEF,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAS,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;IAC/E,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC;QAC3E,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAC7D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mFAAmF,EAAE,KAAK,IAAI,EAAE;IACnG,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAS,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAC7D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mFAAmF,EAAE,KAAK,IAAI,EAAE;IACnG,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;YACrB,MAAM,EAAE,oBAAoB;YAC5B,IAAI,EAAE,oBAAoB;YAC1B,iBAAiB,EAAE,cAAc;YACjC,OAAO,EAAE,oBAAoB;SACvB,CAAC,CAAC;QACV,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;QAC1D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;QAC9D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC3D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;IAC3D,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;YACrB,MAAM,EAAE,oBAAoB;YAC5B,MAAM,EAAE,mBAAmB;YAC3B,WAAW,EAAE,oBAAoB;YACjC,MAAM,EAAE,oBAAoB;YAC5B,iBAAiB,EAAE,cAAc;YACjC,cAAc,EAAE,oBAAoB;YACpC,MAAM,EAAE,qBAAqB;YAC7B,OAAO,EAAE,oBAAoB;YAC7B,IAAI,EAAE,oBAAoB;YAC1B,MAAM,EAAE,qBAAqB;YAC7B,MAAM,EAAE,oBAAoB;YAC5B,wBAAwB,EAAE,cAAc;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wGAAwG,EAAE,KAAK,IAAI,EAAE;IACxH,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;YACrB,OAAO,EAAE,oBAAoB;YAC7B,OAAO,EAAE,mBAAmB;YAC5B,UAAU,EAAE,EAAE,EAAE,4BAA4B;YAC5C,IAAI,EAAE,yBAAyB,EAAE,6BAA6B;SACxD,CAAC,CAAC;QACV,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;QAC1D,gFAAgF;QAChF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;QAC/D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;IACpF,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,4BAA4B,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,EAAS,CAAC,CAAC;QACtF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC;YACrB,eAAe,EAAE;gBACf,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;iBACnC;aACF;YACD,UAAU,EAAE;gBACV;oBACE,OAAO,EAAE;wBACP,KAAK,EAAE;4BACL;gCACE,YAAY,EAAE;oCACZ,IAAI,EAAE,sBAAsB;oCAC5B,IAAI,EAAE;wCACJ,MAAM,EAAE,oBAAoB;wCAC5B,OAAO,EAAE,oBAAoB;qCAC9B;iCACF;6BACF;yBACF;qBACF;iBACF;aACF;SACK,CAAC,CAAC;QACV,MAAM,CAAC,KAAK,CAAE,GAAW,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAC5D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,CAAC,CAAC","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({ 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({ 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({ 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({ 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({ background: \"\" });\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: empty tokens patch 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 await fs.writeFile(\n path.join(workspaceRoot, \"app\", \"styleConfig.json\"),\n JSON.stringify({ version: 1, tokens: { radius: \"0.85rem\" } }),\n \"utf-8\",\n );\n\n const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() } as any);\n const res = await impl({} as any);\n assert.equal((res as any)?.success, false);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.version, 1);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: accepts JSON-string args (primary only)\", 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(JSON.stringify({ primary: \"oklch(0.7 0.15 350)\" }));\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 350)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: accepts wrapped args {tokens:{...}} and still 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: { primary: \"oklch(0.7 0.15 350)\" } } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 350)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: exact case (primary/ring/chart1/primaryForeground) succeeds\", 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({\n chart1: \"oklch(0.7 0.18 50)\",\n ring: \"oklch(0.7 0.18 50)\",\n primaryForeground: \"oklch(1 0 0)\",\n primary: \"oklch(0.7 0.18 50)\",\n } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.18 50)\");\n assert.equal(stored.tokens.primaryForeground, \"oklch(1 0 0)\");\n assert.equal(stored.tokens.ring, \"oklch(0.7 0.18 50)\");\n assert.equal(stored.tokens.chart1, \"oklch(0.7 0.18 50)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: user's failing case\", 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({\n chart2: \"oklch(0.75 0.1 45)\",\n chart5: \"oklch(0.6 0.2 30)\",\n sidebarRing: \"oklch(0.7 0.15 40)\",\n chart1: \"oklch(0.7 0.15 40)\",\n primaryForeground: \"oklch(1 0 0)\",\n sidebarPrimary: \"oklch(0.7 0.15 40)\",\n chart4: \"oklch(0.65 0.18 35)\",\n primary: \"oklch(0.7 0.15 40)\",\n ring: \"oklch(0.7 0.15 40)\",\n accent: \"oklch(0.85 0.12 40)\",\n chart3: \"oklch(0.8 0.08 50)\",\n sidebarPrimaryForeground: \"oklch(1 0 0)\"\n });\n assert.equal((res as any)?.success, true);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: mix of valid and invalid/unknown/unsafe params succeeds by ignoring invalid ones\", 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({\n primary: \"oklch(0.7 0.15 40)\",\n notAKey: \"should be ignored\",\n background: \"\", // empty - should be ignored\n ring: \"<script>unsafe</script>\", // unsafe - should be ignored\n } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 40)\");\n // background, ring, notAKey should not be overwritten/updated to invalid values\n assert.notEqual(stored.tokens.ring, \"<script>unsafe</script>\");\n assert.notEqual(stored.tokens.background, \"\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: handles heavily nested/wrapped SDK responses\", 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({\n sdkHttpResponse: {\n headers: {\n \"content-type\": \"application/json\"\n }\n },\n candidates: [\n {\n content: {\n parts: [\n {\n functionCall: {\n name: \"update_global_styles\",\n args: {\n chart2: \"oklch(0.75 0.1 45)\",\n primary: \"oklch(0.7 0.15 40)\"\n }\n }\n }\n ]\n }\n }\n ]\n } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.chart2, \"oklch(0.75 0.1 45)\");\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 40)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\n\n"]}
|
|
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({ 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({ 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({ 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({ 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({ background: \"\" });\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: empty tokens patch 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 await fs.writeFile(\n path.join(workspaceRoot, \"app\", \"styleConfig.json\"),\n JSON.stringify({ version: 1, tokens: { radius: \"0.85rem\" } }),\n \"utf-8\",\n );\n\n const impl = createUpdateGlobalStylesImpl({ workspaceRoot, fs: makeRealFs() } as any);\n const res = await impl({} as any);\n assert.equal((res as any)?.success, false);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.version, 1);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: accepts JSON-string args (primary only)\", 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(JSON.stringify({ primary: \"oklch(0.7 0.15 350)\" }));\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 350)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: accepts wrapped args {tokens:{...}} and still 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: { primary: \"oklch(0.7 0.15 350)\" } } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 350)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: exact case (primary/ring/chart1/primaryForeground) succeeds\", 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({\n chart1: \"oklch(0.7 0.18 50)\",\n ring: \"oklch(0.7 0.18 50)\",\n primaryForeground: \"oklch(1 0 0)\",\n primary: \"oklch(0.7 0.18 50)\",\n } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.18 50)\");\n assert.equal(stored.tokens.primaryForeground, \"oklch(1 0 0)\");\n assert.equal(stored.tokens.ring, \"oklch(0.7 0.18 50)\");\n assert.equal(stored.tokens.chart1, \"oklch(0.7 0.18 50)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: user's failing case\", 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({\n chart2: \"oklch(0.75 0.1 45)\",\n chart5: \"oklch(0.6 0.2 30)\",\n sidebarRing: \"oklch(0.7 0.15 40)\",\n chart1: \"oklch(0.7 0.15 40)\",\n primaryForeground: \"oklch(1 0 0)\",\n sidebarPrimary: \"oklch(0.7 0.15 40)\",\n chart4: \"oklch(0.65 0.18 35)\",\n primary: \"oklch(0.7 0.15 40)\",\n ring: \"oklch(0.7 0.15 40)\",\n accent: \"oklch(0.85 0.12 40)\",\n chart3: \"oklch(0.8 0.08 50)\",\n sidebarPrimaryForeground: \"oklch(1 0 0)\"\n });\n assert.equal((res as any)?.success, true);\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: mix of valid and invalid/unknown/unsafe params succeeds by ignoring invalid ones\", 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({\n primary: \"oklch(0.7 0.15 40)\",\n notAKey: \"should be ignored\",\n background: \"\", // empty - should be ignored\n ring: \"<script>unsafe</script>\", // unsafe - should be ignored\n } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 40)\");\n // background, ring, notAKey should not be overwritten/updated to invalid values\n assert.notEqual(stored.tokens.ring, \"<script>unsafe</script>\");\n assert.notEqual(stored.tokens.background, \"\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: handles heavily nested/wrapped SDK responses\", 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({\n sdkHttpResponse: {\n headers: {\n \"content-type\": \"application/json\"\n }\n },\n candidates: [\n {\n content: {\n parts: [\n {\n functionCall: {\n name: \"update_global_styles\",\n args: {\n chart2: \"oklch(0.75 0.1 45)\",\n primary: \"oklch(0.7 0.15 40)\"\n }\n }\n }\n ]\n }\n }\n ]\n } as any);\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.chart2, \"oklch(0.75 0.1 45)\");\n assert.equal(stored.tokens.primary, \"oklch(0.7 0.15 40)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: accepts malformed/unquoted JS object string\", 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 // JS object literal format (invalid standard JSON)\n const res = await impl(\"{ primary: 'oklch(0.6, 0.2, 260)' }\");\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.6, 0.2, 260)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\ntest(\"update_global_styles: accepts single valid key/value\", 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({ primary: \"oklch(0.6, 0.2, 260)\" });\n assert.equal((res as any)?.success, true);\n\n const stored = await readStyleConfig(workspaceRoot);\n assert.equal(stored.tokens.primary, \"oklch(0.6, 0.2, 260)\");\n } finally {\n await fs.rm(workspaceRoot, { recursive: true, force: true });\n }\n});\n\n\n\n"]}
|