/** * JSON-typed attribute helpers. * * Why this exists: * * The NEWO platform stores some attributes (e.g. * `project_attributes_private_dynamic_workflow_builder_canvas`) as * `value_type: json`. The API may return the `value` field as either a * STRING containing JSON or as an already-parsed OBJECT. * * Without normalization, several bugs leak through: * * 1. When the API returns the value as an OBJECT, `yaml.dump` serializes * it as a YAML structure (mappings/sequences). Pushing back then sends * `{"value": {...}}` instead of `{"value": "..."}`, breaking the * Workflow Builder which expects the canvas as a JSON STRING. * * 2. The push-time change check used `String(localAttr.value)` for * comparison. With objects this collapses to `"[object Object]"` on * both sides — silently masking real changes — and with mismatched * string vs object representations it triggers spurious pushes that * overwrite the canvas with the wrong shape (Builder shows blank). * * 3. (Bug 3.7.2-a) Canvas JSON strings with structural newlines (real * U+000A between tokens) can be emitted by yaml.dump as double-quoted * scalars with `\n` escape sequences. patchYamlToPyyaml then converts * those to single-quoted YAML scalars, where `\n` is treated as two * literal chars (backslash + n). On push the platform stores those * literal chars and the Builder calls JSON.parse, which fails on * backslash-n as structural whitespace. * * 4. (Bug 3.7.2-b) Canvas body text contains Markdown with `\_` * (backslash + underscore). `\_` is not a valid JSON escape sequence * per RFC 8259 (valid ones: " \ / b f n r t uXXXX). Chrome V8's * JSON.parse is strict: it throws SyntaxError on `\_`, silently * blanking the Builder. * * The fix for (3) and (4): for `value_type: json` string values, strip * invalid escape sequences then compact via JSON.parse + JSON.stringify. * Compaction removes structural newlines and re-serializes all string * values with only valid JSON escapes, producing a single-line string * that round-trips through YAML without corruption. */ /** * True if the attribute is a JSON-typed attribute (case- and * format-insensitive: handles `json`, `JSON`, `AttributeValueTypes.json`, * `ValueType.JSON`, etc.). */ export declare function isJsonValueType(valueType: unknown): boolean; /** * Fix invalid JSON escape sequences inside JSON string values. * * Per RFC 8259, valid escape sequences inside a JSON string are: * \" \\ \/ \b \f \n \r \t \uXXXX * Anything else (e.g. `\_` `\.` from Markdown) is invalid and causes * JSON.parse to throw. Fix: drop the backslash (e.g. `\_` → `_`). * * Only modifies characters inside JSON string values (tracks quote * context). Structural characters outside strings are untouched. */ export declare function fixInvalidJsonEscapes(s: string): string; /** * Coerce a JSON-typed attribute's value to a STRING suitable for storage * in attributes.yaml and for sending to the platform. * * - `null` / `undefined` → `''` * - object → compact JSON string (`JSON.stringify(value)`) * - string → fix invalid escapes (e.g. `\_` → `_`), then compact via * JSON.parse + JSON.stringify. If parsing still fails after * fixing escapes, return the fixed string as-is. * - other → `String(value)` * * Compacting removes structural newlines and guarantees a single-line * string that yaml.dump serializes without escape-sequence corruption in * the patchYamlToPyyaml pass. See module-level comment for full context. */ export declare function normalizeJsonValueForStorage(value: unknown): string; /** * Canonical comparison for JSON-typed attribute values. * * Returns the canonical form (compact JSON if parseable, otherwise the * fixed string). Use this on both sides of a comparison so that pretty- * vs compact-printed JSON does not register as a change, and so that an * object on one side equals its stringified form on the other side. */ export declare function canonicalJsonValue(value: unknown): string; /** * True if two JSON-typed attribute values are semantically equal. * * Handles the four mismatched representations that can occur during a * pull/push cycle: * string vs string (different whitespace/indent), object vs string, * string vs object, object vs object. */ export declare function jsonValuesEqual(a: unknown, b: unknown): boolean; //# sourceMappingURL=json-attr-utils.d.ts.map