@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,1793 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const dayjs = require('dayjs');
6
+ const timezone = require('dayjs/plugin/timezone.js');
7
+ const utc = require('dayjs/plugin/utc.js');
8
+ const fs = require('node:fs');
9
+ const glob = require('glob');
10
+ const path = require('node:path');
11
+ const crypto = require('node:crypto');
12
+ const zod = require('zod');
13
+
14
+ function _interopNamespaceDefault(e) {
15
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
16
+ if (e) {
17
+ for (const k in e) {
18
+ if (k !== 'default') {
19
+ const d = Object.getOwnPropertyDescriptor(e, k);
20
+ Object.defineProperty(n, k, d.get ? d : {
21
+ enumerable: true,
22
+ get: () => e[k]
23
+ });
24
+ }
25
+ }
26
+ }
27
+ n.default = e;
28
+ return Object.freeze(n);
29
+ }
30
+
31
+ const fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
32
+ const path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
33
+ const crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto);
34
+
35
+ const PROGRAM_NAME = 'dreadcabinet';
36
+ const DEFAULT_TIMEZONE = 'Etc/UTC';
37
+ const DATE_FORMAT_MONTH_DAY = 'M-D';
38
+ const DATE_FORMAT_YEAR = 'YYYY';
39
+ const DATE_FORMAT_YEAR_MONTH_DAY = 'YYYY-M-D';
40
+ const DATE_FORMAT_MONTH = 'M';
41
+ const DATE_FORMAT_DAY = 'D';
42
+ const DEFAULT_RECURSIVE = false;
43
+ const DEFAULT_INPUT_DIRECTORY = './';
44
+ const DEFAULT_OUTPUT_DIRECTORY = './';
45
+ const DEFAULT_CONCURRENCY = 1;
46
+ const DEFAULT_OUTPUT_STRUCTURE = 'month';
47
+ const DEFAULT_OUTPUT_FILENAME_OPTIONS = [
48
+ 'date',
49
+ 'subject'
50
+ ];
51
+ const DEFAULT_INPUT_STRUCTURE = 'month';
52
+ const DEFAULT_INPUT_FILENAME_OPTIONS = [
53
+ 'date',
54
+ 'subject'
55
+ ];
56
+ const DEFAULT_EXTENSIONS = [
57
+ 'md'
58
+ ];
59
+ const ALLOWED_INPUT_STRUCTURES = [
60
+ 'none',
61
+ 'year',
62
+ 'month',
63
+ 'day'
64
+ ];
65
+ const ALLOWED_INPUT_FILENAME_OPTIONS = [
66
+ 'date',
67
+ 'time',
68
+ 'subject'
69
+ ];
70
+ const ALLOWED_OUTPUT_STRUCTURES = [
71
+ 'none',
72
+ 'year',
73
+ 'month',
74
+ 'day'
75
+ ];
76
+ const ALLOWED_OUTPUT_FILENAME_OPTIONS = [
77
+ 'date',
78
+ 'time',
79
+ 'subject'
80
+ ];
81
+ const ALLOWED_EXTENSIONS = [
82
+ 'md',
83
+ 'txt'
84
+ ];
85
+
86
+ function _define_property(obj, key, value) {
87
+ if (key in obj) {
88
+ Object.defineProperty(obj, key, {
89
+ value: value,
90
+ enumerable: true,
91
+ configurable: true,
92
+ writable: true
93
+ });
94
+ } else {
95
+ obj[key] = value;
96
+ }
97
+ return obj;
98
+ }
99
+ class ArgumentError extends Error {
100
+ get argument() {
101
+ return this.argumentName;
102
+ }
103
+ constructor(argumentName, message){
104
+ super(`${message}`), _define_property(this, "argumentName", void 0);
105
+ this.name = 'ArgumentError';
106
+ this.argumentName = argumentName;
107
+ }
108
+ }
109
+
110
+ const addOption = (command, option, description, addDefaults, defaultValue)=>{
111
+ if (addDefaults) {
112
+ command.option(option, description, defaultValue);
113
+ } else {
114
+ const defaultDesc = defaultValue === undefined ? 'undefined' : Array.isArray(defaultValue) ? defaultValue.join(',') : defaultValue;
115
+ const descriptionWithDefaults = `${description} (default: ${defaultDesc})`;
116
+ command.option(option, descriptionWithDefaults);
117
+ }
118
+ };
119
+ const configure = async (command, defaults, addDefaults, features)=>{
120
+ const tzDefault = (defaults === null || defaults === void 0 ? void 0 : defaults.timezone) || DEFAULT_TIMEZONE;
121
+ if (addDefaults) {
122
+ command.option('--timezone <timezone>', 'timezone for date calculations', tzDefault);
123
+ } else {
124
+ command.option('--timezone <timezone>', `timezone for date calculations (default: ${tzDefault})`);
125
+ }
126
+ if (features.includes('input')) {
127
+ addOption(command, '-r, --recursive', 'recursive mode, process all files in the input directory', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.recursive) !== undefined ? defaults.recursive : DEFAULT_RECURSIVE);
128
+ addOption(command, '-i, --input-directory <inputDirectory>', 'input directory', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.inputDirectory) || DEFAULT_INPUT_DIRECTORY);
129
+ addOption(command, '--limit <limit>', 'limit the number of files to process', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.limit) ? defaults === null || defaults === void 0 ? void 0 : defaults.limit.toString() : undefined);
130
+ addOption(command, '--concurrency <concurrency>', 'concurrency level for processing files', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.concurrency) ? defaults === null || defaults === void 0 ? void 0 : defaults.concurrency.toString() : undefined);
131
+ }
132
+ if (features.includes('output')) {
133
+ addOption(command, '-o, --output-directory <outputDirectory>', 'output directory', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.outputDirectory) || DEFAULT_OUTPUT_DIRECTORY);
134
+ }
135
+ if (features.includes('structured-output')) {
136
+ addOption(command, '--output-structure <type>', 'output directory structure (none/year/month/day)', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.outputStructure) || DEFAULT_OUTPUT_STRUCTURE);
137
+ addOption(command, '--output-filename-options [outputFilenameOptions...]', 'filename format options (space-separated list of: date,time,subject) example \'date subject\'', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.outputFilenameOptions) || DEFAULT_OUTPUT_FILENAME_OPTIONS);
138
+ }
139
+ if (features.includes('extensions')) {
140
+ addOption(command, '--extensions [extensions...]', 'file extensions to process (space-separated list of: mp3,mp4,mpeg,mpga,m4a,wav,webm)', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.extensions) || DEFAULT_EXTENSIONS);
141
+ }
142
+ if (features.includes('structured-input')) {
143
+ addOption(command, '--input-structure <type>', 'input directory structure (none/year/month/day)', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.inputStructure) || DEFAULT_INPUT_STRUCTURE);
144
+ addOption(command, '--input-filename-options [options...]', 'filename format options (space-separated list of: date,time,subject)', addDefaults, (defaults === null || defaults === void 0 ? void 0 : defaults.inputFilenameOptions) || DEFAULT_INPUT_FILENAME_OPTIONS);
145
+ addOption(command, '--start <date>', `start date filter (${DATE_FORMAT_YEAR_MONTH_DAY})`, addDefaults, undefined);
146
+ addOption(command, '--end <date>', `end date filter (${DATE_FORMAT_YEAR_MONTH_DAY}), defaults to today`, addDefaults, undefined);
147
+ }
148
+ };
149
+
150
+ const applyDefaults = (config, features, defaults)=>{
151
+ const configWithDefaults = {
152
+ ...config
153
+ };
154
+ configWithDefaults.timezone = config.timezone || (defaults === null || defaults === void 0 ? void 0 : defaults.timezone) || DEFAULT_TIMEZONE;
155
+ if (features.includes('input')) {
156
+ var _ref;
157
+ configWithDefaults.recursive = config.recursive === undefined ? (_ref = defaults === null || defaults === void 0 ? void 0 : defaults.recursive) !== null && _ref !== void 0 ? _ref : DEFAULT_RECURSIVE : config.recursive;
158
+ configWithDefaults.inputDirectory = config.inputDirectory || (defaults === null || defaults === void 0 ? void 0 : defaults.inputDirectory) || DEFAULT_INPUT_DIRECTORY;
159
+ configWithDefaults.concurrency = config.concurrency || (defaults === null || defaults === void 0 ? void 0 : defaults.concurrency) || DEFAULT_CONCURRENCY;
160
+ }
161
+ if (features.includes('output')) {
162
+ configWithDefaults.outputDirectory = config.outputDirectory || (defaults === null || defaults === void 0 ? void 0 : defaults.outputDirectory) || DEFAULT_OUTPUT_DIRECTORY;
163
+ }
164
+ if (features.includes('structured-output')) {
165
+ configWithDefaults.outputStructure = config.outputStructure || (defaults === null || defaults === void 0 ? void 0 : defaults.outputStructure) || DEFAULT_OUTPUT_STRUCTURE;
166
+ configWithDefaults.outputFilenameOptions = config.outputFilenameOptions || (defaults === null || defaults === void 0 ? void 0 : defaults.outputFilenameOptions) || DEFAULT_OUTPUT_FILENAME_OPTIONS;
167
+ }
168
+ if (features.includes('extensions')) {
169
+ configWithDefaults.extensions = config.extensions || (defaults === null || defaults === void 0 ? void 0 : defaults.extensions) || DEFAULT_EXTENSIONS;
170
+ }
171
+ if (features.includes('structured-input')) {
172
+ configWithDefaults.inputStructure = config.inputStructure || (defaults === null || defaults === void 0 ? void 0 : defaults.inputStructure) || DEFAULT_INPUT_STRUCTURE;
173
+ configWithDefaults.inputFilenameOptions = config.inputFilenameOptions || (defaults === null || defaults === void 0 ? void 0 : defaults.inputFilenameOptions) || DEFAULT_INPUT_FILENAME_OPTIONS;
174
+ }
175
+ return configWithDefaults;
176
+ };
177
+
178
+ function clean(obj) {
179
+ return Object.fromEntries(Object.entries(obj).filter(([_, v])=>v !== undefined));
180
+ }
181
+ const read = async (args, features)=>{
182
+ const config = {};
183
+ config.timezone = args.timezone;
184
+ if (features.includes('input')) {
185
+ config.inputDirectory = args.inputDirectory;
186
+ config.limit = args.limit;
187
+ }
188
+ if (features.includes('structured-input')) {
189
+ config.inputStructure = args.inputStructure;
190
+ config.inputFilenameOptions = args.inputFilenameOptions;
191
+ }
192
+ if (features.includes('output')) {
193
+ config.outputDirectory = args.outputDirectory;
194
+ }
195
+ if (features.includes('structured-output')) {
196
+ config.outputStructure = args.outputStructure;
197
+ config.outputFilenameOptions = args.outputFilenameOptions;
198
+ }
199
+ if (features.includes('extensions')) {
200
+ config.extensions = args.extensions;
201
+ }
202
+ // Returning a clean object to avoid undefined values
203
+ return clean(config);
204
+ };
205
+
206
+ // eslint-disable-next-line no-restricted-imports
207
+ dayjs.extend(utc);
208
+ dayjs.extend(timezone);
209
+ // Static list of IANA timezone names (replaces moment-timezone dependency)
210
+ const TIMEZONE_NAMES = [
211
+ 'Africa/Abidjan',
212
+ 'Africa/Accra',
213
+ 'Africa/Addis_Ababa',
214
+ 'Africa/Algiers',
215
+ 'Africa/Asmara',
216
+ 'Africa/Asmera',
217
+ 'Africa/Bamako',
218
+ 'Africa/Bangui',
219
+ 'Africa/Banjul',
220
+ 'Africa/Bissau',
221
+ 'Africa/Blantyre',
222
+ 'Africa/Brazzaville',
223
+ 'Africa/Bujumbura',
224
+ 'Africa/Cairo',
225
+ 'Africa/Casablanca',
226
+ 'Africa/Ceuta',
227
+ 'Africa/Conakry',
228
+ 'Africa/Dakar',
229
+ 'Africa/Dar_es_Salaam',
230
+ 'Africa/Djibouti',
231
+ 'Africa/Douala',
232
+ 'Africa/El_Aaiun',
233
+ 'Africa/Freetown',
234
+ 'Africa/Gaborone',
235
+ 'Africa/Harare',
236
+ 'Africa/Johannesburg',
237
+ 'Africa/Juba',
238
+ 'Africa/Kampala',
239
+ 'Africa/Khartoum',
240
+ 'Africa/Kigali',
241
+ 'Africa/Kinshasa',
242
+ 'Africa/Lagos',
243
+ 'Africa/Libreville',
244
+ 'Africa/Lome',
245
+ 'Africa/Luanda',
246
+ 'Africa/Lubumbashi',
247
+ 'Africa/Lusaka',
248
+ 'Africa/Malabo',
249
+ 'Africa/Maputo',
250
+ 'Africa/Maseru',
251
+ 'Africa/Mbabane',
252
+ 'Africa/Mogadishu',
253
+ 'Africa/Monrovia',
254
+ 'Africa/Nairobi',
255
+ 'Africa/Ndjamena',
256
+ 'Africa/Niamey',
257
+ 'Africa/Nouakchott',
258
+ 'Africa/Ouagadougou',
259
+ 'Africa/Porto-Novo',
260
+ 'Africa/Sao_Tome',
261
+ 'Africa/Timbuktu',
262
+ 'Africa/Tripoli',
263
+ 'Africa/Tunis',
264
+ 'Africa/Windhoek',
265
+ 'America/Adak',
266
+ 'America/Anchorage',
267
+ 'America/Anguilla',
268
+ 'America/Antigua',
269
+ 'America/Araguaina',
270
+ 'America/Argentina/Buenos_Aires',
271
+ 'America/Argentina/Catamarca',
272
+ 'America/Argentina/ComodRivadavia',
273
+ 'America/Argentina/Cordoba',
274
+ 'America/Argentina/Jujuy',
275
+ 'America/Argentina/La_Rioja',
276
+ 'America/Argentina/Mendoza',
277
+ 'America/Argentina/Rio_Gallegos',
278
+ 'America/Argentina/Salta',
279
+ 'America/Argentina/San_Juan',
280
+ 'America/Argentina/San_Luis',
281
+ 'America/Argentina/Tucuman',
282
+ 'America/Argentina/Ushuaia',
283
+ 'America/Aruba',
284
+ 'America/Asuncion',
285
+ 'America/Atikokan',
286
+ 'America/Atka',
287
+ 'America/Bahia',
288
+ 'America/Bahia_Banderas',
289
+ 'America/Barbados',
290
+ 'America/Belem',
291
+ 'America/Belize',
292
+ 'America/Blanc-Sablon',
293
+ 'America/Boa_Vista',
294
+ 'America/Bogota',
295
+ 'America/Boise',
296
+ 'America/Buenos_Aires',
297
+ 'America/Cambridge_Bay',
298
+ 'America/Campo_Grande',
299
+ 'America/Cancun',
300
+ 'America/Caracas',
301
+ 'America/Catamarca',
302
+ 'America/Cayenne',
303
+ 'America/Cayman',
304
+ 'America/Chicago',
305
+ 'America/Chihuahua',
306
+ 'America/Coral_Harbour',
307
+ 'America/Cordoba',
308
+ 'America/Costa_Rica',
309
+ 'America/Creston',
310
+ 'America/Cuiaba',
311
+ 'America/Curacao',
312
+ 'America/Danmarkshavn',
313
+ 'America/Dawson',
314
+ 'America/Dawson_Creek',
315
+ 'America/Denver',
316
+ 'America/Detroit',
317
+ 'America/Dominica',
318
+ 'America/Edmonton',
319
+ 'America/Eirunepe',
320
+ 'America/El_Salvador',
321
+ 'America/Ensenada',
322
+ 'America/Fort_Nelson',
323
+ 'America/Fort_Wayne',
324
+ 'America/Fortaleza',
325
+ 'America/Glace_Bay',
326
+ 'America/Godthab',
327
+ 'America/Goose_Bay',
328
+ 'America/Grand_Turk',
329
+ 'America/Grenada',
330
+ 'America/Guadeloupe',
331
+ 'America/Guatemala',
332
+ 'America/Guayaquil',
333
+ 'America/Guyana',
334
+ 'America/Halifax',
335
+ 'America/Havana',
336
+ 'America/Hermosillo',
337
+ 'America/Indiana/Indianapolis',
338
+ 'America/Indiana/Knox',
339
+ 'America/Indiana/Marengo',
340
+ 'America/Indiana/Petersburg',
341
+ 'America/Indiana/Tell_City',
342
+ 'America/Indiana/Vevay',
343
+ 'America/Indiana/Vincennes',
344
+ 'America/Indiana/Winamac',
345
+ 'America/Indianapolis',
346
+ 'America/Inuvik',
347
+ 'America/Iqaluit',
348
+ 'America/Jamaica',
349
+ 'America/Jujuy',
350
+ 'America/Juneau',
351
+ 'America/Kentucky/Louisville',
352
+ 'America/Kentucky/Monticello',
353
+ 'America/Knox_IN',
354
+ 'America/Kralendijk',
355
+ 'America/La_Paz',
356
+ 'America/Lima',
357
+ 'America/Los_Angeles',
358
+ 'America/Louisville',
359
+ 'America/Lower_Princes',
360
+ 'America/Maceio',
361
+ 'America/Managua',
362
+ 'America/Manaus',
363
+ 'America/Marigot',
364
+ 'America/Martinique',
365
+ 'America/Matamoros',
366
+ 'America/Mazatlan',
367
+ 'America/Mendoza',
368
+ 'America/Menominee',
369
+ 'America/Merida',
370
+ 'America/Metlakatla',
371
+ 'America/Mexico_City',
372
+ 'America/Miquelon',
373
+ 'America/Moncton',
374
+ 'America/Monterrey',
375
+ 'America/Montevideo',
376
+ 'America/Montreal',
377
+ 'America/Montserrat',
378
+ 'America/Nassau',
379
+ 'America/New_York',
380
+ 'America/Nipigon',
381
+ 'America/Nome',
382
+ 'America/Noronha',
383
+ 'America/North_Dakota/Beulah',
384
+ 'America/North_Dakota/Center',
385
+ 'America/North_Dakota/New_Salem',
386
+ 'America/Ojinaga',
387
+ 'America/Panama',
388
+ 'America/Pangnirtung',
389
+ 'America/Paramaribo',
390
+ 'America/Phoenix',
391
+ 'America/Port-au-Prince',
392
+ 'America/Port_of_Spain',
393
+ 'America/Porto_Acre',
394
+ 'America/Porto_Velho',
395
+ 'America/Puerto_Rico',
396
+ 'America/Punta_Arenas',
397
+ 'America/Rainy_River',
398
+ 'America/Rankin_Inlet',
399
+ 'America/Recife',
400
+ 'America/Regina',
401
+ 'America/Resolute',
402
+ 'America/Rio_Branco',
403
+ 'America/Rosario',
404
+ 'America/Santa_Isabel',
405
+ 'America/Santarem',
406
+ 'America/Santiago',
407
+ 'America/Santo_Domingo',
408
+ 'America/Sao_Paulo',
409
+ 'America/Scoresbysund',
410
+ 'America/Shiprock',
411
+ 'America/Sitka',
412
+ 'America/St_Barthelemy',
413
+ 'America/St_Johns',
414
+ 'America/St_Kitts',
415
+ 'America/St_Lucia',
416
+ 'America/St_Thomas',
417
+ 'America/St_Vincent',
418
+ 'America/Swift_Current',
419
+ 'America/Tegucigalpa',
420
+ 'America/Thule',
421
+ 'America/Thunder_Bay',
422
+ 'America/Tijuana',
423
+ 'America/Toronto',
424
+ 'America/Tortola',
425
+ 'America/Vancouver',
426
+ 'America/Virgin',
427
+ 'America/Whitehorse',
428
+ 'America/Winnipeg',
429
+ 'America/Yakutat',
430
+ 'America/Yellowknife',
431
+ 'Antarctica/Casey',
432
+ 'Antarctica/Davis',
433
+ 'Antarctica/DumontDUrville',
434
+ 'Antarctica/Macquarie',
435
+ 'Antarctica/Mawson',
436
+ 'Antarctica/McMurdo',
437
+ 'Antarctica/Palmer',
438
+ 'Antarctica/Rothera',
439
+ 'Antarctica/South_Pole',
440
+ 'Antarctica/Syowa',
441
+ 'Antarctica/Troll',
442
+ 'Antarctica/Vostok',
443
+ 'Arctic/Longyearbyen',
444
+ 'Asia/Aden',
445
+ 'Asia/Almaty',
446
+ 'Asia/Amman',
447
+ 'Asia/Anadyr',
448
+ 'Asia/Aqtau',
449
+ 'Asia/Aqtobe',
450
+ 'Asia/Ashgabat',
451
+ 'Asia/Ashkhabad',
452
+ 'Asia/Atyrau',
453
+ 'Asia/Baghdad',
454
+ 'Asia/Bahrain',
455
+ 'Asia/Baku',
456
+ 'Asia/Bangkok',
457
+ 'Asia/Barnaul',
458
+ 'Asia/Beirut',
459
+ 'Asia/Bishkek',
460
+ 'Asia/Brunei',
461
+ 'Asia/Calcutta',
462
+ 'Asia/Chita',
463
+ 'Asia/Choibalsan',
464
+ 'Asia/Chongqing',
465
+ 'Asia/Chungking',
466
+ 'Asia/Colombo',
467
+ 'Asia/Dacca',
468
+ 'Asia/Damascus',
469
+ 'Asia/Dhaka',
470
+ 'Asia/Dili',
471
+ 'Asia/Dubai',
472
+ 'Asia/Dushanbe',
473
+ 'Asia/Famagusta',
474
+ 'Asia/Gaza',
475
+ 'Asia/Harbin',
476
+ 'Asia/Hebron',
477
+ 'Asia/Ho_Chi_Minh',
478
+ 'Asia/Hong_Kong',
479
+ 'Asia/Hovd',
480
+ 'Asia/Irkutsk',
481
+ 'Asia/Istanbul',
482
+ 'Asia/Jakarta',
483
+ 'Asia/Jayapura',
484
+ 'Asia/Jerusalem',
485
+ 'Asia/Kabul',
486
+ 'Asia/Kamchatka',
487
+ 'Asia/Karachi',
488
+ 'Asia/Kashgar',
489
+ 'Asia/Kathmandu',
490
+ 'Asia/Katmandu',
491
+ 'Asia/Khandyga',
492
+ 'Asia/Kolkata',
493
+ 'Asia/Krasnoyarsk',
494
+ 'Asia/Kuala_Lumpur',
495
+ 'Asia/Kuching',
496
+ 'Asia/Kuwait',
497
+ 'Asia/Macao',
498
+ 'Asia/Macau',
499
+ 'Asia/Magadan',
500
+ 'Asia/Makassar',
501
+ 'Asia/Manila',
502
+ 'Asia/Muscat',
503
+ 'Asia/Nicosia',
504
+ 'Asia/Novokuznetsk',
505
+ 'Asia/Novosibirsk',
506
+ 'Asia/Omsk',
507
+ 'Asia/Oral',
508
+ 'Asia/Phnom_Penh',
509
+ 'Asia/Pontianak',
510
+ 'Asia/Pyongyang',
511
+ 'Asia/Qatar',
512
+ 'Asia/Qyzylorda',
513
+ 'Asia/Rangoon',
514
+ 'Asia/Riyadh',
515
+ 'Asia/Saigon',
516
+ 'Asia/Sakhalin',
517
+ 'Asia/Samarkand',
518
+ 'Asia/Seoul',
519
+ 'Asia/Shanghai',
520
+ 'Asia/Singapore',
521
+ 'Asia/Srednekolymsk',
522
+ 'Asia/Taipei',
523
+ 'Asia/Tashkent',
524
+ 'Asia/Tbilisi',
525
+ 'Asia/Tehran',
526
+ 'Asia/Tel_Aviv',
527
+ 'Asia/Thimbu',
528
+ 'Asia/Thimphu',
529
+ 'Asia/Tokyo',
530
+ 'Asia/Tomsk',
531
+ 'Asia/Ujung_Pandang',
532
+ 'Asia/Ulaanbaatar',
533
+ 'Asia/Ulan_Bator',
534
+ 'Asia/Urumqi',
535
+ 'Asia/Ust-Nera',
536
+ 'Asia/Vientiane',
537
+ 'Asia/Vladivostok',
538
+ 'Asia/Yakutsk',
539
+ 'Asia/Yangon',
540
+ 'Asia/Yekaterinburg',
541
+ 'Asia/Yerevan',
542
+ 'Atlantic/Azores',
543
+ 'Atlantic/Bermuda',
544
+ 'Atlantic/Canary',
545
+ 'Atlantic/Cape_Verde',
546
+ 'Atlantic/Faeroe',
547
+ 'Atlantic/Faroe',
548
+ 'Atlantic/Jan_Mayen',
549
+ 'Atlantic/Madeira',
550
+ 'Atlantic/Reykjavik',
551
+ 'Atlantic/South_Georgia',
552
+ 'Atlantic/St_Helena',
553
+ 'Atlantic/Stanley',
554
+ 'Australia/ACT',
555
+ 'Australia/Adelaide',
556
+ 'Australia/Brisbane',
557
+ 'Australia/Broken_Hill',
558
+ 'Australia/Canberra',
559
+ 'Australia/Currie',
560
+ 'Australia/Darwin',
561
+ 'Australia/Eucla',
562
+ 'Australia/Hobart',
563
+ 'Australia/LHI',
564
+ 'Australia/Lindeman',
565
+ 'Australia/Lord_Howe',
566
+ 'Australia/Melbourne',
567
+ 'Australia/NSW',
568
+ 'Australia/North',
569
+ 'Australia/Perth',
570
+ 'Australia/Queensland',
571
+ 'Australia/South',
572
+ 'Australia/Sydney',
573
+ 'Australia/Tasmania',
574
+ 'Australia/Victoria',
575
+ 'Australia/West',
576
+ 'Australia/Yancowinna',
577
+ 'Brazil/Acre',
578
+ 'Brazil/DeNoronha',
579
+ 'Brazil/East',
580
+ 'Brazil/West',
581
+ 'CET',
582
+ 'CST6CDT',
583
+ 'Canada/Atlantic',
584
+ 'Canada/Central',
585
+ 'Canada/Eastern',
586
+ 'Canada/Mountain',
587
+ 'Canada/Newfoundland',
588
+ 'Canada/Pacific',
589
+ 'Canada/Saskatchewan',
590
+ 'Canada/Yukon',
591
+ 'Chile/Continental',
592
+ 'Chile/EasterIsland',
593
+ 'Cuba',
594
+ 'EET',
595
+ 'EST',
596
+ 'EST5EDT',
597
+ 'Egypt',
598
+ 'Eire',
599
+ 'Etc/GMT',
600
+ 'Etc/GMT+0',
601
+ 'Etc/GMT+1',
602
+ 'Etc/GMT+10',
603
+ 'Etc/GMT+11',
604
+ 'Etc/GMT+12',
605
+ 'Etc/GMT+2',
606
+ 'Etc/GMT+3',
607
+ 'Etc/GMT+4',
608
+ 'Etc/GMT+5',
609
+ 'Etc/GMT+6',
610
+ 'Etc/GMT+7',
611
+ 'Etc/GMT+8',
612
+ 'Etc/GMT+9',
613
+ 'Etc/GMT-0',
614
+ 'Etc/GMT-1',
615
+ 'Etc/GMT-10',
616
+ 'Etc/GMT-11',
617
+ 'Etc/GMT-12',
618
+ 'Etc/GMT-13',
619
+ 'Etc/GMT-14',
620
+ 'Etc/GMT-2',
621
+ 'Etc/GMT-3',
622
+ 'Etc/GMT-4',
623
+ 'Etc/GMT-5',
624
+ 'Etc/GMT-6',
625
+ 'Etc/GMT-7',
626
+ 'Etc/GMT-8',
627
+ 'Etc/GMT-9',
628
+ 'Etc/GMT0',
629
+ 'Etc/Greenwich',
630
+ 'Etc/UCT',
631
+ 'Etc/UTC',
632
+ 'Etc/Universal',
633
+ 'Etc/Zulu',
634
+ 'Europe/Amsterdam',
635
+ 'Europe/Andorra',
636
+ 'Europe/Astrakhan',
637
+ 'Europe/Athens',
638
+ 'Europe/Belfast',
639
+ 'Europe/Belgrade',
640
+ 'Europe/Berlin',
641
+ 'Europe/Bratislava',
642
+ 'Europe/Brussels',
643
+ 'Europe/Bucharest',
644
+ 'Europe/Budapest',
645
+ 'Europe/Busingen',
646
+ 'Europe/Chisinau',
647
+ 'Europe/Copenhagen',
648
+ 'Europe/Dublin',
649
+ 'Europe/Gibraltar',
650
+ 'Europe/Guernsey',
651
+ 'Europe/Helsinki',
652
+ 'Europe/Isle_of_Man',
653
+ 'Europe/Istanbul',
654
+ 'Europe/Jersey',
655
+ 'Europe/Kaliningrad',
656
+ 'Europe/Kiev',
657
+ 'Europe/Kirov',
658
+ 'Europe/Lisbon',
659
+ 'Europe/Ljubljana',
660
+ 'Europe/London',
661
+ 'Europe/Luxembourg',
662
+ 'Europe/Madrid',
663
+ 'Europe/Malta',
664
+ 'Europe/Mariehamn',
665
+ 'Europe/Minsk',
666
+ 'Europe/Monaco',
667
+ 'Europe/Moscow',
668
+ 'Europe/Nicosia',
669
+ 'Europe/Oslo',
670
+ 'Europe/Paris',
671
+ 'Europe/Podgorica',
672
+ 'Europe/Prague',
673
+ 'Europe/Riga',
674
+ 'Europe/Rome',
675
+ 'Europe/Samara',
676
+ 'Europe/San_Marino',
677
+ 'Europe/Sarajevo',
678
+ 'Europe/Saratov',
679
+ 'Europe/Simferopol',
680
+ 'Europe/Skopje',
681
+ 'Europe/Sofia',
682
+ 'Europe/Stockholm',
683
+ 'Europe/Tallinn',
684
+ 'Europe/Tirane',
685
+ 'Europe/Tiraspol',
686
+ 'Europe/Ulyanovsk',
687
+ 'Europe/Uzhgorod',
688
+ 'Europe/Vaduz',
689
+ 'Europe/Vatican',
690
+ 'Europe/Vienna',
691
+ 'Europe/Vilnius',
692
+ 'Europe/Volgograd',
693
+ 'Europe/Warsaw',
694
+ 'Europe/Zagreb',
695
+ 'Europe/Zaporozhye',
696
+ 'Europe/Zurich',
697
+ 'GB',
698
+ 'GB-Eire',
699
+ 'GMT',
700
+ 'GMT+0',
701
+ 'GMT-0',
702
+ 'GMT0',
703
+ 'Greenwich',
704
+ 'HST',
705
+ 'Hongkong',
706
+ 'Iceland',
707
+ 'Indian/Antananarivo',
708
+ 'Indian/Chagos',
709
+ 'Indian/Christmas',
710
+ 'Indian/Cocos',
711
+ 'Indian/Comoro',
712
+ 'Indian/Kerguelen',
713
+ 'Indian/Mahe',
714
+ 'Indian/Maldives',
715
+ 'Indian/Mauritius',
716
+ 'Indian/Mayotte',
717
+ 'Indian/Reunion',
718
+ 'Iran',
719
+ 'Israel',
720
+ 'Jamaica',
721
+ 'Japan',
722
+ 'Kwajalein',
723
+ 'Libya',
724
+ 'MET',
725
+ 'MST',
726
+ 'MST7MDT',
727
+ 'Mexico/BajaNorte',
728
+ 'Mexico/BajaSur',
729
+ 'Mexico/General',
730
+ 'NZ',
731
+ 'NZ-CHAT',
732
+ 'Navajo',
733
+ 'PRC',
734
+ 'PST8PDT',
735
+ 'Pacific/Apia',
736
+ 'Pacific/Auckland',
737
+ 'Pacific/Bougainville',
738
+ 'Pacific/Chatham',
739
+ 'Pacific/Chuuk',
740
+ 'Pacific/Easter',
741
+ 'Pacific/Efate',
742
+ 'Pacific/Enderbury',
743
+ 'Pacific/Fakaofo',
744
+ 'Pacific/Fiji',
745
+ 'Pacific/Funafuti',
746
+ 'Pacific/Galapagos',
747
+ 'Pacific/Gambier',
748
+ 'Pacific/Guadalcanal',
749
+ 'Pacific/Guam',
750
+ 'Pacific/Honolulu',
751
+ 'Pacific/Johnston',
752
+ 'Pacific/Kiritimati',
753
+ 'Pacific/Kosrae',
754
+ 'Pacific/Kwajalein',
755
+ 'Pacific/Majuro',
756
+ 'Pacific/Marquesas',
757
+ 'Pacific/Midway',
758
+ 'Pacific/Nauru',
759
+ 'Pacific/Niue',
760
+ 'Pacific/Norfolk',
761
+ 'Pacific/Noumea',
762
+ 'Pacific/Pago_Pago',
763
+ 'Pacific/Palau',
764
+ 'Pacific/Pitcairn',
765
+ 'Pacific/Pohnpei',
766
+ 'Pacific/Ponape',
767
+ 'Pacific/Port_Moresby',
768
+ 'Pacific/Rarotonga',
769
+ 'Pacific/Saipan',
770
+ 'Pacific/Samoa',
771
+ 'Pacific/Tahiti',
772
+ 'Pacific/Tarawa',
773
+ 'Pacific/Tongatapu',
774
+ 'Pacific/Truk',
775
+ 'Pacific/Wake',
776
+ 'Pacific/Wallis',
777
+ 'Pacific/Yap',
778
+ 'Poland',
779
+ 'Portugal',
780
+ 'ROC',
781
+ 'ROK',
782
+ 'Singapore',
783
+ 'Turkey',
784
+ 'UCT',
785
+ 'US/Alaska',
786
+ 'US/Aleutian',
787
+ 'US/Arizona',
788
+ 'US/Central',
789
+ 'US/East-Indiana',
790
+ 'US/Eastern',
791
+ 'US/Hawaii',
792
+ 'US/Indiana-Starke',
793
+ 'US/Michigan',
794
+ 'US/Mountain',
795
+ 'US/Pacific',
796
+ 'US/Pacific-New',
797
+ 'US/Samoa',
798
+ 'UTC',
799
+ 'Universal',
800
+ 'W-SU',
801
+ 'WET',
802
+ 'Zulu'
803
+ ];
804
+ const create$5 = (parameters)=>{
805
+ const { timezone } = parameters;
806
+ const now = ()=>{
807
+ return dayjs().tz(timezone).toDate();
808
+ };
809
+ const today = ()=>{
810
+ // Return today's date formatted as YYYY-M-D in the specified timezone
811
+ return dayjs().tz(timezone).format('YYYY-M-D');
812
+ };
813
+ const date = (date)=>{
814
+ let value;
815
+ if (date) {
816
+ value = dayjs.tz(date, timezone);
817
+ } else {
818
+ value = dayjs().tz(timezone);
819
+ }
820
+ if (!value.isValid()) {
821
+ throw new Error(`Invalid date: ${date}`);
822
+ }
823
+ return value.toDate();
824
+ };
825
+ const parse = (date, format)=>{
826
+ const value = dayjs.tz(date, format, timezone);
827
+ if (!value.isValid()) {
828
+ throw new Error(`Invalid date: ${date}, expected format: ${format}`);
829
+ }
830
+ return value.toDate();
831
+ };
832
+ const isValidDate = (date, format)=>{
833
+ return dayjs(date, format, true).isValid(); // Use strict parsing
834
+ };
835
+ const addDays = (date, days)=>{
836
+ return dayjs.tz(date, timezone).add(days, 'day').toDate();
837
+ };
838
+ const addMonths = (date, months)=>{
839
+ return dayjs.tz(date, timezone).add(months, 'month').toDate();
840
+ };
841
+ const addYears = (date, years)=>{
842
+ return dayjs.tz(date, timezone).add(years, 'year').toDate();
843
+ };
844
+ const format = (date, format)=>{
845
+ return dayjs.tz(date, timezone).format(format);
846
+ };
847
+ const subDays = (date, days)=>{
848
+ return dayjs.tz(date, timezone).subtract(days, 'day').toDate();
849
+ };
850
+ const subMonths = (date, months)=>{
851
+ return dayjs.tz(date, timezone).subtract(months, 'month').toDate();
852
+ };
853
+ const subYears = (date, years)=>{
854
+ return dayjs.tz(date, timezone).subtract(years, 'year').toDate();
855
+ };
856
+ const startOfMonth = (date)=>{
857
+ return dayjs.tz(date, timezone).startOf('month').toDate();
858
+ };
859
+ const endOfMonth = (date)=>{
860
+ return dayjs.tz(date, timezone).endOf('month').toDate();
861
+ };
862
+ const startOfYear = (date)=>{
863
+ return dayjs.tz(date, timezone).startOf('year').toDate();
864
+ };
865
+ const endOfYear = (date)=>{
866
+ return dayjs.tz(date, timezone).endOf('year').toDate();
867
+ };
868
+ const isBefore = (date, other)=>{
869
+ return dayjs.tz(date, timezone).isBefore(dayjs.tz(other, timezone));
870
+ };
871
+ const isAfter = (date, other)=>{
872
+ return dayjs.tz(date, timezone).isAfter(dayjs.tz(other, timezone));
873
+ };
874
+ return {
875
+ now,
876
+ today,
877
+ date,
878
+ parse,
879
+ isValidDate,
880
+ addDays,
881
+ addMonths,
882
+ addYears,
883
+ format,
884
+ subDays,
885
+ subMonths,
886
+ subYears,
887
+ startOfMonth,
888
+ endOfMonth,
889
+ startOfYear,
890
+ endOfYear,
891
+ isBefore,
892
+ isAfter
893
+ };
894
+ };
895
+ const validTimezones = ()=>{
896
+ return TIMEZONE_NAMES;
897
+ };
898
+
899
+ const create$4 = (params)=>{
900
+ // eslint-disable-next-line no-console
901
+ const log = params.log || console.log;
902
+ const exists = async (path)=>{
903
+ try {
904
+ await fs__namespace.promises.stat(path);
905
+ return true;
906
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
907
+ } catch (error) {
908
+ return false;
909
+ }
910
+ };
911
+ const isDirectory = async (path)=>{
912
+ const stats = await fs__namespace.promises.stat(path);
913
+ if (!stats.isDirectory()) {
914
+ log(`${path} is not a directory`);
915
+ return false;
916
+ }
917
+ return true;
918
+ };
919
+ const isFile = async (path)=>{
920
+ const stats = await fs__namespace.promises.stat(path);
921
+ if (!stats.isFile()) {
922
+ log(`${path} is not a file`);
923
+ return false;
924
+ }
925
+ return true;
926
+ };
927
+ const isReadable = async (path)=>{
928
+ try {
929
+ await fs__namespace.promises.access(path, fs__namespace.constants.R_OK);
930
+ } catch (error) {
931
+ log(`${path} is not readable: %s %s`, error.message, error.stack);
932
+ return false;
933
+ }
934
+ return true;
935
+ };
936
+ const isWritable = async (path)=>{
937
+ try {
938
+ await fs__namespace.promises.access(path, fs__namespace.constants.W_OK);
939
+ } catch (error) {
940
+ log(`${path} is not writable: %s %s`, error.message, error.stack);
941
+ return false;
942
+ }
943
+ return true;
944
+ };
945
+ const isFileReadable = async (path)=>{
946
+ return await exists(path) && await isFile(path) && await isReadable(path);
947
+ };
948
+ const isDirectoryWritable = async (path)=>{
949
+ return await exists(path) && await isDirectory(path) && await isWritable(path);
950
+ };
951
+ const isDirectoryReadable = async (path)=>{
952
+ return await exists(path) && await isDirectory(path) && await isReadable(path);
953
+ };
954
+ const createDirectory = async (path)=>{
955
+ try {
956
+ await fs__namespace.promises.mkdir(path, {
957
+ recursive: true
958
+ });
959
+ } catch (mkdirError) {
960
+ throw new Error(`Failed to create output directory ${path}: ${mkdirError.message} ${mkdirError.stack}`);
961
+ }
962
+ };
963
+ const readFile = async (path, encoding)=>{
964
+ return await fs__namespace.promises.readFile(path, {
965
+ encoding: encoding
966
+ });
967
+ };
968
+ const writeFile = async (path, data, encoding)=>{
969
+ await fs__namespace.promises.writeFile(path, data, {
970
+ encoding: encoding
971
+ });
972
+ };
973
+ const forEachFileIn = async (directory, callback, options = {
974
+ pattern: '*.*'
975
+ })=>{
976
+ try {
977
+ let filesProcessed = 0;
978
+ const files = await glob.glob(options.pattern, {
979
+ cwd: directory,
980
+ nodir: true
981
+ });
982
+ const concurrency = options.concurrency || 1;
983
+ let index = 0;
984
+ async function worker() {
985
+ while(index < files.length && (!options.limit || filesProcessed < options.limit)){
986
+ const i = index++;
987
+ if (options.limit && filesProcessed >= options.limit) break;
988
+ await callback(path__namespace.join(directory, files[i]));
989
+ filesProcessed++;
990
+ }
991
+ }
992
+ const workers = Array.from({
993
+ length: concurrency
994
+ }, ()=>worker());
995
+ await Promise.all(workers);
996
+ if (options.limit && filesProcessed >= options.limit) {
997
+ log(`Reached limit of ${options.limit} files, stopping`);
998
+ }
999
+ } catch (err) {
1000
+ throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);
1001
+ }
1002
+ };
1003
+ const readStream = async (path)=>{
1004
+ return fs__namespace.createReadStream(path);
1005
+ };
1006
+ const hashFile = async (path, length)=>{
1007
+ const file = await readFile(path, 'utf8');
1008
+ return crypto__namespace.createHash('sha256').update(file).digest('hex').slice(0, length);
1009
+ };
1010
+ const listFiles = async (directory)=>{
1011
+ return await fs__namespace.promises.readdir(directory);
1012
+ };
1013
+ return {
1014
+ exists,
1015
+ isDirectory,
1016
+ isFile,
1017
+ isReadable,
1018
+ isWritable,
1019
+ isFileReadable,
1020
+ isDirectoryWritable,
1021
+ isDirectoryReadable,
1022
+ createDirectory,
1023
+ readFile,
1024
+ readStream,
1025
+ writeFile,
1026
+ forEachFileIn,
1027
+ hashFile,
1028
+ listFiles
1029
+ };
1030
+ };
1031
+
1032
+ const validate = async (config, options)=>{
1033
+ const logger = console;
1034
+ const storage = create$4({
1035
+ log: logger.debug
1036
+ });
1037
+ const validateInputDirectory = async (inputDirectory)=>{
1038
+ // eslint-disable-next-line no-console
1039
+ const storage = create$4({
1040
+ log: console.log
1041
+ });
1042
+ if (!storage.isDirectoryReadable(inputDirectory)) {
1043
+ throw new Error(`Input directory does not exist: ${inputDirectory}`);
1044
+ }
1045
+ };
1046
+ const validateOutputDirectory = async (outputDirectory)=>{
1047
+ const isDirectoryWritable = await storage.isDirectoryWritable(outputDirectory);
1048
+ if (!isDirectoryWritable) {
1049
+ throw new Error(`Output directory does not exist: ${outputDirectory}`);
1050
+ }
1051
+ };
1052
+ const validateOutputStructure = (outputStructure)=>{
1053
+ var _options_allowed;
1054
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.outputStructures) || ALLOWED_OUTPUT_STRUCTURES;
1055
+ if (outputStructure && !validOptions.includes(outputStructure)) {
1056
+ throw new ArgumentError('--output-structure', `Invalid output structure: ${outputStructure}. Valid options are: ${validOptions.join(', ')}`);
1057
+ }
1058
+ };
1059
+ const validateOutputFilenameOptions = (outputFilenameOptions, outputStructure)=>{
1060
+ if (outputFilenameOptions) {
1061
+ var _options_allowed;
1062
+ // Check if first argument contains commas - likely a comma-separated list
1063
+ if (outputFilenameOptions[0].includes(',')) {
1064
+ throw new ArgumentError('--output-filename-options', 'Filename options should be space-separated, not comma-separated. Example: --output-filename-options date time subject');
1065
+ }
1066
+ // Check if first argument looks like a quoted string containing multiple options
1067
+ if (outputFilenameOptions.length === 1 && outputFilenameOptions[0].split(' ').length > 1) {
1068
+ 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"');
1069
+ }
1070
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.outputFilenameOptions) || ALLOWED_OUTPUT_FILENAME_OPTIONS;
1071
+ const invalidOptions = outputFilenameOptions.filter((opt)=>!validOptions.includes(opt));
1072
+ if (invalidOptions.length > 0) {
1073
+ throw new ArgumentError('--output-filename-options', `Invalid filename options: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);
1074
+ }
1075
+ // Validate date option against output structure
1076
+ if (outputFilenameOptions.includes('date')) {
1077
+ if (outputStructure && outputStructure === 'day') {
1078
+ throw new ArgumentError('--output-filename-options', 'Cannot use date in filename when output structure is "day"');
1079
+ }
1080
+ }
1081
+ }
1082
+ };
1083
+ const validateInputStructure = (inputStructure)=>{
1084
+ var _options_allowed;
1085
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.inputStructures) || ALLOWED_INPUT_STRUCTURES;
1086
+ if (inputStructure && !validOptions.includes(inputStructure)) {
1087
+ throw new ArgumentError('--input-structure', `Invalid input structure: ${inputStructure}. Valid options are: ${validOptions.join(', ')}`);
1088
+ }
1089
+ };
1090
+ const validateInputFilenameOptions = (inputFilenameOptions, inputStructure)=>{
1091
+ if (inputFilenameOptions) {
1092
+ var _options_allowed;
1093
+ // Check if first argument contains commas - likely a comma-separated list
1094
+ if (inputFilenameOptions[0].includes(',')) {
1095
+ throw new ArgumentError('--input-filename-options', 'Filename options should be space-separated, not comma-separated. Example: --input-filename-options date time subject');
1096
+ }
1097
+ // Check if first argument looks like a quoted string containing multiple options
1098
+ if (inputFilenameOptions.length === 1 && inputFilenameOptions[0].split(' ').length > 1) {
1099
+ 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"');
1100
+ }
1101
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.inputFilenameOptions) || ALLOWED_INPUT_FILENAME_OPTIONS;
1102
+ const invalidOptions = inputFilenameOptions.filter((opt)=>!validOptions.includes(opt));
1103
+ if (invalidOptions.length > 0) {
1104
+ throw new ArgumentError('--input-filename-options', `Invalid filename options: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);
1105
+ }
1106
+ // Validate date option against input structure
1107
+ if (inputFilenameOptions.includes('date')) {
1108
+ if (inputStructure && inputStructure === 'day') {
1109
+ throw new ArgumentError('--input-filename-options', 'Cannot use date in filename when input structure is "day"');
1110
+ }
1111
+ }
1112
+ }
1113
+ };
1114
+ const validateTimezone = (timezone)=>{
1115
+ const validOptions = validTimezones();
1116
+ if (validOptions.includes(timezone)) {
1117
+ return;
1118
+ }
1119
+ throw new ArgumentError('--timezone', `Invalid timezone: ${timezone}. Valid options are: ${validOptions.join(', ')}`);
1120
+ };
1121
+ const validateExtensions = (extensions)=>{
1122
+ var _options_allowed;
1123
+ const validOptions = ((_options_allowed = options.allowed) === null || _options_allowed === void 0 ? void 0 : _options_allowed.extensions) || ALLOWED_EXTENSIONS;
1124
+ if (extensions) {
1125
+ const invalidOptions = extensions.filter((ext)=>!validOptions.includes(ext));
1126
+ if (invalidOptions.length > 0) {
1127
+ throw new ArgumentError('--extensions', `Invalid extensions: ${invalidOptions.join(', ')}. Valid options are: ${validOptions.join(', ')}`);
1128
+ }
1129
+ }
1130
+ };
1131
+ // Validate timezone
1132
+ validateTimezone(config.timezone);
1133
+ if (options.features.includes('input') && config.inputDirectory) {
1134
+ await validateInputDirectory(config.inputDirectory);
1135
+ }
1136
+ if (options.features.includes('input') && config.limit) {
1137
+ if (config.limit < 1) {
1138
+ throw new ArgumentError('--limit', 'Limit must be greater than 0');
1139
+ }
1140
+ }
1141
+ if (options.features.includes('output') && config.outputDirectory) {
1142
+ await validateOutputDirectory(config.outputDirectory);
1143
+ }
1144
+ if (options.features.includes('structured-output')) {
1145
+ // Validate filename options if provided
1146
+ validateOutputStructure(config.outputStructure);
1147
+ validateOutputFilenameOptions(config.outputFilenameOptions, config.outputStructure);
1148
+ }
1149
+ if (options.features.includes('extensions')) {
1150
+ validateExtensions(config.extensions);
1151
+ }
1152
+ if (options.features.includes('structured-input')) {
1153
+ validateInputStructure(config.inputStructure);
1154
+ validateInputFilenameOptions(config.inputFilenameOptions, config.inputStructure);
1155
+ }
1156
+ return;
1157
+ };
1158
+
1159
+ zod.z.object({
1160
+ start: zod.z.date(),
1161
+ end: zod.z.date()
1162
+ });
1163
+ // Get the appropriate file pattern based on config and options
1164
+ const getFilePattern = (features, extensions, logger)=>{
1165
+ // Validate extensions: they should not start with a dot.
1166
+ if (extensions && extensions.length > 0) {
1167
+ for (const ext of extensions){
1168
+ if (ext.startsWith('.')) {
1169
+ // Throw an error as the dot is added automatically by the pattern generation.
1170
+ // Using ArgumentError might be more consistent if available and appropriate here.
1171
+ throw new Error(`Invalid extension format: "${ext}". Extensions should not start with a dot ('.').`);
1172
+ }
1173
+ }
1174
+ }
1175
+ let pattern = '**/*'; // Start with a broad pattern for recursive search
1176
+ if (features.includes('extensions') && extensions && extensions.length > 0) {
1177
+ if (extensions.length === 1) {
1178
+ pattern = `**/*.${extensions[0]}`;
1179
+ } else {
1180
+ pattern = `**/*.{${extensions.join(',')}}`;
1181
+ }
1182
+ logger.debug(`Applying extension filter: ${extensions.join(',')}`);
1183
+ } else {
1184
+ pattern = `**/*.*`;
1185
+ logger.debug(`No extension filter applied, using pattern: ${pattern}`);
1186
+ }
1187
+ return pattern;
1188
+ };
1189
+ // Helper function to parse date string based on expected format
1190
+ // Returns null if parsing fails
1191
+ const parseDateFromString = (dateStr, format, shouldParseTime, year, month, day)=>{
1192
+ // Basic validation
1193
+ if (!dateStr) return null;
1194
+ try {
1195
+ let y = year !== null && year !== void 0 ? year : 0;
1196
+ let mo = month !== null && month !== void 0 ? month : 0; // JS months are 0-indexed
1197
+ let d = day !== null && day !== void 0 ? day : 1; // JS days are 1-indexed
1198
+ let h = 0; // Default to 0
1199
+ let mi = 0; // Default to 0
1200
+ // Remove potential leading/trailing non-alphanumeric if needed, split by common separators
1201
+ const cleanedDateStr = dateStr.replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu, '');
1202
+ const parts = cleanedDateStr.split(/[-_]/); // Allow dash or underscore
1203
+ switch(format){
1204
+ case 'YYYY-M-D-HHmm':
1205
+ {
1206
+ if (parts.length < 4 && shouldParseTime) return null; // Need time part if parsing it
1207
+ if (parts.length < 3 && !shouldParseTime) return null; // Need at least date part
1208
+ y = parseInt(parts[0], 10);
1209
+ mo = parseInt(parts[1], 10) - 1; // Adjust month
1210
+ d = parseInt(parts[2], 10);
1211
+ if (shouldParseTime) {
1212
+ const timePartYD = parts[3];
1213
+ if (timePartYD.length < 4) return null; // Ensure HHmm exists
1214
+ h = parseInt(timePartYD.substring(0, 2), 10);
1215
+ mi = parseInt(timePartYD.substring(2, 4), 10);
1216
+ }
1217
+ break;
1218
+ }
1219
+ case 'M-D-HHmm':
1220
+ {
1221
+ if (year === undefined) return null;
1222
+ if (parts.length < 3 && shouldParseTime) return null;
1223
+ if (parts.length < 2 && !shouldParseTime) return null;
1224
+ mo = parseInt(parts[0], 10) - 1; // Adjust month
1225
+ d = parseInt(parts[1], 10);
1226
+ if (shouldParseTime) {
1227
+ const timePartMD = parts[2];
1228
+ if (timePartMD.length < 4) return null; // Ensure HHmm exists
1229
+ h = parseInt(timePartMD.substring(0, 2), 10);
1230
+ mi = parseInt(timePartMD.substring(2, 4), 10);
1231
+ }
1232
+ break;
1233
+ }
1234
+ case 'D-HHmm':
1235
+ {
1236
+ if (year === undefined || month === undefined) return null;
1237
+ if (parts.length < 2 && shouldParseTime) return null;
1238
+ if (parts.length < 1 && !shouldParseTime) return null;
1239
+ d = parseInt(parts[0], 10);
1240
+ if (shouldParseTime) {
1241
+ const timePartD = parts[1];
1242
+ if (timePartD.length < 4) return null; // Ensure HHmm exists
1243
+ h = parseInt(timePartD.substring(0, 2), 10);
1244
+ mi = parseInt(timePartD.substring(2, 4), 10);
1245
+ }
1246
+ break;
1247
+ }
1248
+ case 'HHmm':
1249
+ if (year === undefined || month === undefined || day === undefined) return null;
1250
+ if (shouldParseTime) {
1251
+ if (parts[0].length !== 4) return null;
1252
+ h = parseInt(parts[0].substring(0, 2), 10);
1253
+ mi = parseInt(parts[0].substring(2, 4), 10);
1254
+ } // Else h=0, mi=0 (set by defaults)
1255
+ break;
1256
+ default:
1257
+ return null;
1258
+ }
1259
+ // Validate parsed numbers
1260
+ if (isNaN(y) || isNaN(mo) || isNaN(d)) {
1261
+ throw new Error(`Invalid date components in date string "${dateStr}" with format ${format}: Y:${y} M:${mo} D:${d}`);
1262
+ }
1263
+ // Set hour and minute to 0 if not provided
1264
+ if (isNaN(h)) {
1265
+ h = 0;
1266
+ }
1267
+ if (isNaN(mi)) {
1268
+ mi = 0;
1269
+ }
1270
+ if (mo < 0 || mo > 11 || d < 1 || d > 31 || h < 0 || h > 23 || mi < 0 || mi > 59) {
1271
+ throw new Error(`Invalid date components in date string "${dateStr}" with format ${format}: Y:${y} M:${mo + 1} D:${d} H:${h} m:${mi}`);
1272
+ }
1273
+ const date = new Date(Date.UTC(y, mo, d, h, mi));
1274
+ // Double check components as Date object might adjust invalid dates (e.g. Feb 30th -> Mar 2nd)
1275
+ if (date.getUTCFullYear() !== y || date.getUTCMonth() !== mo || date.getUTCDate() !== d || date.getUTCHours() !== h || date.getUTCMinutes() !== mi) {
1276
+ // console.debug(`Date validation failed for Y:${y} M:${mo} D:${d} H:${h} m:${mi}. JS Date adjusted it.`);
1277
+ return null;
1278
+ }
1279
+ return date;
1280
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1281
+ } catch (e) {
1282
+ // console.error(`Error parsing date string "${dateStr}" with format ${format}:`, e);
1283
+ return null;
1284
+ }
1285
+ };
1286
+ // Helper to check if date is within range (start inclusive, end exclusive)
1287
+ const isDateInRange = (date, range)=>{
1288
+ if (!range || !range.start && !range.end) return true; // No range or empty range means all dates are valid
1289
+ // Ensure range dates are Date objects
1290
+ const startDate = range.start ? range.start instanceof Date ? range.start : new Date(range.start) : null;
1291
+ const endDate = range.end ? range.end instanceof Date ? range.end : new Date(range.end) : null;
1292
+ // Validate parsed range dates
1293
+ const isStartDateValid = startDate && !isNaN(startDate.getTime());
1294
+ const isEndDateValid = endDate && !isNaN(endDate.getTime());
1295
+ if (isStartDateValid && date < startDate) {
1296
+ return false;
1297
+ }
1298
+ // End date is exclusive
1299
+ if (isEndDateValid && date >= endDate) {
1300
+ return false;
1301
+ }
1302
+ return true;
1303
+ };
1304
+ const calculateDateRange = (timezone, startDate, endDate)=>{
1305
+ // Create date utility after timezone is validated
1306
+ const dateUtil = create$5({
1307
+ timezone
1308
+ });
1309
+ const now = dateUtil.now();
1310
+ const range = {
1311
+ start: dateUtil.subDays(now, 31),
1312
+ end: now
1313
+ };
1314
+ // Note: Validation ensures dates are valid and start <= end if both are provided
1315
+ if (startDate || endDate) {
1316
+ // Handle end date
1317
+ if (endDate) {
1318
+ range.end = dateUtil.parse(endDate, DATE_FORMAT_YEAR_MONTH_DAY);
1319
+ }
1320
+ // Handle start date
1321
+ if (startDate) {
1322
+ range.start = dateUtil.parse(startDate, DATE_FORMAT_YEAR_MONTH_DAY);
1323
+ }
1324
+ // We re-check the order here after defaults might have been applied,
1325
+ // although validateStartEndDates should catch explicit invalid orders.
1326
+ if (dateUtil.isBefore(range.end, range.start)) {
1327
+ // This case should theoretically not be reachable due to prior validation
1328
+ // but is kept as a safeguard.
1329
+ throw new ArgumentError('--start', `Start date (${dateUtil.format(range.start, DATE_FORMAT_YEAR_MONTH_DAY)}) cannot be after end date (${dateUtil.format(range.end, DATE_FORMAT_YEAR_MONTH_DAY)}).`);
1330
+ }
1331
+ }
1332
+ return range;
1333
+ };
1334
+ // Parse date from file path based on the input structure
1335
+ const parseDateFromFilePath = (relativePath, filename, structure, shouldParseTime, logger)=>{
1336
+ const pathParts = relativePath.split(path__namespace.sep);
1337
+ const filenameWithoutExt = path__namespace.basename(filename, path__namespace.extname(filename));
1338
+ let parsedDate = null;
1339
+ let year;
1340
+ let month; // 0-indexed month for Date constructor
1341
+ let day;
1342
+ switch(structure){
1343
+ case 'none':
1344
+ // Filename format: YYYY-M-D-HHmm...
1345
+ parsedDate = parseDateFromString(filenameWithoutExt, 'YYYY-M-D-HHmm', shouldParseTime);
1346
+ break;
1347
+ case 'year':
1348
+ // Path: YYYY / M-D-HHmm...
1349
+ if (pathParts.length >= 1) {
1350
+ year = parseInt(pathParts[0], 10);
1351
+ if (!isNaN(year)) {
1352
+ parsedDate = parseDateFromString(filenameWithoutExt, 'M-D-HHmm', shouldParseTime, year);
1353
+ } else {
1354
+ logger.warn(`Invalid year format in path: ${pathParts[0]}`);
1355
+ }
1356
+ } else {
1357
+ logger.warn(`File path does not match expected 'year' structure (YYYY/...)`);
1358
+ }
1359
+ break;
1360
+ case 'month':
1361
+ // Path: YYYY / MM / D-HHmm...
1362
+ if (pathParts.length >= 2) {
1363
+ year = parseInt(pathParts[0], 10);
1364
+ const monthDir = parseInt(pathParts[1], 10); // Month from dir (1-indexed)
1365
+ if (!isNaN(year) && !isNaN(monthDir) && monthDir >= 1 && monthDir <= 12) {
1366
+ month = monthDir - 1; // Adjust month for Date object (0-indexed)
1367
+ parsedDate = parseDateFromString(filenameWithoutExt, 'D-HHmm', shouldParseTime, year, month);
1368
+ } else {
1369
+ logger.warn(`Invalid year/month format in path: ${pathParts[0]}/${pathParts[1]}`);
1370
+ }
1371
+ } else {
1372
+ logger.warn(`File path does not match expected 'month' structure (YYYY/MM/...)`);
1373
+ }
1374
+ break;
1375
+ case 'day':
1376
+ // Path: YYYY / MM / DD / HHmm...
1377
+ if (pathParts.length >= 3) {
1378
+ year = parseInt(pathParts[0], 10);
1379
+ const monthDir = parseInt(pathParts[1], 10); // Month from dir (1-indexed)
1380
+ day = parseInt(pathParts[2], 10); // Day from dir (1-indexed)
1381
+ if (!isNaN(year) && !isNaN(monthDir) && monthDir >= 1 && monthDir <= 12 && !isNaN(day) && day >= 1 && day <= 31) {
1382
+ month = monthDir - 1; // Adjust month (0-indexed)
1383
+ parsedDate = parseDateFromString(filenameWithoutExt, 'HHmm', shouldParseTime, year, month, day);
1384
+ } else {
1385
+ logger.warn(`Invalid year/month/day format in path: ${pathParts[0]}/${pathParts[1]}/${pathParts[2]}`);
1386
+ }
1387
+ } else {
1388
+ logger.warn(`File path does not match expected 'day' structure (YYYY/MM/DD/...)`);
1389
+ }
1390
+ break;
1391
+ default:
1392
+ logger.error(`Fatal: Unknown input structure "${structure}" specified in config.`);
1393
+ throw new Error(`Unknown input structure "${structure}" specified.`);
1394
+ }
1395
+ return parsedDate;
1396
+ };
1397
+ // Process a single file from the structured input
1398
+ const processStructuredFile = async (filePath, inputDirectory, structure, shouldParseTime, callback, pattern, dateRange, logger)=>{
1399
+ // Skip if filePath somehow points to the inputDirectory itself or is not a file
1400
+ if (filePath === inputDirectory || !path__namespace.extname(filePath) && pattern.endsWith('*.*')) {
1401
+ return false;
1402
+ }
1403
+ const relativePath = path__namespace.relative(inputDirectory, filePath);
1404
+ const pathParts = relativePath.split(path__namespace.sep);
1405
+ const filename = pathParts.pop(); // Filename is the last part
1406
+ if (!filename) {
1407
+ logger.warn(`Could not determine filename for path: ${filePath}`);
1408
+ return false;
1409
+ }
1410
+ try {
1411
+ const parsedDate = parseDateFromFilePath(relativePath, filename, structure, shouldParseTime, logger);
1412
+ if (parsedDate) {
1413
+ // Apply date range filtering
1414
+ if (isDateInRange(parsedDate, dateRange)) {
1415
+ logger.debug('Processing file %s with date %s', filePath, parsedDate.toISOString());
1416
+ await callback(filePath, parsedDate);
1417
+ return true;
1418
+ } else {
1419
+ const dateRangeDisplay = dateRange ? `from ${dateRange.start ? new Date(dateRange.start).toISOString() : 'beginning'} up to ${dateRange.end ? new Date(dateRange.end).toISOString() : 'end'}` : 'all dates';
1420
+ logger.debug('Skipping file %s, date %s out of range %s', filePath, parsedDate.toISOString(), dateRangeDisplay);
1421
+ }
1422
+ } else {
1423
+ logger.warn('Could not parse date for file %s with structure "%s" (filename base: "%s", path parts: %s)', filePath, structure, path__namespace.basename(filename, path__namespace.extname(filename)), pathParts.join('/'));
1424
+ }
1425
+ } catch (error) {
1426
+ // Log error from the callback or date parsing/filtering itself
1427
+ if (error instanceof Error) {
1428
+ logger.error('Error processing file %s: %s\n%s', filePath, error.message, error.stack);
1429
+ } else {
1430
+ logger.error('Error processing file %s: %s', filePath, error);
1431
+ }
1432
+ }
1433
+ return false;
1434
+ };
1435
+ const process$2 = async (inputStructure, inputFilenameOptions, extensions, timezone, start, end, limit, features, logger, inputDirectory, callback, concurrency)=>{
1436
+ var _ref;
1437
+ const storage = create$4({
1438
+ log: logger.debug
1439
+ });
1440
+ const dateRange = calculateDateRange(timezone, start, end);
1441
+ let fileCount = 0;
1442
+ // Validate date range dates if provided
1443
+ if ((dateRange === null || dateRange === void 0 ? void 0 : dateRange.start) && (!dateRange.start || isNaN(dateRange.start.getTime()))) {
1444
+ logger.warn(`Invalid start date provided in dateRange: ${dateRange.start}`);
1445
+ }
1446
+ if ((dateRange === null || dateRange === void 0 ? void 0 : dateRange.end) && (!dateRange.end || isNaN(dateRange.end.getTime()))) {
1447
+ logger.warn(`Invalid end date provided in dateRange: ${dateRange.end}`);
1448
+ }
1449
+ // Structured Input Logic
1450
+ const structure = inputStructure !== null && inputStructure !== void 0 ? inputStructure : 'none'; // Default to 'none' if not specified
1451
+ logger.info(`Processing structured input with structure "${structure}" in %s for date range: ${JSON.stringify(dateRange)}`, inputDirectory);
1452
+ // Determine if time should be parsed from filenames
1453
+ const shouldParseTime = (_ref = inputFilenameOptions === null || inputFilenameOptions === void 0 ? void 0 : inputFilenameOptions.includes('time')) !== null && _ref !== void 0 ? _ref : false;
1454
+ if (shouldParseTime) {
1455
+ logger.debug('Filename time parsing enabled based on inputFilenameOptions.');
1456
+ } else {
1457
+ logger.debug('Filename time parsing disabled; defaulting times to 00:00 UTC.');
1458
+ }
1459
+ const filePattern = getFilePattern(features, extensions || [], logger);
1460
+ logger.debug('Processing Structured Input with pattern %s from %s', filePattern, inputDirectory);
1461
+ await storage.forEachFileIn(inputDirectory, async (filePath)=>{
1462
+ const processed = await processStructuredFile(filePath, inputDirectory, structure, shouldParseTime, callback, filePattern, dateRange, logger);
1463
+ if (processed) {
1464
+ fileCount++;
1465
+ }
1466
+ }, {
1467
+ pattern: filePattern,
1468
+ limit,
1469
+ concurrency
1470
+ });
1471
+ return fileCount;
1472
+ };
1473
+
1474
+ // Process files with unstructured input pattern
1475
+ const process$1 = async (inputDirectory, recursive, extensions, limit, logger, callback, concurrency)=>{
1476
+ const storage = create$4({
1477
+ log: logger.debug
1478
+ });
1479
+ let fileCount = 0;
1480
+ let filePattern = `${recursive ? '**/' : ''}*`;
1481
+ if (extensions && extensions.length > 0) {
1482
+ // Ensure the pattern correctly handles extensions with or without recursion
1483
+ if (recursive) {
1484
+ filePattern = `**/*.{${extensions.join(',')}}`;
1485
+ } else {
1486
+ filePattern = `*.{${extensions.join(',')}}`;
1487
+ }
1488
+ logger.debug(`Applying extension filter: ${extensions.join(',')}`);
1489
+ } else if (!recursive) {
1490
+ // Non-recursive without extension filter: only files in the top directory
1491
+ filePattern = `*.*`; // Adjust if files without extensions need matching
1492
+ }
1493
+ logger.info('Processing unstructured files %s in %s with pattern %s', recursive ? 'recursively' : 'non-recursively', inputDirectory, filePattern);
1494
+ await storage.forEachFileIn(inputDirectory, async (file)=>{
1495
+ try {
1496
+ logger.debug('Processing file %s', file);
1497
+ // Call callback without date for unstructured input
1498
+ await callback(file); // Pass undefined for the date parameter
1499
+ fileCount++;
1500
+ } catch (error) {
1501
+ if (error instanceof Error) {
1502
+ logger.error('Error processing file %s: %s\n%s', file, error.message, error.stack);
1503
+ } else {
1504
+ logger.error('Error processing file %s: %s', file, error);
1505
+ }
1506
+ }
1507
+ }, {
1508
+ pattern: filePattern,
1509
+ limit,
1510
+ concurrency
1511
+ });
1512
+ return fileCount;
1513
+ };
1514
+
1515
+ const process = async (config, features, logger, callback, { start, end } = {})=>{
1516
+ if (!features.includes('input')) {
1517
+ throw new Error('Input feature is not enabled, skipping input processing');
1518
+ }
1519
+ const concurrency = config.concurrency;
1520
+ if (!concurrency) {
1521
+ throw new Error('Concurrency is not configured');
1522
+ }
1523
+ const inputDirectory = config.inputDirectory;
1524
+ if (!inputDirectory) {
1525
+ throw new Error('Input directory is not configured');
1526
+ }
1527
+ let fileCount = 0;
1528
+ if (features.includes('structured-input')) {
1529
+ logger.debug('Processing Structured Input from %s with start date %s and end date %s', inputDirectory, start, end);
1530
+ if (!start || !end) {
1531
+ throw new Error('Start or end date are both required for structured input');
1532
+ } else {
1533
+ fileCount = await process$2(config.inputStructure, config.inputFilenameOptions, config.extensions, config.timezone, start, end, config.limit, features, logger, inputDirectory, callback, concurrency);
1534
+ }
1535
+ } else {
1536
+ // Original Unstructured Input Logic
1537
+ logger.debug('Processing Unstructured Input from %s', inputDirectory);
1538
+ if (start || end) {
1539
+ throw new Error('Start or end date is not allowed for unstructured input');
1540
+ }
1541
+ fileCount = await process$1(inputDirectory, config.recursive || false, config.extensions || [], config.limit, logger, callback, concurrency);
1542
+ }
1543
+ logger.info('Processed %d files matching criteria.', fileCount);
1544
+ };
1545
+
1546
+ const create$3 = (config, options)=>{
1547
+ return {
1548
+ process: (callback, { start, end } = {})=>process(config, options.features, options.logger, callback, {
1549
+ start,
1550
+ end
1551
+ })
1552
+ };
1553
+ };
1554
+
1555
+ const create$2 = (config, options)=>{
1556
+ const logger = options.logger;
1557
+ const timezone = (config === null || config === void 0 ? void 0 : config.timezone) || 'UTC';
1558
+ const dates = create$5({
1559
+ timezone
1560
+ });
1561
+ const storage = create$4({
1562
+ log: logger.debug
1563
+ });
1564
+ const { outputDirectory, outputStructure, outputFilenameOptions } = config;
1565
+ function formatDate(date, outputStructure) {
1566
+ if (!outputStructure) {
1567
+ throw new Error('Unable to Create Output: Output structure is not set');
1568
+ }
1569
+ switch(outputStructure){
1570
+ case 'none':
1571
+ return dates.format(date, DATE_FORMAT_YEAR_MONTH_DAY);
1572
+ case 'year':
1573
+ return dates.format(date, DATE_FORMAT_MONTH_DAY);
1574
+ case 'month':
1575
+ return dates.format(date, DATE_FORMAT_DAY);
1576
+ case 'day':
1577
+ throw new Error('Cannot use date in filename when output structure is "day"');
1578
+ }
1579
+ }
1580
+ function sanitizeFilenameString(str) {
1581
+ // Replace any character that is not alphanumeric, hyphen, underscore, or dot with an underscore
1582
+ return str.replace(/[^a-zA-Z0-9\-_.]/g, '_')// Replace multiple consecutive underscores with a single underscore
1583
+ .replace(/_+/g, '_')// Remove leading and trailing underscores
1584
+ .replace(/^_+|_+$/g, '')// Ensure the string is not empty
1585
+ .replace(/^$/, 'untitled');
1586
+ }
1587
+ function constructFilename(date, type, hash, options = {}) {
1588
+ const parts = [];
1589
+ // Add date if requested
1590
+ if (outputFilenameOptions === null || outputFilenameOptions === void 0 ? void 0 : outputFilenameOptions.includes('date')) {
1591
+ const dateStr = formatDate(date, outputStructure);
1592
+ parts.push(dateStr);
1593
+ }
1594
+ // Add time if requested
1595
+ if (outputFilenameOptions === null || outputFilenameOptions === void 0 ? void 0 : outputFilenameOptions.includes('time')) {
1596
+ const dates = create$5({
1597
+ timezone
1598
+ });
1599
+ const timeStr = dates.format(date, 'HHmm');
1600
+ parts.push(timeStr);
1601
+ }
1602
+ // Add message ID
1603
+ parts.push(hash);
1604
+ parts.push(type);
1605
+ // Add subject if requested
1606
+ if (outputFilenameOptions === null || outputFilenameOptions === void 0 ? void 0 : outputFilenameOptions.includes('subject')) {
1607
+ // Sanitize the provided subject, defaulting to empty string if undefined/null
1608
+ parts.push(sanitizeFilenameString(options.subject || ''));
1609
+ }
1610
+ return parts.join('-');
1611
+ }
1612
+ function constructOutputDirectory(creationTime) {
1613
+ // Throw this error to ensure that we don't success if outputDirectory or outputStructure are not set
1614
+ if (!outputDirectory) {
1615
+ throw new Error('Unable to Create Output: Output directory is not set');
1616
+ }
1617
+ if (!outputStructure) {
1618
+ throw new Error('Unable to Create Output: Output structure is not set');
1619
+ }
1620
+ const date = dates.date(creationTime);
1621
+ const year = dates.format(date, DATE_FORMAT_YEAR);
1622
+ const month = dates.format(date, DATE_FORMAT_MONTH);
1623
+ const day = dates.format(date, DATE_FORMAT_DAY);
1624
+ let outputPath;
1625
+ switch(outputStructure){
1626
+ case 'year':
1627
+ outputPath = path__namespace.join(outputDirectory, year);
1628
+ break;
1629
+ case 'month':
1630
+ outputPath = path__namespace.join(outputDirectory, year, month);
1631
+ break;
1632
+ case 'day':
1633
+ outputPath = path__namespace.join(outputDirectory, year, month, day);
1634
+ break;
1635
+ default:
1636
+ outputPath = outputDirectory;
1637
+ }
1638
+ storage.createDirectory(outputPath);
1639
+ return outputPath;
1640
+ }
1641
+ return {
1642
+ constructFilename,
1643
+ constructOutputDirectory
1644
+ };
1645
+ };
1646
+
1647
+ const create$1 = async (config, args, options)=>{
1648
+ const output = create$2(config, options);
1649
+ const input = create$3(config, options);
1650
+ const constructFilename = async (createDate, type, hash, context)=>{
1651
+ if (!options.features.includes('output')) {
1652
+ throw new Error('Output feature is not enabled, skipping output construction');
1653
+ }
1654
+ return output.constructFilename(createDate, type, hash, context);
1655
+ };
1656
+ const constructOutputDirectory = async (createDate)=>{
1657
+ if (!options.features.includes('output')) {
1658
+ throw new Error('Output feature is not enabled, skipping output construction');
1659
+ }
1660
+ return output.constructOutputDirectory(createDate);
1661
+ };
1662
+ return {
1663
+ process: input.process,
1664
+ constructFilename,
1665
+ constructOutputDirectory
1666
+ };
1667
+ };
1668
+
1669
+ const wrapLogger = (toWrap)=>{
1670
+ const log = (level, message, ...args)=>{
1671
+ message = `[${PROGRAM_NAME}] ${message}`;
1672
+ toWrap[level](message, ...args);
1673
+ };
1674
+ return {
1675
+ debug: (message, ...args)=>log('debug', message, ...args),
1676
+ info: (message, ...args)=>log('info', message, ...args),
1677
+ warn: (message, ...args)=>log('warn', message, ...args),
1678
+ error: (message, ...args)=>log('error', message, ...args),
1679
+ verbose: (message, ...args)=>log('verbose', message, ...args),
1680
+ silly: (message, ...args)=>log('silly', message, ...args)
1681
+ };
1682
+ };
1683
+
1684
+ const FilenameOptionSchema = zod.z.enum([
1685
+ 'date',
1686
+ 'time',
1687
+ 'subject'
1688
+ ]);
1689
+ const FilesystemStructureSchema = zod.z.enum([
1690
+ 'none',
1691
+ 'year',
1692
+ 'month',
1693
+ 'day'
1694
+ ]);
1695
+ const DEFAULT_APP_OPTIONS = {
1696
+ timezone: DEFAULT_TIMEZONE,
1697
+ recursive: DEFAULT_RECURSIVE,
1698
+ inputDirectory: DEFAULT_INPUT_DIRECTORY,
1699
+ inputStructure: DEFAULT_INPUT_STRUCTURE,
1700
+ inputFilenameOptions: DEFAULT_INPUT_FILENAME_OPTIONS,
1701
+ outputDirectory: DEFAULT_OUTPUT_DIRECTORY,
1702
+ outputStructure: DEFAULT_OUTPUT_STRUCTURE,
1703
+ outputFilenameOptions: DEFAULT_OUTPUT_FILENAME_OPTIONS,
1704
+ extensions: DEFAULT_EXTENSIONS,
1705
+ concurrency: DEFAULT_CONCURRENCY
1706
+ };
1707
+ const DEFAULT_ALLOWED_OPTIONS = {
1708
+ inputStructures: ALLOWED_INPUT_STRUCTURES,
1709
+ inputFilenameOptions: ALLOWED_INPUT_FILENAME_OPTIONS,
1710
+ outputStructures: ALLOWED_OUTPUT_STRUCTURES,
1711
+ outputFilenameOptions: ALLOWED_OUTPUT_FILENAME_OPTIONS,
1712
+ extensions: ALLOWED_EXTENSIONS
1713
+ };
1714
+ const DEFAULT_FEATURES = [
1715
+ 'output',
1716
+ 'structured-output',
1717
+ 'input',
1718
+ 'extensions'
1719
+ ];
1720
+ const DEFAULT_LOGGER = {
1721
+ // eslint-disable-next-line no-console
1722
+ debug: (message, ...args)=>console.debug(message, ...args),
1723
+ // eslint-disable-next-line no-console
1724
+ info: (message, ...args)=>console.info(message, ...args),
1725
+ // eslint-disable-next-line no-console
1726
+ warn: (message, ...args)=>console.warn(message, ...args),
1727
+ // eslint-disable-next-line no-console
1728
+ error: (message, ...args)=>console.error(message, ...args),
1729
+ // eslint-disable-next-line no-console
1730
+ verbose: (message, ...args)=>console.log(message, ...args),
1731
+ // eslint-disable-next-line no-console
1732
+ silly: (message, ...args)=>console.log(message, ...args)
1733
+ };
1734
+ const DEFAULT_OPTIONS = {
1735
+ defaults: DEFAULT_APP_OPTIONS,
1736
+ allowed: DEFAULT_ALLOWED_OPTIONS,
1737
+ features: DEFAULT_FEATURES,
1738
+ addDefaults: true,
1739
+ logger: DEFAULT_LOGGER
1740
+ };
1741
+ const ConfigSchema = zod.z.object({
1742
+ timezone: zod.z.string(),
1743
+ inputDirectory: zod.z.string().optional(),
1744
+ inputStructure: FilesystemStructureSchema.optional(),
1745
+ inputFilenameOptions: zod.z.array(FilenameOptionSchema).optional(),
1746
+ recursive: zod.z.boolean().optional(),
1747
+ outputDirectory: zod.z.string().optional(),
1748
+ outputStructure: FilesystemStructureSchema.optional(),
1749
+ outputFilenameOptions: zod.z.array(FilenameOptionSchema).optional(),
1750
+ extensions: zod.z.array(zod.z.string()).optional(),
1751
+ limit: zod.z.number().optional(),
1752
+ concurrency: zod.z.number().optional()
1753
+ });
1754
+ const create = (creationOptsParam = {})=>{
1755
+ let args;
1756
+ const options = {
1757
+ defaults: {
1758
+ ...DEFAULT_APP_OPTIONS,
1759
+ ...creationOptsParam.defaults
1760
+ },
1761
+ allowed: {
1762
+ ...DEFAULT_ALLOWED_OPTIONS,
1763
+ ...creationOptsParam.allowed
1764
+ },
1765
+ features: creationOptsParam.features || DEFAULT_FEATURES,
1766
+ addDefaults: creationOptsParam.addDefaults === undefined ? DEFAULT_OPTIONS.addDefaults : creationOptsParam.addDefaults,
1767
+ logger: wrapLogger(creationOptsParam.logger || DEFAULT_OPTIONS.logger)
1768
+ };
1769
+ return {
1770
+ configure: async (command)=>configure(command, options.defaults || {}, options.addDefaults, options.features),
1771
+ setLogger: (logger)=>{
1772
+ options.logger = wrapLogger(logger);
1773
+ },
1774
+ read: async (pArgs)=>{
1775
+ args = pArgs;
1776
+ return read(args, options.features);
1777
+ },
1778
+ applyDefaults: (config)=>applyDefaults(config, options.features, options.defaults || {}),
1779
+ validate: async (config)=>validate(config, options),
1780
+ operate: async (config)=>create$1(config, args, options)
1781
+ };
1782
+ };
1783
+
1784
+ exports.ConfigSchema = ConfigSchema;
1785
+ exports.DEFAULT_ALLOWED_OPTIONS = DEFAULT_ALLOWED_OPTIONS;
1786
+ exports.DEFAULT_APP_OPTIONS = DEFAULT_APP_OPTIONS;
1787
+ exports.DEFAULT_FEATURES = DEFAULT_FEATURES;
1788
+ exports.DEFAULT_LOGGER = DEFAULT_LOGGER;
1789
+ exports.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
1790
+ exports.FilenameOptionSchema = FilenameOptionSchema;
1791
+ exports.FilesystemStructureSchema = FilesystemStructureSchema;
1792
+ exports.create = create;
1793
+ //# sourceMappingURL=dreadcabinet.cjs.map