@mdfriday/foundry 25.8.11 → 25.9.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.
Files changed (180) hide show
  1. package/README.md +9 -0
  2. package/dist/internal/application/ssg.d.ts.map +1 -1
  3. package/dist/internal/application/ssg.js +29 -6
  4. package/dist/internal/application/ssg.js.map +1 -1
  5. package/dist/internal/domain/config/entity/language.d.ts +5 -1
  6. package/dist/internal/domain/config/entity/language.d.ts.map +1 -1
  7. package/dist/internal/domain/config/entity/language.js +20 -4
  8. package/dist/internal/domain/config/entity/language.js.map +1 -1
  9. package/dist/internal/domain/config/entity/service.d.ts +2 -3
  10. package/dist/internal/domain/config/entity/service.d.ts.map +1 -1
  11. package/dist/internal/domain/config/entity/service.js +6 -3
  12. package/dist/internal/domain/config/entity/service.js.map +1 -1
  13. package/dist/internal/domain/config/factory/config.js +1 -1
  14. package/dist/internal/domain/config/factory/config.js.map +1 -1
  15. package/dist/internal/domain/config/tests/index.test.js +2 -4
  16. package/dist/internal/domain/config/tests/index.test.js.map +1 -1
  17. package/dist/internal/domain/config/tests/type.test.js +4 -0
  18. package/dist/internal/domain/config/tests/type.test.js.map +1 -1
  19. package/dist/internal/domain/config/tests/vo-service.test.js +95 -145
  20. package/dist/internal/domain/config/tests/vo-service.test.js.map +1 -1
  21. package/dist/internal/domain/config/type.d.ts +5 -0
  22. package/dist/internal/domain/config/type.d.ts.map +1 -1
  23. package/dist/internal/domain/config/type.js.map +1 -1
  24. package/dist/internal/domain/config/vo/language.d.ts +0 -3
  25. package/dist/internal/domain/config/vo/language.d.ts.map +1 -1
  26. package/dist/internal/domain/config/vo/language.js +22 -26
  27. package/dist/internal/domain/config/vo/language.js.map +1 -1
  28. package/dist/internal/domain/config/vo/service.d.ts +1 -1
  29. package/dist/internal/domain/config/vo/service.d.ts.map +1 -1
  30. package/dist/internal/domain/config/vo/service.js +15 -36
  31. package/dist/internal/domain/config/vo/service.js.map +1 -1
  32. package/dist/internal/domain/content/entity/content.d.ts +21 -6
  33. package/dist/internal/domain/content/entity/content.d.ts.map +1 -1
  34. package/dist/internal/domain/content/entity/content.js +51 -55
  35. package/dist/internal/domain/content/entity/content.js.map +1 -1
  36. package/dist/internal/domain/content/entity/page.d.ts +4 -2
  37. package/dist/internal/domain/content/entity/page.d.ts.map +1 -1
  38. package/dist/internal/domain/content/entity/page.js +65 -12
  39. package/dist/internal/domain/content/entity/page.js.map +1 -1
  40. package/dist/internal/domain/content/entity/pagebuilder.d.ts.map +1 -1
  41. package/dist/internal/domain/content/entity/pagebuilder.js +2 -2
  42. package/dist/internal/domain/content/entity/pagebuilder.js.map +1 -1
  43. package/dist/internal/domain/content/entity/pagecollector.d.ts +0 -3
  44. package/dist/internal/domain/content/entity/pagecollector.d.ts.map +1 -1
  45. package/dist/internal/domain/content/entity/pagecollector.js +19 -16
  46. package/dist/internal/domain/content/entity/pagecollector.js.map +1 -1
  47. package/dist/internal/domain/content/entity/pagemap.d.ts +2 -2
  48. package/dist/internal/domain/content/entity/pagemap.d.ts.map +1 -1
  49. package/dist/internal/domain/content/entity/pagemap.js +19 -24
  50. package/dist/internal/domain/content/entity/pagemap.js.map +1 -1
  51. package/dist/internal/domain/content/entity/pagetrees.d.ts.map +1 -1
  52. package/dist/internal/domain/content/entity/pagetrees.js.map +1 -1
  53. package/dist/internal/domain/content/entity/paginator.d.ts.map +1 -1
  54. package/dist/internal/domain/content/entity/paginator.js +8 -11
  55. package/dist/internal/domain/content/entity/paginator.js.map +1 -1
  56. package/dist/internal/domain/content/entity/taxonomy.d.ts +1 -1
  57. package/dist/internal/domain/content/entity/taxonomy.d.ts.map +1 -1
  58. package/dist/internal/domain/content/entity/taxonomy.js +6 -8
  59. package/dist/internal/domain/content/entity/taxonomy.js.map +1 -1
  60. package/dist/internal/domain/content/entity/term.d.ts +1 -1
  61. package/dist/internal/domain/content/entity/term.d.ts.map +1 -1
  62. package/dist/internal/domain/content/entity/term.js +17 -14
  63. package/dist/internal/domain/content/entity/term.js.map +1 -1
  64. package/dist/internal/domain/content/entity/translator.d.ts +42 -0
  65. package/dist/internal/domain/content/entity/translator.d.ts.map +1 -0
  66. package/dist/internal/domain/content/entity/translator.js +187 -0
  67. package/dist/internal/domain/content/entity/translator.js.map +1 -0
  68. package/dist/internal/domain/content/factory/hub.d.ts.map +1 -1
  69. package/dist/internal/domain/content/factory/hub.js +20 -1
  70. package/dist/internal/domain/content/factory/hub.js.map +1 -1
  71. package/dist/internal/domain/content/index.d.ts +1 -0
  72. package/dist/internal/domain/content/index.d.ts.map +1 -1
  73. package/dist/internal/domain/content/index.js +1 -0
  74. package/dist/internal/domain/content/index.js.map +1 -1
  75. package/dist/internal/domain/content/type.d.ts +6 -7
  76. package/dist/internal/domain/content/type.d.ts.map +1 -1
  77. package/dist/internal/domain/content/type.js.map +1 -1
  78. package/dist/internal/domain/content/vo/sort.d.ts +0 -1
  79. package/dist/internal/domain/content/vo/sort.d.ts.map +1 -1
  80. package/dist/internal/domain/content/vo/sort.js +4 -3
  81. package/dist/internal/domain/content/vo/sort.js.map +1 -1
  82. package/dist/internal/domain/fs/entity/fs.d.ts +6 -4
  83. package/dist/internal/domain/fs/entity/fs.d.ts.map +1 -1
  84. package/dist/internal/domain/fs/entity/fs.js +7 -3
  85. package/dist/internal/domain/fs/entity/fs.js.map +1 -1
  86. package/dist/internal/domain/fs/factory/fs.d.ts.map +1 -1
  87. package/dist/internal/domain/fs/factory/fs.js +1 -1
  88. package/dist/internal/domain/fs/factory/fs.js.map +1 -1
  89. package/dist/internal/domain/fs/tests/entity-fs.test.js +10 -8
  90. package/dist/internal/domain/fs/tests/entity-fs.test.js.map +1 -1
  91. package/dist/internal/domain/fs/tests/vo-filesystemscollector.test.js +7 -0
  92. package/dist/internal/domain/fs/tests/vo-filesystemscollector.test.js.map +1 -1
  93. package/dist/internal/domain/fs/tests/vo-incremental-file-collector.test.js +23 -23
  94. package/dist/internal/domain/fs/tests/vo-incremental-file-collector.test.js.map +1 -1
  95. package/dist/internal/domain/fs/vo/filesystemscollector.d.ts +3 -1
  96. package/dist/internal/domain/fs/vo/filesystemscollector.d.ts.map +1 -1
  97. package/dist/internal/domain/fs/vo/filesystemscollector.js +18 -3
  98. package/dist/internal/domain/fs/vo/filesystemscollector.js.map +1 -1
  99. package/dist/internal/domain/fs/vo/incremental-file-collector.d.ts +1 -1
  100. package/dist/internal/domain/fs/vo/incremental-file-collector.d.ts.map +1 -1
  101. package/dist/internal/domain/fs/vo/incremental-file-collector.js +5 -3
  102. package/dist/internal/domain/fs/vo/incremental-file-collector.js.map +1 -1
  103. package/dist/internal/domain/module/entity/lang.d.ts.map +1 -1
  104. package/dist/internal/domain/module/entity/lang.js +5 -1
  105. package/dist/internal/domain/module/entity/lang.js.map +1 -1
  106. package/dist/internal/domain/module/entity/module.d.ts +17 -12
  107. package/dist/internal/domain/module/entity/module.d.ts.map +1 -1
  108. package/dist/internal/domain/module/entity/module.js +169 -55
  109. package/dist/internal/domain/module/entity/module.js.map +1 -1
  110. package/dist/internal/domain/module/type.d.ts +16 -1
  111. package/dist/internal/domain/module/type.d.ts.map +1 -1
  112. package/dist/internal/domain/module/type.js +3 -1
  113. package/dist/internal/domain/module/type.js.map +1 -1
  114. package/dist/internal/domain/module/vo/module.d.ts +6 -13
  115. package/dist/internal/domain/module/vo/module.d.ts.map +1 -1
  116. package/dist/internal/domain/module/vo/module.js +44 -17
  117. package/dist/internal/domain/module/vo/module.js.map +1 -1
  118. package/dist/internal/domain/module/vo/mount.d.ts +4 -0
  119. package/dist/internal/domain/module/vo/mount.d.ts.map +1 -1
  120. package/dist/internal/domain/module/vo/mount.js +6 -0
  121. package/dist/internal/domain/module/vo/mount.js.map +1 -1
  122. package/dist/internal/domain/module/vo/themes.d.ts +64 -0
  123. package/dist/internal/domain/module/vo/themes.d.ts.map +1 -0
  124. package/dist/internal/domain/module/vo/themes.js +92 -0
  125. package/dist/internal/domain/module/vo/themes.js.map +1 -0
  126. package/dist/internal/domain/module/vo/themes.test.d.ts +2 -0
  127. package/dist/internal/domain/module/vo/themes.test.d.ts.map +1 -0
  128. package/dist/internal/domain/module/vo/themes.test.js +109 -0
  129. package/dist/internal/domain/module/vo/themes.test.js.map +1 -0
  130. package/dist/internal/domain/resources/entity/http.d.ts +20 -0
  131. package/dist/internal/domain/resources/entity/http.d.ts.map +1 -0
  132. package/dist/internal/domain/resources/entity/http.js +131 -0
  133. package/dist/internal/domain/resources/entity/http.js.map +1 -0
  134. package/dist/internal/domain/resources/entity/resources.d.ts +6 -0
  135. package/dist/internal/domain/resources/entity/resources.d.ts.map +1 -1
  136. package/dist/internal/domain/resources/entity/resources.js +44 -6
  137. package/dist/internal/domain/resources/entity/resources.js.map +1 -1
  138. package/dist/internal/domain/site/entity/language.d.ts +1 -0
  139. package/dist/internal/domain/site/entity/language.d.ts.map +1 -1
  140. package/dist/internal/domain/site/entity/language.js +3 -0
  141. package/dist/internal/domain/site/entity/language.js.map +1 -1
  142. package/dist/internal/domain/site/entity/page.d.ts +7 -7
  143. package/dist/internal/domain/site/entity/page.d.ts.map +1 -1
  144. package/dist/internal/domain/site/entity/page.js +8 -30
  145. package/dist/internal/domain/site/entity/page.js.map +1 -1
  146. package/dist/internal/domain/site/entity/pager.d.ts.map +1 -1
  147. package/dist/internal/domain/site/entity/pager.js.map +1 -1
  148. package/dist/internal/domain/site/entity/site.d.ts +11 -0
  149. package/dist/internal/domain/site/entity/site.d.ts.map +1 -1
  150. package/dist/internal/domain/site/entity/site.js +42 -19
  151. package/dist/internal/domain/site/entity/site.js.map +1 -1
  152. package/dist/internal/domain/site/type.d.ts +8 -1
  153. package/dist/internal/domain/site/type.d.ts.map +1 -1
  154. package/dist/internal/domain/template/type.d.ts +2 -0
  155. package/dist/internal/domain/template/type.d.ts.map +1 -1
  156. package/dist/internal/domain/template/vo/namespace.d.ts.map +1 -1
  157. package/dist/internal/domain/template/vo/namespace.js +5 -1
  158. package/dist/internal/domain/template/vo/namespace.js.map +1 -1
  159. package/dist/internal/domain/template/vo/registry.d.ts +32 -0
  160. package/dist/internal/domain/template/vo/registry.d.ts.map +1 -1
  161. package/dist/internal/domain/template/vo/registry.js +401 -15
  162. package/dist/internal/domain/template/vo/registry.js.map +1 -1
  163. package/dist/pkg/lang/data.d.ts +28 -0
  164. package/dist/pkg/lang/data.d.ts.map +1 -0
  165. package/dist/pkg/lang/data.js +151 -0
  166. package/dist/pkg/lang/data.js.map +1 -0
  167. package/dist/pkg/lang/index.d.ts +65 -0
  168. package/dist/pkg/lang/index.d.ts.map +1 -0
  169. package/dist/pkg/lang/index.js +79 -0
  170. package/dist/pkg/lang/index.js.map +1 -0
  171. package/dist/pkg/lang/service.d.ts +67 -0
  172. package/dist/pkg/lang/service.d.ts.map +1 -0
  173. package/dist/pkg/lang/service.js +115 -0
  174. package/dist/pkg/lang/service.js.map +1 -0
  175. package/dist/pkg/lang/types.d.ts +51 -0
  176. package/dist/pkg/lang/types.d.ts.map +1 -0
  177. package/dist/pkg/lang/types.js +7 -0
  178. package/dist/pkg/lang/types.js.map +1 -0
  179. package/dist/pkg/log/manager.js +1 -1
  180. package/package.json +1 -1
