@zenoaihq/tson 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../LICENSE)
6
6
  [![npm version](https://img.shields.io/npm/v/@zenoaihq/tson.svg)](https://www.npmjs.com/package/@zenoaihq/tson)
7
+ [![NPM Downloads](https://img.shields.io/npm/dm/@zenoaihq/tson.svg)](https://www.npmjs.com/package/@zenoaihq/tson)
7
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.3+-blue.svg)](https://www.typescriptlang.org/)
8
9
 
9
10
  A compact serialization format designed for efficient data exchange with Large Language Models (LLMs). TSON achieves **25-70% token savings** compared to JSON while maintaining perfect round-trip conversion.
@@ -345,7 +346,7 @@ Run the test suite:
345
346
  npm test
346
347
  ```
347
348
 
348
- All 13 tests should pass:
349
+ All 14 tests should pass:
349
350
 
350
351
  ```
351
352
  ✓ should handle simple objects
@@ -454,7 +455,7 @@ MIT License - see [LICENSE](../LICENSE) file for details.
454
455
  ---
455
456
 
456
457
  **Package:** `@zenoaihq/tson`
457
- **Version:** 1.0.0
458
+ **Version:** 1.0.2
458
459
  **Status:** Production Ready
459
460
  **Node.js:** 16.0.0+
460
461
  **TypeScript:** 5.3+
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/utils.ts
4
- var SPECIAL_CHARS = /* @__PURE__ */ new Set([",", "|", "@", "#", "{", "}", "[", "]", "\n", "\r", " ", " "]);
4
+ var SPECIAL_CHARS = /* @__PURE__ */ new Set([",", "|", "@", "#", "{", "}", "[", "]", "\n", "\r", " ", " ", '"', "(", ")"]);
5
5
  function needsQuoting(value) {
6
6
  if (value.length === 0) {
7
7
  return true;
@@ -33,7 +33,36 @@ function escapeString(value) {
33
33
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
34
34
  }
35
35
  function unescapeString(value) {
36
- return value.replace(/\\t/g, " ").replace(/\\r/g, "\r").replace(/\\n/g, "\n").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
36
+ const result = [];
37
+ let i = 0;
38
+ while (i < value.length) {
39
+ if (value[i] === "\\" && i + 1 < value.length) {
40
+ const nextChar = value[i + 1];
41
+ if (nextChar === "\\") {
42
+ result.push("\\");
43
+ i += 2;
44
+ } else if (nextChar === '"') {
45
+ result.push('"');
46
+ i += 2;
47
+ } else if (nextChar === "n") {
48
+ result.push("\n");
49
+ i += 2;
50
+ } else if (nextChar === "r") {
51
+ result.push("\r");
52
+ i += 2;
53
+ } else if (nextChar === "t") {
54
+ result.push(" ");
55
+ i += 2;
56
+ } else {
57
+ result.push(value[i]);
58
+ i += 1;
59
+ }
60
+ } else {
61
+ result.push(value[i]);
62
+ i += 1;
63
+ }
64
+ }
65
+ return result.join("");
37
66
  }
38
67
  function formatPrimitive(value) {
39
68
  if (value === null) {
@@ -162,11 +191,17 @@ function splitByDelimiter(text, delimiter) {
162
191
  }
163
192
  function parseKeySchema(keyString) {
164
193
  const trimmed = keyString.trim();
194
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
195
+ return { keyName: unescapeString(trimmed.slice(1, -1)), schema: null };
196
+ }
165
197
  if (!trimmed.includes("(")) {
166
198
  return { keyName: trimmed, schema: null };
167
199
  }
168
200
  const parenIdx = trimmed.indexOf("(");
169
- const keyName = trimmed.slice(0, parenIdx).trim();
201
+ let keyName = trimmed.slice(0, parenIdx).trim();
202
+ if (keyName.startsWith('"') && keyName.endsWith('"')) {
203
+ keyName = unescapeString(keyName.slice(1, -1));
204
+ }
170
205
  if (!trimmed.endsWith(")")) {
171
206
  throw new Error(`Invalid key schema syntax: ${keyString}`);
172
207
  }
@@ -186,13 +221,35 @@ function buildSchemaMap(keys) {
186
221
  return schemaMap;
187
222
  }
188
223
  function parseKeys(keysStr) {
189
- if (keysStr.includes("#")) {
190
- const lastHashIdx = keysStr.lastIndexOf("#");
191
- const keysPart = keysStr.slice(0, lastHashIdx);
192
- const countPart = keysStr.slice(lastHashIdx + 1).trim();
224
+ let hashIdx = -1;
225
+ let inQuotes = false;
226
+ for (let i = keysStr.length - 1; i >= 0; i--) {
227
+ const char = keysStr[i];
228
+ if (char === '"') {
229
+ let backslashCount = 0;
230
+ for (let j = i - 1; j >= 0; j--) {
231
+ if (keysStr[j] === "\\") {
232
+ backslashCount++;
233
+ } else {
234
+ break;
235
+ }
236
+ }
237
+ if (backslashCount % 2 === 0) {
238
+ inQuotes = !inQuotes;
239
+ }
240
+ }
241
+ if (char === "#" && !inQuotes) {
242
+ hashIdx = i;
243
+ break;
244
+ }
245
+ }
246
+ if (hashIdx !== -1) {
247
+ const keysPart = keysStr.slice(0, hashIdx);
248
+ const countPart = keysStr.slice(hashIdx + 1).trim();
193
249
  const count = parseInt(countPart, 10);
194
250
  if (isNaN(count)) {
195
- throw new Error(`Invalid row count: ${countPart}`);
251
+ const keys2 = splitByDelimiter(keysStr, ",");
252
+ return { keys: keys2, count: null };
196
253
  }
197
254
  const keys = splitByDelimiter(keysPart, ",");
198
255
  return { keys, count };
@@ -275,7 +332,13 @@ function serializeTabular(arr) {
275
332
  }
276
333
  if (key in nestedSchemas) {
277
334
  const schemaKeys = nestedSchemas[key];
278
- const schemaStr = schemaKeys.join(",");
335
+ const formattedSchemaKeys = schemaKeys.map((sk) => {
336
+ if (needsQuoting(sk)) {
337
+ return `"${escapeString(sk)}"`;
338
+ }
339
+ return sk;
340
+ });
341
+ const schemaStr = formattedSchemaKeys.join(",");
279
342
  keyStr = `${keyStr}(@${schemaStr})`;
280
343
  }
281
344
  keyParts.push(keyStr);
@@ -382,7 +445,7 @@ function parseKeyedObject(content) {
382
445
  const keysPart = parts[0];
383
446
  const { keys, count } = parseKeys(keysPart);
384
447
  const schemaMap = buildSchemaMap(keys);
385
- const fieldNames = keys.map((k) => k.split("(")[0]);
448
+ const fieldNames = keys.map((k) => parseKeySchema(k).keyName);
386
449
  if (parts.length === 1) {
387
450
  throw new Error("Invalid object format: missing values");
388
451
  }
@@ -446,7 +509,7 @@ function parseSchematizedValue(valueStr, schema) {
446
509
  );
447
510
  }
448
511
  const nestedSchemaMap = buildSchemaMap(schema);
449
- const fieldNames = schema.map((k) => k.split("(")[0]);
512
+ const fieldNames = schema.map((k) => parseKeySchema(k).keyName);
450
513
  const obj = {};
451
514
  for (let i = 0; i < fieldNames.length; i++) {
452
515
  const fieldName = fieldNames[i];
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/serializer.ts","../src/deserializer.ts"],"names":["valueStr"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * TSON Utility Functions\n *\n * Helper functions for serialization, deserialization, and validation.\n */\n\nimport type { TSONValue, TSONObject, SchemaMap, KeySchema, ParsedKeys } from './types';\n\n/**\n * Special characters that require string quoting\n */\nexport const SPECIAL_CHARS = new Set([',', '|', '@', '#', '{', '}', '[', ']', '\\n', '\\r', '\\t', ' ']);\n\n/**\n * Determine if a string value needs to be quoted in TSON format.\n *\n * Strings need quoting if they:\n * - Are empty\n * - Contain special delimiter characters\n * - Have leading/trailing whitespace\n * - Look like numbers (to preserve them as strings)\n * - Look like reserved words (true/false/null) when we want them as strings\n */\nexport function needsQuoting(value: string): boolean {\n if (value.length === 0) {\n return true;\n }\n\n // Check for reserved words that we want to keep as strings\n if (value === 'true' || value === 'false' || value === 'null') {\n return true;\n }\n\n // Check for leading/trailing whitespace\n if (value[0].trim() === '' || value[value.length - 1].trim() === '') {\n return true;\n }\n\n // Check if it looks like a number (preserve type distinction)\n if (looksLikeNumber(value)) {\n return true;\n }\n\n // Check for special characters\n for (const char of value) {\n if (SPECIAL_CHARS.has(char)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if a string looks like a numeric value.\n *\n * Used to determine if we should quote a string to preserve it as a string\n * rather than having it parsed as a number.\n */\nexport function looksLikeNumber(value: string): boolean {\n if (value.length === 0) {\n return false;\n }\n\n // Try parsing as number\n const num = Number(value);\n return !isNaN(num) && value.trim() === value && isFinite(num);\n}\n\n/**\n * Escape special characters in a string for quoted representation.\n *\n * Uses standard JSON escape sequences.\n */\nexport function escapeString(value: string): string {\n // Order matters: backslash first to avoid double-escaping\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\n/**\n * Unescape a quoted string back to its original form.\n *\n * Reverses the escaping done by escapeString().\n */\nexport function unescapeString(value: string): string {\n // Order matters: process in reverse order of escaping\n return value\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n}\n\n/**\n * Format a primitive value as TSON string.\n */\nexport function formatPrimitive(value: TSONValue): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n return String(value);\n }\n\n if (typeof value === 'string') {\n if (needsQuoting(value)) {\n return `\"${escapeString(value)}\"`;\n }\n return value;\n }\n\n throw new Error(`Cannot format non-primitive type: ${typeof value}`);\n}\n\n/**\n * Parse a TSON primitive value string to JavaScript type.\n */\nexport function parsePrimitive(value: string): TSONValue {\n const trimmed = value.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check for boolean\n if (trimmed === 'true') {\n return true;\n }\n if (trimmed === 'false') {\n return false;\n }\n\n // Check for null\n if (trimmed === 'null') {\n return null;\n }\n\n // Check for quoted string\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeString(trimmed.slice(1, -1));\n }\n\n // Try to parse as number\n if (looksLikeNumber(trimmed)) {\n const num = Number(trimmed);\n if (!isNaN(num)) {\n return num;\n }\n }\n\n // Otherwise it's an unquoted string\n return trimmed;\n}\n\n/**\n * Check if a value is an array of objects with identical keys.\n *\n * This determines if we can use tabular format optimization.\n */\nexport function isUniformObjectArray(data: unknown): data is TSONObject[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n // All elements must be plain objects\n if (!data.every(item => isPlainObject(item))) {\n return false;\n }\n\n // Get keys from first element\n const firstKeys = Object.keys(data[0]);\n\n // Check that all elements have the same keys in the same order\n for (let i = 1; i < data.length; i++) {\n const keys = Object.keys(data[i]);\n if (keys.length !== firstKeys.length) {\n return false;\n }\n for (let j = 0; j < keys.length; j++) {\n if (keys[j] !== firstKeys[j]) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Check if value is a plain object (not array, null, or other special object)\n */\nfunction isPlainObject(value: unknown): value is TSONObject {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.prototype.toString.call(value) === '[object Object]'\n );\n}\n\n/**\n * Split text by delimiter, respecting quoted strings and nested structures.\n *\n * This is more sophisticated than string.split() because it handles:\n * - Quoted strings (don't split on delimiters inside quotes)\n * - Nested braces/brackets/parentheses (don't split inside nested structures)\n * - Escaped characters\n */\nexport function splitByDelimiter(text: string, delimiter: string): string[] {\n const result: string[] = [];\n const current: string[] = [];\n let inQuotes = false;\n let escapeNext = false;\n let depthCurly = 0;\n let depthSquare = 0;\n let depthParen = 0;\n\n for (const char of text) {\n // Handle escape sequences\n if (escapeNext) {\n current.push(char);\n escapeNext = false;\n continue;\n }\n\n if (char === '\\\\') {\n current.push(char);\n escapeNext = true;\n continue;\n }\n\n // Handle quotes\n if (char === '\"') {\n inQuotes = !inQuotes;\n current.push(char);\n continue;\n }\n\n // Inside quotes, add everything\n if (inQuotes) {\n current.push(char);\n continue;\n }\n\n // Track nesting depth\n if (char === '{') {\n depthCurly++;\n current.push(char);\n } else if (char === '}') {\n depthCurly--;\n current.push(char);\n } else if (char === '[') {\n depthSquare++;\n current.push(char);\n } else if (char === ']') {\n depthSquare--;\n current.push(char);\n } else if (char === '(') {\n depthParen++;\n current.push(char);\n } else if (char === ')') {\n depthParen--;\n current.push(char);\n } else if (\n char === delimiter &&\n depthCurly === 0 &&\n depthSquare === 0 &&\n depthParen === 0\n ) {\n // Found unquoted, unnested delimiter - split here\n result.push(current.join('').trim());\n current.length = 0;\n } else {\n current.push(char);\n }\n }\n\n // Add final segment\n if (current.length > 0) {\n result.push(current.join('').trim());\n }\n\n return result;\n}\n\n/**\n * Parse a key which may include nested schema notation.\n *\n * Examples:\n * \"name\" -> { keyName: \"name\", schema: null }\n * \"address(@city,zip)\" -> { keyName: \"address\", schema: [\"city\", \"zip\"] }\n * \"location(@coords(@lat,lng))\" -> { keyName: \"location\", schema: [\"coords(@lat,lng)\"] }\n */\nexport function parseKeySchema(keyString: string): KeySchema {\n const trimmed = keyString.trim();\n\n // Check if key has nested schema\n if (!trimmed.includes('(')) {\n return { keyName: trimmed, schema: null };\n }\n\n // Find the opening parenthesis\n const parenIdx = trimmed.indexOf('(');\n const keyName = trimmed.slice(0, parenIdx).trim();\n\n // Extract schema (everything between outermost parentheses)\n if (!trimmed.endsWith(')')) {\n throw new Error(`Invalid key schema syntax: ${keyString}`);\n }\n\n let schemaStr = trimmed.slice(parenIdx + 1, -1).trim();\n\n // Strip leading @ if present (part of notation, not key name)\n if (schemaStr.startsWith('@')) {\n schemaStr = schemaStr.slice(1);\n }\n\n // Split schema by commas (respecting nested parentheses)\n const schemaKeys = splitByDelimiter(schemaStr, ',');\n\n return { keyName, schema: schemaKeys };\n}\n\n/**\n * Build a mapping of field names to their nested schemas.\n *\n * Example:\n * [\"id\", \"address(@city,zip)\"]\n * -> { id: null, address: [\"city\", \"zip\"] }\n */\nexport function buildSchemaMap(keys: string[]): SchemaMap {\n const schemaMap: SchemaMap = {};\n\n for (const key of keys) {\n const { keyName, schema } = parseKeySchema(key);\n schemaMap[keyName] = schema;\n }\n\n return schemaMap;\n}\n\n/**\n * Parse keys string and extract row count if present.\n *\n * Format: key1,key2,key3 or key1,key2,key3#N\n */\nexport function parseKeys(keysStr: string): ParsedKeys {\n // Check for row count marker\n if (keysStr.includes('#')) {\n // Split from right in case # appears in key name\n const lastHashIdx = keysStr.lastIndexOf('#');\n const keysPart = keysStr.slice(0, lastHashIdx);\n const countPart = keysStr.slice(lastHashIdx + 1).trim();\n\n const count = parseInt(countPart, 10);\n if (isNaN(count)) {\n throw new Error(`Invalid row count: ${countPart}`);\n }\n\n const keys = splitByDelimiter(keysPart, ',');\n return { keys, count };\n } else {\n const keys = splitByDelimiter(keysStr, ',');\n return { keys, count: null };\n }\n}\n","/**\n * TSON Serializer\n *\n * Converts JavaScript data structures to TSON format.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n formatPrimitive,\n needsQuoting,\n escapeString,\n isUniformObjectArray,\n} from './utils';\n\n/**\n * Serialize JavaScript object to TSON formatted string.\n *\n * @example\n * dumps({ name: \"Alice\", age: 30 })\n * // Returns: '{@name,age|Alice,30}'\n *\n * @example\n * dumps([{ id: 1, name: \"Alice\" }, { id: 2, name: \"Bob\" }])\n * // Returns: '{@id,name#2|1,Alice|2,Bob}'\n */\nexport function dumps(data: TSONValue): string {\n return serializeValue(data);\n}\n\n/**\n * Serialize JavaScript object to TSON formatted file (Node.js only).\n *\n * @param data - JavaScript object to serialize\n * @param filePath - Path to file to write\n */\nexport async function dump(data: TSONValue, filePath: string): Promise<void> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n await fs.writeFile(filePath, dumps(data), 'utf-8');\n}\n\n/**\n * Serialize any JavaScript value to TSON format.\n *\n * Dispatches to appropriate serializer based on type.\n */\nexport function serializeValue(value: TSONValue): string {\n // Handle primitives\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string'\n ) {\n return formatPrimitive(value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n // Check if it's a uniform array of objects (tabular optimization)\n if (isUniformObjectArray(value)) {\n return serializeTabular(value);\n } else {\n return serializeArray(value);\n }\n }\n\n // Handle objects\n if (typeof value === 'object' && value !== null) {\n return serializeObject(value as TSONObject);\n }\n\n throw new TypeError(`Cannot serialize type: ${typeof value}`);\n}\n\n/**\n * Serialize a JavaScript object to TSON object format.\n *\n * Format: {@key1,key2|value1,value2}\n */\nexport function serializeObject(obj: TSONObject): string {\n const keys = Object.keys(obj);\n\n if (keys.length === 0) {\n return '{@}';\n }\n\n // Format keys\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n keyParts.push(keyStr);\n }\n\n // Format values\n const valueParts: string[] = [];\n for (const key of keys) {\n valueParts.push(serializeValue(obj[key]));\n }\n\n // Build object string\n const keysStr = keyParts.join(',');\n const valuesStr = valueParts.join(',');\n\n return `{@${keysStr}|${valuesStr}}`;\n}\n\n/**\n * Serialize a JavaScript array to TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function serializeArray(arr: TSONArray): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n // Serialize each element\n const valueParts: string[] = [];\n for (const value of arr) {\n valueParts.push(serializeValue(value));\n }\n\n return '[' + valueParts.join(',') + ']';\n}\n\n/**\n * Serialize a uniform array of objects in tabular format.\n *\n * Format: {@key1,key2#N|val1,val2|val1,val2}\n *\n * This is the key optimization: keys are declared once instead of repeated\n * for each object in the array.\n */\nexport function serializeTabular(arr: TSONObject[]): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n if (!isUniformObjectArray(arr)) {\n throw new Error('Array is not uniform - cannot use tabular format');\n }\n\n // Get keys from first object\n const keys = Object.keys(arr[0]);\n const count = arr.length;\n\n // Check if any values are objects with uniform structure (nested schema opportunity)\n const nestedSchemas = detectNestedSchemas(arr, keys);\n\n // Format keys (with nested schemas if applicable)\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n\n // Add nested schema notation if applicable\n if (key in nestedSchemas) {\n const schemaKeys = nestedSchemas[key]!;\n const schemaStr = schemaKeys.join(',');\n keyStr = `${keyStr}(@${schemaStr})`;\n }\n\n keyParts.push(keyStr);\n }\n\n const keysStr = keyParts.join(',');\n\n // Format rows\n const rowParts: string[] = [];\n for (const obj of arr) {\n const valueParts: string[] = [];\n for (const key of keys) {\n const value = obj[key];\n\n // If this key has a nested schema, serialize as schematized object\n if (key in nestedSchemas) {\n valueParts.push(serializeSchematizedObject(value as TSONObject, nestedSchemas[key]!));\n } else {\n valueParts.push(serializeValue(value));\n }\n }\n rowParts.push(valueParts.join(','));\n }\n\n const rowsStr = rowParts.join('|');\n\n return `{@${keysStr}#${count}|${rowsStr}}`;\n}\n\n/**\n * Detect if any fields contain uniform nested objects that can use schema notation.\n *\n * For each key, checks if all values are objects with identical keys.\n * If so, that field can use nested schema notation.\n */\nexport function detectNestedSchemas(arr: TSONObject[], keys: string[]): SchemaMap {\n const nestedSchemas: SchemaMap = {};\n\n for (const key of keys) {\n // Get all values for this key\n const values = arr.map(obj => obj[key]);\n\n // Check if all values are plain objects\n if (!values.every(v => typeof v === 'object' && v !== null && !Array.isArray(v))) {\n continue;\n }\n\n if (values.length === 0) {\n continue;\n }\n\n // Check if all objects have the same keys\n const firstKeys = Object.keys(values[0] as TSONObject);\n const allSame = values.slice(1).every(v => {\n const objKeys = Object.keys(v as TSONObject);\n return (\n objKeys.length === firstKeys.length &&\n objKeys.every((k, i) => k === firstKeys[i])\n );\n });\n\n if (allSame) {\n // This field can use nested schema\n nestedSchemas[key] = firstKeys;\n }\n }\n\n return nestedSchemas;\n}\n\n/**\n * Serialize an object using a pre-declared schema.\n *\n * Format: {value1,value2} (no @ marker, values only)\n *\n * The @ marker is omitted because the schema was already declared in the\n * parent structure.\n */\nexport function serializeSchematizedObject(obj: TSONObject, schema: string[]): string {\n if (Object.keys(obj).length === 0) {\n return '{}';\n }\n\n // Serialize values in schema order\n const valueParts: string[] = [];\n for (const key of schema) {\n const value = obj[key];\n valueParts.push(serializeValue(value));\n }\n\n return '{' + valueParts.join(',') + '}';\n}\n","/**\n * TSON Deserializer\n *\n * Parses TSON format back to JavaScript data structures.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n parsePrimitive,\n splitByDelimiter,\n buildSchemaMap,\n parseKeys,\n} from './utils';\n\n/**\n * Deserialize TSON formatted string to JavaScript object.\n *\n * @example\n * loads('{@name,age|Alice,30}')\n * // Returns: { name: 'Alice', age: 30 }\n *\n * @example\n * loads('{@id,name#2|1,Alice|2,Bob}')\n * // Returns: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]\n */\nexport function loads(s: string): TSONValue {\n const trimmed = s.trim();\n if (trimmed.length === 0) {\n return null;\n }\n\n return parseValue(trimmed);\n}\n\n/**\n * Deserialize TSON formatted file to JavaScript object (Node.js only).\n *\n * @param filePath - Path to file to read\n * @returns Parsed JavaScript object\n */\nexport async function load(filePath: string): Promise<TSONValue> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n const content = await fs.readFile(filePath, 'utf-8');\n return loads(content);\n}\n\n/**\n * Parse a TSON value of any type.\n *\n * Determines the type by looking at the first character and dispatches\n * to the appropriate parser.\n */\nexport function parseValue(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check first character to determine type\n const firstChar = trimmed[0];\n\n if (firstChar === '{') {\n // Object (with @ marker) or schematized object\n return parseObject(trimmed);\n } else if (firstChar === '[') {\n // Array\n return parseArray(trimmed);\n } else {\n // Primitive value\n return parsePrimitive(trimmed);\n }\n}\n\n/**\n * Parse TSON object format.\n *\n * Handles both:\n * - {@key1,key2|val1,val2} - Single object or array of objects\n * - {val1,val2} - Schematized object (no @ marker)\n */\nexport function parseObject(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Invalid object format: ${text}`);\n }\n\n // Extract content between braces\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content === '@' || content === '') {\n return {};\n }\n\n // Check if this has @ marker (object with keys)\n if (content.startsWith('@')) {\n return parseKeyedObject(content.slice(1)); // Remove @ marker\n } else {\n // Schematized object without @ marker (just values)\n // This shouldn't happen at top level but can occur as nested value\n // Parse as comma-separated values\n const values = splitByDelimiter(content, ',');\n const parsedValues = values.map(v => parseValue(v));\n\n // Return as array (since we don't have keys)\n // In practice, this shouldn't be hit at top level\n return parsedValues;\n }\n}\n\n/**\n * Parse content after @ marker in object.\n *\n * Format: key1,key2|val1,val2 or key1,key2#N|val1,val2|val1,val2\n */\nexport function parseKeyedObject(content: string): TSONValue {\n // Split by pipe to separate keys from values\n const parts = splitByDelimiter(content, '|');\n\n if (parts.length < 1) {\n throw new Error('Invalid object format: missing keys');\n }\n\n // First part contains keys (and possibly row count)\n const keysPart = parts[0];\n\n // Parse keys and extract count if present\n const { keys, count } = parseKeys(keysPart);\n\n // Build schema map (maps field names to nested schemas)\n const schemaMap = buildSchemaMap(keys);\n\n // Get actual field names (without schema notation)\n const fieldNames = keys.map(k => k.split('(')[0]);\n\n // If only one part, it's an error (no values)\n if (parts.length === 1) {\n throw new Error('Invalid object format: missing values');\n }\n\n // If two parts, could be single object or array with one row\n // If more than two parts, definitely array (multiple rows)\n const valueParts = parts.slice(1);\n\n // Check if this is tabular format (array) or single object\n // If count is specified or multiple value parts, it's tabular\n const isTabular = count !== null || valueParts.length > 1;\n\n if (isTabular) {\n // Array of objects (tabular format)\n return parseTabularArray(fieldNames, valueParts, schemaMap, count);\n } else {\n // Single object\n return parseSingleObject(fieldNames, valueParts[0], schemaMap);\n }\n}\n\n/**\n * Parse a single object from keys and values.\n */\nexport function parseSingleObject(\n fieldNames: string[],\n valuesStr: string,\n schemaMap: SchemaMap\n): TSONObject {\n // Split values\n const values = splitByDelimiter(valuesStr, ',');\n\n if (values.length !== fieldNames.length) {\n throw new Error(\n `Field count mismatch: ${fieldNames.length} fields but ${values.length} values`\n );\n }\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field has a nested schema\n const schema = schemaMap[fieldName];\n\n if (schema) {\n // Parse as schematized object\n obj[fieldName] = parseSchematizedValue(valueStr, schema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse tabular format into array of objects.\n */\nexport function parseTabularArray(\n fieldNames: string[],\n rowParts: string[],\n schemaMap: SchemaMap,\n expectedCount: number | null\n): TSONObject[] {\n const result: TSONObject[] = [];\n\n for (const rowStr of rowParts) {\n if (rowStr.trim().length === 0) {\n continue;\n }\n\n const obj = parseSingleObject(fieldNames, rowStr, schemaMap);\n result.push(obj);\n }\n\n // Verify count if specified\n if (expectedCount !== null && result.length !== expectedCount) {\n throw new Error(\n `Row count mismatch: expected ${expectedCount} rows but got ${result.length}`\n );\n }\n\n return result;\n}\n\n/**\n * Parse a value that uses a nested schema.\n *\n * The value should be in format {val1,val2} where values correspond to\n * the keys in the schema.\n */\nexport function parseSchematizedValue(valueStr: string, schema: string[]): TSONObject {\n const trimmed = valueStr.trim();\n\n // Should be wrapped in braces\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Schematized value must be wrapped in braces: ${valueStr}`);\n }\n\n // Extract content\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content.length === 0) {\n return {};\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n if (values.length !== schema.length) {\n throw new Error(\n `Schema mismatch: ${schema.length} keys but ${values.length} values`\n );\n }\n\n // Build nested schema map for recursive schemas\n const nestedSchemaMap = buildSchemaMap(schema);\n\n // Get field names (without schema notation)\n const fieldNames = schema.map(k => k.split('(')[0]);\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field itself has a nested schema\n const nestedSchema = nestedSchemaMap[fieldName];\n\n if (nestedSchema) {\n // Recursively parse with nested schema\n obj[fieldName] = parseSchematizedValue(valueStr, nestedSchema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function parseArray(text: string): TSONArray {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('[') || !trimmed.endsWith(']')) {\n throw new Error(`Invalid array format: ${text}`);\n }\n\n // Extract content between brackets\n const content = trimmed.slice(1, -1).trim();\n\n // Empty array\n if (content.length === 0) {\n return [];\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n // Parse each value\n const result: TSONArray = [];\n for (const valueStr of values) {\n if (valueStr.trim().length > 0) {\n // Skip empty strings from trailing commas\n result.push(parseValue(valueStr));\n }\n }\n\n return result;\n}\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/serializer.ts","../src/deserializer.ts"],"names":["keys","valueStr"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * TSON Utility Functions\n *\n * Helper functions for serialization, deserialization, and validation.\n */\n\nimport type { TSONValue, TSONObject, SchemaMap, KeySchema, ParsedKeys } from './types';\n\n/**\n * Special characters that require string quoting\n */\nexport const SPECIAL_CHARS = new Set([',', '|', '@', '#', '{', '}', '[', ']', '\\n', '\\r', '\\t', ' ', '\"', '(', ')']);\n\n/**\n * Determine if a string value needs to be quoted in TSON format.\n *\n * Strings need quoting if they:\n * - Are empty\n * - Contain special delimiter characters\n * - Have leading/trailing whitespace\n * - Look like numbers (to preserve them as strings)\n * - Look like reserved words (true/false/null) when we want them as strings\n */\nexport function needsQuoting(value: string): boolean {\n if (value.length === 0) {\n return true;\n }\n\n // Check for reserved words that we want to keep as strings\n if (value === 'true' || value === 'false' || value === 'null') {\n return true;\n }\n\n // Check for leading/trailing whitespace\n if (value[0].trim() === '' || value[value.length - 1].trim() === '') {\n return true;\n }\n\n // Check if it looks like a number (preserve type distinction)\n if (looksLikeNumber(value)) {\n return true;\n }\n\n // Check for special characters\n for (const char of value) {\n if (SPECIAL_CHARS.has(char)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if a string looks like a numeric value.\n *\n * Used to determine if we should quote a string to preserve it as a string\n * rather than having it parsed as a number.\n */\nexport function looksLikeNumber(value: string): boolean {\n if (value.length === 0) {\n return false;\n }\n\n // Try parsing as number\n const num = Number(value);\n return !isNaN(num) && value.trim() === value && isFinite(num);\n}\n\n/**\n * Escape special characters in a string for quoted representation.\n *\n * Uses standard JSON escape sequences.\n */\nexport function escapeString(value: string): string {\n // Order matters: backslash first to avoid double-escaping\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\n/**\n * Unescape a quoted string back to its original form.\n *\n * Reverses the escaping done by escapeString().\n * Must process character by character to handle sequences like \\\\n correctly.\n */\nexport function unescapeString(value: string): string {\n const result: string[] = [];\n let i = 0;\n while (i < value.length) {\n if (value[i] === '\\\\' && i + 1 < value.length) {\n const nextChar = value[i + 1];\n if (nextChar === '\\\\') {\n result.push('\\\\');\n i += 2;\n } else if (nextChar === '\"') {\n result.push('\"');\n i += 2;\n } else if (nextChar === 'n') {\n result.push('\\n');\n i += 2;\n } else if (nextChar === 'r') {\n result.push('\\r');\n i += 2;\n } else if (nextChar === 't') {\n result.push('\\t');\n i += 2;\n } else {\n // Unknown escape, keep as-is\n result.push(value[i]);\n i += 1;\n }\n } else {\n result.push(value[i]);\n i += 1;\n }\n }\n return result.join('');\n}\n\n/**\n * Format a primitive value as TSON string.\n */\nexport function formatPrimitive(value: TSONValue): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n return String(value);\n }\n\n if (typeof value === 'string') {\n if (needsQuoting(value)) {\n return `\"${escapeString(value)}\"`;\n }\n return value;\n }\n\n throw new Error(`Cannot format non-primitive type: ${typeof value}`);\n}\n\n/**\n * Parse a TSON primitive value string to JavaScript type.\n */\nexport function parsePrimitive(value: string): TSONValue {\n const trimmed = value.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check for boolean\n if (trimmed === 'true') {\n return true;\n }\n if (trimmed === 'false') {\n return false;\n }\n\n // Check for null\n if (trimmed === 'null') {\n return null;\n }\n\n // Check for quoted string\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeString(trimmed.slice(1, -1));\n }\n\n // Try to parse as number\n if (looksLikeNumber(trimmed)) {\n const num = Number(trimmed);\n if (!isNaN(num)) {\n return num;\n }\n }\n\n // Otherwise it's an unquoted string\n return trimmed;\n}\n\n/**\n * Check if a value is an array of objects with identical keys.\n *\n * This determines if we can use tabular format optimization.\n */\nexport function isUniformObjectArray(data: unknown): data is TSONObject[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n // All elements must be plain objects\n if (!data.every(item => isPlainObject(item))) {\n return false;\n }\n\n // Get keys from first element\n const firstKeys = Object.keys(data[0]);\n\n // Check that all elements have the same keys in the same order\n for (let i = 1; i < data.length; i++) {\n const keys = Object.keys(data[i]);\n if (keys.length !== firstKeys.length) {\n return false;\n }\n for (let j = 0; j < keys.length; j++) {\n if (keys[j] !== firstKeys[j]) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Check if value is a plain object (not array, null, or other special object)\n */\nfunction isPlainObject(value: unknown): value is TSONObject {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.prototype.toString.call(value) === '[object Object]'\n );\n}\n\n/**\n * Split text by delimiter, respecting quoted strings and nested structures.\n *\n * This is more sophisticated than string.split() because it handles:\n * - Quoted strings (don't split on delimiters inside quotes)\n * - Nested braces/brackets/parentheses (don't split inside nested structures)\n * - Escaped characters\n */\nexport function splitByDelimiter(text: string, delimiter: string): string[] {\n const result: string[] = [];\n const current: string[] = [];\n let inQuotes = false;\n let escapeNext = false;\n let depthCurly = 0;\n let depthSquare = 0;\n let depthParen = 0;\n\n for (const char of text) {\n // Handle escape sequences\n if (escapeNext) {\n current.push(char);\n escapeNext = false;\n continue;\n }\n\n if (char === '\\\\') {\n current.push(char);\n escapeNext = true;\n continue;\n }\n\n // Handle quotes\n if (char === '\"') {\n inQuotes = !inQuotes;\n current.push(char);\n continue;\n }\n\n // Inside quotes, add everything\n if (inQuotes) {\n current.push(char);\n continue;\n }\n\n // Track nesting depth\n if (char === '{') {\n depthCurly++;\n current.push(char);\n } else if (char === '}') {\n depthCurly--;\n current.push(char);\n } else if (char === '[') {\n depthSquare++;\n current.push(char);\n } else if (char === ']') {\n depthSquare--;\n current.push(char);\n } else if (char === '(') {\n depthParen++;\n current.push(char);\n } else if (char === ')') {\n depthParen--;\n current.push(char);\n } else if (\n char === delimiter &&\n depthCurly === 0 &&\n depthSquare === 0 &&\n depthParen === 0\n ) {\n // Found unquoted, unnested delimiter - split here\n result.push(current.join('').trim());\n current.length = 0;\n } else {\n current.push(char);\n }\n }\n\n // Add final segment\n if (current.length > 0) {\n result.push(current.join('').trim());\n }\n\n return result;\n}\n\n/**\n * Parse a key which may include nested schema notation.\n *\n * Examples:\n * \"name\" -> { keyName: \"name\", schema: null }\n * \"address(@city,zip)\" -> { keyName: \"address\", schema: [\"city\", \"zip\"] }\n * \"location(@coords(@lat,lng))\" -> { keyName: \"location\", schema: [\"coords(@lat,lng)\"] }\n */\nexport function parseKeySchema(keyString: string): KeySchema {\n const trimmed = keyString.trim();\n\n // If the entire key is quoted, it's a simple key (any parens inside are literal)\n // Must check this BEFORE looking for '(' to handle keys like \"company(\"\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return { keyName: unescapeString(trimmed.slice(1, -1)), schema: null };\n }\n\n // Check if key has nested schema (only for unquoted keys)\n if (!trimmed.includes('(')) {\n return { keyName: trimmed, schema: null };\n }\n\n // Find the opening parenthesis\n const parenIdx = trimmed.indexOf('(');\n let keyName = trimmed.slice(0, parenIdx).trim();\n\n // Unquote the key name if it's quoted\n if (keyName.startsWith('\"') && keyName.endsWith('\"')) {\n keyName = unescapeString(keyName.slice(1, -1));\n }\n\n // Extract schema (everything between outermost parentheses)\n if (!trimmed.endsWith(')')) {\n throw new Error(`Invalid key schema syntax: ${keyString}`);\n }\n\n let schemaStr = trimmed.slice(parenIdx + 1, -1).trim();\n\n // Strip leading @ if present (part of notation, not key name)\n if (schemaStr.startsWith('@')) {\n schemaStr = schemaStr.slice(1);\n }\n\n // Split schema by commas (respecting nested parentheses)\n const schemaKeys = splitByDelimiter(schemaStr, ',');\n\n return { keyName, schema: schemaKeys };\n}\n\n/**\n * Build a mapping of field names to their nested schemas.\n *\n * Example:\n * [\"id\", \"address(@city,zip)\"]\n * -> { id: null, address: [\"city\", \"zip\"] }\n */\nexport function buildSchemaMap(keys: string[]): SchemaMap {\n const schemaMap: SchemaMap = {};\n\n for (const key of keys) {\n const { keyName, schema } = parseKeySchema(key);\n schemaMap[keyName] = schema;\n }\n\n return schemaMap;\n}\n\n/**\n * Parse keys string and extract row count if present.\n *\n * Format: key1,key2,key3 or key1,key2,key3#N\n */\nexport function parseKeys(keysStr: string): ParsedKeys {\n // Check for row count marker, respecting quotes\n let hashIdx = -1;\n let inQuotes = false;\n\n // Scan backwards to find the last # that is NOT inside quotes\n for (let i = keysStr.length - 1; i >= 0; i--) {\n const char = keysStr[i];\n\n if (char === '\"') {\n // Check for escaped quote (count preceding backslashes)\n let backslashCount = 0;\n for (let j = i - 1; j >= 0; j--) {\n if (keysStr[j] === '\\\\') {\n backslashCount++;\n } else {\n break;\n }\n }\n\n // If even number of backslashes, it's a real quote\n if (backslashCount % 2 === 0) {\n inQuotes = !inQuotes;\n }\n }\n\n if (char === '#' && !inQuotes) {\n hashIdx = i;\n break;\n }\n }\n\n if (hashIdx !== -1) {\n // Found separator\n const keysPart = keysStr.slice(0, hashIdx);\n const countPart = keysStr.slice(hashIdx + 1).trim();\n\n const count = parseInt(countPart, 10);\n if (isNaN(count)) {\n // If it's not a valid number, ignore the hash (treat as part of key)\n // This handles edge cases where # might appear unquoted but not as separator\n // though strictly that should be quoted according to spec.\n // Fallback to normal parsing\n const keys = splitByDelimiter(keysStr, ',');\n return { keys, count: null };\n }\n\n const keys = splitByDelimiter(keysPart, ',');\n return { keys, count };\n } else {\n const keys = splitByDelimiter(keysStr, ',');\n return { keys, count: null };\n }\n}\n","/**\n * TSON Serializer\n *\n * Converts JavaScript data structures to TSON format.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n formatPrimitive,\n needsQuoting,\n escapeString,\n isUniformObjectArray,\n} from './utils';\n\n/**\n * Serialize JavaScript object to TSON formatted string.\n *\n * @example\n * dumps({ name: \"Alice\", age: 30 })\n * // Returns: '{@name,age|Alice,30}'\n *\n * @example\n * dumps([{ id: 1, name: \"Alice\" }, { id: 2, name: \"Bob\" }])\n * // Returns: '{@id,name#2|1,Alice|2,Bob}'\n */\nexport function dumps(data: TSONValue): string {\n return serializeValue(data);\n}\n\n/**\n * Serialize JavaScript object to TSON formatted file (Node.js only).\n *\n * @param data - JavaScript object to serialize\n * @param filePath - Path to file to write\n */\nexport async function dump(data: TSONValue, filePath: string): Promise<void> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n await fs.writeFile(filePath, dumps(data), 'utf-8');\n}\n\n/**\n * Serialize any JavaScript value to TSON format.\n *\n * Dispatches to appropriate serializer based on type.\n */\nexport function serializeValue(value: TSONValue): string {\n // Handle primitives\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string'\n ) {\n return formatPrimitive(value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n // Check if it's a uniform array of objects (tabular optimization)\n if (isUniformObjectArray(value)) {\n return serializeTabular(value);\n } else {\n return serializeArray(value);\n }\n }\n\n // Handle objects\n if (typeof value === 'object' && value !== null) {\n return serializeObject(value as TSONObject);\n }\n\n throw new TypeError(`Cannot serialize type: ${typeof value}`);\n}\n\n/**\n * Serialize a JavaScript object to TSON object format.\n *\n * Format: {@key1,key2|value1,value2}\n */\nexport function serializeObject(obj: TSONObject): string {\n const keys = Object.keys(obj);\n\n if (keys.length === 0) {\n return '{@}';\n }\n\n // Format keys\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n keyParts.push(keyStr);\n }\n\n // Format values\n const valueParts: string[] = [];\n for (const key of keys) {\n valueParts.push(serializeValue(obj[key]));\n }\n\n // Build object string\n const keysStr = keyParts.join(',');\n const valuesStr = valueParts.join(',');\n\n return `{@${keysStr}|${valuesStr}}`;\n}\n\n/**\n * Serialize a JavaScript array to TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function serializeArray(arr: TSONArray): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n // Serialize each element\n const valueParts: string[] = [];\n for (const value of arr) {\n valueParts.push(serializeValue(value));\n }\n\n return '[' + valueParts.join(',') + ']';\n}\n\n/**\n * Serialize a uniform array of objects in tabular format.\n *\n * Format: {@key1,key2#N|val1,val2|val1,val2}\n *\n * This is the key optimization: keys are declared once instead of repeated\n * for each object in the array.\n */\nexport function serializeTabular(arr: TSONObject[]): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n if (!isUniformObjectArray(arr)) {\n throw new Error('Array is not uniform - cannot use tabular format');\n }\n\n // Get keys from first object\n const keys = Object.keys(arr[0]);\n const count = arr.length;\n\n // Check if any values are objects with uniform structure (nested schema opportunity)\n const nestedSchemas = detectNestedSchemas(arr, keys);\n\n // Format keys (with nested schemas if applicable)\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n\n // Add nested schema notation if applicable\n if (key in nestedSchemas) {\n const schemaKeys = nestedSchemas[key]!;\n // Quote schema keys that need quoting (contain special chars)\n const formattedSchemaKeys = schemaKeys.map(sk => {\n if (needsQuoting(sk)) {\n return `\"${escapeString(sk)}\"`;\n }\n return sk;\n });\n const schemaStr = formattedSchemaKeys.join(',');\n keyStr = `${keyStr}(@${schemaStr})`;\n }\n\n keyParts.push(keyStr);\n }\n\n const keysStr = keyParts.join(',');\n\n // Format rows\n const rowParts: string[] = [];\n for (const obj of arr) {\n const valueParts: string[] = [];\n for (const key of keys) {\n const value = obj[key];\n\n // If this key has a nested schema, serialize as schematized object\n if (key in nestedSchemas) {\n valueParts.push(serializeSchematizedObject(value as TSONObject, nestedSchemas[key]!));\n } else {\n valueParts.push(serializeValue(value));\n }\n }\n rowParts.push(valueParts.join(','));\n }\n\n const rowsStr = rowParts.join('|');\n\n return `{@${keysStr}#${count}|${rowsStr}}`;\n}\n\n/**\n * Detect if any fields contain uniform nested objects that can use schema notation.\n *\n * For each key, checks if all values are objects with identical keys.\n * If so, that field can use nested schema notation.\n */\nexport function detectNestedSchemas(arr: TSONObject[], keys: string[]): SchemaMap {\n const nestedSchemas: SchemaMap = {};\n\n for (const key of keys) {\n // Get all values for this key\n const values = arr.map(obj => obj[key]);\n\n // Check if all values are plain objects\n if (!values.every(v => typeof v === 'object' && v !== null && !Array.isArray(v))) {\n continue;\n }\n\n if (values.length === 0) {\n continue;\n }\n\n // Check if all objects have the same keys\n const firstKeys = Object.keys(values[0] as TSONObject);\n const allSame = values.slice(1).every(v => {\n const objKeys = Object.keys(v as TSONObject);\n return (\n objKeys.length === firstKeys.length &&\n objKeys.every((k, i) => k === firstKeys[i])\n );\n });\n\n if (allSame) {\n // This field can use nested schema\n nestedSchemas[key] = firstKeys;\n }\n }\n\n return nestedSchemas;\n}\n\n/**\n * Serialize an object using a pre-declared schema.\n *\n * Format: {value1,value2} (no @ marker, values only)\n *\n * The @ marker is omitted because the schema was already declared in the\n * parent structure.\n */\nexport function serializeSchematizedObject(obj: TSONObject, schema: string[]): string {\n if (Object.keys(obj).length === 0) {\n return '{}';\n }\n\n // Serialize values in schema order\n const valueParts: string[] = [];\n for (const key of schema) {\n const value = obj[key];\n valueParts.push(serializeValue(value));\n }\n\n return '{' + valueParts.join(',') + '}';\n}\n","/**\n * TSON Deserializer\n *\n * Parses TSON format back to JavaScript data structures.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n parsePrimitive,\n splitByDelimiter,\n buildSchemaMap,\n parseKeys,\n parseKeySchema,\n} from './utils';\n\n/**\n * Deserialize TSON formatted string to JavaScript object.\n *\n * @example\n * loads('{@name,age|Alice,30}')\n * // Returns: { name: 'Alice', age: 30 }\n *\n * @example\n * loads('{@id,name#2|1,Alice|2,Bob}')\n * // Returns: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]\n */\nexport function loads(s: string): TSONValue {\n const trimmed = s.trim();\n if (trimmed.length === 0) {\n return null;\n }\n\n return parseValue(trimmed);\n}\n\n/**\n * Deserialize TSON formatted file to JavaScript object (Node.js only).\n *\n * @param filePath - Path to file to read\n * @returns Parsed JavaScript object\n */\nexport async function load(filePath: string): Promise<TSONValue> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n const content = await fs.readFile(filePath, 'utf-8');\n return loads(content);\n}\n\n/**\n * Parse a TSON value of any type.\n *\n * Determines the type by looking at the first character and dispatches\n * to the appropriate parser.\n */\nexport function parseValue(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check first character to determine type\n const firstChar = trimmed[0];\n\n if (firstChar === '{') {\n // Object (with @ marker) or schematized object\n return parseObject(trimmed);\n } else if (firstChar === '[') {\n // Array\n return parseArray(trimmed);\n } else {\n // Primitive value\n return parsePrimitive(trimmed);\n }\n}\n\n/**\n * Parse TSON object format.\n *\n * Handles both:\n * - {@key1,key2|val1,val2} - Single object or array of objects\n * - {val1,val2} - Schematized object (no @ marker)\n */\nexport function parseObject(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Invalid object format: ${text}`);\n }\n\n // Extract content between braces\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content === '@' || content === '') {\n return {};\n }\n\n // Check if this has @ marker (object with keys)\n if (content.startsWith('@')) {\n return parseKeyedObject(content.slice(1)); // Remove @ marker\n } else {\n // Schematized object without @ marker (just values)\n // This shouldn't happen at top level but can occur as nested value\n // Parse as comma-separated values\n const values = splitByDelimiter(content, ',');\n const parsedValues = values.map(v => parseValue(v));\n\n // Return as array (since we don't have keys)\n // In practice, this shouldn't be hit at top level\n return parsedValues;\n }\n}\n\n/**\n * Parse content after @ marker in object.\n *\n * Format: key1,key2|val1,val2 or key1,key2#N|val1,val2|val1,val2\n */\nexport function parseKeyedObject(content: string): TSONValue {\n // Split by pipe to separate keys from values\n const parts = splitByDelimiter(content, '|');\n\n if (parts.length < 1) {\n throw new Error('Invalid object format: missing keys');\n }\n\n // First part contains keys (and possibly row count)\n const keysPart = parts[0];\n\n // Parse keys and extract count if present\n const { keys, count } = parseKeys(keysPart);\n\n // Build schema map (maps field names to nested schemas)\n const schemaMap = buildSchemaMap(keys);\n\n // Get actual field names (without schema notation)\n const fieldNames = keys.map(k => parseKeySchema(k).keyName);\n\n // If only one part, it's an error (no values)\n if (parts.length === 1) {\n throw new Error('Invalid object format: missing values');\n }\n\n // If two parts, could be single object or array with one row\n // If more than two parts, definitely array (multiple rows)\n const valueParts = parts.slice(1);\n\n // Check if this is tabular format (array) or single object\n // If count is specified or multiple value parts, it's tabular\n const isTabular = count !== null || valueParts.length > 1;\n\n if (isTabular) {\n // Array of objects (tabular format)\n return parseTabularArray(fieldNames, valueParts, schemaMap, count);\n } else {\n // Single object\n return parseSingleObject(fieldNames, valueParts[0], schemaMap);\n }\n}\n\n/**\n * Parse a single object from keys and values.\n */\nexport function parseSingleObject(\n fieldNames: string[],\n valuesStr: string,\n schemaMap: SchemaMap\n): TSONObject {\n // Split values\n const values = splitByDelimiter(valuesStr, ',');\n\n if (values.length !== fieldNames.length) {\n throw new Error(\n `Field count mismatch: ${fieldNames.length} fields but ${values.length} values`\n );\n }\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field has a nested schema\n const schema = schemaMap[fieldName];\n\n if (schema) {\n // Parse as schematized object\n obj[fieldName] = parseSchematizedValue(valueStr, schema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse tabular format into array of objects.\n */\nexport function parseTabularArray(\n fieldNames: string[],\n rowParts: string[],\n schemaMap: SchemaMap,\n expectedCount: number | null\n): TSONObject[] {\n const result: TSONObject[] = [];\n\n for (const rowStr of rowParts) {\n if (rowStr.trim().length === 0) {\n continue;\n }\n\n const obj = parseSingleObject(fieldNames, rowStr, schemaMap);\n result.push(obj);\n }\n\n // Verify count if specified\n if (expectedCount !== null && result.length !== expectedCount) {\n throw new Error(\n `Row count mismatch: expected ${expectedCount} rows but got ${result.length}`\n );\n }\n\n return result;\n}\n\n/**\n * Parse a value that uses a nested schema.\n *\n * The value should be in format {val1,val2} where values correspond to\n * the keys in the schema.\n */\nexport function parseSchematizedValue(valueStr: string, schema: string[]): TSONObject {\n const trimmed = valueStr.trim();\n\n // Should be wrapped in braces\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Schematized value must be wrapped in braces: ${valueStr}`);\n }\n\n // Extract content\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content.length === 0) {\n return {};\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n if (values.length !== schema.length) {\n throw new Error(\n `Schema mismatch: ${schema.length} keys but ${values.length} values`\n );\n }\n\n // Build nested schema map for recursive schemas\n const nestedSchemaMap = buildSchemaMap(schema);\n\n // Get field names (without schema notation)\n const fieldNames = schema.map(k => parseKeySchema(k).keyName);\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field itself has a nested schema\n const nestedSchema = nestedSchemaMap[fieldName];\n\n if (nestedSchema) {\n // Recursively parse with nested schema\n obj[fieldName] = parseSchematizedValue(valueStr, nestedSchema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function parseArray(text: string): TSONArray {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('[') || !trimmed.endsWith(']')) {\n throw new Error(`Invalid array format: ${text}`);\n }\n\n // Extract content between brackets\n const content = trimmed.slice(1, -1).trim();\n\n // Empty array\n if (content.length === 0) {\n return [];\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n // Parse each value\n const result: TSONArray = [];\n for (const valueStr of values) {\n if (valueStr.trim().length > 0) {\n // Skip empty strings from trailing commas\n result.push(parseValue(valueStr));\n }\n }\n\n return result;\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -127,6 +127,7 @@ declare function escapeString(value: string): string;
127
127
  * Unescape a quoted string back to its original form.
128
128
  *
129
129
  * Reverses the escaping done by escapeString().
130
+ * Must process character by character to handle sequences like \\n correctly.
130
131
  */
131
132
  declare function unescapeString(value: string): string;
132
133
  /**
package/dist/index.d.ts CHANGED
@@ -127,6 +127,7 @@ declare function escapeString(value: string): string;
127
127
  * Unescape a quoted string back to its original form.
128
128
  *
129
129
  * Reverses the escaping done by escapeString().
130
+ * Must process character by character to handle sequences like \\n correctly.
130
131
  */
131
132
  declare function unescapeString(value: string): string;
132
133
  /**
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/utils.ts
2
- var SPECIAL_CHARS = /* @__PURE__ */ new Set([",", "|", "@", "#", "{", "}", "[", "]", "\n", "\r", " ", " "]);
2
+ var SPECIAL_CHARS = /* @__PURE__ */ new Set([",", "|", "@", "#", "{", "}", "[", "]", "\n", "\r", " ", " ", '"', "(", ")"]);
3
3
  function needsQuoting(value) {
4
4
  if (value.length === 0) {
5
5
  return true;
@@ -31,7 +31,36 @@ function escapeString(value) {
31
31
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
32
32
  }
33
33
  function unescapeString(value) {
34
- return value.replace(/\\t/g, " ").replace(/\\r/g, "\r").replace(/\\n/g, "\n").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
34
+ const result = [];
35
+ let i = 0;
36
+ while (i < value.length) {
37
+ if (value[i] === "\\" && i + 1 < value.length) {
38
+ const nextChar = value[i + 1];
39
+ if (nextChar === "\\") {
40
+ result.push("\\");
41
+ i += 2;
42
+ } else if (nextChar === '"') {
43
+ result.push('"');
44
+ i += 2;
45
+ } else if (nextChar === "n") {
46
+ result.push("\n");
47
+ i += 2;
48
+ } else if (nextChar === "r") {
49
+ result.push("\r");
50
+ i += 2;
51
+ } else if (nextChar === "t") {
52
+ result.push(" ");
53
+ i += 2;
54
+ } else {
55
+ result.push(value[i]);
56
+ i += 1;
57
+ }
58
+ } else {
59
+ result.push(value[i]);
60
+ i += 1;
61
+ }
62
+ }
63
+ return result.join("");
35
64
  }
36
65
  function formatPrimitive(value) {
37
66
  if (value === null) {
@@ -160,11 +189,17 @@ function splitByDelimiter(text, delimiter) {
160
189
  }
161
190
  function parseKeySchema(keyString) {
162
191
  const trimmed = keyString.trim();
192
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
193
+ return { keyName: unescapeString(trimmed.slice(1, -1)), schema: null };
194
+ }
163
195
  if (!trimmed.includes("(")) {
164
196
  return { keyName: trimmed, schema: null };
165
197
  }
166
198
  const parenIdx = trimmed.indexOf("(");
167
- const keyName = trimmed.slice(0, parenIdx).trim();
199
+ let keyName = trimmed.slice(0, parenIdx).trim();
200
+ if (keyName.startsWith('"') && keyName.endsWith('"')) {
201
+ keyName = unescapeString(keyName.slice(1, -1));
202
+ }
168
203
  if (!trimmed.endsWith(")")) {
169
204
  throw new Error(`Invalid key schema syntax: ${keyString}`);
170
205
  }
@@ -184,13 +219,35 @@ function buildSchemaMap(keys) {
184
219
  return schemaMap;
185
220
  }
186
221
  function parseKeys(keysStr) {
187
- if (keysStr.includes("#")) {
188
- const lastHashIdx = keysStr.lastIndexOf("#");
189
- const keysPart = keysStr.slice(0, lastHashIdx);
190
- const countPart = keysStr.slice(lastHashIdx + 1).trim();
222
+ let hashIdx = -1;
223
+ let inQuotes = false;
224
+ for (let i = keysStr.length - 1; i >= 0; i--) {
225
+ const char = keysStr[i];
226
+ if (char === '"') {
227
+ let backslashCount = 0;
228
+ for (let j = i - 1; j >= 0; j--) {
229
+ if (keysStr[j] === "\\") {
230
+ backslashCount++;
231
+ } else {
232
+ break;
233
+ }
234
+ }
235
+ if (backslashCount % 2 === 0) {
236
+ inQuotes = !inQuotes;
237
+ }
238
+ }
239
+ if (char === "#" && !inQuotes) {
240
+ hashIdx = i;
241
+ break;
242
+ }
243
+ }
244
+ if (hashIdx !== -1) {
245
+ const keysPart = keysStr.slice(0, hashIdx);
246
+ const countPart = keysStr.slice(hashIdx + 1).trim();
191
247
  const count = parseInt(countPart, 10);
192
248
  if (isNaN(count)) {
193
- throw new Error(`Invalid row count: ${countPart}`);
249
+ const keys2 = splitByDelimiter(keysStr, ",");
250
+ return { keys: keys2, count: null };
194
251
  }
195
252
  const keys = splitByDelimiter(keysPart, ",");
196
253
  return { keys, count };
@@ -273,7 +330,13 @@ function serializeTabular(arr) {
273
330
  }
274
331
  if (key in nestedSchemas) {
275
332
  const schemaKeys = nestedSchemas[key];
276
- const schemaStr = schemaKeys.join(",");
333
+ const formattedSchemaKeys = schemaKeys.map((sk) => {
334
+ if (needsQuoting(sk)) {
335
+ return `"${escapeString(sk)}"`;
336
+ }
337
+ return sk;
338
+ });
339
+ const schemaStr = formattedSchemaKeys.join(",");
277
340
  keyStr = `${keyStr}(@${schemaStr})`;
278
341
  }
279
342
  keyParts.push(keyStr);
@@ -380,7 +443,7 @@ function parseKeyedObject(content) {
380
443
  const keysPart = parts[0];
381
444
  const { keys, count } = parseKeys(keysPart);
382
445
  const schemaMap = buildSchemaMap(keys);
383
- const fieldNames = keys.map((k) => k.split("(")[0]);
446
+ const fieldNames = keys.map((k) => parseKeySchema(k).keyName);
384
447
  if (parts.length === 1) {
385
448
  throw new Error("Invalid object format: missing values");
386
449
  }
@@ -444,7 +507,7 @@ function parseSchematizedValue(valueStr, schema) {
444
507
  );
445
508
  }
446
509
  const nestedSchemaMap = buildSchemaMap(schema);
447
- const fieldNames = schema.map((k) => k.split("(")[0]);
510
+ const fieldNames = schema.map((k) => parseKeySchema(k).keyName);
448
511
  const obj = {};
449
512
  for (let i = 0; i < fieldNames.length; i++) {
450
513
  const fieldName = fieldNames[i];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/serializer.ts","../src/deserializer.ts"],"names":["valueStr"],"mappings":";AAWO,IAAM,gCAAgB,IAAI,GAAA,CAAI,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAA,EAAK,IAAA,EAAM,IAAA,EAAM,GAAA,EAAM,GAAG,CAAC,CAAA;AAY7F,SAAS,aAAa,KAAA,EAAwB;AACnD,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,KAAA,KAAU,MAAA,IAAU,KAAA,KAAU,OAAA,IAAW,UAAU,MAAA,EAAQ;AAC7D,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,EAAK,KAAM,EAAA,IAAM,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA,CAAE,IAAA,OAAW,EAAA,EAAI;AACnE,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,eAAA,CAAgB,KAAK,CAAA,EAAG;AAC1B,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,EAAG;AAC3B,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;AAQO,SAAS,gBAAgB,KAAA,EAAwB;AACtD,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,EAAA,OAAO,CAAC,MAAM,GAAG,CAAA,IAAK,MAAM,IAAA,EAAK,KAAM,KAAA,IAAS,QAAA,CAAS,GAAG,CAAA;AAC9D;AAOO,SAAS,aAAa,KAAA,EAAuB;AAElD,EAAA,OAAO,MACJ,OAAA,CAAQ,KAAA,EAAO,MAAM,CAAA,CACrB,OAAA,CAAQ,MAAM,KAAK,CAAA,CACnB,QAAQ,KAAA,EAAO,KAAK,EACpB,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA,CACpB,OAAA,CAAQ,OAAO,KAAK,CAAA;AACzB;AAOO,SAAS,eAAe,KAAA,EAAuB;AAEpD,EAAA,OAAO,MACJ,OAAA,CAAQ,MAAA,EAAQ,GAAI,CAAA,CACpB,OAAA,CAAQ,QAAQ,IAAI,CAAA,CACpB,QAAQ,MAAA,EAAQ,IAAI,EACpB,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,CACnB,OAAA,CAAQ,SAAS,IAAI,CAAA;AAC1B;AAKO,SAAS,gBAAgB,KAAA,EAA0B;AACxD,EAAA,IAAI,UAAU,IAAA,EAAM;AAClB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAO,UAAU,SAAA,EAAW;AAC9B,IAAA,OAAO,QAAQ,MAAA,GAAS,OAAA;AAAA,EAC1B;AAEA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AAEA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,IAAI,YAAA,CAAa,KAAK,CAAA,EAAG;AACvB,MAAA,OAAO,CAAA,CAAA,EAAI,YAAA,CAAa,KAAK,CAAC,CAAA,CAAA,CAAA;AAAA,IAChC;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,OAAO,KAAK,CAAA,CAAE,CAAA;AACrE;AAKO,SAAS,eAAe,KAAA,EAA0B;AACvD,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAE3B,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAA;AAAA,EACT;AAGA,EAAA,IAAI,YAAY,MAAA,EAAQ;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,YAAY,OAAA,EAAS;AACvB,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,YAAY,MAAA,EAAQ;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,QAAQ,UAAA,CAAW,GAAG,KAAK,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AACpD,IAAA,OAAO,cAAA,CAAe,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,EAC5C;AAGA,EAAA,IAAI,eAAA,CAAgB,OAAO,CAAA,EAAG;AAC5B,IAAA,MAAM,GAAA,GAAM,OAAO,OAAO,CAAA;AAC1B,IAAA,IAAI,CAAC,KAAA,CAAM,GAAG,CAAA,EAAG;AACf,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,OAAO,OAAA;AACT;AAOO,SAAS,qBAAqB,IAAA,EAAqC;AACxE,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,WAAW,CAAA,EAAG;AAC7C,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,CAAC,IAAA,CAAK,KAAA,CAAM,UAAQ,aAAA,CAAc,IAAI,CAAC,CAAA,EAAG;AAC5C,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,CAAC,CAAC,CAAA;AAGrC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACpC,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,CAAC,CAAC,CAAA;AAChC,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,SAAA,CAAU,MAAA,EAAQ;AACpC,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACpC,MAAA,IAAI,IAAA,CAAK,CAAC,CAAA,KAAM,SAAA,CAAU,CAAC,CAAA,EAAG;AAC5B,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,cAAc,KAAA,EAAqC;AAC1D,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,QACV,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,KACpB,MAAA,CAAO,SAAA,CAAU,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA,KAAM,iBAAA;AAE9C;AAUO,SAAS,gBAAA,CAAiB,MAAc,SAAA,EAA6B;AAC1E,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,UAAA,GAAa,KAAA;AACjB,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,UAAA,GAAa,CAAA;AAEjB,EAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AAEvB,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,MAAA,UAAA,GAAa,KAAA;AACb,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,MAAA,UAAA,GAAa,IAAA;AACb,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,SAAS,GAAA,EAAK;AAChB,MAAA,QAAA,GAAW,CAAC,QAAA;AACZ,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,SAAS,GAAA,EAAK;AAChB,MAAA,UAAA,EAAA;AACA,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB,CAAA,MAAA,IAAW,SAAS,GAAA,EAAK;AACvB,MAAA,UAAA,EAAA;AACA,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB,CAAA,MAAA,IAAW,SAAS,GAAA,EAAK;AACvB,MAAA,WAAA,EAAA;AACA,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB,CAAA,MAAA,IAAW,SAAS,GAAA,EAAK;AACvB,MAAA,WAAA,EAAA;AACA,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB,CAAA,MAAA,IAAW,SAAS,GAAA,EAAK;AACvB,MAAA,UAAA,EAAA;AACA,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB,CAAA,MAAA,IAAW,SAAS,GAAA,EAAK;AACvB,MAAA,UAAA,EAAA;AACA,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB,CAAA,MAAA,IACE,SAAS,SAAA,IACT,UAAA,KAAe,KACf,WAAA,KAAgB,CAAA,IAChB,eAAe,CAAA,EACf;AAEA,MAAA,MAAA,CAAO,KAAK,OAAA,CAAQ,IAAA,CAAK,EAAE,CAAA,CAAE,MAAM,CAAA;AACnC,MAAA,OAAA,CAAQ,MAAA,GAAS,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB;AAAA,EACF;AAGA,EAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,IAAA,MAAA,CAAO,KAAK,OAAA,CAAQ,IAAA,CAAK,EAAE,CAAA,CAAE,MAAM,CAAA;AAAA,EACrC;AAEA,EAAA,OAAO,MAAA;AACT;AAUO,SAAS,eAAe,SAAA,EAA8B;AAC3D,EAAA,MAAM,OAAA,GAAU,UAAU,IAAA,EAAK;AAG/B,EAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAC1B,IAAA,OAAO,EAAE,OAAA,EAAS,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAK;AAAA,EAC1C;AAGA,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AACpC,EAAA,MAAM,UAAU,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,QAAQ,EAAE,IAAA,EAAK;AAGhD,EAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,SAAS,CAAA,CAAE,CAAA;AAAA,EAC3D;AAEA,EAAA,IAAI,YAAY,OAAA,CAAQ,KAAA,CAAM,WAAW,CAAA,EAAG,EAAE,EAAE,IAAA,EAAK;AAGrD,EAAA,IAAI,SAAA,CAAU,UAAA,CAAW,GAAG,CAAA,EAAG;AAC7B,IAAA,SAAA,GAAY,SAAA,CAAU,MAAM,CAAC,CAAA;AAAA,EAC/B;AAGA,EAAA,MAAM,UAAA,GAAa,gBAAA,CAAiB,SAAA,EAAW,GAAG,CAAA;AAElD,EAAA,OAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAW;AACvC;AASO,SAAS,eAAe,IAAA,EAA2B;AACxD,EAAA,MAAM,YAAuB,EAAC;AAE9B,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAO,GAAI,eAAe,GAAG,CAAA;AAC9C,IAAA,SAAA,CAAU,OAAO,CAAA,GAAI,MAAA;AAAA,EACvB;AAEA,EAAA,OAAO,SAAA;AACT;AAOO,SAAS,UAAU,OAAA,EAA6B;AAErD,EAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAEzB,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,WAAA,CAAY,GAAG,CAAA;AAC3C,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA;AAC7C,IAAA,MAAM,YAAY,OAAA,CAAQ,KAAA,CAAM,WAAA,GAAc,CAAC,EAAE,IAAA,EAAK;AAEtD,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,SAAA,EAAW,EAAE,CAAA;AACpC,IAAA,IAAI,KAAA,CAAM,KAAK,CAAA,EAAG;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,IACnD;AAEA,IAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,QAAA,EAAU,GAAG,CAAA;AAC3C,IAAA,OAAO,EAAE,MAAM,KAAA,EAAM;AAAA,EACvB,CAAA,MAAO;AACL,IAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,OAAA,EAAS,GAAG,CAAA;AAC1C,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK;AAAA,EAC7B;AACF;;;AC/VO,SAAS,MAAM,IAAA,EAAyB;AAC7C,EAAA,OAAO,eAAe,IAAI,CAAA;AAC5B;AAQA,eAAsB,IAAA,CAAK,MAAiB,QAAA,EAAiC;AAE3E,EAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AACrC,EAAA,MAAM,GAAG,SAAA,CAAU,QAAA,EAAU,KAAA,CAAM,IAAI,GAAG,OAAO,CAAA;AACnD;AAOO,SAAS,eAAe,KAAA,EAA0B;AAEvD,EAAA,IACE,KAAA,KAAU,IAAA,IACV,OAAO,KAAA,KAAU,SAAA,IACjB,OAAO,KAAA,KAAU,QAAA,IACjB,OAAO,KAAA,KAAU,QAAA,EACjB;AACA,IAAA,OAAO,gBAAgB,KAAK,CAAA;AAAA,EAC9B;AAGA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAExB,IAAA,IAAI,oBAAA,CAAqB,KAAK,CAAA,EAAG;AAC/B,MAAA,OAAO,iBAAiB,KAAK,CAAA;AAAA,IAC/B,CAAA,MAAO;AACL,MAAA,OAAO,eAAe,KAAK,CAAA;AAAA,IAC7B;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,EAAM;AAC/C,IAAA,OAAO,gBAAgB,KAAmB,CAAA;AAAA,EAC5C;AAEA,EAAA,MAAM,IAAI,SAAA,CAAU,CAAA,uBAAA,EAA0B,OAAO,KAAK,CAAA,CAAE,CAAA;AAC9D;AAOO,SAAS,gBAAgB,GAAA,EAAyB;AACvD,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAE5B,EAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,MAAA,GAAS,OAAO,GAAG,CAAA;AACvB,IAAA,IAAI,YAAA,CAAa,MAAM,CAAA,EAAG;AACxB,MAAA,MAAA,GAAS,CAAA,CAAA,EAAI,YAAA,CAAa,MAAM,CAAC,CAAA,CAAA,CAAA;AAAA,IACnC;AACA,IAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AAAA,EACtB;AAGA,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,UAAA,CAAW,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,GAAG,CAAC,CAAC,CAAA;AAAA,EAC1C;AAGA,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AACjC,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AAErC,EAAA,OAAO,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,CAAA;AAClC;AAOO,SAAS,eAAe,GAAA,EAAwB;AACrD,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,SAAS,GAAA,EAAK;AACvB,IAAA,UAAA,CAAW,IAAA,CAAK,cAAA,CAAe,KAAK,CAAC,CAAA;AAAA,EACvC;AAEA,EAAA,OAAO,GAAA,GAAM,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA,GAAI,GAAA;AACtC;AAUO,SAAS,iBAAiB,GAAA,EAA2B;AAC1D,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAC,oBAAA,CAAqB,GAAG,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,EACpE;AAGA,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAC,CAAA;AAC/B,EAAA,MAAM,QAAQ,GAAA,CAAI,MAAA;AAGlB,EAAA,MAAM,aAAA,GAAgB,mBAAA,CAAoB,GAAA,EAAK,IAAI,CAAA;AAGnD,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,MAAA,GAAS,OAAO,GAAG,CAAA;AACvB,IAAA,IAAI,YAAA,CAAa,MAAM,CAAA,EAAG;AACxB,MAAA,MAAA,GAAS,CAAA,CAAA,EAAI,YAAA,CAAa,MAAM,CAAC,CAAA,CAAA,CAAA;AAAA,IACnC;AAGA,IAAA,IAAI,OAAO,aAAA,EAAe;AACxB,MAAA,MAAM,UAAA,GAAa,cAAc,GAAG,CAAA;AACpC,MAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AACrC,MAAA,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,EAAA,EAAK,SAAS,CAAA,CAAA,CAAA;AAAA,IAClC;AAEA,IAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AAAA,EACtB;AAEA,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAGjC,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,OAAO,GAAA,EAAK;AACrB,IAAA,MAAM,aAAuB,EAAC;AAC9B,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAM,KAAA,GAAQ,IAAI,GAAG,CAAA;AAGrB,MAAA,IAAI,OAAO,aAAA,EAAe;AACxB,QAAA,UAAA,CAAW,KAAK,0BAAA,CAA2B,KAAA,EAAqB,aAAA,CAAc,GAAG,CAAE,CAAC,CAAA;AAAA,MACtF,CAAA,MAAO;AACL,QAAA,UAAA,CAAW,IAAA,CAAK,cAAA,CAAe,KAAK,CAAC,CAAA;AAAA,MACvC;AAAA,IACF;AACA,IAAA,QAAA,CAAS,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,EACpC;AAEA,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAEjC,EAAA,OAAO,CAAA,EAAA,EAAK,OAAO,CAAA,CAAA,EAAI,KAAK,IAAI,OAAO,CAAA,CAAA,CAAA;AACzC;AAQO,SAAS,mBAAA,CAAoB,KAAmB,IAAA,EAA2B;AAChF,EAAA,MAAM,gBAA2B,EAAC;AAElC,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AAEtB,IAAA,MAAM,SAAS,GAAA,CAAI,GAAA,CAAI,CAAA,GAAA,KAAO,GAAA,CAAI,GAAG,CAAC,CAAA;AAGtC,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,CAAA,CAAA,KAAK,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,KAAM,IAAA,IAAQ,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAG;AAChF,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,CAAC,CAAe,CAAA;AACrD,IAAA,MAAM,UAAU,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,CAAE,MAAM,CAAA,CAAA,KAAK;AACzC,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,CAAe,CAAA;AAC3C,MAAA,OACE,OAAA,CAAQ,MAAA,KAAW,SAAA,CAAU,MAAA,IAC7B,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,KAAM,SAAA,CAAU,CAAC,CAAC,CAAA;AAAA,IAE9C,CAAC,CAAA;AAED,IAAA,IAAI,OAAA,EAAS;AAEX,MAAA,aAAA,CAAc,GAAG,CAAA,GAAI,SAAA;AAAA,IACvB;AAAA,EACF;AAEA,EAAA,OAAO,aAAA;AACT;AAUO,SAAS,0BAAA,CAA2B,KAAiB,MAAA,EAA0B;AACpF,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,WAAW,CAAA,EAAG;AACjC,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,OAAO,MAAA,EAAQ;AACxB,IAAA,MAAM,KAAA,GAAQ,IAAI,GAAG,CAAA;AACrB,IAAA,UAAA,CAAW,IAAA,CAAK,cAAA,CAAe,KAAK,CAAC,CAAA;AAAA,EACvC;AAEA,EAAA,OAAO,GAAA,GAAM,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA,GAAI,GAAA;AACtC;;;ACxOO,SAAS,MAAM,CAAA,EAAsB;AAC1C,EAAA,MAAM,OAAA,GAAU,EAAE,IAAA,EAAK;AACvB,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,WAAW,OAAO,CAAA;AAC3B;AAQA,eAAsB,KAAK,QAAA,EAAsC;AAE/D,EAAA,MAAM,EAAA,GAAK,MAAM,OAAO,aAAa,CAAA;AACrC,EAAA,MAAM,OAAA,GAAU,MAAM,EAAA,CAAG,QAAA,CAAS,UAAU,OAAO,CAAA;AACnD,EAAA,OAAO,MAAM,OAAO,CAAA;AACtB;AAQO,SAAS,WAAW,IAAA,EAAyB;AAClD,EAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAE1B,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAA;AAAA,EACT;AAGA,EAAA,MAAM,SAAA,GAAY,QAAQ,CAAC,CAAA;AAE3B,EAAA,IAAI,cAAc,GAAA,EAAK;AAErB,IAAA,OAAO,YAAY,OAAO,CAAA;AAAA,EAC5B,CAAA,MAAA,IAAW,cAAc,GAAA,EAAK;AAE5B,IAAA,OAAO,WAAW,OAAO,CAAA;AAAA,EAC3B,CAAA,MAAO;AAEL,IAAA,OAAO,eAAe,OAAO,CAAA;AAAA,EAC/B;AACF;AASO,SAAS,YAAY,IAAA,EAAyB;AACnD,EAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAE1B,EAAA,IAAI,CAAC,QAAQ,UAAA,CAAW,GAAG,KAAK,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AACtD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,IAAI,CAAA,CAAE,CAAA;AAAA,EAClD;AAGA,EAAA,MAAM,UAAU,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,EAAE,IAAA,EAAK;AAG1C,EAAA,IAAI,OAAA,KAAY,GAAA,IAAO,OAAA,KAAY,EAAA,EAAI;AACrC,IAAA,OAAO,EAAC;AAAA,EACV;AAGA,EAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AAC3B,IAAA,OAAO,gBAAA,CAAiB,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EAC1C,CAAA,MAAO;AAIL,IAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,OAAA,EAAS,GAAG,CAAA;AAC5C,IAAA,MAAM,eAAe,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK,UAAA,CAAW,CAAC,CAAC,CAAA;AAIlD,IAAA,OAAO,YAAA;AAAA,EACT;AACF;AAOO,SAAS,iBAAiB,OAAA,EAA4B;AAE3D,EAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,OAAA,EAAS,GAAG,CAAA;AAE3C,EAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,EACvD;AAGA,EAAA,MAAM,QAAA,GAAW,MAAM,CAAC,CAAA;AAGxB,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,UAAU,QAAQ,CAAA;AAG1C,EAAA,MAAM,SAAA,GAAY,eAAe,IAAI,CAAA;AAGrC,EAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAC,CAAA;AAGhD,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACzD;AAIA,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA;AAIhC,EAAA,MAAM,SAAA,GAAY,KAAA,KAAU,IAAA,IAAQ,UAAA,CAAW,MAAA,GAAS,CAAA;AAExD,EAAA,IAAI,SAAA,EAAW;AAEb,IAAA,OAAO,iBAAA,CAAkB,UAAA,EAAY,UAAA,EAAY,SAAA,EAAW,KAAK,CAAA;AAAA,EACnE,CAAA,MAAO;AAEL,IAAA,OAAO,iBAAA,CAAkB,UAAA,EAAY,UAAA,CAAW,CAAC,GAAG,SAAS,CAAA;AAAA,EAC/D;AACF;AAKO,SAAS,iBAAA,CACd,UAAA,EACA,SAAA,EACA,SAAA,EACY;AAEZ,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,SAAA,EAAW,GAAG,CAAA;AAE9C,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,UAAA,CAAW,MAAA,EAAQ;AACvC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,sBAAA,EAAyB,UAAA,CAAW,MAAM,CAAA,YAAA,EAAe,OAAO,MAAM,CAAA,OAAA;AAAA,KACxE;AAAA,EACF;AAGA,EAAA,MAAM,MAAkB,EAAC;AACzB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,SAAA,GAAY,WAAW,CAAC,CAAA;AAC9B,IAAA,MAAM,QAAA,GAAW,OAAO,CAAC,CAAA;AAGzB,IAAA,MAAM,MAAA,GAAS,UAAU,SAAS,CAAA;AAElC,IAAA,IAAI,MAAA,EAAQ;AAEV,MAAA,GAAA,CAAI,SAAS,CAAA,GAAI,qBAAA,CAAsB,QAAA,EAAU,MAAM,CAAA;AAAA,IACzD,CAAA,MAAO;AAEL,MAAA,GAAA,CAAI,SAAS,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA;AAAA,IACtC;AAAA,EACF;AAEA,EAAA,OAAO,GAAA;AACT;AAKO,SAAS,iBAAA,CACd,UAAA,EACA,QAAA,EACA,SAAA,EACA,aAAA,EACc;AACd,EAAA,MAAM,SAAuB,EAAC;AAE9B,EAAA,KAAA,MAAW,UAAU,QAAA,EAAU;AAC7B,IAAA,IAAI,MAAA,CAAO,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,EAAG;AAC9B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,iBAAA,CAAkB,UAAA,EAAY,MAAA,EAAQ,SAAS,CAAA;AAC3D,IAAA,MAAA,CAAO,KAAK,GAAG,CAAA;AAAA,EACjB;AAGA,EAAA,IAAI,aAAA,KAAkB,IAAA,IAAQ,MAAA,CAAO,MAAA,KAAW,aAAA,EAAe;AAC7D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,6BAAA,EAAgC,aAAa,CAAA,cAAA,EAAiB,MAAA,CAAO,MAAM,CAAA;AAAA,KAC7E;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAQO,SAAS,qBAAA,CAAsB,UAAkB,MAAA,EAA8B;AACpF,EAAA,MAAM,OAAA,GAAU,SAAS,IAAA,EAAK;AAG9B,EAAA,IAAI,CAAC,QAAQ,UAAA,CAAW,GAAG,KAAK,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AACtD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6CAAA,EAAgD,QAAQ,CAAA,CAAE,CAAA;AAAA,EAC5E;AAGA,EAAA,MAAM,UAAU,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,EAAE,IAAA,EAAK;AAG1C,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAC;AAAA,EACV;AAGA,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,OAAA,EAAS,GAAG,CAAA;AAE5C,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,MAAA,CAAO,MAAA,EAAQ;AACnC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,iBAAA,EAAoB,MAAA,CAAO,MAAM,CAAA,UAAA,EAAa,OAAO,MAAM,CAAA,OAAA;AAAA,KAC7D;AAAA,EACF;AAGA,EAAA,MAAM,eAAA,GAAkB,eAAe,MAAM,CAAA;AAG7C,EAAA,MAAM,UAAA,GAAa,OAAO,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAC,CAAA;AAGlD,EAAA,MAAM,MAAkB,EAAC;AACzB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,SAAA,GAAY,WAAW,CAAC,CAAA;AAC9B,IAAA,MAAMA,SAAAA,GAAW,OAAO,CAAC,CAAA;AAGzB,IAAA,MAAM,YAAA,GAAe,gBAAgB,SAAS,CAAA;AAE9C,IAAA,IAAI,YAAA,EAAc;AAEhB,MAAA,GAAA,CAAI,SAAS,CAAA,GAAI,qBAAA,CAAsBA,SAAAA,EAAU,YAAY,CAAA;AAAA,IAC/D,CAAA,MAAO;AAEL,MAAA,GAAA,CAAI,SAAS,CAAA,GAAI,UAAA,CAAWA,SAAQ,CAAA;AAAA,IACtC;AAAA,EACF;AAEA,EAAA,OAAO,GAAA;AACT;AAOO,SAAS,WAAW,IAAA,EAAyB;AAClD,EAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAE1B,EAAA,IAAI,CAAC,QAAQ,UAAA,CAAW,GAAG,KAAK,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AACtD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,IAAI,CAAA,CAAE,CAAA;AAAA,EACjD;AAGA,EAAA,MAAM,UAAU,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,EAAE,IAAA,EAAK;AAG1C,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAC;AAAA,EACV;AAGA,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,OAAA,EAAS,GAAG,CAAA;AAG5C,EAAA,MAAM,SAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,YAAY,MAAA,EAAQ;AAC7B,IAAA,IAAI,QAAA,CAAS,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG;AAE9B,MAAA,MAAA,CAAO,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAC,CAAA;AAAA,IAClC;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT","file":"index.js","sourcesContent":["/**\n * TSON Utility Functions\n *\n * Helper functions for serialization, deserialization, and validation.\n */\n\nimport type { TSONValue, TSONObject, SchemaMap, KeySchema, ParsedKeys } from './types';\n\n/**\n * Special characters that require string quoting\n */\nexport const SPECIAL_CHARS = new Set([',', '|', '@', '#', '{', '}', '[', ']', '\\n', '\\r', '\\t', ' ']);\n\n/**\n * Determine if a string value needs to be quoted in TSON format.\n *\n * Strings need quoting if they:\n * - Are empty\n * - Contain special delimiter characters\n * - Have leading/trailing whitespace\n * - Look like numbers (to preserve them as strings)\n * - Look like reserved words (true/false/null) when we want them as strings\n */\nexport function needsQuoting(value: string): boolean {\n if (value.length === 0) {\n return true;\n }\n\n // Check for reserved words that we want to keep as strings\n if (value === 'true' || value === 'false' || value === 'null') {\n return true;\n }\n\n // Check for leading/trailing whitespace\n if (value[0].trim() === '' || value[value.length - 1].trim() === '') {\n return true;\n }\n\n // Check if it looks like a number (preserve type distinction)\n if (looksLikeNumber(value)) {\n return true;\n }\n\n // Check for special characters\n for (const char of value) {\n if (SPECIAL_CHARS.has(char)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if a string looks like a numeric value.\n *\n * Used to determine if we should quote a string to preserve it as a string\n * rather than having it parsed as a number.\n */\nexport function looksLikeNumber(value: string): boolean {\n if (value.length === 0) {\n return false;\n }\n\n // Try parsing as number\n const num = Number(value);\n return !isNaN(num) && value.trim() === value && isFinite(num);\n}\n\n/**\n * Escape special characters in a string for quoted representation.\n *\n * Uses standard JSON escape sequences.\n */\nexport function escapeString(value: string): string {\n // Order matters: backslash first to avoid double-escaping\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\n/**\n * Unescape a quoted string back to its original form.\n *\n * Reverses the escaping done by escapeString().\n */\nexport function unescapeString(value: string): string {\n // Order matters: process in reverse order of escaping\n return value\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n}\n\n/**\n * Format a primitive value as TSON string.\n */\nexport function formatPrimitive(value: TSONValue): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n return String(value);\n }\n\n if (typeof value === 'string') {\n if (needsQuoting(value)) {\n return `\"${escapeString(value)}\"`;\n }\n return value;\n }\n\n throw new Error(`Cannot format non-primitive type: ${typeof value}`);\n}\n\n/**\n * Parse a TSON primitive value string to JavaScript type.\n */\nexport function parsePrimitive(value: string): TSONValue {\n const trimmed = value.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check for boolean\n if (trimmed === 'true') {\n return true;\n }\n if (trimmed === 'false') {\n return false;\n }\n\n // Check for null\n if (trimmed === 'null') {\n return null;\n }\n\n // Check for quoted string\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeString(trimmed.slice(1, -1));\n }\n\n // Try to parse as number\n if (looksLikeNumber(trimmed)) {\n const num = Number(trimmed);\n if (!isNaN(num)) {\n return num;\n }\n }\n\n // Otherwise it's an unquoted string\n return trimmed;\n}\n\n/**\n * Check if a value is an array of objects with identical keys.\n *\n * This determines if we can use tabular format optimization.\n */\nexport function isUniformObjectArray(data: unknown): data is TSONObject[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n // All elements must be plain objects\n if (!data.every(item => isPlainObject(item))) {\n return false;\n }\n\n // Get keys from first element\n const firstKeys = Object.keys(data[0]);\n\n // Check that all elements have the same keys in the same order\n for (let i = 1; i < data.length; i++) {\n const keys = Object.keys(data[i]);\n if (keys.length !== firstKeys.length) {\n return false;\n }\n for (let j = 0; j < keys.length; j++) {\n if (keys[j] !== firstKeys[j]) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Check if value is a plain object (not array, null, or other special object)\n */\nfunction isPlainObject(value: unknown): value is TSONObject {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.prototype.toString.call(value) === '[object Object]'\n );\n}\n\n/**\n * Split text by delimiter, respecting quoted strings and nested structures.\n *\n * This is more sophisticated than string.split() because it handles:\n * - Quoted strings (don't split on delimiters inside quotes)\n * - Nested braces/brackets/parentheses (don't split inside nested structures)\n * - Escaped characters\n */\nexport function splitByDelimiter(text: string, delimiter: string): string[] {\n const result: string[] = [];\n const current: string[] = [];\n let inQuotes = false;\n let escapeNext = false;\n let depthCurly = 0;\n let depthSquare = 0;\n let depthParen = 0;\n\n for (const char of text) {\n // Handle escape sequences\n if (escapeNext) {\n current.push(char);\n escapeNext = false;\n continue;\n }\n\n if (char === '\\\\') {\n current.push(char);\n escapeNext = true;\n continue;\n }\n\n // Handle quotes\n if (char === '\"') {\n inQuotes = !inQuotes;\n current.push(char);\n continue;\n }\n\n // Inside quotes, add everything\n if (inQuotes) {\n current.push(char);\n continue;\n }\n\n // Track nesting depth\n if (char === '{') {\n depthCurly++;\n current.push(char);\n } else if (char === '}') {\n depthCurly--;\n current.push(char);\n } else if (char === '[') {\n depthSquare++;\n current.push(char);\n } else if (char === ']') {\n depthSquare--;\n current.push(char);\n } else if (char === '(') {\n depthParen++;\n current.push(char);\n } else if (char === ')') {\n depthParen--;\n current.push(char);\n } else if (\n char === delimiter &&\n depthCurly === 0 &&\n depthSquare === 0 &&\n depthParen === 0\n ) {\n // Found unquoted, unnested delimiter - split here\n result.push(current.join('').trim());\n current.length = 0;\n } else {\n current.push(char);\n }\n }\n\n // Add final segment\n if (current.length > 0) {\n result.push(current.join('').trim());\n }\n\n return result;\n}\n\n/**\n * Parse a key which may include nested schema notation.\n *\n * Examples:\n * \"name\" -> { keyName: \"name\", schema: null }\n * \"address(@city,zip)\" -> { keyName: \"address\", schema: [\"city\", \"zip\"] }\n * \"location(@coords(@lat,lng))\" -> { keyName: \"location\", schema: [\"coords(@lat,lng)\"] }\n */\nexport function parseKeySchema(keyString: string): KeySchema {\n const trimmed = keyString.trim();\n\n // Check if key has nested schema\n if (!trimmed.includes('(')) {\n return { keyName: trimmed, schema: null };\n }\n\n // Find the opening parenthesis\n const parenIdx = trimmed.indexOf('(');\n const keyName = trimmed.slice(0, parenIdx).trim();\n\n // Extract schema (everything between outermost parentheses)\n if (!trimmed.endsWith(')')) {\n throw new Error(`Invalid key schema syntax: ${keyString}`);\n }\n\n let schemaStr = trimmed.slice(parenIdx + 1, -1).trim();\n\n // Strip leading @ if present (part of notation, not key name)\n if (schemaStr.startsWith('@')) {\n schemaStr = schemaStr.slice(1);\n }\n\n // Split schema by commas (respecting nested parentheses)\n const schemaKeys = splitByDelimiter(schemaStr, ',');\n\n return { keyName, schema: schemaKeys };\n}\n\n/**\n * Build a mapping of field names to their nested schemas.\n *\n * Example:\n * [\"id\", \"address(@city,zip)\"]\n * -> { id: null, address: [\"city\", \"zip\"] }\n */\nexport function buildSchemaMap(keys: string[]): SchemaMap {\n const schemaMap: SchemaMap = {};\n\n for (const key of keys) {\n const { keyName, schema } = parseKeySchema(key);\n schemaMap[keyName] = schema;\n }\n\n return schemaMap;\n}\n\n/**\n * Parse keys string and extract row count if present.\n *\n * Format: key1,key2,key3 or key1,key2,key3#N\n */\nexport function parseKeys(keysStr: string): ParsedKeys {\n // Check for row count marker\n if (keysStr.includes('#')) {\n // Split from right in case # appears in key name\n const lastHashIdx = keysStr.lastIndexOf('#');\n const keysPart = keysStr.slice(0, lastHashIdx);\n const countPart = keysStr.slice(lastHashIdx + 1).trim();\n\n const count = parseInt(countPart, 10);\n if (isNaN(count)) {\n throw new Error(`Invalid row count: ${countPart}`);\n }\n\n const keys = splitByDelimiter(keysPart, ',');\n return { keys, count };\n } else {\n const keys = splitByDelimiter(keysStr, ',');\n return { keys, count: null };\n }\n}\n","/**\n * TSON Serializer\n *\n * Converts JavaScript data structures to TSON format.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n formatPrimitive,\n needsQuoting,\n escapeString,\n isUniformObjectArray,\n} from './utils';\n\n/**\n * Serialize JavaScript object to TSON formatted string.\n *\n * @example\n * dumps({ name: \"Alice\", age: 30 })\n * // Returns: '{@name,age|Alice,30}'\n *\n * @example\n * dumps([{ id: 1, name: \"Alice\" }, { id: 2, name: \"Bob\" }])\n * // Returns: '{@id,name#2|1,Alice|2,Bob}'\n */\nexport function dumps(data: TSONValue): string {\n return serializeValue(data);\n}\n\n/**\n * Serialize JavaScript object to TSON formatted file (Node.js only).\n *\n * @param data - JavaScript object to serialize\n * @param filePath - Path to file to write\n */\nexport async function dump(data: TSONValue, filePath: string): Promise<void> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n await fs.writeFile(filePath, dumps(data), 'utf-8');\n}\n\n/**\n * Serialize any JavaScript value to TSON format.\n *\n * Dispatches to appropriate serializer based on type.\n */\nexport function serializeValue(value: TSONValue): string {\n // Handle primitives\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string'\n ) {\n return formatPrimitive(value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n // Check if it's a uniform array of objects (tabular optimization)\n if (isUniformObjectArray(value)) {\n return serializeTabular(value);\n } else {\n return serializeArray(value);\n }\n }\n\n // Handle objects\n if (typeof value === 'object' && value !== null) {\n return serializeObject(value as TSONObject);\n }\n\n throw new TypeError(`Cannot serialize type: ${typeof value}`);\n}\n\n/**\n * Serialize a JavaScript object to TSON object format.\n *\n * Format: {@key1,key2|value1,value2}\n */\nexport function serializeObject(obj: TSONObject): string {\n const keys = Object.keys(obj);\n\n if (keys.length === 0) {\n return '{@}';\n }\n\n // Format keys\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n keyParts.push(keyStr);\n }\n\n // Format values\n const valueParts: string[] = [];\n for (const key of keys) {\n valueParts.push(serializeValue(obj[key]));\n }\n\n // Build object string\n const keysStr = keyParts.join(',');\n const valuesStr = valueParts.join(',');\n\n return `{@${keysStr}|${valuesStr}}`;\n}\n\n/**\n * Serialize a JavaScript array to TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function serializeArray(arr: TSONArray): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n // Serialize each element\n const valueParts: string[] = [];\n for (const value of arr) {\n valueParts.push(serializeValue(value));\n }\n\n return '[' + valueParts.join(',') + ']';\n}\n\n/**\n * Serialize a uniform array of objects in tabular format.\n *\n * Format: {@key1,key2#N|val1,val2|val1,val2}\n *\n * This is the key optimization: keys are declared once instead of repeated\n * for each object in the array.\n */\nexport function serializeTabular(arr: TSONObject[]): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n if (!isUniformObjectArray(arr)) {\n throw new Error('Array is not uniform - cannot use tabular format');\n }\n\n // Get keys from first object\n const keys = Object.keys(arr[0]);\n const count = arr.length;\n\n // Check if any values are objects with uniform structure (nested schema opportunity)\n const nestedSchemas = detectNestedSchemas(arr, keys);\n\n // Format keys (with nested schemas if applicable)\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n\n // Add nested schema notation if applicable\n if (key in nestedSchemas) {\n const schemaKeys = nestedSchemas[key]!;\n const schemaStr = schemaKeys.join(',');\n keyStr = `${keyStr}(@${schemaStr})`;\n }\n\n keyParts.push(keyStr);\n }\n\n const keysStr = keyParts.join(',');\n\n // Format rows\n const rowParts: string[] = [];\n for (const obj of arr) {\n const valueParts: string[] = [];\n for (const key of keys) {\n const value = obj[key];\n\n // If this key has a nested schema, serialize as schematized object\n if (key in nestedSchemas) {\n valueParts.push(serializeSchematizedObject(value as TSONObject, nestedSchemas[key]!));\n } else {\n valueParts.push(serializeValue(value));\n }\n }\n rowParts.push(valueParts.join(','));\n }\n\n const rowsStr = rowParts.join('|');\n\n return `{@${keysStr}#${count}|${rowsStr}}`;\n}\n\n/**\n * Detect if any fields contain uniform nested objects that can use schema notation.\n *\n * For each key, checks if all values are objects with identical keys.\n * If so, that field can use nested schema notation.\n */\nexport function detectNestedSchemas(arr: TSONObject[], keys: string[]): SchemaMap {\n const nestedSchemas: SchemaMap = {};\n\n for (const key of keys) {\n // Get all values for this key\n const values = arr.map(obj => obj[key]);\n\n // Check if all values are plain objects\n if (!values.every(v => typeof v === 'object' && v !== null && !Array.isArray(v))) {\n continue;\n }\n\n if (values.length === 0) {\n continue;\n }\n\n // Check if all objects have the same keys\n const firstKeys = Object.keys(values[0] as TSONObject);\n const allSame = values.slice(1).every(v => {\n const objKeys = Object.keys(v as TSONObject);\n return (\n objKeys.length === firstKeys.length &&\n objKeys.every((k, i) => k === firstKeys[i])\n );\n });\n\n if (allSame) {\n // This field can use nested schema\n nestedSchemas[key] = firstKeys;\n }\n }\n\n return nestedSchemas;\n}\n\n/**\n * Serialize an object using a pre-declared schema.\n *\n * Format: {value1,value2} (no @ marker, values only)\n *\n * The @ marker is omitted because the schema was already declared in the\n * parent structure.\n */\nexport function serializeSchematizedObject(obj: TSONObject, schema: string[]): string {\n if (Object.keys(obj).length === 0) {\n return '{}';\n }\n\n // Serialize values in schema order\n const valueParts: string[] = [];\n for (const key of schema) {\n const value = obj[key];\n valueParts.push(serializeValue(value));\n }\n\n return '{' + valueParts.join(',') + '}';\n}\n","/**\n * TSON Deserializer\n *\n * Parses TSON format back to JavaScript data structures.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n parsePrimitive,\n splitByDelimiter,\n buildSchemaMap,\n parseKeys,\n} from './utils';\n\n/**\n * Deserialize TSON formatted string to JavaScript object.\n *\n * @example\n * loads('{@name,age|Alice,30}')\n * // Returns: { name: 'Alice', age: 30 }\n *\n * @example\n * loads('{@id,name#2|1,Alice|2,Bob}')\n * // Returns: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]\n */\nexport function loads(s: string): TSONValue {\n const trimmed = s.trim();\n if (trimmed.length === 0) {\n return null;\n }\n\n return parseValue(trimmed);\n}\n\n/**\n * Deserialize TSON formatted file to JavaScript object (Node.js only).\n *\n * @param filePath - Path to file to read\n * @returns Parsed JavaScript object\n */\nexport async function load(filePath: string): Promise<TSONValue> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n const content = await fs.readFile(filePath, 'utf-8');\n return loads(content);\n}\n\n/**\n * Parse a TSON value of any type.\n *\n * Determines the type by looking at the first character and dispatches\n * to the appropriate parser.\n */\nexport function parseValue(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check first character to determine type\n const firstChar = trimmed[0];\n\n if (firstChar === '{') {\n // Object (with @ marker) or schematized object\n return parseObject(trimmed);\n } else if (firstChar === '[') {\n // Array\n return parseArray(trimmed);\n } else {\n // Primitive value\n return parsePrimitive(trimmed);\n }\n}\n\n/**\n * Parse TSON object format.\n *\n * Handles both:\n * - {@key1,key2|val1,val2} - Single object or array of objects\n * - {val1,val2} - Schematized object (no @ marker)\n */\nexport function parseObject(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Invalid object format: ${text}`);\n }\n\n // Extract content between braces\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content === '@' || content === '') {\n return {};\n }\n\n // Check if this has @ marker (object with keys)\n if (content.startsWith('@')) {\n return parseKeyedObject(content.slice(1)); // Remove @ marker\n } else {\n // Schematized object without @ marker (just values)\n // This shouldn't happen at top level but can occur as nested value\n // Parse as comma-separated values\n const values = splitByDelimiter(content, ',');\n const parsedValues = values.map(v => parseValue(v));\n\n // Return as array (since we don't have keys)\n // In practice, this shouldn't be hit at top level\n return parsedValues;\n }\n}\n\n/**\n * Parse content after @ marker in object.\n *\n * Format: key1,key2|val1,val2 or key1,key2#N|val1,val2|val1,val2\n */\nexport function parseKeyedObject(content: string): TSONValue {\n // Split by pipe to separate keys from values\n const parts = splitByDelimiter(content, '|');\n\n if (parts.length < 1) {\n throw new Error('Invalid object format: missing keys');\n }\n\n // First part contains keys (and possibly row count)\n const keysPart = parts[0];\n\n // Parse keys and extract count if present\n const { keys, count } = parseKeys(keysPart);\n\n // Build schema map (maps field names to nested schemas)\n const schemaMap = buildSchemaMap(keys);\n\n // Get actual field names (without schema notation)\n const fieldNames = keys.map(k => k.split('(')[0]);\n\n // If only one part, it's an error (no values)\n if (parts.length === 1) {\n throw new Error('Invalid object format: missing values');\n }\n\n // If two parts, could be single object or array with one row\n // If more than two parts, definitely array (multiple rows)\n const valueParts = parts.slice(1);\n\n // Check if this is tabular format (array) or single object\n // If count is specified or multiple value parts, it's tabular\n const isTabular = count !== null || valueParts.length > 1;\n\n if (isTabular) {\n // Array of objects (tabular format)\n return parseTabularArray(fieldNames, valueParts, schemaMap, count);\n } else {\n // Single object\n return parseSingleObject(fieldNames, valueParts[0], schemaMap);\n }\n}\n\n/**\n * Parse a single object from keys and values.\n */\nexport function parseSingleObject(\n fieldNames: string[],\n valuesStr: string,\n schemaMap: SchemaMap\n): TSONObject {\n // Split values\n const values = splitByDelimiter(valuesStr, ',');\n\n if (values.length !== fieldNames.length) {\n throw new Error(\n `Field count mismatch: ${fieldNames.length} fields but ${values.length} values`\n );\n }\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field has a nested schema\n const schema = schemaMap[fieldName];\n\n if (schema) {\n // Parse as schematized object\n obj[fieldName] = parseSchematizedValue(valueStr, schema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse tabular format into array of objects.\n */\nexport function parseTabularArray(\n fieldNames: string[],\n rowParts: string[],\n schemaMap: SchemaMap,\n expectedCount: number | null\n): TSONObject[] {\n const result: TSONObject[] = [];\n\n for (const rowStr of rowParts) {\n if (rowStr.trim().length === 0) {\n continue;\n }\n\n const obj = parseSingleObject(fieldNames, rowStr, schemaMap);\n result.push(obj);\n }\n\n // Verify count if specified\n if (expectedCount !== null && result.length !== expectedCount) {\n throw new Error(\n `Row count mismatch: expected ${expectedCount} rows but got ${result.length}`\n );\n }\n\n return result;\n}\n\n/**\n * Parse a value that uses a nested schema.\n *\n * The value should be in format {val1,val2} where values correspond to\n * the keys in the schema.\n */\nexport function parseSchematizedValue(valueStr: string, schema: string[]): TSONObject {\n const trimmed = valueStr.trim();\n\n // Should be wrapped in braces\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Schematized value must be wrapped in braces: ${valueStr}`);\n }\n\n // Extract content\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content.length === 0) {\n return {};\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n if (values.length !== schema.length) {\n throw new Error(\n `Schema mismatch: ${schema.length} keys but ${values.length} values`\n );\n }\n\n // Build nested schema map for recursive schemas\n const nestedSchemaMap = buildSchemaMap(schema);\n\n // Get field names (without schema notation)\n const fieldNames = schema.map(k => k.split('(')[0]);\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field itself has a nested schema\n const nestedSchema = nestedSchemaMap[fieldName];\n\n if (nestedSchema) {\n // Recursively parse with nested schema\n obj[fieldName] = parseSchematizedValue(valueStr, nestedSchema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function parseArray(text: string): TSONArray {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('[') || !trimmed.endsWith(']')) {\n throw new Error(`Invalid array format: ${text}`);\n }\n\n // Extract content between brackets\n const content = trimmed.slice(1, -1).trim();\n\n // Empty array\n if (content.length === 0) {\n return [];\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n // Parse each value\n const result: TSONArray = [];\n for (const valueStr of values) {\n if (valueStr.trim().length > 0) {\n // Skip empty strings from trailing commas\n result.push(parseValue(valueStr));\n }\n }\n\n return result;\n}\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/serializer.ts","../src/deserializer.ts"],"names":["keys","valueStr"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * TSON Utility Functions\n *\n * Helper functions for serialization, deserialization, and validation.\n */\n\nimport type { TSONValue, TSONObject, SchemaMap, KeySchema, ParsedKeys } from './types';\n\n/**\n * Special characters that require string quoting\n */\nexport const SPECIAL_CHARS = new Set([',', '|', '@', '#', '{', '}', '[', ']', '\\n', '\\r', '\\t', ' ', '\"', '(', ')']);\n\n/**\n * Determine if a string value needs to be quoted in TSON format.\n *\n * Strings need quoting if they:\n * - Are empty\n * - Contain special delimiter characters\n * - Have leading/trailing whitespace\n * - Look like numbers (to preserve them as strings)\n * - Look like reserved words (true/false/null) when we want them as strings\n */\nexport function needsQuoting(value: string): boolean {\n if (value.length === 0) {\n return true;\n }\n\n // Check for reserved words that we want to keep as strings\n if (value === 'true' || value === 'false' || value === 'null') {\n return true;\n }\n\n // Check for leading/trailing whitespace\n if (value[0].trim() === '' || value[value.length - 1].trim() === '') {\n return true;\n }\n\n // Check if it looks like a number (preserve type distinction)\n if (looksLikeNumber(value)) {\n return true;\n }\n\n // Check for special characters\n for (const char of value) {\n if (SPECIAL_CHARS.has(char)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if a string looks like a numeric value.\n *\n * Used to determine if we should quote a string to preserve it as a string\n * rather than having it parsed as a number.\n */\nexport function looksLikeNumber(value: string): boolean {\n if (value.length === 0) {\n return false;\n }\n\n // Try parsing as number\n const num = Number(value);\n return !isNaN(num) && value.trim() === value && isFinite(num);\n}\n\n/**\n * Escape special characters in a string for quoted representation.\n *\n * Uses standard JSON escape sequences.\n */\nexport function escapeString(value: string): string {\n // Order matters: backslash first to avoid double-escaping\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\n/**\n * Unescape a quoted string back to its original form.\n *\n * Reverses the escaping done by escapeString().\n * Must process character by character to handle sequences like \\\\n correctly.\n */\nexport function unescapeString(value: string): string {\n const result: string[] = [];\n let i = 0;\n while (i < value.length) {\n if (value[i] === '\\\\' && i + 1 < value.length) {\n const nextChar = value[i + 1];\n if (nextChar === '\\\\') {\n result.push('\\\\');\n i += 2;\n } else if (nextChar === '\"') {\n result.push('\"');\n i += 2;\n } else if (nextChar === 'n') {\n result.push('\\n');\n i += 2;\n } else if (nextChar === 'r') {\n result.push('\\r');\n i += 2;\n } else if (nextChar === 't') {\n result.push('\\t');\n i += 2;\n } else {\n // Unknown escape, keep as-is\n result.push(value[i]);\n i += 1;\n }\n } else {\n result.push(value[i]);\n i += 1;\n }\n }\n return result.join('');\n}\n\n/**\n * Format a primitive value as TSON string.\n */\nexport function formatPrimitive(value: TSONValue): string {\n if (value === null) {\n return 'null';\n }\n\n if (typeof value === 'boolean') {\n return value ? 'true' : 'false';\n }\n\n if (typeof value === 'number') {\n return String(value);\n }\n\n if (typeof value === 'string') {\n if (needsQuoting(value)) {\n return `\"${escapeString(value)}\"`;\n }\n return value;\n }\n\n throw new Error(`Cannot format non-primitive type: ${typeof value}`);\n}\n\n/**\n * Parse a TSON primitive value string to JavaScript type.\n */\nexport function parsePrimitive(value: string): TSONValue {\n const trimmed = value.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check for boolean\n if (trimmed === 'true') {\n return true;\n }\n if (trimmed === 'false') {\n return false;\n }\n\n // Check for null\n if (trimmed === 'null') {\n return null;\n }\n\n // Check for quoted string\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeString(trimmed.slice(1, -1));\n }\n\n // Try to parse as number\n if (looksLikeNumber(trimmed)) {\n const num = Number(trimmed);\n if (!isNaN(num)) {\n return num;\n }\n }\n\n // Otherwise it's an unquoted string\n return trimmed;\n}\n\n/**\n * Check if a value is an array of objects with identical keys.\n *\n * This determines if we can use tabular format optimization.\n */\nexport function isUniformObjectArray(data: unknown): data is TSONObject[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n // All elements must be plain objects\n if (!data.every(item => isPlainObject(item))) {\n return false;\n }\n\n // Get keys from first element\n const firstKeys = Object.keys(data[0]);\n\n // Check that all elements have the same keys in the same order\n for (let i = 1; i < data.length; i++) {\n const keys = Object.keys(data[i]);\n if (keys.length !== firstKeys.length) {\n return false;\n }\n for (let j = 0; j < keys.length; j++) {\n if (keys[j] !== firstKeys[j]) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Check if value is a plain object (not array, null, or other special object)\n */\nfunction isPlainObject(value: unknown): value is TSONObject {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n Object.prototype.toString.call(value) === '[object Object]'\n );\n}\n\n/**\n * Split text by delimiter, respecting quoted strings and nested structures.\n *\n * This is more sophisticated than string.split() because it handles:\n * - Quoted strings (don't split on delimiters inside quotes)\n * - Nested braces/brackets/parentheses (don't split inside nested structures)\n * - Escaped characters\n */\nexport function splitByDelimiter(text: string, delimiter: string): string[] {\n const result: string[] = [];\n const current: string[] = [];\n let inQuotes = false;\n let escapeNext = false;\n let depthCurly = 0;\n let depthSquare = 0;\n let depthParen = 0;\n\n for (const char of text) {\n // Handle escape sequences\n if (escapeNext) {\n current.push(char);\n escapeNext = false;\n continue;\n }\n\n if (char === '\\\\') {\n current.push(char);\n escapeNext = true;\n continue;\n }\n\n // Handle quotes\n if (char === '\"') {\n inQuotes = !inQuotes;\n current.push(char);\n continue;\n }\n\n // Inside quotes, add everything\n if (inQuotes) {\n current.push(char);\n continue;\n }\n\n // Track nesting depth\n if (char === '{') {\n depthCurly++;\n current.push(char);\n } else if (char === '}') {\n depthCurly--;\n current.push(char);\n } else if (char === '[') {\n depthSquare++;\n current.push(char);\n } else if (char === ']') {\n depthSquare--;\n current.push(char);\n } else if (char === '(') {\n depthParen++;\n current.push(char);\n } else if (char === ')') {\n depthParen--;\n current.push(char);\n } else if (\n char === delimiter &&\n depthCurly === 0 &&\n depthSquare === 0 &&\n depthParen === 0\n ) {\n // Found unquoted, unnested delimiter - split here\n result.push(current.join('').trim());\n current.length = 0;\n } else {\n current.push(char);\n }\n }\n\n // Add final segment\n if (current.length > 0) {\n result.push(current.join('').trim());\n }\n\n return result;\n}\n\n/**\n * Parse a key which may include nested schema notation.\n *\n * Examples:\n * \"name\" -> { keyName: \"name\", schema: null }\n * \"address(@city,zip)\" -> { keyName: \"address\", schema: [\"city\", \"zip\"] }\n * \"location(@coords(@lat,lng))\" -> { keyName: \"location\", schema: [\"coords(@lat,lng)\"] }\n */\nexport function parseKeySchema(keyString: string): KeySchema {\n const trimmed = keyString.trim();\n\n // If the entire key is quoted, it's a simple key (any parens inside are literal)\n // Must check this BEFORE looking for '(' to handle keys like \"company(\"\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return { keyName: unescapeString(trimmed.slice(1, -1)), schema: null };\n }\n\n // Check if key has nested schema (only for unquoted keys)\n if (!trimmed.includes('(')) {\n return { keyName: trimmed, schema: null };\n }\n\n // Find the opening parenthesis\n const parenIdx = trimmed.indexOf('(');\n let keyName = trimmed.slice(0, parenIdx).trim();\n\n // Unquote the key name if it's quoted\n if (keyName.startsWith('\"') && keyName.endsWith('\"')) {\n keyName = unescapeString(keyName.slice(1, -1));\n }\n\n // Extract schema (everything between outermost parentheses)\n if (!trimmed.endsWith(')')) {\n throw new Error(`Invalid key schema syntax: ${keyString}`);\n }\n\n let schemaStr = trimmed.slice(parenIdx + 1, -1).trim();\n\n // Strip leading @ if present (part of notation, not key name)\n if (schemaStr.startsWith('@')) {\n schemaStr = schemaStr.slice(1);\n }\n\n // Split schema by commas (respecting nested parentheses)\n const schemaKeys = splitByDelimiter(schemaStr, ',');\n\n return { keyName, schema: schemaKeys };\n}\n\n/**\n * Build a mapping of field names to their nested schemas.\n *\n * Example:\n * [\"id\", \"address(@city,zip)\"]\n * -> { id: null, address: [\"city\", \"zip\"] }\n */\nexport function buildSchemaMap(keys: string[]): SchemaMap {\n const schemaMap: SchemaMap = {};\n\n for (const key of keys) {\n const { keyName, schema } = parseKeySchema(key);\n schemaMap[keyName] = schema;\n }\n\n return schemaMap;\n}\n\n/**\n * Parse keys string and extract row count if present.\n *\n * Format: key1,key2,key3 or key1,key2,key3#N\n */\nexport function parseKeys(keysStr: string): ParsedKeys {\n // Check for row count marker, respecting quotes\n let hashIdx = -1;\n let inQuotes = false;\n\n // Scan backwards to find the last # that is NOT inside quotes\n for (let i = keysStr.length - 1; i >= 0; i--) {\n const char = keysStr[i];\n\n if (char === '\"') {\n // Check for escaped quote (count preceding backslashes)\n let backslashCount = 0;\n for (let j = i - 1; j >= 0; j--) {\n if (keysStr[j] === '\\\\') {\n backslashCount++;\n } else {\n break;\n }\n }\n\n // If even number of backslashes, it's a real quote\n if (backslashCount % 2 === 0) {\n inQuotes = !inQuotes;\n }\n }\n\n if (char === '#' && !inQuotes) {\n hashIdx = i;\n break;\n }\n }\n\n if (hashIdx !== -1) {\n // Found separator\n const keysPart = keysStr.slice(0, hashIdx);\n const countPart = keysStr.slice(hashIdx + 1).trim();\n\n const count = parseInt(countPart, 10);\n if (isNaN(count)) {\n // If it's not a valid number, ignore the hash (treat as part of key)\n // This handles edge cases where # might appear unquoted but not as separator\n // though strictly that should be quoted according to spec.\n // Fallback to normal parsing\n const keys = splitByDelimiter(keysStr, ',');\n return { keys, count: null };\n }\n\n const keys = splitByDelimiter(keysPart, ',');\n return { keys, count };\n } else {\n const keys = splitByDelimiter(keysStr, ',');\n return { keys, count: null };\n }\n}\n","/**\n * TSON Serializer\n *\n * Converts JavaScript data structures to TSON format.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n formatPrimitive,\n needsQuoting,\n escapeString,\n isUniformObjectArray,\n} from './utils';\n\n/**\n * Serialize JavaScript object to TSON formatted string.\n *\n * @example\n * dumps({ name: \"Alice\", age: 30 })\n * // Returns: '{@name,age|Alice,30}'\n *\n * @example\n * dumps([{ id: 1, name: \"Alice\" }, { id: 2, name: \"Bob\" }])\n * // Returns: '{@id,name#2|1,Alice|2,Bob}'\n */\nexport function dumps(data: TSONValue): string {\n return serializeValue(data);\n}\n\n/**\n * Serialize JavaScript object to TSON formatted file (Node.js only).\n *\n * @param data - JavaScript object to serialize\n * @param filePath - Path to file to write\n */\nexport async function dump(data: TSONValue, filePath: string): Promise<void> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n await fs.writeFile(filePath, dumps(data), 'utf-8');\n}\n\n/**\n * Serialize any JavaScript value to TSON format.\n *\n * Dispatches to appropriate serializer based on type.\n */\nexport function serializeValue(value: TSONValue): string {\n // Handle primitives\n if (\n value === null ||\n typeof value === 'boolean' ||\n typeof value === 'number' ||\n typeof value === 'string'\n ) {\n return formatPrimitive(value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n // Check if it's a uniform array of objects (tabular optimization)\n if (isUniformObjectArray(value)) {\n return serializeTabular(value);\n } else {\n return serializeArray(value);\n }\n }\n\n // Handle objects\n if (typeof value === 'object' && value !== null) {\n return serializeObject(value as TSONObject);\n }\n\n throw new TypeError(`Cannot serialize type: ${typeof value}`);\n}\n\n/**\n * Serialize a JavaScript object to TSON object format.\n *\n * Format: {@key1,key2|value1,value2}\n */\nexport function serializeObject(obj: TSONObject): string {\n const keys = Object.keys(obj);\n\n if (keys.length === 0) {\n return '{@}';\n }\n\n // Format keys\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n keyParts.push(keyStr);\n }\n\n // Format values\n const valueParts: string[] = [];\n for (const key of keys) {\n valueParts.push(serializeValue(obj[key]));\n }\n\n // Build object string\n const keysStr = keyParts.join(',');\n const valuesStr = valueParts.join(',');\n\n return `{@${keysStr}|${valuesStr}}`;\n}\n\n/**\n * Serialize a JavaScript array to TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function serializeArray(arr: TSONArray): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n // Serialize each element\n const valueParts: string[] = [];\n for (const value of arr) {\n valueParts.push(serializeValue(value));\n }\n\n return '[' + valueParts.join(',') + ']';\n}\n\n/**\n * Serialize a uniform array of objects in tabular format.\n *\n * Format: {@key1,key2#N|val1,val2|val1,val2}\n *\n * This is the key optimization: keys are declared once instead of repeated\n * for each object in the array.\n */\nexport function serializeTabular(arr: TSONObject[]): string {\n if (arr.length === 0) {\n return '[]';\n }\n\n if (!isUniformObjectArray(arr)) {\n throw new Error('Array is not uniform - cannot use tabular format');\n }\n\n // Get keys from first object\n const keys = Object.keys(arr[0]);\n const count = arr.length;\n\n // Check if any values are objects with uniform structure (nested schema opportunity)\n const nestedSchemas = detectNestedSchemas(arr, keys);\n\n // Format keys (with nested schemas if applicable)\n const keyParts: string[] = [];\n for (const key of keys) {\n let keyStr = String(key);\n if (needsQuoting(keyStr)) {\n keyStr = `\"${escapeString(keyStr)}\"`;\n }\n\n // Add nested schema notation if applicable\n if (key in nestedSchemas) {\n const schemaKeys = nestedSchemas[key]!;\n // Quote schema keys that need quoting (contain special chars)\n const formattedSchemaKeys = schemaKeys.map(sk => {\n if (needsQuoting(sk)) {\n return `\"${escapeString(sk)}\"`;\n }\n return sk;\n });\n const schemaStr = formattedSchemaKeys.join(',');\n keyStr = `${keyStr}(@${schemaStr})`;\n }\n\n keyParts.push(keyStr);\n }\n\n const keysStr = keyParts.join(',');\n\n // Format rows\n const rowParts: string[] = [];\n for (const obj of arr) {\n const valueParts: string[] = [];\n for (const key of keys) {\n const value = obj[key];\n\n // If this key has a nested schema, serialize as schematized object\n if (key in nestedSchemas) {\n valueParts.push(serializeSchematizedObject(value as TSONObject, nestedSchemas[key]!));\n } else {\n valueParts.push(serializeValue(value));\n }\n }\n rowParts.push(valueParts.join(','));\n }\n\n const rowsStr = rowParts.join('|');\n\n return `{@${keysStr}#${count}|${rowsStr}}`;\n}\n\n/**\n * Detect if any fields contain uniform nested objects that can use schema notation.\n *\n * For each key, checks if all values are objects with identical keys.\n * If so, that field can use nested schema notation.\n */\nexport function detectNestedSchemas(arr: TSONObject[], keys: string[]): SchemaMap {\n const nestedSchemas: SchemaMap = {};\n\n for (const key of keys) {\n // Get all values for this key\n const values = arr.map(obj => obj[key]);\n\n // Check if all values are plain objects\n if (!values.every(v => typeof v === 'object' && v !== null && !Array.isArray(v))) {\n continue;\n }\n\n if (values.length === 0) {\n continue;\n }\n\n // Check if all objects have the same keys\n const firstKeys = Object.keys(values[0] as TSONObject);\n const allSame = values.slice(1).every(v => {\n const objKeys = Object.keys(v as TSONObject);\n return (\n objKeys.length === firstKeys.length &&\n objKeys.every((k, i) => k === firstKeys[i])\n );\n });\n\n if (allSame) {\n // This field can use nested schema\n nestedSchemas[key] = firstKeys;\n }\n }\n\n return nestedSchemas;\n}\n\n/**\n * Serialize an object using a pre-declared schema.\n *\n * Format: {value1,value2} (no @ marker, values only)\n *\n * The @ marker is omitted because the schema was already declared in the\n * parent structure.\n */\nexport function serializeSchematizedObject(obj: TSONObject, schema: string[]): string {\n if (Object.keys(obj).length === 0) {\n return '{}';\n }\n\n // Serialize values in schema order\n const valueParts: string[] = [];\n for (const key of schema) {\n const value = obj[key];\n valueParts.push(serializeValue(value));\n }\n\n return '{' + valueParts.join(',') + '}';\n}\n","/**\n * TSON Deserializer\n *\n * Parses TSON format back to JavaScript data structures.\n */\n\nimport type { TSONValue, TSONObject, TSONArray, SchemaMap } from './types';\nimport {\n parsePrimitive,\n splitByDelimiter,\n buildSchemaMap,\n parseKeys,\n parseKeySchema,\n} from './utils';\n\n/**\n * Deserialize TSON formatted string to JavaScript object.\n *\n * @example\n * loads('{@name,age|Alice,30}')\n * // Returns: { name: 'Alice', age: 30 }\n *\n * @example\n * loads('{@id,name#2|1,Alice|2,Bob}')\n * // Returns: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]\n */\nexport function loads(s: string): TSONValue {\n const trimmed = s.trim();\n if (trimmed.length === 0) {\n return null;\n }\n\n return parseValue(trimmed);\n}\n\n/**\n * Deserialize TSON formatted file to JavaScript object (Node.js only).\n *\n * @param filePath - Path to file to read\n * @returns Parsed JavaScript object\n */\nexport async function load(filePath: string): Promise<TSONValue> {\n // Dynamic import for Node.js fs module\n const fs = await import('fs/promises');\n const content = await fs.readFile(filePath, 'utf-8');\n return loads(content);\n}\n\n/**\n * Parse a TSON value of any type.\n *\n * Determines the type by looking at the first character and dispatches\n * to the appropriate parser.\n */\nexport function parseValue(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (trimmed.length === 0) {\n return '';\n }\n\n // Check first character to determine type\n const firstChar = trimmed[0];\n\n if (firstChar === '{') {\n // Object (with @ marker) or schematized object\n return parseObject(trimmed);\n } else if (firstChar === '[') {\n // Array\n return parseArray(trimmed);\n } else {\n // Primitive value\n return parsePrimitive(trimmed);\n }\n}\n\n/**\n * Parse TSON object format.\n *\n * Handles both:\n * - {@key1,key2|val1,val2} - Single object or array of objects\n * - {val1,val2} - Schematized object (no @ marker)\n */\nexport function parseObject(text: string): TSONValue {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Invalid object format: ${text}`);\n }\n\n // Extract content between braces\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content === '@' || content === '') {\n return {};\n }\n\n // Check if this has @ marker (object with keys)\n if (content.startsWith('@')) {\n return parseKeyedObject(content.slice(1)); // Remove @ marker\n } else {\n // Schematized object without @ marker (just values)\n // This shouldn't happen at top level but can occur as nested value\n // Parse as comma-separated values\n const values = splitByDelimiter(content, ',');\n const parsedValues = values.map(v => parseValue(v));\n\n // Return as array (since we don't have keys)\n // In practice, this shouldn't be hit at top level\n return parsedValues;\n }\n}\n\n/**\n * Parse content after @ marker in object.\n *\n * Format: key1,key2|val1,val2 or key1,key2#N|val1,val2|val1,val2\n */\nexport function parseKeyedObject(content: string): TSONValue {\n // Split by pipe to separate keys from values\n const parts = splitByDelimiter(content, '|');\n\n if (parts.length < 1) {\n throw new Error('Invalid object format: missing keys');\n }\n\n // First part contains keys (and possibly row count)\n const keysPart = parts[0];\n\n // Parse keys and extract count if present\n const { keys, count } = parseKeys(keysPart);\n\n // Build schema map (maps field names to nested schemas)\n const schemaMap = buildSchemaMap(keys);\n\n // Get actual field names (without schema notation)\n const fieldNames = keys.map(k => parseKeySchema(k).keyName);\n\n // If only one part, it's an error (no values)\n if (parts.length === 1) {\n throw new Error('Invalid object format: missing values');\n }\n\n // If two parts, could be single object or array with one row\n // If more than two parts, definitely array (multiple rows)\n const valueParts = parts.slice(1);\n\n // Check if this is tabular format (array) or single object\n // If count is specified or multiple value parts, it's tabular\n const isTabular = count !== null || valueParts.length > 1;\n\n if (isTabular) {\n // Array of objects (tabular format)\n return parseTabularArray(fieldNames, valueParts, schemaMap, count);\n } else {\n // Single object\n return parseSingleObject(fieldNames, valueParts[0], schemaMap);\n }\n}\n\n/**\n * Parse a single object from keys and values.\n */\nexport function parseSingleObject(\n fieldNames: string[],\n valuesStr: string,\n schemaMap: SchemaMap\n): TSONObject {\n // Split values\n const values = splitByDelimiter(valuesStr, ',');\n\n if (values.length !== fieldNames.length) {\n throw new Error(\n `Field count mismatch: ${fieldNames.length} fields but ${values.length} values`\n );\n }\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field has a nested schema\n const schema = schemaMap[fieldName];\n\n if (schema) {\n // Parse as schematized object\n obj[fieldName] = parseSchematizedValue(valueStr, schema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse tabular format into array of objects.\n */\nexport function parseTabularArray(\n fieldNames: string[],\n rowParts: string[],\n schemaMap: SchemaMap,\n expectedCount: number | null\n): TSONObject[] {\n const result: TSONObject[] = [];\n\n for (const rowStr of rowParts) {\n if (rowStr.trim().length === 0) {\n continue;\n }\n\n const obj = parseSingleObject(fieldNames, rowStr, schemaMap);\n result.push(obj);\n }\n\n // Verify count if specified\n if (expectedCount !== null && result.length !== expectedCount) {\n throw new Error(\n `Row count mismatch: expected ${expectedCount} rows but got ${result.length}`\n );\n }\n\n return result;\n}\n\n/**\n * Parse a value that uses a nested schema.\n *\n * The value should be in format {val1,val2} where values correspond to\n * the keys in the schema.\n */\nexport function parseSchematizedValue(valueStr: string, schema: string[]): TSONObject {\n const trimmed = valueStr.trim();\n\n // Should be wrapped in braces\n if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n throw new Error(`Schematized value must be wrapped in braces: ${valueStr}`);\n }\n\n // Extract content\n const content = trimmed.slice(1, -1).trim();\n\n // Empty object\n if (content.length === 0) {\n return {};\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n if (values.length !== schema.length) {\n throw new Error(\n `Schema mismatch: ${schema.length} keys but ${values.length} values`\n );\n }\n\n // Build nested schema map for recursive schemas\n const nestedSchemaMap = buildSchemaMap(schema);\n\n // Get field names (without schema notation)\n const fieldNames = schema.map(k => parseKeySchema(k).keyName);\n\n // Build object\n const obj: TSONObject = {};\n for (let i = 0; i < fieldNames.length; i++) {\n const fieldName = fieldNames[i];\n const valueStr = values[i];\n\n // Check if this field itself has a nested schema\n const nestedSchema = nestedSchemaMap[fieldName];\n\n if (nestedSchema) {\n // Recursively parse with nested schema\n obj[fieldName] = parseSchematizedValue(valueStr, nestedSchema);\n } else {\n // Parse as regular value\n obj[fieldName] = parseValue(valueStr);\n }\n }\n\n return obj;\n}\n\n/**\n * Parse TSON array format.\n *\n * Format: [value1,value2,value3]\n */\nexport function parseArray(text: string): TSONArray {\n const trimmed = text.trim();\n\n if (!trimmed.startsWith('[') || !trimmed.endsWith(']')) {\n throw new Error(`Invalid array format: ${text}`);\n }\n\n // Extract content between brackets\n const content = trimmed.slice(1, -1).trim();\n\n // Empty array\n if (content.length === 0) {\n return [];\n }\n\n // Split by comma\n const values = splitByDelimiter(content, ',');\n\n // Parse each value\n const result: TSONArray = [];\n for (const valueStr of values) {\n if (valueStr.trim().length > 0) {\n // Skip empty strings from trailing commas\n result.push(parseValue(valueStr));\n }\n }\n\n return result;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenoaihq/tson",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Token-efficient Structured Object Notation – a compact serialization format designed for efficient data exchange with LLMs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -73,4 +73,4 @@
73
73
  "typescript": "^5.3.3",
74
74
  "vitest": "^1.2.0"
75
75
  }
76
- }
76
+ }