@utilarium/dreadcabinet 0.0.16-dev.0

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 (128) hide show
  1. package/.nvmrc +2 -0
  2. package/LICENSE +190 -0
  3. package/README.md +95 -0
  4. package/dist/configure.d.ts +5 -0
  5. package/dist/configure.js +44 -0
  6. package/dist/configure.js.map +1 -0
  7. package/dist/constants.d.ts +36 -0
  8. package/dist/constants.js +53 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/defaults.d.ts +2 -0
  11. package/dist/defaults.js +32 -0
  12. package/dist/defaults.js.map +1 -0
  13. package/dist/dreadcabinet.cjs +1793 -0
  14. package/dist/dreadcabinet.cjs.map +1 -0
  15. package/dist/dreadcabinet.d.ts +131 -0
  16. package/dist/dreadcabinet.js +111 -0
  17. package/dist/dreadcabinet.js.map +1 -0
  18. package/dist/error/ArgumentError.d.ts +5 -0
  19. package/dist/error/ArgumentError.js +26 -0
  20. package/dist/error/ArgumentError.js.map +1 -0
  21. package/dist/input/input.d.ts +7 -0
  22. package/dist/input/input.js +13 -0
  23. package/dist/input/input.js.map +1 -0
  24. package/dist/input/process.d.ts +5 -0
  25. package/dist/input/process.js +36 -0
  26. package/dist/input/process.js.map +1 -0
  27. package/dist/input/structured.d.ts +15 -0
  28. package/dist/input/structured.js +324 -0
  29. package/dist/input/structured.js.map +1 -0
  30. package/dist/input/unstructured.d.ts +2 -0
  31. package/dist/input/unstructured.js +45 -0
  32. package/dist/input/unstructured.js.map +1 -0
  33. package/dist/logger.d.ts +2 -0
  34. package/dist/logger.js +19 -0
  35. package/dist/logger.js.map +1 -0
  36. package/dist/operate.d.ts +2 -0
  37. package/dist/operate.js +27 -0
  38. package/dist/operate.js.map +1 -0
  39. package/dist/output.d.ts +7 -0
  40. package/dist/output.js +99 -0
  41. package/dist/output.js.map +1 -0
  42. package/dist/read.d.ts +4 -0
  43. package/dist/read.js +30 -0
  44. package/dist/read.js.map +1 -0
  45. package/dist/util/dates.d.ts +60 -0
  46. package/dist/util/dates.js +699 -0
  47. package/dist/util/dates.js.map +1 -0
  48. package/dist/util/storage.d.ts +33 -0
  49. package/dist/util/storage.js +140 -0
  50. package/dist/util/storage.js.map +1 -0
  51. package/dist/validate.d.ts +4 -0
  52. package/dist/validate.js +134 -0
  53. package/dist/validate.js.map +1 -0
  54. package/guide/architecture.md +60 -0
  55. package/guide/configuration.md +132 -0
  56. package/guide/development.md +110 -0
  57. package/guide/index.md +62 -0
  58. package/guide/usage.md +166 -0
  59. package/output/kodrdriv/250703-0645-commit-message.md +21 -0
  60. package/output/kodrdriv/250703-0653-commit-message.md +1 -0
  61. package/output/kodrdriv/250703-0654-commit-message.md +1 -0
  62. package/output/kodrdriv/250703-0655-release-notes.md +51 -0
  63. package/output/kodrdriv/250703-0700-commit-message.md +1 -0
  64. package/output/kodrdriv/250703-0700-release-notes.md +8 -0
  65. package/output/kodrdriv/250703-0706-commit-message.md +1 -0
  66. package/output/kodrdriv/250703-0706-release-notes.md +11 -0
  67. package/output/kodrdriv/250703-0717-commit-message.md +1 -0
  68. package/output/kodrdriv/250703-0719-commit-message.md +1 -0
  69. package/output/kodrdriv/250703-0719-release-notes.md +17 -0
  70. package/output/kodrdriv/250703-0730-commit-message.md +1 -0
  71. package/output/kodrdriv/250703-0730-release-notes.md +11 -0
  72. package/output/kodrdriv/250703-1510-commit-message.md +1 -0
  73. package/output/kodrdriv/250710-0805-commit-message.md +3 -0
  74. package/output/kodrdriv/250710-0815-commit-message.md +1 -0
  75. package/output/kodrdriv/250710-0815-release-notes.md +39 -0
  76. package/output/kodrdriv/260107-2021-commit-message.md +37 -0
  77. package/output/kodrdriv/260108-0432-commit-message.md +6 -0
  78. package/output/kodrdriv/260108-0435-commit-message.md +3 -0
  79. package/output/kodrdriv/260108-0436-commit-message.md +4 -0
  80. package/output/kodrdriv/260108-0439-release-notes.md +63 -0
  81. package/output/kodrdriv/260108-0543-commit-message.md +19 -0
  82. package/output/kodrdriv/260108-0550-commit-message.md +3 -0
  83. package/output/kodrdriv/260108-0550-release-notes.md +19 -0
  84. package/output/kodrdriv/260108-0600-commit-message.md +3 -0
  85. package/output/kodrdriv/260110-0717-commit-message.md +4 -0
  86. package/output/kodrdriv/260110-1152-commit-message.md +1 -0
  87. package/output/kodrdriv/260110-1850-commit-message.md +1 -0
  88. package/output/kodrdriv/260110-1852-release-notes.md +33 -0
  89. package/output/kodrdriv/260112-2257-commit-message.md +5 -0
  90. package/output/kodrdriv/260112-2317-commit-message.md +1 -0
  91. package/output/kodrdriv/260112-2318-release-notes.md +42 -0
  92. package/output/kodrdriv/260113-0053-commit-message.md +1 -0
  93. package/output/kodrdriv/260113-0054-commit-message.md +1 -0
  94. package/output/kodrdriv/260113-0054-release-notes.md +49 -0
  95. package/output/kodrdriv/260130-1132-commit-message.md +1 -0
  96. package/output/kodrdriv/260130-1135-commit-message.md +1 -0
  97. package/output/kodrdriv/260130-1335-commit-message.md +10 -0
  98. package/output/kodrdriv/RELEASE_NOTES.md +47 -0
  99. package/output/kodrdriv/RELEASE_TITLE.md +1 -0
  100. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T04-21-54-623Z.md +372 -0
  101. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T12-32-36-513Z.md +55 -0
  102. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T12-35-58-580Z.md +105 -0
  103. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T12-36-05-658Z.md +53 -0
  104. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T13-43-55-498Z.md +178 -0
  105. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T13-50-10-230Z.md +53 -0
  106. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T13-50-35-136Z.md +52 -0
  107. package/output/kodrdriv/agentic-reflection-commit-2026-01-08T14-00-30-772Z.md +52 -0
  108. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T15-17-43-324Z.md +53 -0
  109. package/output/kodrdriv/agentic-reflection-commit-2026-01-10T19-52-47-424Z.md +97 -0
  110. package/output/kodrdriv/agentic-reflection-commit-2026-01-11T02-50-23-123Z.md +138 -0
  111. package/output/kodrdriv/agentic-reflection-commit-2026-01-11T02-50-45-038Z.md +114 -0
  112. package/output/kodrdriv/agentic-reflection-commit-2026-01-11T02-50-49-467Z.md +114 -0
  113. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T06-57-00-384Z.md +169 -0
  114. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T07-17-29-292Z.md +114 -0
  115. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T07-17-47-579Z.md +114 -0
  116. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T08-48-55-599Z.md +144 -0
  117. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T08-53-53-725Z.md +114 -0
  118. package/output/kodrdriv/agentic-reflection-commit-2026-01-13T08-54-11-600Z.md +97 -0
  119. package/output/kodrdriv/agentic-reflection-commit-2026-01-30T19-32-17-053Z.md +174 -0
  120. package/output/kodrdriv/agentic-reflection-commit-2026-01-30T19-35-00-887Z.md +152 -0
  121. package/output/kodrdriv/agentic-reflection-commit-2026-01-30T21-02-16-553Z.md +236 -0
  122. package/output/kodrdriv/agentic-reflection-commit-2026-01-30T21-17-22-227Z.md +347 -0
  123. package/output/kodrdriv/agentic-reflection-release-2026-01-08T12-39-08-279Z.md +507 -0
  124. package/output/kodrdriv/agentic-reflection-release-2026-01-08T13-50-57-683Z.md +183 -0
  125. package/output/kodrdriv/agentic-reflection-release-2026-01-11T02-52-39-082Z.md +347 -0
  126. package/output/kodrdriv/agentic-reflection-release-2026-01-13T07-18-21-218Z.md +315 -0
  127. package/output/kodrdriv/agentic-reflection-release-2026-01-13T08-54-59-340Z.md +354 -0
  128. package/package.json +80 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dates.js","sources":["../../src/util/dates.ts"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport dayjs from 'dayjs';\nimport timezone from 'dayjs/plugin/timezone';\nimport utc from 'dayjs/plugin/utc';\n\ndayjs.extend(utc);\ndayjs.extend(timezone);\n\n// Static list of IANA timezone names (replaces moment-timezone dependency)\nconst TIMEZONE_NAMES = [\n 'Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', 'Africa/Asmara', 'Africa/Asmera',\n 'Africa/Bamako', 'Africa/Bangui', 'Africa/Banjul', 'Africa/Bissau', 'Africa/Blantyre', 'Africa/Brazzaville',\n 'Africa/Bujumbura', 'Africa/Cairo', 'Africa/Casablanca', 'Africa/Ceuta', 'Africa/Conakry', 'Africa/Dakar',\n 'Africa/Dar_es_Salaam', 'Africa/Djibouti', 'Africa/Douala', 'Africa/El_Aaiun', 'Africa/Freetown', 'Africa/Gaborone',\n 'Africa/Harare', 'Africa/Johannesburg', 'Africa/Juba', 'Africa/Kampala', 'Africa/Khartoum', 'Africa/Kigali',\n 'Africa/Kinshasa', 'Africa/Lagos', 'Africa/Libreville', 'Africa/Lome', 'Africa/Luanda', 'Africa/Lubumbashi',\n 'Africa/Lusaka', 'Africa/Malabo', 'Africa/Maputo', 'Africa/Maseru', 'Africa/Mbabane', 'Africa/Mogadishu',\n 'Africa/Monrovia', 'Africa/Nairobi', 'Africa/Ndjamena', 'Africa/Niamey', 'Africa/Nouakchott', 'Africa/Ouagadougou',\n 'Africa/Porto-Novo', 'Africa/Sao_Tome', 'Africa/Timbuktu', 'Africa/Tripoli', 'Africa/Tunis', 'Africa/Windhoek',\n 'America/Adak', 'America/Anchorage', 'America/Anguilla', 'America/Antigua', 'America/Araguaina',\n 'America/Argentina/Buenos_Aires', 'America/Argentina/Catamarca', 'America/Argentina/ComodRivadavia',\n 'America/Argentina/Cordoba', 'America/Argentina/Jujuy', 'America/Argentina/La_Rioja', 'America/Argentina/Mendoza',\n 'America/Argentina/Rio_Gallegos', 'America/Argentina/Salta', 'America/Argentina/San_Juan', 'America/Argentina/San_Luis',\n 'America/Argentina/Tucuman', 'America/Argentina/Ushuaia', 'America/Aruba', 'America/Asuncion', 'America/Atikokan',\n 'America/Atka', 'America/Bahia', 'America/Bahia_Banderas', 'America/Barbados', 'America/Belem', 'America/Belize',\n 'America/Blanc-Sablon', 'America/Boa_Vista', 'America/Bogota', 'America/Boise', 'America/Buenos_Aires',\n 'America/Cambridge_Bay', 'America/Campo_Grande', 'America/Cancun', 'America/Caracas', 'America/Catamarca',\n 'America/Cayenne', 'America/Cayman', 'America/Chicago', 'America/Chihuahua', 'America/Coral_Harbour',\n 'America/Cordoba', 'America/Costa_Rica', 'America/Creston', 'America/Cuiaba', 'America/Curacao',\n 'America/Danmarkshavn', 'America/Dawson', 'America/Dawson_Creek', 'America/Denver', 'America/Detroit',\n 'America/Dominica', 'America/Edmonton', 'America/Eirunepe', 'America/El_Salvador', 'America/Ensenada',\n 'America/Fort_Nelson', 'America/Fort_Wayne', 'America/Fortaleza', 'America/Glace_Bay', 'America/Godthab',\n 'America/Goose_Bay', 'America/Grand_Turk', 'America/Grenada', 'America/Guadeloupe', 'America/Guatemala',\n 'America/Guayaquil', 'America/Guyana', 'America/Halifax', 'America/Havana', 'America/Hermosillo',\n 'America/Indiana/Indianapolis', 'America/Indiana/Knox', 'America/Indiana/Marengo', 'America/Indiana/Petersburg',\n 'America/Indiana/Tell_City', 'America/Indiana/Vevay', 'America/Indiana/Vincennes', 'America/Indiana/Winamac',\n 'America/Indianapolis', 'America/Inuvik', 'America/Iqaluit', 'America/Jamaica', 'America/Jujuy', 'America/Juneau',\n 'America/Kentucky/Louisville', 'America/Kentucky/Monticello', 'America/Knox_IN', 'America/Kralendijk',\n 'America/La_Paz', 'America/Lima', 'America/Los_Angeles', 'America/Louisville', 'America/Lower_Princes',\n 'America/Maceio', 'America/Managua', 'America/Manaus', 'America/Marigot', 'America/Martinique',\n 'America/Matamoros', 'America/Mazatlan', 'America/Mendoza', 'America/Menominee', 'America/Merida',\n 'America/Metlakatla', 'America/Mexico_City', 'America/Miquelon', 'America/Moncton', 'America/Monterrey',\n 'America/Montevideo', 'America/Montreal', 'America/Montserrat', 'America/Nassau', 'America/New_York',\n 'America/Nipigon', 'America/Nome', 'America/Noronha', 'America/North_Dakota/Beulah', 'America/North_Dakota/Center',\n 'America/North_Dakota/New_Salem', 'America/Ojinaga', 'America/Panama', 'America/Pangnirtung', 'America/Paramaribo',\n 'America/Phoenix', 'America/Port-au-Prince', 'America/Port_of_Spain', 'America/Porto_Acre', 'America/Porto_Velho',\n 'America/Puerto_Rico', 'America/Punta_Arenas', 'America/Rainy_River', 'America/Rankin_Inlet', 'America/Recife',\n 'America/Regina', 'America/Resolute', 'America/Rio_Branco', 'America/Rosario', 'America/Santa_Isabel',\n 'America/Santarem', 'America/Santiago', 'America/Santo_Domingo', 'America/Sao_Paulo', 'America/Scoresbysund',\n 'America/Shiprock', 'America/Sitka', 'America/St_Barthelemy', 'America/St_Johns', 'America/St_Kitts',\n 'America/St_Lucia', 'America/St_Thomas', 'America/St_Vincent', 'America/Swift_Current', 'America/Tegucigalpa',\n 'America/Thule', 'America/Thunder_Bay', 'America/Tijuana', 'America/Toronto', 'America/Tortola',\n 'America/Vancouver', 'America/Virgin', 'America/Whitehorse', 'America/Winnipeg', 'America/Yakutat',\n 'America/Yellowknife', 'Antarctica/Casey', 'Antarctica/Davis', 'Antarctica/DumontDUrville', 'Antarctica/Macquarie',\n 'Antarctica/Mawson', 'Antarctica/McMurdo', 'Antarctica/Palmer', 'Antarctica/Rothera', 'Antarctica/South_Pole',\n 'Antarctica/Syowa', 'Antarctica/Troll', 'Antarctica/Vostok', 'Arctic/Longyearbyen', 'Asia/Aden', 'Asia/Almaty',\n 'Asia/Amman', 'Asia/Anadyr', 'Asia/Aqtau', 'Asia/Aqtobe', 'Asia/Ashgabat', 'Asia/Ashkhabad', 'Asia/Atyrau',\n 'Asia/Baghdad', 'Asia/Bahrain', 'Asia/Baku', 'Asia/Bangkok', 'Asia/Barnaul', 'Asia/Beirut', 'Asia/Bishkek',\n 'Asia/Brunei', 'Asia/Calcutta', 'Asia/Chita', 'Asia/Choibalsan', 'Asia/Chongqing', 'Asia/Chungking',\n 'Asia/Colombo', 'Asia/Dacca', 'Asia/Damascus', 'Asia/Dhaka', 'Asia/Dili', 'Asia/Dubai', 'Asia/Dushanbe',\n 'Asia/Famagusta', 'Asia/Gaza', 'Asia/Harbin', 'Asia/Hebron', 'Asia/Ho_Chi_Minh', 'Asia/Hong_Kong', 'Asia/Hovd',\n 'Asia/Irkutsk', 'Asia/Istanbul', 'Asia/Jakarta', 'Asia/Jayapura', 'Asia/Jerusalem', 'Asia/Kabul', 'Asia/Kamchatka',\n 'Asia/Karachi', 'Asia/Kashgar', 'Asia/Kathmandu', 'Asia/Katmandu', 'Asia/Khandyga', 'Asia/Kolkata',\n 'Asia/Krasnoyarsk', 'Asia/Kuala_Lumpur', 'Asia/Kuching', 'Asia/Kuwait', 'Asia/Macao', 'Asia/Macau',\n 'Asia/Magadan', 'Asia/Makassar', 'Asia/Manila', 'Asia/Muscat', 'Asia/Nicosia', 'Asia/Novokuznetsk',\n 'Asia/Novosibirsk', 'Asia/Omsk', 'Asia/Oral', 'Asia/Phnom_Penh', 'Asia/Pontianak', 'Asia/Pyongyang',\n 'Asia/Qatar', 'Asia/Qyzylorda', 'Asia/Rangoon', 'Asia/Riyadh', 'Asia/Saigon', 'Asia/Sakhalin', 'Asia/Samarkand',\n 'Asia/Seoul', 'Asia/Shanghai', 'Asia/Singapore', 'Asia/Srednekolymsk', 'Asia/Taipei', 'Asia/Tashkent',\n 'Asia/Tbilisi', 'Asia/Tehran', 'Asia/Tel_Aviv', 'Asia/Thimbu', 'Asia/Thimphu', 'Asia/Tokyo', 'Asia/Tomsk',\n 'Asia/Ujung_Pandang', 'Asia/Ulaanbaatar', 'Asia/Ulan_Bator', 'Asia/Urumqi', 'Asia/Ust-Nera', 'Asia/Vientiane',\n 'Asia/Vladivostok', 'Asia/Yakutsk', 'Asia/Yangon', 'Asia/Yekaterinburg', 'Asia/Yerevan', 'Atlantic/Azores',\n 'Atlantic/Bermuda', 'Atlantic/Canary', 'Atlantic/Cape_Verde', 'Atlantic/Faeroe', 'Atlantic/Faroe',\n 'Atlantic/Jan_Mayen', 'Atlantic/Madeira', 'Atlantic/Reykjavik', 'Atlantic/South_Georgia', 'Atlantic/St_Helena',\n 'Atlantic/Stanley', 'Australia/ACT', 'Australia/Adelaide', 'Australia/Brisbane', 'Australia/Broken_Hill',\n 'Australia/Canberra', 'Australia/Currie', 'Australia/Darwin', 'Australia/Eucla', 'Australia/Hobart',\n 'Australia/LHI', 'Australia/Lindeman', 'Australia/Lord_Howe', 'Australia/Melbourne', 'Australia/NSW',\n 'Australia/North', 'Australia/Perth', 'Australia/Queensland', 'Australia/South', 'Australia/Sydney',\n 'Australia/Tasmania', 'Australia/Victoria', 'Australia/West', 'Australia/Yancowinna', 'Brazil/Acre',\n 'Brazil/DeNoronha', 'Brazil/East', 'Brazil/West', 'CET', 'CST6CDT', 'Canada/Atlantic', 'Canada/Central',\n 'Canada/Eastern', 'Canada/Mountain', 'Canada/Newfoundland', 'Canada/Pacific', 'Canada/Saskatchewan',\n 'Canada/Yukon', 'Chile/Continental', 'Chile/EasterIsland', 'Cuba', 'EET', 'EST', 'EST5EDT', 'Egypt', 'Eire',\n 'Etc/GMT', 'Etc/GMT+0', 'Etc/GMT+1', 'Etc/GMT+10', 'Etc/GMT+11', 'Etc/GMT+12', 'Etc/GMT+2', 'Etc/GMT+3',\n 'Etc/GMT+4', 'Etc/GMT+5', 'Etc/GMT+6', 'Etc/GMT+7', 'Etc/GMT+8', 'Etc/GMT+9', 'Etc/GMT-0', 'Etc/GMT-1',\n 'Etc/GMT-10', 'Etc/GMT-11', 'Etc/GMT-12', 'Etc/GMT-13', 'Etc/GMT-14', 'Etc/GMT-2', 'Etc/GMT-3', 'Etc/GMT-4',\n 'Etc/GMT-5', 'Etc/GMT-6', 'Etc/GMT-7', 'Etc/GMT-8', 'Etc/GMT-9', 'Etc/GMT0', 'Etc/Greenwich', 'Etc/UCT',\n 'Etc/UTC', 'Etc/Universal', 'Etc/Zulu', 'Europe/Amsterdam', 'Europe/Andorra', 'Europe/Astrakhan', 'Europe/Athens',\n 'Europe/Belfast', 'Europe/Belgrade', 'Europe/Berlin', 'Europe/Bratislava', 'Europe/Brussels', 'Europe/Bucharest',\n 'Europe/Budapest', 'Europe/Busingen', 'Europe/Chisinau', 'Europe/Copenhagen', 'Europe/Dublin', 'Europe/Gibraltar',\n 'Europe/Guernsey', 'Europe/Helsinki', 'Europe/Isle_of_Man', 'Europe/Istanbul', 'Europe/Jersey', 'Europe/Kaliningrad',\n 'Europe/Kiev', 'Europe/Kirov', 'Europe/Lisbon', 'Europe/Ljubljana', 'Europe/London', 'Europe/Luxembourg',\n 'Europe/Madrid', 'Europe/Malta', 'Europe/Mariehamn', 'Europe/Minsk', 'Europe/Monaco', 'Europe/Moscow',\n 'Europe/Nicosia', 'Europe/Oslo', 'Europe/Paris', 'Europe/Podgorica', 'Europe/Prague', 'Europe/Riga',\n 'Europe/Rome', 'Europe/Samara', 'Europe/San_Marino', 'Europe/Sarajevo', 'Europe/Saratov', 'Europe/Simferopol',\n 'Europe/Skopje', 'Europe/Sofia', 'Europe/Stockholm', 'Europe/Tallinn', 'Europe/Tirane', 'Europe/Tiraspol',\n 'Europe/Ulyanovsk', 'Europe/Uzhgorod', 'Europe/Vaduz', 'Europe/Vatican', 'Europe/Vienna', 'Europe/Vilnius',\n 'Europe/Volgograd', 'Europe/Warsaw', 'Europe/Zagreb', 'Europe/Zaporozhye', 'Europe/Zurich', 'GB', 'GB-Eire',\n 'GMT', 'GMT+0', 'GMT-0', 'GMT0', 'Greenwich', 'HST', 'Hongkong', 'Iceland', 'Indian/Antananarivo', 'Indian/Chagos',\n 'Indian/Christmas', 'Indian/Cocos', 'Indian/Comoro', 'Indian/Kerguelen', 'Indian/Mahe', 'Indian/Maldives',\n 'Indian/Mauritius', 'Indian/Mayotte', 'Indian/Reunion', 'Iran', 'Israel', 'Jamaica', 'Japan', 'Kwajalein',\n 'Libya', 'MET', 'MST', 'MST7MDT', 'Mexico/BajaNorte', 'Mexico/BajaSur', 'Mexico/General', 'NZ', 'NZ-CHAT',\n 'Navajo', 'PRC', 'PST8PDT', 'Pacific/Apia', 'Pacific/Auckland', 'Pacific/Bougainville', 'Pacific/Chatham',\n 'Pacific/Chuuk', 'Pacific/Easter', 'Pacific/Efate', 'Pacific/Enderbury', 'Pacific/Fakaofo', 'Pacific/Fiji',\n 'Pacific/Funafuti', 'Pacific/Galapagos', 'Pacific/Gambier', 'Pacific/Guadalcanal', 'Pacific/Guam',\n 'Pacific/Honolulu', 'Pacific/Johnston', 'Pacific/Kiritimati', 'Pacific/Kosrae', 'Pacific/Kwajalein',\n 'Pacific/Majuro', 'Pacific/Marquesas', 'Pacific/Midway', 'Pacific/Nauru', 'Pacific/Niue', 'Pacific/Norfolk',\n 'Pacific/Noumea', 'Pacific/Pago_Pago', 'Pacific/Palau', 'Pacific/Pitcairn', 'Pacific/Pohnpei', 'Pacific/Ponape',\n 'Pacific/Port_Moresby', 'Pacific/Rarotonga', 'Pacific/Saipan', 'Pacific/Samoa', 'Pacific/Tahiti', 'Pacific/Tarawa',\n 'Pacific/Tongatapu', 'Pacific/Truk', 'Pacific/Wake', 'Pacific/Wallis', 'Pacific/Yap', 'Poland', 'Portugal',\n 'ROC', 'ROK', 'Singapore', 'Turkey', 'UCT', 'US/Alaska', 'US/Aleutian', 'US/Arizona', 'US/Central',\n 'US/East-Indiana', 'US/Eastern', 'US/Hawaii', 'US/Indiana-Starke', 'US/Michigan', 'US/Mountain', 'US/Pacific',\n 'US/Pacific-New', 'US/Samoa', 'UTC', 'Universal', 'W-SU', 'WET', 'Zulu'\n];\n\n/**\n * Yes, wrapping dayjs is a bit annoying and might seem overly paranoid. However, I feel strongly\n * about not letting Dayjs instances leak into the rest of the codebase. Having Dayjs objects\n * floating around the application leads to inconsistent timezone handling, makes testing more\n * difficult, and creates subtle bugs that are hard to track down.\n *\n * By wrapping dayjs completely and only exposing plain JavaScript Date objects, we get several\n * key benefits:\n * 1. Consistent timezone handling through a single configuration point\n * 2. Simpler testing since we only need to mock this one library\n * 3. Type safety - the rest of the codebase only deals with standard Date objects\n * 4. No risk of dayjs method chains creating unexpected timezone shifts\n *\n * The Library interface gives us full control over all date operations while keeping the messy\n * details of timezone manipulation contained in one place. Yes it's more code, but the peace of\n * mind is worth it.\n */\nexport interface Utility {\n now: () => Date;\n today: () => string;\n date: (date: string | number | Date | null | undefined) => Date;\n parse: (date: string | number | Date | null | undefined, format: string) => Date;\n isValidDate: (date: string, format: string) => boolean;\n addDays: (date: Date, days: number) => Date;\n addMonths: (date: Date, months: number) => Date;\n addYears: (date: Date, years: number) => Date;\n format: (date: Date, format: string) => string;\n subDays: (date: Date, days: number) => Date;\n subMonths: (date: Date, months: number) => Date;\n subYears: (date: Date, years: number) => Date;\n startOfMonth: (date: Date) => Date;\n endOfMonth: (date: Date) => Date;\n startOfYear: (date: Date) => Date;\n endOfYear: (date: Date) => Date;\n isBefore: (date: Date, other: Date) => boolean;\n isAfter: (date: Date, other: Date) => boolean;\n}\n\nexport const create = (parameters: { timezone: string }) => {\n const { timezone } = parameters;\n const now = () => {\n return dayjs().tz(timezone).toDate();\n }\n\n const today = () => {\n // Return today's date formatted as YYYY-M-D in the specified timezone\n return dayjs().tz(timezone).format('YYYY-M-D');\n }\n\n const date = (date: string | number | Date | null | undefined) => {\n let value: dayjs.Dayjs;\n if (date) {\n value = dayjs.tz(date, timezone);\n } else {\n value = dayjs().tz(timezone);\n }\n\n if (!value.isValid()) {\n throw new Error(`Invalid date: ${date}`);\n }\n\n return value.toDate();\n }\n\n const parse = (date: string | number | Date | null | undefined, format: string) => {\n const value = dayjs.tz(date, format, timezone);\n if (!value.isValid()) {\n throw new Error(`Invalid date: ${date}, expected format: ${format}`);\n }\n\n return value.toDate();\n }\n\n const isValidDate = (date: string, format: string): boolean => {\n return dayjs(date, format, true).isValid(); // Use strict parsing\n }\n\n const addDays = (date: Date, days: number) => {\n return dayjs.tz(date, timezone).add(days, 'day').toDate();\n }\n\n const addMonths = (date: Date, months: number) => {\n return dayjs.tz(date, timezone).add(months, 'month').toDate();\n }\n\n const addYears = (date: Date, years: number) => {\n return dayjs.tz(date, timezone).add(years, 'year').toDate();\n }\n\n const format = (date: Date, format: string) => {\n return dayjs.tz(date, timezone).format(format);\n }\n\n const subDays = (date: Date, days: number) => {\n return dayjs.tz(date, timezone).subtract(days, 'day').toDate();\n }\n\n const subMonths = (date: Date, months: number) => {\n return dayjs.tz(date, timezone).subtract(months, 'month').toDate();\n }\n\n const subYears = (date: Date, years: number) => {\n return dayjs.tz(date, timezone).subtract(years, 'year').toDate();\n }\n\n const startOfMonth = (date: Date) => {\n return dayjs.tz(date, timezone).startOf('month').toDate();\n }\n\n const endOfMonth = (date: Date) => {\n return dayjs.tz(date, timezone).endOf('month').toDate();\n }\n\n const startOfYear = (date: Date) => {\n return dayjs.tz(date, timezone).startOf('year').toDate();\n }\n\n const endOfYear = (date: Date) => {\n return dayjs.tz(date, timezone).endOf('year').toDate();\n }\n\n const isBefore = (date: Date, other: Date) => {\n return dayjs.tz(date, timezone).isBefore(dayjs.tz(other, timezone));\n }\n\n const isAfter = (date: Date, other: Date) => {\n return dayjs.tz(date, timezone).isAfter(dayjs.tz(other, timezone));\n }\n\n return { now, today, date, parse, isValidDate, addDays, addMonths, addYears, format, subDays, subMonths, subYears, startOfMonth, endOfMonth, startOfYear, endOfYear, isBefore, isAfter };\n}\n\nexport const validTimezones = () => {\n return TIMEZONE_NAMES;\n}\n"],"names":["dayjs","extend","utc","timezone","TIMEZONE_NAMES","create","parameters","now","tz","toDate","today","format","date","value","isValid","Error","parse","isValidDate","addDays","days","add","addMonths","months","addYears","years","subDays","subtract","subMonths","subYears","startOfMonth","startOf","endOfMonth","endOf","startOfYear","endOfYear","isBefore","other","isAfter","validTimezones"],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import * as fs from 'node:fs';