@@ -137,6 +137,8 @@ class DefaultTemplateRegistry {
137
137
  this.registerFmtFunctions(funcMap);
138
138
  // Path functions
139
139
  this.registerPathFunctions(funcMap);
140
+ // Transform functions (unmarshal, etc.)
141
+ this.registerTransformFunctions(funcMap);
140
142
  }
141
143
  /**
142
144
  * Register cryptographic hash functions
@@ -367,6 +369,7 @@ class DefaultTemplateRegistry {
367
369
  registerResourcesFunctions(funcMap, services) {
368
370
  funcMap.set('resources', () => ({
369
371
  Get: async (filename) => await services.Get(filename),
372
+ GetRemote: async (uri) => await services.GetRemote(uri),
370
373
  Minify: async (resource) => await services.Minify(resource),
371
374
  Fingerprint: async (resource) => await services.Fingerprint(resource),
372
375
  ExecuteAsTemplate: async (targetPath, data, resource) => await services.ExecuteAsTemplate(targetPath, data, resource)
@@ -388,9 +391,43 @@ class DefaultTemplateRegistry {
388
391
  * Equivalent to Go's registerLang()
389
392
  */
390
393
  registerLanguageFunctions(funcMap, services) {
394
+ // Import language service
395
+ const { lang } = require('../../../../pkg/lang');
396
+ // Language namespace functions
397
+ funcMap.set('lang', () => ({
398
+ // Get all language codes
399
+ getAllCodes: () => lang.getAllCodes(),
400
+ // Get all language names
401
+ getAllNames: () => lang.getAllNames(),
402
+ // Get language codes by direction
403
+ getCodesByDirection: (direction) => lang.getCodesByDirection(direction),
404
+ // Get language names by direction
405
+ getNamesByDirection: (direction) => lang.getNamesByDirection(direction),
406
+ // Get code-name mapping
407
+ getCodeNameMap: () => lang.getCodeNameMap(),
408
+ // Get code-name mapping by direction
409
+ getCodeNameMapByDirection: (direction) => lang.getCodeNameMapByDirection(direction),
410
+ // Get language name by code
411
+ getNameByCode: (code) => lang.getNameByCode(code),
412
+ // Get language info by code
413
+ getLanguageInfo: (code) => lang.getLanguageInfo(code),
414
+ // Check if language is supported
415
+ isSupported: (code) => lang.isSupported(code),
416
+ // Get language direction
417
+ getDirection: (code) => lang.getDirection(code),
418
+ // Check if language is LTR
419
+ isLTR: (code) => lang.isLTR(code),
420
+ // Check if language is RTL
421
+ isRTL: (code) => lang.isRTL(code)
422
+ }));
423
+ // Standalone functions for convenience
424
+ funcMap.set('langName', (code) => lang.getNameByCode(code) || code);
425
+ funcMap.set('langDirection', (code) => lang.getDirection(code) || 'ltr');
426
+ funcMap.set('isLTR', (code) => lang.isLTR(code));
427
+ funcMap.set('isRTL', (code) => lang.isRTL(code));
428
+ // i18n placeholder (can be extended later)
391
429
  funcMap.set('i18n', (key) => {
392
- // Placeholder for i18n functionality
393
- return key;
430
+ return services.translate(key);
394
431
  });
395
432
  }
