@bccampus/utils 0.1.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/README.md +8 -0
  2. package/dist/array/chunk.d.ts +1 -0
  3. package/dist/array/chunk.js +9 -0
  4. package/dist/array/index.d.ts +1 -0
  5. package/dist/array/index.js +4 -0
  6. package/dist/date/index.d.ts +1 -0
  7. package/dist/date/index.js +8 -0
  8. package/dist/date/iso-date-time.d.ts +127 -0
  9. package/dist/date/iso-date-time.js +256 -0
  10. package/dist/duration/add-durations.d.ts +1 -0
  11. package/dist/duration/add-durations.js +12 -0
  12. package/dist/duration/index.d.ts +3 -0
  13. package/dist/duration/index.js +8 -0
  14. package/dist/duration/is-duration.d.ts +1 -0
  15. package/dist/duration/is-duration.js +7 -0
  16. package/dist/duration/to-number.d.ts +1 -0
  17. package/dist/duration/to-number.js +14 -0
  18. package/dist/format/formatter.d.ts +5 -0
  19. package/dist/format/formatter.js +40 -0
  20. package/dist/format/index.d.ts +3 -0
  21. package/dist/format/index.js +13 -0
  22. package/dist/format/stringify.d.ts +38 -0
  23. package/dist/format/stringify.js +42 -0
  24. package/dist/format/template.d.ts +6 -0
  25. package/dist/format/template.js +35 -0
  26. package/dist/object/get.d.ts +1 -0
  27. package/dist/object/get.js +7 -0
  28. package/dist/object/index.d.ts +5 -0
  29. package/dist/object/index.js +12 -0
  30. package/dist/object/is-object.d.ts +1 -0
  31. package/dist/object/is-object.js +4 -0
  32. package/dist/object/omit.d.ts +1 -0
  33. package/dist/object/omit.js +18 -0
  34. package/dist/object/pick.d.ts +1 -0
  35. package/dist/object/pick.js +11 -0
  36. package/dist/object/set.d.ts +1 -0
  37. package/dist/object/set.js +14 -0
  38. package/dist/set/difference.d.ts +1 -0
  39. package/dist/set/difference.js +10 -0
  40. package/dist/set/index.d.ts +5 -0
  41. package/dist/set/index.js +12 -0
  42. package/dist/set/intersection.d.ts +1 -0
  43. package/dist/set/intersection.js +13 -0
  44. package/dist/set/is-superset.d.ts +1 -0
  45. package/dist/set/is-superset.js +12 -0
  46. package/dist/set/symmetric-difference.d.ts +1 -0
  47. package/dist/set/symmetric-difference.js +14 -0
  48. package/dist/set/union.d.ts +1 -0
  49. package/dist/set/union.js +10 -0
  50. package/dist/string/capitalize.d.ts +1 -0
  51. package/dist/string/capitalize.js +4 -0
  52. package/dist/string/index.d.ts +6 -0
  53. package/dist/string/index.js +14 -0
  54. package/dist/string/pluralize/index.d.ts +2 -0
  55. package/dist/string/pluralize/index.js +4 -0
  56. package/dist/string/pluralize/pluralize.d.ts +85 -0
  57. package/dist/string/pluralize/pluralize.js +210 -0
  58. package/dist/string/pluralize/rules/index.d.ts +4 -0
  59. package/dist/string/pluralize/rules/index.js +10 -0
  60. package/dist/string/pluralize/rules/irregular.d.ts +1 -0
  61. package/dist/string/pluralize/rules/irregular.js +62 -0
  62. package/dist/string/pluralize/rules/pluralization.d.ts +2 -0
  63. package/dist/string/pluralize/rules/pluralization.js +39 -0
  64. package/dist/string/pluralize/rules/singularization.d.ts +2 -0
  65. package/dist/string/pluralize/rules/singularization.js +47 -0
  66. package/dist/string/pluralize/rules/uncountable.d.ts +2 -0
  67. package/dist/string/pluralize/rules/uncountable.js +113 -0
  68. package/dist/string/pluralize/types.d.ts +3 -0
  69. package/dist/string/pluralize/types.js +1 -0
  70. package/dist/string/slugify/index.d.ts +1 -0
  71. package/dist/string/slugify/index.js +2263 -0
  72. package/dist/string/strip-html-tags.d.ts +1 -0
  73. package/dist/string/strip-html-tags.js +7 -0
  74. package/dist/string/to-int.d.ts +9 -0
  75. package/dist/string/to-int.js +10 -0
  76. package/dist/string/to-sentence-case.d.ts +1 -0
  77. package/dist/string/to-sentence-case.js +8 -0
  78. package/dist/string/trim.d.ts +1 -0
  79. package/dist/string/trim.js +11 -0
  80. package/dist/string/truncate.d.ts +1 -0
  81. package/dist/string/truncate.js +9 -0
  82. package/eslint.config.js +19 -0
  83. package/package.json +68 -0
  84. package/src/array/chunk.ts +6 -0
  85. package/src/array/index.ts +1 -0
  86. package/src/date/index.ts +1 -0
  87. package/src/date/iso-date-time.ts +356 -0
  88. package/src/duration/add-durations.ts +16 -0
  89. package/src/duration/index.ts +3 -0
  90. package/src/duration/is-duration.ts +5 -0
  91. package/src/duration/to-number.ts +18 -0
  92. package/src/format/formatter.ts +37 -0
  93. package/src/format/index.ts +3 -0
  94. package/src/format/stringify.ts +87 -0
  95. package/src/format/template.ts +48 -0
  96. package/src/object/get.ts +9 -0
  97. package/src/object/index.ts +5 -0
  98. package/src/object/is-object.ts +2 -0
  99. package/src/object/omit.ts +21 -0
  100. package/src/object/pick.ts +10 -0
  101. package/src/object/set.ts +15 -0
  102. package/src/set/difference.ts +9 -0
  103. package/src/set/index.ts +5 -0
  104. package/src/set/intersection.ts +12 -0
  105. package/src/set/is-superset.ts +12 -0
  106. package/src/set/symmetric-difference.ts +12 -0
  107. package/src/set/union.ts +8 -0
  108. package/src/string/capitalize.ts +2 -0
  109. package/src/string/index.ts +6 -0
  110. package/src/string/pluralize/index.ts +2 -0
  111. package/src/string/pluralize/pluralize.ts +296 -0
  112. package/src/string/pluralize/rules/index.ts +4 -0
  113. package/src/string/pluralize/rules/irregular.ts +59 -0
  114. package/src/string/pluralize/rules/pluralization.ts +40 -0
  115. package/src/string/pluralize/rules/singularization.ts +46 -0
  116. package/src/string/pluralize/rules/uncountable.ts +107 -0
  117. package/src/string/pluralize/types.ts +4 -0
  118. package/src/string/slugify/index.ts +3 -0
  119. package/src/string/strip-html-tags.ts +4 -0
  120. package/src/string/to-int.ts +20 -0
  121. package/src/string/to-sentence-case.ts +6 -0
  122. package/src/string/trim.ts +11 -0
  123. package/src/string/truncate.ts +11 -0
  124. package/tsconfig.json +18 -0
  125. package/tsconfig.lib.json +36 -0
  126. package/tsconfig.lib.tsbuildinfo +1 -0
  127. package/tsconfig.node.json +25 -0
  128. package/vite.config.ts +77 -0
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # @bccampus/utils
2
+
3
+ BCcampus' Utility Box
4
+
5
+ ## ToDo
6
+
7
+ - Write some tests
8
+ - Expected coverage: 80%
@@ -0,0 +1 @@
1
+ export declare function chunk<T>(arr: T[], size?: number): T[][];
@@ -0,0 +1,9 @@
1
+ function chunk(arr, size = 5) {
2
+ const chunks = [];
3
+ for (let i = 0; i < arr.length; i += size)
4
+ chunks.push(arr.slice(i, i + size));
5
+ return chunks;
6
+ }
7
+ export {
8
+ chunk
9
+ };
@@ -0,0 +1 @@
1
+ export * from './chunk';
@@ -0,0 +1,4 @@
1
+ import { chunk } from "./chunk.js";
2
+ export {
3
+ chunk
4
+ };
@@ -0,0 +1 @@
1
+ export * from './iso-date-time';
@@ -0,0 +1,8 @@
1
+ import { DefaultDateFormat, DefaultTimeFormat, DefaultTimezone, ISODateTime, InvalidDate } from "./iso-date-time.js";
2
+ export {
3
+ DefaultDateFormat,
4
+ DefaultTimeFormat,
5
+ DefaultTimezone,
6
+ ISODateTime,
7
+ InvalidDate
8
+ };
@@ -0,0 +1,127 @@
1
+ export declare const InvalidDate: unique symbol;
2
+ export type InvalidDate = typeof InvalidDate;
3
+ export declare const DefaultDateFormat: DateFormatOptions;
4
+ export declare const DefaultTimeFormat: DateFormatOptions;
5
+ export declare const DefaultTimezone = "America/Vancouver";
6
+ /**
7
+ * Enables storage, retrieval and formating of ISO dates and times
8
+ * with time zone information.
9
+ */
10
+ export declare class ISODateTime {
11
+ #private;
12
+ constructor();
13
+ constructor(isoDatetime: number);
14
+ constructor(isoDatetime: string);
15
+ /**
16
+ * Get date and time components
17
+ */
18
+ get parts(): ParsedDateTime | undefined;
19
+ /**
20
+ * Get timezone
21
+ */
22
+ get timezone(): ISOTimezone | "UTC";
23
+ /**
24
+ * Parse a string in ISO DateTime format.
25
+ * If the input is valid, returns date and time components;
26
+ * otherwise, returns `undefined`.
27
+ */
28
+ static parse(isoDatetime: string): ParsedDateTime | undefined;
29
+ static getISOString(parts?: ParsedDateTime): string;
30
+ /**
31
+ * Retruns ISO date and time string
32
+ */
33
+ static toString(parsedDateTime: string): string;
34
+ static toString(parsedDateTime: ISODateTime): string;
35
+ /**
36
+ * Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC.
37
+ */
38
+ valueOf(): number;
39
+ /**
40
+ * Retruns ISO date and time string
41
+ */
42
+ toString(): string;
43
+ /**
44
+ * Retruns Javascript date object
45
+ */
46
+ toDate(): typeof InvalidDate | Date;
47
+ get [Symbol.toStringTag](): string;
48
+ [Symbol.toPrimitive](hint: 'default'): number;
49
+ [Symbol.toPrimitive](hint: 'string'): string;
50
+ [Symbol.toPrimitive](hint: 'number'): number;
51
+ toJSON(): string;
52
+ private static getFormatter;
53
+ /**
54
+ * Returns formated date and time string
55
+ */
56
+ static format(isoDatetime: string, config?: DateFormatterConfig): string;
57
+ static format(isoDatetime: ISODateTime, config?: DateFormatterConfig): string;
58
+ /**
59
+ * Returns formated date and time range string
60
+ */
61
+ static formatRange(startDate: string, endDate: string, config?: DateFormatterConfig): string;
62
+ static formatRange(startDate: ISODateTime, endDate: ISODateTime, config?: DateFormatterConfig): string;
63
+ /**
64
+ * Returns formated date and time string
65
+ */
66
+ format(config?: DateFormatterConfig): string;
67
+ /**
68
+ * Adds milliseconds to the date and returns it as a new ISODateTime object
69
+ */
70
+ addMillisecond(milliseconds: number): ISODateTime;
71
+ /**
72
+ * Adds seconds to the date and returns it as a new ISODateTime object
73
+ */
74
+ addSecond(seconds: number): ISODateTime;
75
+ /**
76
+ * Adds minutes to the date and returns it as a new ISODateTime object
77
+ */
78
+ addMinute(minutes: number): ISODateTime;
79
+ /**
80
+ * Adds hours to the date and returns it as a new ISODateTime object
81
+ */
82
+ addHour(hours: number): ISODateTime;
83
+ /**
84
+ * Adds days to the date and returns it as a new ISODateTime object
85
+ */
86
+ addDay(days: number): ISODateTime;
87
+ /**
88
+ * Returns the start of the previous month as a new ISODateTime object
89
+ */
90
+ static getPrevMonthStart(date: ISODateTime): ISODateTime;
91
+ /**
92
+ * Returns the start of the previous month as a new ISODateTime object
93
+ */
94
+ getPrevMonthStart(): ISODateTime;
95
+ /**
96
+ * Returns the start of the next month as a new ISODateTime object
97
+ */
98
+ static getNextMonthStart(date: ISODateTime): ISODateTime;
99
+ /**
100
+ * Returns the start of the next month as a new ISODateTime object
101
+ */
102
+ getNextMonthStart(): ISODateTime;
103
+ }
104
+ interface ISODateParts {
105
+ year: string;
106
+ month?: string;
107
+ day?: string;
108
+ }
109
+ interface ISOTimeParts {
110
+ hours: string;
111
+ minutes?: string;
112
+ seconds?: string;
113
+ milliseconds?: string;
114
+ }
115
+ type ISOTimezone = 'Z' | `${'+' | '-'}${string}`;
116
+ export interface ParsedDateTime {
117
+ date: ISODateParts;
118
+ time?: ISOTimeParts;
119
+ timezone?: ISOTimezone;
120
+ }
121
+ export type DateFormatOptions = Partial<Intl.DateTimeFormatOptions>;
122
+ export interface DateFormatterConfig {
123
+ noDate?: boolean;
124
+ noTime?: boolean;
125
+ customFormat?: DateFormatOptions;
126
+ }
127
+ export {};
@@ -0,0 +1,256 @@
1
+ const isoDateTimeRegEx = new RegExp("^([0-9-]+)(T([0-9:.,]+)(Z|[+-]([0-9:]+))?)?$");
2
+ const dateRegEx = new RegExp("^(\\d{4})-?(\\d{2})?-?(\\d{2})?$");
3
+ const timeRegEx = new RegExp("^(\\d{2}):?(\\d{2})?:?(\\d{2})?(\\.(\\d{3}))?$");
4
+ const timezoneRegEx = new RegExp("^Z|^[+-]((\\d{2}):?(\\d{2})?)$");
5
+ const InvalidDate = /* @__PURE__ */ Symbol("Invalid Date");
6
+ const DefaultDateFormat = {
7
+ year: "numeric",
8
+ month: "long",
9
+ day: "2-digit"
10
+ };
11
+ const DefaultTimeFormat = {
12
+ hour: "2-digit",
13
+ minute: "2-digit",
14
+ timeZoneName: "short"
15
+ };
16
+ const DefaultTimezone = "America/Vancouver";
17
+ class ISODateTime {
18
+ #parsed;
19
+ #date;
20
+ #string;
21
+ constructor(isoDatetime) {
22
+ if (typeof isoDatetime === "string") {
23
+ this.#parsed = ISODateTime.parse(isoDatetime);
24
+ if (this.#parsed) {
25
+ this.#date = new Date(ISODateTime.toString(this));
26
+ } else {
27
+ this.#date = InvalidDate;
28
+ console.error(`Failed to parse date for value: ${isoDatetime}`);
29
+ }
30
+ } else if (typeof isoDatetime === "number" && Number.isFinite(isoDatetime)) {
31
+ this.#date = new Date(isoDatetime);
32
+ this.#parsed = ISODateTime.parse(this.#date.toISOString());
33
+ } else {
34
+ this.#date = /* @__PURE__ */ new Date();
35
+ this.#parsed = ISODateTime.parse(this.#date.toISOString());
36
+ }
37
+ if (this.#date !== InvalidDate) this.#string = this.#date.toISOString();
38
+ else this.#string = "Invalid Date";
39
+ }
40
+ /**
41
+ * Get date and time components
42
+ */
43
+ get parts() {
44
+ return this.#parsed;
45
+ }
46
+ /**
47
+ * Get timezone
48
+ */
49
+ get timezone() {
50
+ return this.parts?.timezone ?? "UTC";
51
+ }
52
+ /**
53
+ * Parse a string in ISO DateTime format.
54
+ * If the input is valid, returns date and time components;
55
+ * otherwise, returns `undefined`.
56
+ */
57
+ static parse(isoDatetime) {
58
+ const isoDatetimeParts = isoDatetime.match(isoDateTimeRegEx);
59
+ if (isoDatetimeParts) {
60
+ const dateParts = isoDatetimeParts[1] && isoDatetimeParts[1].match(dateRegEx);
61
+ if (!dateParts) return void 0;
62
+ const parsedDateTime = {
63
+ date: { year: dateParts[1], month: dateParts[2], day: dateParts[3] }
64
+ };
65
+ const timeParts = isoDatetimeParts[3] && isoDatetimeParts[3].match(timeRegEx);
66
+ if (timeParts) {
67
+ parsedDateTime.time = {
68
+ hours: timeParts[1],
69
+ minutes: timeParts[2],
70
+ seconds: timeParts[3],
71
+ milliseconds: timeParts[5]
72
+ };
73
+ }
74
+ const tzParts = isoDatetimeParts[4] && isoDatetimeParts[4].match(timezoneRegEx);
75
+ if (tzParts) {
76
+ parsedDateTime.timezone = tzParts[0];
77
+ }
78
+ return parsedDateTime;
79
+ }
80
+ return void 0;
81
+ }
82
+ static getISOString(parts) {
83
+ if (!parts) return "Invalid Date";
84
+ return `${parts.date.year}-${parts.date.month ?? "01"}-${parts.date.day ?? "01"}T${parts.time?.hours ?? "00"}:${parts.time?.minutes ?? "00"}:${parts.time?.seconds ?? "00"}.${parts.time?.milliseconds ?? "000"}${parts.timezone ?? "Z"}`;
85
+ }
86
+ static toString(dateTime) {
87
+ const _p = typeof dateTime === "string" ? ISODateTime.parse(dateTime) : dateTime.parts;
88
+ return ISODateTime.getISOString(_p);
89
+ }
90
+ /**
91
+ * Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC.
92
+ */
93
+ valueOf() {
94
+ if (this.#date === InvalidDate) return Number.NaN;
95
+ return this.#date.valueOf();
96
+ }
97
+ /**
98
+ * Retruns ISO date and time string
99
+ */
100
+ toString() {
101
+ return this.#string;
102
+ }
103
+ /**
104
+ * Retruns Javascript date object
105
+ */
106
+ toDate() {
107
+ return this.#date;
108
+ }
109
+ get [Symbol.toStringTag]() {
110
+ return "ISODateTime";
111
+ }
112
+ [Symbol.toPrimitive](hint) {
113
+ if (hint === "string") return this.toString();
114
+ return this.valueOf();
115
+ }
116
+ toJSON() {
117
+ return this.toString();
118
+ }
119
+ static getFormatter(isoDatetime, config) {
120
+ let _format = {};
121
+ if (config?.customFormat?.dateStyle || config?.customFormat?.timeStyle) {
122
+ _format = {
123
+ dateStyle: config?.customFormat?.dateStyle,
124
+ timeStyle: config?.customFormat?.timeStyle
125
+ };
126
+ } else {
127
+ if (config?.noDate === true && config?.noTime === true) {
128
+ _format = { ...config.customFormat };
129
+ } else if (config?.noDate === true && !config?.noTime) {
130
+ _format = { ...DefaultTimeFormat, ...config.customFormat };
131
+ } else if (config?.noTime === true && !config.noDate) {
132
+ _format = { ...DefaultDateFormat, ...config.customFormat };
133
+ } else {
134
+ _format = { ...DefaultDateFormat, ...DefaultTimeFormat, ...config?.customFormat };
135
+ }
136
+ }
137
+ if (config?.customFormat?.timeZone) _format.timeZone = config.customFormat.timeZone;
138
+ else if (isoDatetime.parts?.time === void 0) _format.timeZone = "UTC";
139
+ else _format.timeZone = DefaultTimezone;
140
+ return new Intl.DateTimeFormat("en", _format);
141
+ }
142
+ static format(isoDatetime, config) {
143
+ const _isoDatetime = typeof isoDatetime === "string" ? new ISODateTime(isoDatetime) : isoDatetime;
144
+ const _date = _isoDatetime.toDate();
145
+ if (_date === InvalidDate) return _isoDatetime.toString();
146
+ const formatter = ISODateTime.getFormatter(_isoDatetime, config);
147
+ return formatter.format(_date);
148
+ }
149
+ static formatRange(startDate, endDate, config) {
150
+ const _startISODateTime = typeof startDate === "string" ? new ISODateTime(startDate) : startDate;
151
+ const _startDate = _startISODateTime.toDate();
152
+ if (_startDate === InvalidDate) return _startISODateTime.toString();
153
+ const _endISODateTime = typeof endDate === "string" ? new ISODateTime(endDate) : endDate;
154
+ const _endDate = _endISODateTime.toDate();
155
+ if (_endDate === InvalidDate) return _endISODateTime.toString();
156
+ if (_startISODateTime.timezone !== _endISODateTime.timezone) throw "Start and end dates in different time zones";
157
+ const formatter = ISODateTime.getFormatter(_startISODateTime, config);
158
+ const formatedRange = formatter.formatRange(_startDate, _endDate).replace(/\s/g, " ");
159
+ return formatedRange.replace(/\s/g, " ");
160
+ }
161
+ /**
162
+ * Returns formated date and time string
163
+ */
164
+ format(config) {
165
+ return ISODateTime.format(this, config);
166
+ }
167
+ /**
168
+ * Adds milliseconds to the date and returns it as a new ISODateTime object
169
+ */
170
+ addMillisecond(milliseconds) {
171
+ return new ISODateTime(this.valueOf() + milliseconds);
172
+ }
173
+ /**
174
+ * Adds seconds to the date and returns it as a new ISODateTime object
175
+ */
176
+ addSecond(seconds) {
177
+ return this.addMillisecond(seconds * 1e3);
178
+ }
179
+ /**
180
+ * Adds minutes to the date and returns it as a new ISODateTime object
181
+ */
182
+ addMinute(minutes) {
183
+ return this.addMillisecond(minutes * 6e4);
184
+ }
185
+ /**
186
+ * Adds hours to the date and returns it as a new ISODateTime object
187
+ */
188
+ addHour(hours) {
189
+ return this.addMillisecond(hours * 36e5);
190
+ }
191
+ /**
192
+ * Adds days to the date and returns it as a new ISODateTime object
193
+ */
194
+ addDay(days) {
195
+ return this.addMillisecond(days * 864e5);
196
+ }
197
+ /**
198
+ * Returns the start of the previous month as a new ISODateTime object
199
+ */
200
+ static getPrevMonthStart(date) {
201
+ if (date.parts) {
202
+ const month = date.parts.date.month ? Number(date.parts.date.month) : 1;
203
+ const prevMonth = month === 1 ? 12 : month - 1;
204
+ const year = month === 1 ? (Number(date.parts.date.year) - 1).toString() : date.parts.date.year;
205
+ const prevParts = {
206
+ date: {
207
+ year,
208
+ month: prevMonth.toString().padStart(2, "0"),
209
+ day: "01"
210
+ },
211
+ timezone: date.parts.timezone
212
+ };
213
+ return new ISODateTime(ISODateTime.getISOString(prevParts));
214
+ }
215
+ return date;
216
+ }
217
+ /**
218
+ * Returns the start of the previous month as a new ISODateTime object
219
+ */
220
+ getPrevMonthStart() {
221
+ return ISODateTime.getPrevMonthStart(this);
222
+ }
223
+ /**
224
+ * Returns the start of the next month as a new ISODateTime object
225
+ */
226
+ static getNextMonthStart(date) {
227
+ if (date.parts) {
228
+ const month = date.parts.date.month ? Number(date.parts.date.month) : 1;
229
+ const nextMonth = month % 12 + 1;
230
+ const year = month === 12 ? (Number(date.parts.date.year) + 1).toString() : date.parts.date.year;
231
+ const nextParts = {
232
+ date: {
233
+ year,
234
+ month: nextMonth.toString().padStart(2, "0"),
235
+ day: "01"
236
+ },
237
+ timezone: date.parts.timezone
238
+ };
239
+ return new ISODateTime(ISODateTime.getISOString(nextParts));
240
+ }
241
+ return date;
242
+ }
243
+ /**
244
+ * Returns the start of the next month as a new ISODateTime object
245
+ */
246
+ getNextMonthStart() {
247
+ return ISODateTime.getNextMonthStart(this);
248
+ }
249
+ }
250
+ export {
251
+ DefaultDateFormat,
252
+ DefaultTimeFormat,
253
+ DefaultTimezone,
254
+ ISODateTime,
255
+ InvalidDate
256
+ };
@@ -0,0 +1 @@
1
+ export declare function addDuration(left: string, right: string): string;
@@ -0,0 +1,12 @@
1
+ import "./is-duration.js";
2
+ import { toNumber } from "./to-number.js";
3
+ function addDuration(left, right) {
4
+ const totalDurationInSeconds = toNumber(left, "second") + toNumber(right, "second");
5
+ const hours = Math.floor(totalDurationInSeconds / 3600).toString().padStart(2, "0");
6
+ const minutes = Math.floor(totalDurationInSeconds % 3600 / 60).toString().padStart(2, "0");
7
+ const seconds = (totalDurationInSeconds % 60).toString().padStart(2, "0");
8
+ return `${hours}:${minutes}:${seconds}`;
9
+ }
10
+ export {
11
+ addDuration
12
+ };
@@ -0,0 +1,3 @@
1
+ export * from './is-duration';
2
+ export * from './to-number';
3
+ export * from './add-durations';
@@ -0,0 +1,8 @@
1
+ import { isDuration } from "./is-duration.js";
2
+ import { toNumber } from "./to-number.js";
3
+ import { addDuration } from "./add-durations.js";
4
+ export {
5
+ addDuration,
6
+ isDuration,
7
+ toNumber
8
+ };
@@ -0,0 +1 @@
1
+ export declare function isDuration(duration: string): boolean;
@@ -0,0 +1,7 @@
1
+ const durationRegExp = /^\d{2}:\d{2}:\d{2}$/;
2
+ function isDuration(duration) {
3
+ return durationRegExp.test(duration);
4
+ }
5
+ export {
6
+ isDuration
7
+ };
@@ -0,0 +1 @@
1
+ export declare function toNumber(duration: string, unit?: "hour" | "minute" | "second"): number;
@@ -0,0 +1,14 @@
1
+ import { isDuration } from "./is-duration.js";
2
+ function toNumber(duration, unit = "hour") {
3
+ if (!isDuration(duration)) {
4
+ console.error(new Error(`Malformed duration value: ${duration}`));
5
+ return 0;
6
+ }
7
+ const parts = duration.split(":").map((p) => Number(p));
8
+ if (unit === "minute") return parts[0] * 60 + parts[1] + parts[2] / 60;
9
+ if (unit === "second") return parts[0] * 3600 + parts[1] * 60 + parts[2];
10
+ return parts[0] + parts[1] / 60 + parts[2] / 3600;
11
+ }
12
+ export {
13
+ toNumber
14
+ };
@@ -0,0 +1,5 @@
1
+ export declare const dateFormatter: Intl.DateTimeFormat;
2
+ export declare const formatDate: (date?: Date | null) => string;
3
+ export declare const formatList: (list?: string[] | null) => string;
4
+ export declare const formatNumber: (num?: number | null) => string;
5
+ export declare const formatCurrency: (num?: number | null) => string;
@@ -0,0 +1,40 @@
1
+ const dateFormatter = new Intl.DateTimeFormat("en", {
2
+ dateStyle: "full",
3
+ timeStyle: "short",
4
+ timeZone: "America/Vancouver"
5
+ });
6
+ const formatDate = (date) => {
7
+ if (date) return dateFormatter.format(date);
8
+ return "";
9
+ };
10
+ const listFormatter = new Intl.ListFormat("en", {
11
+ style: "long",
12
+ type: "conjunction"
13
+ });
14
+ const formatList = (list) => {
15
+ if (Array.isArray(list)) return listFormatter.format(list);
16
+ return "";
17
+ };
18
+ const numberFormatter = new Intl.NumberFormat("en", {
19
+ maximumFractionDigits: 2
20
+ });
21
+ const formatNumber = (num) => {
22
+ if (num) return numberFormatter.format(num);
23
+ return "";
24
+ };
25
+ const currencyFormatter = new Intl.NumberFormat("en", {
26
+ style: "currency",
27
+ currency: "CAD",
28
+ maximumFractionDigits: 2
29
+ });
30
+ const formatCurrency = (num) => {
31
+ if (num) return currencyFormatter.format(num);
32
+ return "";
33
+ };
34
+ export {
35
+ dateFormatter,
36
+ formatCurrency,
37
+ formatDate,
38
+ formatList,
39
+ formatNumber
40
+ };
@@ -0,0 +1,3 @@
1
+ export * from './formatter';
2
+ export * from './stringify';
3
+ export * from './template';
@@ -0,0 +1,13 @@
1
+ import { dateFormatter, formatCurrency, formatDate, formatList, formatNumber } from "./formatter.js";
2
+ import { stringify } from "./stringify.js";
3
+ import { template, templateObject } from "./template.js";
4
+ export {
5
+ dateFormatter,
6
+ formatCurrency,
7
+ formatDate,
8
+ formatList,
9
+ formatNumber,
10
+ stringify,
11
+ template,
12
+ templateObject
13
+ };
@@ -0,0 +1,38 @@
1
+ export interface StringifyValueOptions {
2
+ /**
3
+ * String value to return when the value undefined or null.
4
+ *
5
+ * Default Unicode NUL(\u0000) character,
6
+ * guarantees that the function always returns a string and
7
+ * allows to distinguish invalid values from an empty string.
8
+ *
9
+ * ```ts
10
+ * const stringValue = stringify(value);
11
+ * console.log(stringValue !== '\u0000' ? 'Invalid' : stringValue)
12
+ * ```
13
+ */
14
+ invalidValueString?: string;
15
+ /**
16
+ * `stringify` prepends type info to the return value.
17
+ */
18
+ withTypeInfo?: boolean;
19
+ /**
20
+ * If the value is a function that doesn't expect an argument,
21
+ * `stringify` calls the function recursively.
22
+ */
23
+ callFunctions?: boolean;
24
+ /**
25
+ * `stringify` adds indentation and new lines to object return values.
26
+ */
27
+ prettyObjects?: boolean;
28
+ /**
29
+ * `stringify` returns verbose value.
30
+ */
31
+ verbose?: boolean;
32
+ }
33
+ /**
34
+ * Returns string representation of the value;
35
+ *
36
+ * If the valid is null or undefined, returns `options.invalidValueString`.
37
+ */
38
+ export declare const stringify: (value: unknown, options?: StringifyValueOptions) => string;
@@ -0,0 +1,42 @@
1
+ import { formatNumber, formatList, dateFormatter } from "./formatter.js";
2
+ import { ISODateTime } from "../date/iso-date-time.js";
3
+ const stringify = (value, options) => {
4
+ const _options = {
5
+ invalidValueString: "\0",
6
+ // Unicode NUL
7
+ withTypeInfo: options?.verbose,
8
+ prettyObjects: options?.verbose,
9
+ ...options
10
+ };
11
+ if (value === void 0)
12
+ return _options.withTypeInfo ? "[undefined]" : _options.invalidValueString;
13
+ if (value === null)
14
+ return _options.withTypeInfo ? "[null]" : _options.invalidValueString;
15
+ if (typeof value === "string")
16
+ return `${_options.withTypeInfo ? "[string] " : ""}${value}`;
17
+ if (typeof value === "number")
18
+ return `${_options.withTypeInfo ? "[number] " : ""}${formatNumber(value)}`;
19
+ if (typeof value === "bigint")
20
+ return `${_options.withTypeInfo ? "[bigint] " : ""}${value}`;
21
+ if (typeof value === "boolean")
22
+ return `${_options.withTypeInfo ? "[boolean] " : ""}${value}`;
23
+ if (typeof value === "object") {
24
+ if (Array.isArray(value)) {
25
+ const stringfiedValue = value.map((el) => stringify(el, _options));
26
+ return `${_options.withTypeInfo ? "[array] " : ""}${_options.verbose ? stringfiedValue.join(", ") : formatList(stringfiedValue)}`;
27
+ }
28
+ if (value instanceof Date)
29
+ return `${_options.withTypeInfo ? "[date] " : ""}${dateFormatter.format(value)}`;
30
+ if (value instanceof ISODateTime)
31
+ return `${_options.withTypeInfo ? "[date] " : ""}${value.format()}`;
32
+ return `${_options.withTypeInfo ? "[object] " : ""}${JSON.stringify(value, null, _options.prettyObjects ? 2 : void 0)}`;
33
+ }
34
+ if (typeof value === "function")
35
+ return `${_options.withTypeInfo ? "[function] " : ""}${_options.callFunctions && value.length === 0 ? stringify(value(), _options) : value.toString()}`;
36
+ if (typeof value === "symbol")
37
+ return `${_options.withTypeInfo ? "[symbol] " : ""}${value.toString()}`;
38
+ return _options.invalidValueString;
39
+ };
40
+ export {
41
+ stringify
42
+ };
@@ -0,0 +1,6 @@
1
+ type TemplateVarValue = unknown | undefined | null;
2
+ export type TemplateVar = TemplateVarValue | (() => TemplateVarValue);
3
+ export type TemplateVars = Record<string, TemplateVar>;
4
+ export declare const template: (text: string, templateVars: TemplateVars) => string;
5
+ export declare const templateObject: <T extends object>(obj: T, templateVars: TemplateVars) => T;
6
+ export {};