2
+ /**
3
+ * This module exists to isolate filesystem operations from the rest of the codebase.
4
+ * This makes testing easier by avoiding direct fs mocking in jest configuration.
5
+ *
6
+ * Additionally, abstracting storage operations allows for future flexibility -
7
+ * this export utility may need to work with storage systems other than the local filesystem
8
+ * (e.g. S3, Google Cloud Storage, etc).
9
+ */
10
+ export interface Utility {
11
+ exists: (path: string) => Promise<boolean>;
12
+ isDirectory: (path: string) => Promise<boolean>;
13
+ isFile: (path: string) => Promise<boolean>;
14
+ isReadable: (path: string) => Promise<boolean>;
15
+ isWritable: (path: string) => Promise<boolean>;
16
+ isFileReadable: (path: string) => Promise<boolean>;
17
+ isDirectoryWritable: (path: string) => Promise<boolean>;
18
+ isDirectoryReadable: (path: string) => Promise<boolean>;
19
+ createDirectory: (path: string) => Promise<void>;
20
+ readFile: (path: string, encoding: string) => Promise<string>;
21
+ readStream: (path: string) => Promise<fs.ReadStream>;
22
+ writeFile: (path: string, data: string | Buffer, encoding: string) => Promise<void>;
23
+ forEachFileIn: (directory: string, callback: (path: string) => Promise<void>, options?: {
24
+ pattern: string;
25
+ limit?: number;
26
+ concurrency?: number;
27
+ }) => Promise<void>;
28
+ hashFile: (path: string, length: number) => Promise<string>;
29
+ listFiles: (directory: string) => Promise<string[]>;
30
+ }
31
+ export declare const create: (params: {
32
+ log?: (message: string, ...args: any[]) => void;
33
+ }) => Utility;
@@ -0,0 +1,140 @@
1
+ import * as fs from 'node:fs';
2
+ import { glob } from 'glob';
3
+ import * as path from 'node:path';
4
+ import * as crypto from 'node:crypto';
5
+
6
+ const create = (params)=>{
7
+ // eslint-disable-next-line no-console
8
+ const log = params.log || console.log;
9
+ const exists = async (path)=>{
10
+ try {
11
+ await fs.promises.stat(path);
12
+ return true;
13
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
14
+ } catch (error) {
15
+ return false;
16
+ }
17
+ };
18
+ const isDirectory = async (path)=>{
19
+ const stats = await fs.promises.stat(path);
20
+ if (!stats.isDirectory()) {
21
+ log(`${path} is not a directory`);
22
+ return false;
23
+ }
24
+ return true;
25
+ };
26
+ const isFile = async (path)=>{
27
+ const stats = await fs.promises.stat(path);
28
+ if (!stats.isFile()) {
29
+ log(`${path} is not a file`);
30
+ return false;
31
+ }
32
+ return true;
33
+ };
34
+ const isReadable = async (path)=>{
35
+ try {
36
+ await fs.promises.access(path, fs.constants.R_OK);
37
+ } catch (error) {
38
+ log(`${path} is not readable: %s %s`, error.message, error.stack);
39
+ return false;
40
+ }
41
+ return true;
42
+ };
43
+ const isWritable = async (path)=>{
44
+ try {
45
+ await fs.promises.access(path, fs.constants.W_OK);
46
+ } catch (error) {
47
+ log(`${path} is not writable: %s %s`, error.message, error.stack);
48
+ return false;
49
+ }
50
+ return true;
51
+ };
52
+ const isFileReadable = async (path)=>{
53
+ return await exists(path) && await isFile(path) && await isReadable(path);
54
+ };
55
+ const isDirectoryWritable = async (path)=>{
56
+ return await exists(path) && await isDirectory(path) && await isWritable(path);
57
+ };
58
+ const isDirectoryReadable = async (path)=>{
59
+ return await exists(path) && await isDirectory(path) && await isReadable(path);
60
+ };
61
+ const createDirectory = async (path)=>{
62
+ try {
63
+ await fs.promises.mkdir(path, {
64
+ recursive: true
65
+ });
66
+ } catch (mkdirError) {
67
+ throw new Error(`Failed to create output directory ${path}: ${mkdirError.message} ${mkdirError.stack}`);
68
+ }
69
+ };
70
+ const readFile = async (path, encoding)=>{
71
+ return await fs.promises.readFile(path, {
72
+ encoding: encoding
73
+ });
74
+ };
75
+ const writeFile = async (path, data, encoding)=>{
76
+ await fs.promises.writeFile(path, data, {
77
+ encoding: encoding
78
+ });
79
+ };
80
+ const forEachFileIn = async (directory, callback, options = {
81
+ pattern: '*.*'
82
+ })=>{
83
+ try {
84
+ let filesProcessed = 0;
85
+ const files = await glob(options.pattern, {
86
+ cwd: directory,
87
+ nodir: true
88
+ });
89
+ const concurrency = options.concurrency || 1;
90
+ let index = 0;
91
+ async function worker() {
92
+ while(index < files.length && (!options.limit || filesProcessed < options.limit)){
93
+ const i = index++;
94
+ if (options.limit && filesProcessed >= options.limit) break;
95
+ await callback(path.join(directory, files[i]));
96
+ filesProcessed++;
97
+ }
98
+ }
99
+ const workers = Array.from({
100
+ length: concurrency
101
+ }, ()=>worker());
102
+ await Promise.all(workers);
103
+ if (options.limit && filesProcessed >= options.limit) {
104
+ log(`Reached limit of ${options.limit} files, stopping`);
105
+ }
106
+ } catch (err) {
107
+ throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);
108
+ }
109
+ };
110
+ const readStream = async (path)=>{
111
+ return fs.createReadStream(path);
112
+ };
113
+ const hashFile = async (path, length)=>{
114
+ const file = await readFile(path, 'utf8');
115
+ return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);
116
+ };
117
+ const listFiles = async (directory)=>{
118
+ return await fs.promises.readdir(directory);
119
+ };
120
+ return {
121
+ exists,
122
+ isDirectory,
123
+ isFile,
124
+ isReadable,
125
+ isWritable,
126
+ isFileReadable,
127
+ isDirectoryWritable,
128
+ isDirectoryReadable,
129
+ createDirectory,
130
+ readFile,
131
+ readStream,
132
+ writeFile,
133
+ forEachFileIn,
134
+ hashFile,
135
+ listFiles
136
+ };
137
+ };
138
+
139
+ export { create };
140
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sources":["../../src/util/storage.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport { glob } from 'glob';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\n/**\n * This module exists to isolate filesystem operations from the rest of the codebase.\n * This makes testing easier by avoiding direct fs mocking in jest configuration.\n * \n * Additionally, abstracting storage operations allows for future flexibility - \n * this export utility may need to work with storage systems other than the local filesystem\n * (e.g. S3, Google Cloud Storage, etc).\n */\n\nexport interface Utility {\n exists: (path: string) => Promise<boolean>;\n isDirectory: (path: string) => Promise<boolean>;\n isFile: (path: string) => Promise<boolean>;\n isReadable: (path: string) => Promise<boolean>;\n isWritable: (path: string) => Promise<boolean>;\n isFileReadable: (path: string) => Promise<boolean>;\n isDirectoryWritable: (path: string) => Promise<boolean>;\n isDirectoryReadable: (path: string) => Promise<boolean>;\n createDirectory: (path: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n readStream: (path: string) => Promise<fs.ReadStream>;\n writeFile: (path: string, data: string | Buffer, encoding: string) => Promise<void>;\n forEachFileIn: (directory: string, callback: (path: string) => Promise<void>, options?: { pattern: string, limit?: number, concurrency?: number }) => Promise<void>;\n hashFile: (path: string, length: number) => Promise<string>;\n listFiles: (directory: string) => Promise<string[]>;\n}\n\nexport const create = (params: { log?: (message: string, ...args: any[]) => void }): Utility => {\n\n // eslint-disable-next-line no-console\n const log = params.log || console.log;\n\n const exists = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.stat(path);\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error: any) {\n return false;\n }\n }\n\n const isDirectory = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isDirectory()) {\n log(`${path} is not a directory`);\n return false;\n }\n return true;\n }\n\n const isFile = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isFile()) {\n log(`${path} is not a file`);\n return false;\n }\n return true;\n }\n\n const isReadable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.R_OK);\n } catch (error: any) {\n log(`${path} is not readable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isWritable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.W_OK);\n } catch (error: any) {\n log(`${path} is not writable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isFileReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isFile(path) && await isReadable(path);\n }\n\n const isDirectoryWritable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isWritable(path);\n }\n\n const isDirectoryReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isReadable(path);\n }\n\n const createDirectory = async (path: string): Promise<void> => {\n try {\n await fs.promises.mkdir(path, { recursive: true });\n } catch (mkdirError: any) {\n throw new Error(`Failed to create output directory ${path}: ${mkdirError.message} ${mkdirError.stack}`);\n }\n }\n\n const readFile = async (path: string, encoding: string): Promise<string> => {\n return await fs.promises.readFile(path, { encoding: encoding as BufferEncoding });\n }\n\n const writeFile = async (path: string, data: string | Buffer, encoding: string): Promise<void> => {\n await fs.promises.writeFile(path, data, { encoding: encoding as BufferEncoding });\n }\n\n const forEachFileIn = async (\n directory: string,\n callback: (file: string) => Promise<void>,\n options: { pattern: string | string[], limit?: number, concurrency?: number } = { pattern: '*.*' },\n ): Promise<void> => {\n try {\n let filesProcessed = 0;\n const files = await glob(options.pattern, { cwd: directory, nodir: true });\n const concurrency = options.concurrency || 1;\n let index = 0;\n async function worker() {\n while (index < files.length && (!options.limit || filesProcessed < options.limit)) {\n const i = index++;\n if (options.limit && filesProcessed >= options.limit) break;\n await callback(path.join(directory, files[i]));\n filesProcessed++;\n }\n }\n const workers = Array.from({ length: concurrency }, () => worker());\n await Promise.all(workers);\n if (options.limit && filesProcessed >= options.limit) {\n log(`Reached limit of ${options.limit} files, stopping`);\n }\n } catch (err: any) {\n throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);\n }\n }\n\n const readStream = async (path: string): Promise<fs.ReadStream> => {\n return fs.createReadStream(path);\n }\n\n const hashFile = async (path: string, length: number): Promise<string> => {\n const file = await readFile(path, 'utf8');\n return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);\n }\n\n const listFiles = async (directory: string): Promise<string[]> => {\n return await fs.promises.readdir(directory);\n }\n\n return {\n exists,\n isDirectory,\n isFile,\n isReadable,\n isWritable,\n isFileReadable,\n isDirectoryWritable,\n isDirectoryReadable,\n createDirectory,\n readFile,\n readStream,\n writeFile,\n forEachFileIn,\n hashFile,\n listFiles,\n };\n}"],"names":["create","params","log","console","exists","path","fs","promises","stat","error","isDirectory","stats","isFile","isReadable","access","constants","R_OK","message","stack","isWritable","W_OK","isFileReadable","isDirectoryWritable","isDirectoryReadable","createDirectory","mkdir","recursive","mkdirError","Error","readFile","encoding","writeFile","data","forEachFileIn","directory","callback","options","pattern","filesProcessed","files","glob","cwd","nodir","concurrency","index","worker","length","limit","i","join","workers","Array","from","Promise","all","err","readStream","createReadStream","hashFile","file","crypto","createHash","update","digest","slice","listFiles","readdir"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Config, Options } from './dreadcabinet';
2
+ import { ArgumentError } from './error/ArgumentError';
3
+ export { ArgumentError };
4
+ export declare const validate: (config: Config, options: Options) => Promise<void>;
@@ -0,0 +1,134 @@
1
+ import { ALLOWED_OUTPUT_STRUCTURES, ALLOWED_OUTPUT_FILENAME_OPTIONS, ALLOWED_EXTENSIONS, ALLOWED_INPUT_STRUCTURES, ALLOWED_INPUT_FILENAME_OPTIONS } from './constants.js';
2
+ import { ArgumentError } from './error/ArgumentError.js';
3
+ import { validTimezones } from './util/dates.js';
4
+ import { create } from './util/storage.js';
5
+
6
+ const validate = async (config, options)=>{
7
+ const logger = console;
8
+ const storage = create({
9
+ log: logger.debug
10
+ });
11
+ const validateInputDirectory = async (inputDirectory)=>{
12
+ // eslint-disable-next-line no-console
13
+ const storage = create({
14
+ log: console.log
15
+ });
16
+ if (!storage.isDirectoryReadable(inputDirectory)) {
17
+ throw new Error(`Input directory does not exist: ${inputDirectory}`);
18
+ }
19
+ };
20
+ const validateOutputDirectory = async (outputDirectory)=>{
21
+ const isDirectoryWritable = await storage.isDirectoryWritable(outputDirectory);
22
+ if (!isDirectoryWritable) {
23
+ throw new Error(`Output directory does not exist: ${outputDirectory}`);
24
+ }
25
+ };
26
+ const validateOutputStructure = (outputStructure)=>{
27
+ var _options_allowed;
28
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.outputStructures) || ALLOWED_OUTPUT_STRUCTURES;
29
+ if (outputStructure && !validOptions.includes(outputStructure)) {
30
+ throw new ArgumentError('--output-structure', `Invalid output structure: ${outputStructure}. Valid options are: ${validOptions.join(', ')}`);
31
+ }
32
+ };
33
+ const validateOutputFilenameOptions = (outputFilenameOptions, outputStructure)=>{
34
+ if (outputFilenameOptions) {
35
+ var _options_allowed;
36
+ // Check if first argument contains commas - likely a comma-separated list
37
+ if (outputFilenameOptions[0].includes(',')) {
38
+ throw new ArgumentError('--output-filename-options', 'Filename options should be space-separated, not comma-separated. Example: --output-filename-options date time subject');
39
+ }
40
+ // Check if first argument looks like a quoted string containing multiple options
41
+ if (outputFilenameOptions.length === 1 && outputFilenameOptions[0].split(' ').length > 1) {
42
+ throw new ArgumentError('--output-filename-options', 'Filename options should not be quoted. Use: --output-filename-options date time subject instead of --output-filename-options "date time subject"');
43
+ }
44
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.outputFilenameOptions) || ALLOWED_OUTPUT_FILENAME_OPTIONS;
45
+ const invalidOptions = outputFilenameOptions.filter((opt)=>!validOptions.includes(opt));
46
+ if (invalidOptions.length > 0) {
47
+ throw new ArgumentError('--output-filename-options', `Invalid filename options: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);
48
+ }
49
+ // Validate date option against output structure
50
+ if (outputFilenameOptions.includes('date')) {
51
+ if (outputStructure && outputStructure === 'day') {
52
+ throw new ArgumentError('--output-filename-options', 'Cannot use date in filename when output structure is "day"');
53
+ }
54
+ }
55
+ }
56
+ };
57
+ const validateInputStructure = (inputStructure)=>{
58
+ var _options_allowed;
59
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.inputStructures) || ALLOWED_INPUT_STRUCTURES;
60
+ if (inputStructure && !validOptions.includes(inputStructure)) {
61
+ throw new ArgumentError('--input-structure', `Invalid input structure: ${inputStructure}. Valid options are: ${validOptions.join(', ')}`);
62
+ }
63
+ };
64
+ const validateInputFilenameOptions = (inputFilenameOptions, inputStructure)=>{
65
+ if (inputFilenameOptions) {
66
+ var _options_allowed;
67
+ // Check if first argument contains commas - likely a comma-separated list
68
+ if (inputFilenameOptions[0].includes(',')) {
69
+ throw new ArgumentError('--input-filename-options', 'Filename options should be space-separated, not comma-separated. Example: --input-filename-options date time subject');
70
+ }
71
+ // Check if first argument looks like a quoted string containing multiple options
72
+ if (inputFilenameOptions.length === 1 && inputFilenameOptions[0].split(' ').length > 1) {
73
+ throw new ArgumentError('--input-filename-options', 'Filename options should not be quoted. Use: --input-filename-options date time subject instead of --input-filename-options "date time subject"');
74
+ }
75
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.inputFilenameOptions) || ALLOWED_INPUT_FILENAME_OPTIONS;
76
+ const invalidOptions = inputFilenameOptions.filter((opt)=>!validOptions.includes(opt));
77
+ if (invalidOptions.length > 0) {
78
+ throw new ArgumentError('--input-filename-options', `Invalid filename options: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);
79
+ }
80
+ // Validate date option against input structure
81
+ if (inputFilenameOptions.includes('date')) {
82
+ if (inputStructure && inputStructure === 'day') {
83
+ throw new ArgumentError('--input-filename-options', 'Cannot use date in filename when input structure is "day"');
84
+ }
85
+ }
86
+ }
87
+ };
88
+ const validateTimezone = (timezone)=>{
89
+ const validOptions = validTimezones();
90
+ if (validOptions.includes(timezone)) {
91
+ return;
92
+ }
93
+ throw new ArgumentError('--timezone', `Invalid timezone: ${timezone}. Valid options are: ${validOptions.join(', ')}`);
94
+ };
95
+ const validateExtensions = (extensions)=>{
96
+ var _options_allowed;
97
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.extensions) || ALLOWED_EXTENSIONS;
98
+ if (extensions) {
99
+ const invalidOptions = extensions.filter((ext)=>!validOptions.includes(ext));
100
+ if (invalidOptions.length > 0) {
101
+ throw new ArgumentError('--extensions', `Invalid extensions: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);
102
+ }
103
+ }
104
+ };
105
+ // Validate timezone
106
+ validateTimezone(config.timezone);
107
+ if (options.features.includes('input') && config.inputDirectory) {
108
+ await validateInputDirectory(config.inputDirectory);
109
+ }
110
+ if (options.features.includes('input') && config.limit) {
111
+ if (config.limit < 1) {
112
+ throw new ArgumentError('--limit', 'Limit must be greater than 0');
113
+ }
114
+ }
115
+ if (options.features.includes('output') && config.outputDirectory) {
116
+ await validateOutputDirectory(config.outputDirectory);
117
+ }
118
+ if (options.features.includes('structured-output')) {
119
+ // Validate filename options if provided
120
+ validateOutputStructure(config.outputStructure);
121
+ validateOutputFilenameOptions(config.outputFilenameOptions, config.outputStructure);
122
+ }
123
+ if (options.features.includes('extensions')) {
124
+ validateExtensions(config.extensions);
125
+ }
126
+ if (options.features.includes('structured-input')) {
127
+ validateInputStructure(config.inputStructure);
128
+ validateInputFilenameOptions(config.inputFilenameOptions, config.inputStructure);
129
+ }
130
+ return;
131
+ };
132
+
133
+ export { ArgumentError, validate };
134
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sources":["../src/validate.ts"],"sourcesContent":["import { Config } from \"./dreadcabinet\";\nimport {\n ALLOWED_EXTENSIONS,\n ALLOWED_INPUT_FILENAME_OPTIONS,\n ALLOWED_INPUT_STRUCTURES,\n ALLOWED_OUTPUT_FILENAME_OPTIONS,\n ALLOWED_OUTPUT_STRUCTURES,\n} from \"./constants\";\nimport { ArgumentError } from \"./error/ArgumentError\";\nimport { FilenameOption, FilesystemStructure, Options } from \"./dreadcabinet\";\nimport * as Dates from \"./util/dates\";\nimport * as Storage from \"./util/storage\";\n\nexport { ArgumentError };\n\nexport const validate = async (config: Config, options: Options): Promise<void> => {\n\n const logger: typeof console = console;\n const storage = Storage.create({ log: logger.debug });\n\n const validateInputDirectory = async (inputDirectory: string) => {\n // eslint-disable-next-line no-console\n const storage = Storage.create({ log: console.log });\n if (!storage.isDirectoryReadable(inputDirectory)) {\n throw new Error(`Input directory does not exist: ${inputDirectory}`);\n }\n }\n\n const validateOutputDirectory = async (outputDirectory: string) => {\n const isDirectoryWritable = await storage.isDirectoryWritable(outputDirectory);\n if (!isDirectoryWritable) {\n throw new Error(`Output directory does not exist: ${outputDirectory}`);\n }\n }\n\n const validateOutputStructure = (outputStructure: string | undefined): void => {\n const validOptions: FilesystemStructure[] = options.allowed?.outputStructures || ALLOWED_OUTPUT_STRUCTURES;\n if (outputStructure && !validOptions.includes(outputStructure as FilesystemStructure)) {\n throw new ArgumentError('--output-structure', `Invalid output structure: ${outputStructure}. Valid options are: ${validOptions.join(', ')}`);\n }\n }\n\n const validateOutputFilenameOptions = (outputFilenameOptions: string[] | undefined, outputStructure: FilesystemStructure | undefined): void => {\n if (outputFilenameOptions) {\n // Check if first argument contains commas - likely a comma-separated list\n if (outputFilenameOptions[0].includes(',')) {\n throw new ArgumentError('--output-filename-options', 'Filename options should be space-separated, not comma-separated. Example: --output-filename-options date time subject');\n }\n\n // Check if first argument looks like a quoted string containing multiple options\n if (outputFilenameOptions.length === 1 && outputFilenameOptions[0].split(' ').length > 1) {\n throw new ArgumentError('--output-filename-options', 'Filename options should not be quoted. Use: --output-filename-options date time subject instead of --output-filename-options \"date time subject\"');\n }\n const validOptions = options.allowed?.outputFilenameOptions || ALLOWED_OUTPUT_FILENAME_OPTIONS;\n const invalidOptions = outputFilenameOptions.filter(opt => !validOptions.includes(opt as FilenameOption));\n if (invalidOptions.length > 0) {\n throw new ArgumentError('--output-filename-options', `Invalid filename options: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);\n }\n\n // Validate date option against output structure\n if (outputFilenameOptions.includes('date')) {\n if (outputStructure && outputStructure === 'day') {\n throw new ArgumentError('--output-filename-options', 'Cannot use date in filename when output structure is \"day\"');\n }\n }\n }\n }\n\n const validateInputStructure = (inputStructure: string | undefined): void => {\n const validOptions: FilesystemStructure[] = options.allowed?.inputStructures || ALLOWED_INPUT_STRUCTURES;\n if (inputStructure && !validOptions.includes(inputStructure as FilesystemStructure)) {\n throw new ArgumentError('--input-structure', `Invalid input structure: ${inputStructure}. Valid options are: ${validOptions.join(', ')}`);\n }\n }\n\n const validateInputFilenameOptions = (inputFilenameOptions: string[] | undefined, inputStructure: FilesystemStructure | undefined): void => {\n if (inputFilenameOptions) {\n // Check if first argument contains commas - likely a comma-separated list\n if (inputFilenameOptions[0].includes(',')) {\n throw new ArgumentError('--input-filename-options', 'Filename options should be space-separated, not comma-separated. Example: --input-filename-options date time subject');\n }\n\n // Check if first argument looks like a quoted string containing multiple options\n if (inputFilenameOptions.length === 1 && inputFilenameOptions[0].split(' ').length > 1) {\n throw new ArgumentError('--input-filename-options', 'Filename options should not be quoted. Use: --input-filename-options date time subject instead of --input-filename-options \"date time subject\"');\n }\n const validOptions = options.allowed?.inputFilenameOptions || ALLOWED_INPUT_FILENAME_OPTIONS;\n const invalidOptions = inputFilenameOptions.filter(opt => !validOptions.includes(opt as FilenameOption));\n if (invalidOptions.length > 0) {\n throw new ArgumentError('--input-filename-options', `Invalid filename options: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);\n }\n\n // Validate date option against input structure\n if (inputFilenameOptions.includes('date')) {\n if (inputStructure && inputStructure === 'day') {\n throw new ArgumentError('--input-filename-options', 'Cannot use date in filename when input structure is \"day\"');\n }\n }\n }\n }\n\n const validateTimezone = (timezone: string): void => {\n const validOptions = Dates.validTimezones();\n if (validOptions.includes(timezone)) {\n return;\n }\n throw new ArgumentError('--timezone', `Invalid timezone: ${timezone}. Valid options are: ${validOptions.join(', ')}`);\n }\n\n const validateExtensions = (extensions: string[] | undefined): void => {\n const validOptions = options.allowed?.extensions || ALLOWED_EXTENSIONS;\n if (extensions) {\n const invalidOptions = extensions.filter(ext => !validOptions.includes(ext));\n if (invalidOptions.length > 0) {\n throw new ArgumentError('--extensions', `Invalid extensions: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);\n }\n }\n }\n\n // Validate timezone\n validateTimezone(config.timezone);\n\n if (options.features.includes('input') && config.inputDirectory) {\n await validateInputDirectory(config.inputDirectory);\n }\n\n if (options.features.includes('input') && config.limit) {\n if (config.limit < 1) {\n throw new ArgumentError('--limit', 'Limit must be greater than 0');\n }\n }\n\n if (options.features.includes('output') && config.outputDirectory) {\n await validateOutputDirectory(config.outputDirectory);\n }\n\n if (options.features.includes('structured-output')) {\n // Validate filename options if provided\n validateOutputStructure(config.outputStructure);\n validateOutputFilenameOptions(config.outputFilenameOptions, config.outputStructure as FilesystemStructure);\n }\n\n if (options.features.includes('extensions')) {\n validateExtensions(config.extensions);\n }\n\n if (options.features.includes('structured-input')) {\n validateInputStructure(config.inputStructure);\n validateInputFilenameOptions(config.inputFilenameOptions, config.inputStructure as FilesystemStructure);\n }\n\n return;\n}\n\n\n\n\n\n"],"names":["validate","config","options","logger","console","storage","Storage","log","debug","validateInputDirectory","inputDirectory","isDirectoryReadable","Error","validateOutputDirectory","outputDirectory","isDirectoryWritable","validateOutputStructure","outputStructure","validOptions","allowed","outputStructures","ALLOWED_OUTPUT_STRUCTURES","includes","ArgumentError","join","validateOutputFilenameOptions","outputFilenameOptions","length","split","ALLOWED_OUTPUT_FILENAME_OPTIONS","invalidOptions","filter","opt","validateInputStructure","inputStructure","inputStructures","ALLOWED_INPUT_STRUCTURES","validateInputFilenameOptions","inputFilenameOptions","ALLOWED_INPUT_FILENAME_OPTIONS","validateTimezone","timezone","Dates","validateExtensions","extensions","ALLOWED_EXTENSIONS","ext","features","limit"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ # Architecture
2
+
3
+ **Purpose**: High-level overview of the internal design of `dreadcabinet`.
4
+
5
+ ## Module Structure
6
+
7
+ The project is organized into distinct logical modules:
8
+
9
+ * **`src/dreadcabinet.ts`**: Main entry point. Exports the `create` factory, types, schemas, and constants.
10
+ * **`src/configure.ts`**: Handles Commander.js integration and CLI option configuration based on enabled features.
11
+ * **`src/read.ts`**: Reads CLI arguments and converts them to partial configuration.
12
+ * **`src/defaults.ts`**: Applies default values to partial configuration based on enabled features.
13
+ * **`src/validate.ts`**: Validates final configuration against allowed options using Zod.
14
+ * **`src/operate.ts`**: Creates the Operator interface for file processing.
15
+ * **`src/output.ts`**: Constructs output directory paths and filenames based on dates and structure.
16
+ * **`src/input/`**:
17
+ * **`input.ts`**: Factory for input processing.
18
+ * **`process.ts`**: Core file iteration logic with concurrency support.
19
+ * **`structured.ts`**: Handles structured input (date-organized directories).
20
+ * **`unstructured.ts`**: Handles flat/recursive input directories.
21
+ * **`src/util/`**:
22
+ * **`dates.ts`**: Date formatting and timezone handling using dayjs.
23
+ * **`storage.ts`**: Abstracted filesystem operations.
24
+ * **`src/error/`**: Custom error types (`ArgumentError`).
25
+ * **`src/constants.ts`**: Default values, date formats, and allowed options.
26
+ * **`src/logger.ts`**: Logger wrapper for consistent logging interface.
27
+
28
+ ## Data Flow
29
+
30
+ 1. **Initialization**: User calls `create()` with defaults, allowed options, and features.
31
+ 2. **Configuration**: `configure()` adds CLI flags to Commander based on enabled features.
32
+ 3. **Read Phase**: `read()` extracts values from CLI arguments.
33
+ 4. **Defaults Phase**: `applyDefaults()` fills in missing values from defaults.
34
+ 5. **Validation Phase**: `validate()` checks config against allowed values.
35
+ 6. **Operation Phase**: `operate()` creates an Operator with:
36
+ * `process(callback)`: Iterates over input files, calling callback for each.
37
+ * `constructFilename()`: Generates output filenames.
38
+ * `constructOutputDirectory()`: Creates date-based directory paths.
39
+
40
+ ## Key Types
41
+
42
+ ```typescript
43
+ // Filesystem structure options
44
+ type FilesystemStructure = 'none' | 'year' | 'month' | 'day';
45
+
46
+ // Filename components
47
+ type FilenameOption = 'date' | 'time' | 'subject';
48
+
49
+ // Feature flags control which CLI options are added
50
+ type Feature = 'input' | 'output' | 'structured-output' | 'structured-input' | 'extensions';
51
+ ```
52
+
53
+ ## Design Decisions
54
+
55
+ * **Feature Flags**: CLI options are conditionally added based on `features` array. This allows building focused tools without exposing irrelevant options.
56
+ * **Non-Destructive**: The library only reads from input and writes to output. Original files are never modified or deleted.
57
+ * **Timezone-Aware**: All date operations go through `dayjs` with timezone support for consistent cross-timezone behavior.
58
+ * **Callback Pattern**: The `process()` method uses a callback pattern, giving consumers full control over what happens to each file.
59
+ * **Testability**: The `storage` module abstracts filesystem calls for easy mocking.
60
+