396
433
  /**
@@ -1281,6 +1318,43 @@ class DefaultTemplateRegistry {
1281
1318
  }
1282
1319
  return set1.filter(item => set2.includes(item));
1283
1320
  });
1321
+ // querify function - converts key-value pairs to URL query string
1322
+ // Usage: {{ querify "foo" 1 "bar" 2 "baz" "with spaces" }}
1323
+ // Returns: bar=2&baz=with+spaces&foo=1
1324
+ // Also supports array input: {{ slice "foo" 1 "bar" 2 | querify }}
1325
+ funcMap.set('querify', (...args) => {
1326
+ let params = [];
1327
+ // Handle single array argument (from pipe)
1328
+ if (args.length === 1 && Array.isArray(args[0])) {
1329
+ params = args[0];
1330
+ }
1331
+ else {
1332
+ params = args;
1333
+ }
1334
+ // Must have even number of parameters (key-value pairs)
1335
+ if (params.length % 2 !== 0) {
1336
+ throw new Error('querify requires an even number of arguments (key-value pairs)');
1337
+ }
1338
+ const queryParams = [];
1339
+ // Process key-value pairs
1340
+ for (let i = 0; i < params.length; i += 2) {
1341
+ const key = String(params[i]);
1342
+ const value = String(params[i + 1]);
1343
+ queryParams.push([key, value]);
1344
+ }
1345
+ // Sort by key for consistent output (like Go's implementation)
1346
+ queryParams.sort((a, b) => a[0].localeCompare(b[0]));
1347
+ // Build query string
1348
+ const queryString = queryParams
1349
+ .map(([key, value]) => {
1350
+ // URL encode key and value, replacing %20 with + for spaces (query string convention)
1351
+ const encodedKey = encodeURIComponent(key).replace(/%20/g, '+');
1352
+ const encodedValue = encodeURIComponent(value).replace(/%20/g, '+');
1353
+ return `${encodedKey}=${encodedValue}`;
1354
+ })
1355
+ .join('&');
1356
+ return queryString;
1357
+ });
1284
1358
  }
1285
1359
  /**
1286
1360
  * Core indexing implementation following Go's doIndex logic
@@ -1560,15 +1634,6 @@ class DefaultTemplateRegistry {
1560
1634
  funcMap.set('slice', (...args) => {
1561
1635
  return args;
1562
1636
  });
1563
- // Printf function for string formatting
1564
- funcMap.set('printf', (format, ...args) => {
1565
- // Simple printf implementation
1566
- let result = format;
1567
- args.forEach((arg, index) => {
1568
- result = result.replace(new RegExp(`%[sdf]`, 'g'), String(arg));
1569
- });
1570
- return result;
1571
- });
1572
1637
  // Default function for providing default values
1573
1638
  // TypeScript equivalent of Go's default function
1574
1639
  funcMap.set('default', (defaultValue, value) => {
@@ -1641,11 +1706,32 @@ class DefaultTemplateRegistry {
1641
1706
  registerFmtFunctions(funcMap) {
1642
1707
  // Basic printf, print, println functions (for backward compatibility)
1643
1708
  funcMap.set('printf', (format, ...args) => {
1644
- // Simple printf implementation - you can enhance this with a proper sprintf library
1709
+ // Enhanced printf implementation supporting %v, %s, %d, %f, %t
1645
1710
  let result = format;
1646
- for (let i = 0; i < args.length; i++) {
1647
- result = result.replace(/%[sd%]/, String(args[i]));
1648
- }
1711
+ let argIndex = 0;
1712
+ // Replace format specifiers sequentially
1713
+ result = result.replace(/%[vsdft%]/g, (match) => {
1714
+ if (match === '%%') {
1715
+ return '%'; // Literal %
1716
+ }
1717
+ if (argIndex >= args.length) {
1718
+ return match; // Not enough arguments, keep the format specifier
1719
+ }
1720
+ const arg = args[argIndex++];
1721
+ switch (match) {
1722
+ case '%v': // Go's general format specifier
1723
+ case '%s': // String
1724
+ return String(arg);
1725
+ case '%d': // Integer
1726
+ return String(Math.floor(Number(arg) || 0));
1727
+ case '%f': // Float
1728
+ return String(Number(arg) || 0);
1729
+ case '%t': // Boolean
1730
+ return String(Boolean(arg));
1731
+ default:
1732
+ return String(arg);
1733
+ }
1734
+ });
1649
1735
  return result;
1650
1736
  });
1651
1737
  funcMap.set('print', (...args) => {
@@ -1884,6 +1970,306 @@ class DefaultTemplateRegistry {
1884
1970
  }
1885
1971
  }));
1886
1972
  }
1973
+ /**
1974
+ * Register transform functions (unmarshal, etc.)
1975
+ * Equivalent to Go's transform package functions
1976
+ */
1977
+ registerTransformFunctions(funcMap) {
1978
+ // Transform namespace functions - following Go's transform package
1979
+ funcMap.set('transform', () => ({
1980
+ // Unmarshal unmarshals data from JSON, YAML, TOML, CSV formats
1981
+ // Usage: {{ $data := "{"key": "value"}" | transform.Unmarshal }}
1982
+ // Usage: {{ $data := (dict "format" "json") $jsonString | transform.Unmarshal }}
1983
+ Unmarshal: (...args) => {
1984
+ if (args.length < 1 || args.length > 2) {
1985
+ throw new Error('unmarshal takes 1 or 2 arguments');
1986
+ }
1987
+ let data;
1988
+ let options = {};
1989
+ if (args.length === 1) {
1990
+ data = args[0];
1991
+ }
1992
+ else {
1993
+ // First argument is options map
1994
+ const opts = args[0];
1995
+ if (!opts || typeof opts !== 'object') {
1996
+ throw new Error('first argument must be a map');
1997
+ }
1998
+ options = opts;
1999
+ data = args[1];
2000
+ }
2001
+ // Handle Resource objects (if data has Content method)
2002
+ if (data && typeof data === 'object' && typeof data.Content === 'function') {
2003
+ try {
2004
+ const content = data.Content();
2005
+ return this.unmarshalContent(content, options);
2006
+ }
2007
+ catch (error) {
2008
+ throw new Error(`failed to get content from resource: ${error.message}`);
2009
+ }
2010
+ }
2011
+ // Handle string data
2012
+ let dataStr;
2013
+ if (typeof data === 'string') {
2014
+ dataStr = data;
2015
+ }
2016
+ else if (data && typeof data.toString === 'function') {
2017
+ dataStr = data.toString();
2018
+ }
2019
+ else {
2020
+ throw new Error(`type ${typeof data} not supported`);
2021
+ }
2022
+ if (!dataStr || dataStr.trim() === '') {
2023
+ return null;
2024
+ }
2025
+ return this.unmarshalContent(dataStr, options);
2026
+ }
2027
+ }));
2028
+ // Also register unmarshal as a standalone function for backward compatibility
2029
+ funcMap.set('unmarshal', (...args) => {
2030
+ const transform = funcMap.get('transform')();
2031
+ return transform.Unmarshal(...args);
2032
+ });
2033
+ }
2034
+ /**
2035
+ * Unmarshal content from string based on format
2036
+ * Supports JSON, YAML, TOML, CSV formats
2037
+ */
2038
+ unmarshalContent(content, options = {}) {
2039
+ const trimmedContent = content.trim();
2040
+ if (!trimmedContent) {
2041
+ return null;
2042
+ }
2043
+ // Determine format
2044
+ let format = options.format;
2045
+ if (!format) {
2046
+ format = this.detectFormat(trimmedContent);
2047
+ }
2048
+ try {
2049
+ switch (format.toLowerCase()) {
2050
+ case 'json':
2051
+ return JSON.parse(trimmedContent);
2052
+ case 'yaml':
2053
+ case 'yml':
2054
+ return this.parseYAML(trimmedContent);
2055
+ case 'toml':
2056
+ return this.parseTOML(trimmedContent);
2057
+ case 'csv':
2058
+ return this.parseCSV(trimmedContent);
2059
+ default:
2060
+ throw new Error(`format "${format}" not supported`);
2061
+ }
2062
+ }
2063
+ catch (error) {
2064
+ throw new Error(`failed to unmarshal ${format}: ${error.message}`);
2065
+ }
2066
+ }
2067
+ /**
2068
+ * Detect format from content
2069
+ */
2070
+ detectFormat(content) {
2071
+ const trimmed = content.trim();
2072
+ // JSON detection
2073
+ if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
2074
+ (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
2075
+ try {
2076
+ JSON.parse(trimmed);
2077
+ return 'json';
2078
+ }
2079
+ catch {
2080
+ // Not valid JSON, continue checking
2081
+ }
2082
+ }
2083
+ // YAML detection (starts with --- or has key: value patterns)
2084
+ if (trimmed.startsWith('---') || /^[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*.+/m.test(trimmed)) {
2085
+ return 'yaml';
2086
+ }
2087
+ // TOML detection (has [section] or key = value patterns)
2088
+ if (/^\[.*\]$/m.test(trimmed) || /^[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*.+/m.test(trimmed)) {
2089
+ return 'toml';
2090
+ }
2091
+ // CSV detection (has comma-separated values)
2092
+ if (/^[^,\n]*,[^,\n]*/.test(trimmed)) {
2093
+ return 'csv';
2094
+ }
2095
+ // Default to JSON if uncertain
2096
+ return 'json';
2097
+ }
2098
+ /**
2099
+ * Parse YAML content (basic implementation)
2100
+ * For a full implementation, you'd want to use a proper YAML library
2101
+ */
2102
+ parseYAML(content) {
2103
+ // This is a very basic YAML parser for simple key-value pairs
2104
+ // For production use, consider integrating a proper YAML library like js-yaml
2105
+ const lines = content.split('\n');
2106
+ const result = {};
2107
+ for (const line of lines) {
2108
+ const trimmedLine = line.trim();
2109
+ if (!trimmedLine || trimmedLine.startsWith('#') || trimmedLine === '---') {
2110
+ continue;
2111
+ }
2112
+ const colonIndex = trimmedLine.indexOf(':');
2113
+ if (colonIndex > 0) {
2114
+ const key = trimmedLine.substring(0, colonIndex).trim();
2115
+ let value = trimmedLine.substring(colonIndex + 1).trim();
2116
+ // Remove quotes if present
2117
+ if ((value.startsWith('"') && value.endsWith('"')) ||
2118
+ (value.startsWith("'") && value.endsWith("'"))) {
2119
+ value = value.slice(1, -1);
2120
+ }
2121
+ // Try to parse as number or boolean
2122
+ if (value === 'true') {
2123
+ result[key] = true;
2124
+ }
2125
+ else if (value === 'false') {
2126
+ result[key] = false;
2127
+ }
2128
+ else if (/^\d+$/.test(value)) {
2129
+ result[key] = parseInt(value, 10);
2130
+ }
2131
+ else if (/^\d*\.\d+$/.test(value)) {
2132
+ result[key] = parseFloat(value);
2133
+ }
2134
+ else {
2135
+ result[key] = value;
2136
+ }
2137
+ }
2138
+ }
2139
+ return result;
2140
+ }
2141
+ /**
2142
+ * Parse TOML content (basic implementation)
2143
+ * For a full implementation, you'd want to use a proper TOML library
2144
+ */
2145
+ parseTOML(content) {
2146
+ // This is a very basic TOML parser for simple key-value pairs
2147
+ // For production use, consider integrating a proper TOML library
2148
+ const lines = content.split('\n');
2149
+ const result = {};
2150
+ let currentSection = '';
2151
+ for (const line of lines) {
2152
+ const trimmedLine = line.trim();
2153
+ if (!trimmedLine || trimmedLine.startsWith('#')) {
2154
+ continue;
2155
+ }
2156
+ // Section headers [section]
2157
+ if (trimmedLine.startsWith('[') && trimmedLine.endsWith(']')) {
2158
+ currentSection = trimmedLine.slice(1, -1);
2159
+ if (!result[currentSection]) {
2160
+ result[currentSection] = {};
2161
+ }
2162
+ continue;
2163
+ }
2164
+ // Key-value pairs
2165
+ const equalIndex = trimmedLine.indexOf('=');
2166
+ if (equalIndex > 0) {
2167
+ const key = trimmedLine.substring(0, equalIndex).trim();
2168
+ let value = trimmedLine.substring(equalIndex + 1).trim();
2169
+ // Remove quotes if present
2170
+ if ((value.startsWith('"') && value.endsWith('"')) ||
2171
+ (value.startsWith("'") && value.endsWith("'"))) {
2172
+ value = value.slice(1, -1);
2173
+ }
2174
+ // Parse value
2175
+ let parsedValue;
2176
+ if (value === 'true') {
2177
+ parsedValue = true;
2178
+ }
2179
+ else if (value === 'false') {
2180
+ parsedValue = false;
2181
+ }
2182
+ else if (/^\d+$/.test(value)) {
2183
+ parsedValue = parseInt(value, 10);
2184
+ }
2185
+ else if (/^\d*\.\d+$/.test(value)) {
2186
+ parsedValue = parseFloat(value);
2187
+ }
2188
+ else {
2189
+ parsedValue = value;
2190
+ }
2191
+ if (currentSection) {
2192
+ result[currentSection][key] = parsedValue;
2193
+ }
2194
+ else {
2195
+ result[key] = parsedValue;
2196
+ }
2197
+ }
2198
+ }
2199
+ return result;
2200
+ }
2201
+ /**
2202
+ * Parse CSV content (basic implementation)
2203
+ */
2204
+ parseCSV(content) {
2205
+ const lines = content.trim().split('\n');
2206
+ if (lines.length === 0) {
2207
+ return [];
2208
+ }
2209
+ // Parse header row
2210
+ const headers = this.parseCSVLine(lines[0]);
2211
+ const result = [];
2212
+ // Parse data rows
2213
+ for (let i = 1; i < lines.length; i++) {
2214
+ const values = this.parseCSVLine(lines[i]);
2215
+ const row = {};
2216
+ for (let j = 0; j < headers.length; j++) {
2217
+ const header = headers[j];
2218
+ const value = j < values.length ? values[j] : '';
2219
+ // Try to parse as number
2220
+ if (/^\d+$/.test(value)) {
2221
+ row[header] = parseInt(value, 10);
2222
+ }
2223
+ else if (/^\d*\.\d+$/.test(value)) {
2224
+ row[header] = parseFloat(value);
2225
+ }
2226
+ else if (value === 'true') {
2227
+ row[header] = true;
2228
+ }
2229
+ else if (value === 'false') {
2230
+ row[header] = false;
2231
+ }
2232
+ else {
2233
+ row[header] = value;
2234
+ }
2235
+ }
2236
+ result.push(row);
2237
+ }
2238
+ return result;
2239
+ }
2240
+ /**
2241
+ * Parse a single CSV line, handling quoted values
2242
+ */
2243
+ parseCSVLine(line) {
2244
+ const result = [];
2245
+ let current = '';
2246
+ let inQuotes = false;
2247
+ for (let i = 0; i < line.length; i++) {
2248
+ const char = line[i];
2249
+ if (char === '"') {
2250
+ if (inQuotes && line[i + 1] === '"') {
2251
+ // Escaped quote
2252
+ current += '"';
2253
+ i++; // Skip next quote
2254
+ }
2255
+ else {
2256
+ // Toggle quote state
2257
+ inQuotes = !inQuotes;
2258
+ }
2259
+ }
2260
+ else if (char === ',' && !inQuotes) {
2261
+ // Field separator
2262
+ result.push(current.trim());
2263
+ current = '';
2264
+ }
2265
+ else {
2266
+ current += char;
2267
+ }
2268
+ }
2269
+ // Add the last field
2270
+ result.push(current.trim());
2271
+ return result;
2272
+ }
1887
2273
  /**
1888
2274
  * Get nested value from object using dot notation path
1889
2275
  * Following golang's path resolution logic