@softure-ai/core 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +31 -1
- package/dist/calendar-day.d.ts +3 -0
- package/dist/calendar-day.d.ts.map +1 -1
- package/dist/calendar-day.js +5 -0
- package/dist/calendar-day.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/format.d.ts +26 -3
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +82 -10
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/memoize.d.ts +16 -0
- package/dist/memoize.d.ts.map +1 -0
- package/dist/memoize.js +81 -0
- package/dist/memoize.js.map +1 -0
- package/dist/messages/en.d.ts +15 -0
- package/dist/messages/en.d.ts.map +1 -1
- package/dist/messages/en.js +5 -0
- package/dist/messages/en.js.map +1 -1
- package/dist/messages/index.d.ts +1 -1
- package/dist/messages/index.d.ts.map +1 -1
- package/dist/messages/index.js +1 -1
- package/dist/messages/index.js.map +1 -1
- package/dist/messages/pl.d.ts.map +1 -1
- package/dist/messages/pl.js +5 -0
- package/dist/messages/pl.js.map +1 -1
- package/dist/og/index.d.ts +2 -0
- package/dist/og/index.d.ts.map +1 -0
- package/dist/og/index.js +4 -0
- package/dist/og/index.js.map +1 -0
- package/dist/og/og-fonts.d.ts +37 -0
- package/dist/og/og-fonts.d.ts.map +1 -0
- package/dist/og/og-fonts.js +95 -0
- package/dist/og/og-fonts.js.map +1 -0
- package/package.json +6 -1
- package/src/calendar-day.ts +4 -0
- package/src/config.ts +9 -0
- package/src/format.ts +89 -11
- package/src/index.ts +14 -1
- package/src/memoize.ts +89 -0
- package/src/messages/en.ts +5 -0
- package/src/messages/index.ts +1 -1
- package/src/messages/pl.ts +5 -0
- package/src/og/index.ts +12 -0
- package/src/og/og-fonts.ts +127 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ Newest first. Each version lists what changed for an app that uses `@softure-ai/
|
|
|
4
4
|
production, the version gets a line `verified in: <app>@<commit>` ([docs/05](../../docs/05-adoption-playbook.md),
|
|
5
5
|
"Definition of done"). Versions before the first one below are described in their GitHub Releases (`core@x.y.z`).
|
|
6
6
|
|
|
7
|
+
## 0.1.11
|
|
8
|
+
|
|
9
|
+
- Formatting (#410): `formatCalendarMonth(month, locale, "long" | "genitive" | "roman")` for `YYYY-MM` months
|
|
10
|
+
(`isCalendarMonth`) or days, `formatDuration(months, locale)` ("3 years and 2 months", plural forms from
|
|
11
|
+
`coreMessages`), and `formatPercent(basisPoints, locale, { signed, tight })`. `formatPercent` never puts a minus on
|
|
12
|
+
a value that rounds to zero, as `formatMoney` does.
|
|
13
|
+
- `memoizeByContent(fn, { max })`: an LRU cache keyed by the arguments' content, no TTL (#410).
|
|
14
|
+
- The config takes `landingOrigin` (optional; `SoftureConfig.landingOrigin` defaults to `appOrigin`), the public
|
|
15
|
+
landing site beside an app on a subdomain (#410).
|
|
16
|
+
- `calendarDaySchema`: a zod schema for a `YYYY-MM-DD` calendar day (#410).
|
|
17
|
+
- New server-only entry `@softure-ai/core/og`: the OG card font loader the modules share (#414).
|
|
18
|
+
`createOgFontLoader({ root, label?, readFile?, fetchImpl? })` and `loadOgFonts(fonts)` (from the working
|
|
19
|
+
directory) read a `.ttf`, `.otf` or `.woff` path or https URL once and answer `{ ok, fonts }` or `{ ok: false, error }`;
|
|
20
|
+
with `OgFontSource`, `OgFont`, `OgFontWeight`, `OG_FONT_WEIGHTS`. Moved from the blog.
|
|
21
|
+
|
|
7
22
|
## 0.1.10
|
|
8
23
|
|
|
9
24
|
- `formatMoney` never puts a minus on zero: a negative zero, or an amount that rounds to zero under `rounded` or
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ The contract every SOFTURE module stands on. Standard:
|
|
|
8
8
|
The app configuration (`defineSoftureConfig`), the module contract (`defineModule`), `Result`
|
|
9
9
|
with namespaced error codes, an injectable `Clock`, `pl`/`en` messages with partial overrides,
|
|
10
10
|
and `safeError` with `PublicError`. `@softure-ai/core/cli` loads the app's config for the modules' command-line tools.
|
|
11
|
+
`@softure-ai/core/og` (server only) is the OG card font loader the modules share (`createOgFontLoader`,
|
|
12
|
+
`loadOgFonts`); an app takes it from `@softure-ai/seo/server`, where it is documented.
|
|
11
13
|
|
|
12
14
|
## 2. Installation
|
|
13
15
|
|
|
@@ -28,6 +30,7 @@ interface SoftureConfigInput {
|
|
|
28
30
|
locale: "en" | "pl";
|
|
29
31
|
timezone: string; // IANA zone, e.g. "Europe/Warsaw"
|
|
30
32
|
appOrigin: string; // http(s) origin without a path
|
|
33
|
+
landingOrigin?: string; // the public landing site beside the app (default: appOrigin)
|
|
31
34
|
origins?: { // read by resolveAppOrigin, see "Request origins" below
|
|
32
35
|
trustedOrigins?: string[]; // other origins the app is served under (at most 16)
|
|
33
36
|
trustRequestHost?: boolean; // trust Host for any host (default false)
|
|
@@ -54,6 +57,10 @@ registerSoftureConfig(config);
|
|
|
54
57
|
export default config;
|
|
55
58
|
```
|
|
56
59
|
|
|
60
|
+
`landingOrigin` names the public landing site when the app lives on a subdomain beside it (`https://example.com`
|
|
61
|
+
next to `https://app.example.com`); `SoftureConfig.landingOrigin` is always filled, with `appOrigin` when the app names
|
|
62
|
+
none. Use it for links from the app to its marketing pages, never for the app's own absolute URLs.
|
|
63
|
+
|
|
57
64
|
`defineSoftureConfig` throws `SoftureConfigError` with every problem listed (`issues`): an
|
|
58
65
|
unknown locale or zone, an origin with a path, a module listed twice, two modules on one database
|
|
59
66
|
schema, a required dependency missing, a dependency outside its version range (also an optional
|
|
@@ -308,6 +315,8 @@ or a fractional count.
|
|
|
308
315
|
| `calendarDaysBetween(from, to)` | `to - from` in days; negative when `to` comes first. |
|
|
309
316
|
| `wholeMonthsBetween(from, to)` | The most months `n` with `addCalendarMonths(from, n)` (clamped) not after `to`: Jan 31 to Feb 28 is 1. Swapping the days turns the sign. |
|
|
310
317
|
|
|
318
|
+
`calendarDaySchema` is `isCalendarDay` as a zod schema, for tool and form inputs that take a day.
|
|
319
|
+
|
|
311
320
|
**Display.** One way to show days, money and percentages in every module and app, in `config.locale`:
|
|
312
321
|
|
|
313
322
|
```ts
|
|
@@ -316,12 +325,33 @@ formatCalendarDay(toCalendarDay(instant, config.timezone), config.locale); // an
|
|
|
316
325
|
formatMoney(123456, "PLN", "en"); // "PLN 1,234.56"; pl groups four digits too
|
|
317
326
|
formatMoney(-123456, "PLN", "en", { rounded: true, signed: true }); // "-PLN 1,235"; { compact: true }: "PLN 1.2K"
|
|
318
327
|
formatPercent(1250, "en"); // "12.5%" (basis points, at most two fraction digits)
|
|
328
|
+
formatPercent(-50, "en", { signed: true, tight: true }); // "-0.5%"; 1250 signed: "+12.5%"
|
|
329
|
+
formatCalendarMonth("2026-10", "en"); // "October 2026"; "genitive": pl's genitive month; "roman": "X 2026"
|
|
330
|
+
formatDuration(38, "en"); // "3 years and 2 months" (whole months, as wholeMonthsBetween returns them)
|
|
319
331
|
```
|
|
320
332
|
|
|
321
333
|
A day is formatted at UTC midnight in UTC, so no zone moves it; the Polish long style names the month in
|
|
322
334
|
the genitive. `formatMoney` takes the amount in the currency's minor unit, read from the pinned ISO 4217
|
|
323
335
|
table `CURRENCY_MINOR_UNIT_DIGITS` (a code outside it gets `Intl`'s digits), and always groups thousands.
|
|
324
|
-
Zero never carries a sign: a negative zero (`Math.round(-0.4)`) or an amount that rounds to zero shows as `PLN 0.00
|
|
336
|
+
Zero never carries a sign: a negative zero (`Math.round(-0.4)`) or an amount that rounds to zero shows as `PLN 0.00`,
|
|
337
|
+
and a percentage that rounds to zero as `0%`. `signed` puts a `+` before a positive amount or percentage; the minus is
|
|
338
|
+
the one `Intl` writes (a hyphen-minus in en and pl). `tight` drops any space a locale's pattern puts before `%`.
|
|
339
|
+
|
|
340
|
+
`formatCalendarMonth(month, locale, style)` takes `YYYY-MM` (`isCalendarMonth`) or a `YYYY-MM-DD` day. `long` is the
|
|
341
|
+
month as written alone (the nominative in pl), `genitive` the form a full date uses (pl: "4 [month] 2026" inflects
|
|
342
|
+
it), `roman` the month in Roman numerals for compact tables. `formatDuration(months, locale)` writes years and months
|
|
343
|
+
with the locale's plural forms (copy in `coreMessages.<locale>.duration`); a part that is zero is left out, and zero
|
|
344
|
+
itself is "0 months".
|
|
345
|
+
|
|
346
|
+
**Memoization.** `memoizeByContent(fn, { max })` caches a pure function of plain data by the content of its arguments:
|
|
347
|
+
two equal objects built apart (key order aside) hit the same entry. The least recently used entry goes beyond `max`;
|
|
348
|
+
nothing expires by time, and `clear()` empties the cache. Arguments may hold primitives, arrays, `Date`s and plain
|
|
349
|
+
objects; anything else (a function, a `Map`, a class instance, a cycle) throws a `TypeError`. A promise that rejects
|
|
350
|
+
is dropped, so the next call tries again.
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
const getProjection = memoizeByContent((input: ProjectionInput) => simulate(input), { max: 100 });
|
|
354
|
+
```
|
|
325
355
|
|
|
326
356
|
## 10. Hooks
|
|
327
357
|
|
package/dist/calendar-day.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import type { Clock } from "./clock.js";
|
|
2
3
|
/** The calendar day (`YYYY-MM-DD`) of `instant` in `timeZone`. Throws a `RangeError` for an invalid date or zone. */
|
|
3
4
|
export declare function toCalendarDay(instant: Date, timeZone: string): string;
|
|
@@ -7,6 +8,8 @@ export declare function getCalendarDay(clock: Clock, timeZone: string): string;
|
|
|
7
8
|
export type EndOfMonth = "clamp" | "overflow";
|
|
8
9
|
/** Whether `value` is a real calendar day written `YYYY-MM-DD` (`2026-02-29` and `2026-1-1` are not). */
|
|
9
10
|
export declare function isCalendarDay(value: unknown): value is string;
|
|
11
|
+
/** A `YYYY-MM-DD` calendar day in tool and form input: `isCalendarDay` as a zod schema. */
|
|
12
|
+
export declare const calendarDaySchema: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
|
|
10
13
|
/** `day` moved by `days` calendar days (negative goes back). Throws a `RangeError` for a malformed day or count. */
|
|
11
14
|
export declare function addCalendarDays(day: string, days: number): string;
|
|
12
15
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calendar-day.d.ts","sourceRoot":"","sources":["../src/calendar-day.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAIxC,qHAAqH;AACrH,wBAAgB,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQrE;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErE;AAiCD,8FAA8F;AAC9F,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAE9C,yGAAyG;AACzG,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE7D;AAED,oHAAoH;AACpH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIjE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;CAAO,GAAG,MAAM,CAQzH;AAED,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAOnE"}
|
|
1
|
+
{"version":3,"file":"calendar-day.d.ts","sourceRoot":"","sources":["../src/calendar-day.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAIxC,qHAAqH;AACrH,wBAAgB,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQrE;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErE;AAiCD,8FAA8F;AAC9F,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAE9C,yGAAyG;AACzG,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE7D;AAED,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,mFAAyF,CAAC;AAExH,oHAAoH;AACpH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIjE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;CAAO,GAAG,MAAM,CAQzH;AAED,qGAAqG;AACrG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAOnE"}
|
package/dist/calendar-day.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// The calendar day of an instant in a given IANA time zone, as `YYYY-MM-DD`. "Today" computed in the
|
|
2
|
+
// process zone is a classic date bug: on a server in UTC, an evening in New York is already tomorrow.
|
|
3
|
+
import { z } from "zod";
|
|
1
4
|
const formatters = new Map();
|
|
2
5
|
/** The calendar day (`YYYY-MM-DD`) of `instant` in `timeZone`. Throws a `RangeError` for an invalid date or zone. */
|
|
3
6
|
export function toCalendarDay(instant, timeZone) {
|
|
@@ -38,6 +41,8 @@ const DAY_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
|
38
41
|
export function isCalendarDay(value) {
|
|
39
42
|
return typeof value === "string" && parseCivilDate(value) !== null;
|
|
40
43
|
}
|
|
44
|
+
/** A `YYYY-MM-DD` calendar day in tool and form input: `isCalendarDay` as a zod schema. */
|
|
45
|
+
export const calendarDaySchema = z.string().refine(isCalendarDay, "must be a YYYY-MM-DD calendar day, e.g. 2026-10-04");
|
|
41
46
|
/** `day` moved by `days` calendar days (negative goes back). Throws a `RangeError` for a malformed day or count. */
|
|
42
47
|
export function addCalendarDays(day, days) {
|
|
43
48
|
const operation = "addCalendarDays";
|
package/dist/calendar-day.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calendar-day.js","sourceRoot":"","sources":["../src/calendar-day.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"calendar-day.js","sourceRoot":"","sources":["../src/calendar-day.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -52,6 +52,11 @@ export interface SoftureConfig {
|
|
|
52
52
|
readonly timezone: string;
|
|
53
53
|
/** Scheme, host and port of the app, without a path: `https://app.example.com`. */
|
|
54
54
|
readonly appOrigin: string;
|
|
55
|
+
/**
|
|
56
|
+
* The public landing site (`https://example.com`) when the app lives on a subdomain beside it; `appOrigin` when
|
|
57
|
+
* the app does not name one. For links from the app to its marketing pages, not for the app's own URLs.
|
|
58
|
+
*/
|
|
59
|
+
readonly landingOrigin: string;
|
|
55
60
|
/** Every origin the app is served under besides `appOrigin`, read by `resolveAppOrigin`. */
|
|
56
61
|
readonly origins: SoftureOrigins;
|
|
57
62
|
/** Enabled modules, in the order the app listed them. */
|
|
@@ -63,6 +68,8 @@ export interface SoftureConfigInput {
|
|
|
63
68
|
readonly locale: Locale;
|
|
64
69
|
readonly timezone: string;
|
|
65
70
|
readonly appOrigin: string;
|
|
71
|
+
/** The public landing site beside the app; defaults to `appOrigin`. */
|
|
72
|
+
readonly landingOrigin?: string;
|
|
66
73
|
readonly origins?: SoftureOriginsInput;
|
|
67
74
|
readonly modules: readonly AnySoftureModule[];
|
|
68
75
|
}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAGnD;;;GAGG;AAEH,MAAM,WAAW,0BAA0B;CAAG;AAE9C,iHAAiH;AACjH,MAAM,MAAM,qBAAqB,GAAG,0BAA0B,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5H,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC,qBAAqB,CAAC,CAAC;CAC7D;AAED,qHAAqH;AACrH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAGnD;;;GAGG;AAEH,MAAM,WAAW,0BAA0B;CAAG;AAE9C,iHAAiH;AACjH,MAAM,MAAM,qBAAqB,GAAG,0BAA0B,SAAS;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5H,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC,qBAAqB,CAAC,CAAC;CAC7D;AAED,qHAAqH;AACrH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AAED,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC/C;AA+BD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,aAAa,CAoB5E;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEzF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,gBAAgB,EAAE,GACnC,MAAM,CAAC,gBAAgB,EAAE,EAAE,uBAAuB,CAAC,CAGrD"}
|
package/dist/config.js
CHANGED
|
@@ -23,6 +23,7 @@ const configSchema = z.object({
|
|
|
23
23
|
locale: z.enum(LOCALES),
|
|
24
24
|
timezone: z.string().refine(isTimeZone, "must be an IANA time zone, e.g. Europe/Warsaw"),
|
|
25
25
|
appOrigin: z.string().refine(isOrigin, ORIGIN_MESSAGE),
|
|
26
|
+
landingOrigin: z.string().refine(isOrigin, ORIGIN_MESSAGE).optional(),
|
|
26
27
|
origins: z
|
|
27
28
|
.strictObject({
|
|
28
29
|
trustedOrigins: z.array(z.string().refine(isOrigin, ORIGIN_MESSAGE)).max(16, "takes at most 16 origins").default([]),
|
|
@@ -48,6 +49,7 @@ export function defineSoftureConfig(input) {
|
|
|
48
49
|
}
|
|
49
50
|
return Object.freeze({
|
|
50
51
|
...config,
|
|
52
|
+
landingOrigin: config.landingOrigin ?? config.appOrigin,
|
|
51
53
|
database: config.database === null ? null : Object.freeze({ ...config.database }),
|
|
52
54
|
origins: Object.freeze({ ...config.origins, trustedOrigins: Object.freeze([...config.origins.trustedOrigins]) }),
|
|
53
55
|
modules: Object.freeze([...config.modules]),
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,gEAAgE;AAChE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAe,MAAM,WAAW,CAAC;AAEjD,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/format.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Locale } from "./i18n.js";
|
|
2
2
|
/** `long`: October 4, 2026 (pl names the month in the genitive); `medium`: Oct 4, 2026; `numeric`: 10/04/2026 (pl: 04.10.2026). */
|
|
3
3
|
export type CalendarDayStyle = "long" | "medium" | "numeric";
|
|
4
4
|
export interface FormatMoneyOptions {
|
|
@@ -9,8 +9,28 @@ export interface FormatMoneyOptions {
|
|
|
9
9
|
/** The locale's short notation for large amounts: PLN 1.2M. */
|
|
10
10
|
readonly compact?: boolean;
|
|
11
11
|
}
|
|
12
|
+
/** `long`: October 2026 (pl: the month in the nominative); `genitive`: pl's genitive month, as inside a date; `roman`: X 2026. */
|
|
13
|
+
export type CalendarMonthStyle = "long" | "genitive" | "roman";
|
|
14
|
+
export interface FormatPercentOptions {
|
|
15
|
+
/** A `+` before a positive value (a `-` before a negative one is always there). Zero has neither in any mode. */
|
|
16
|
+
readonly signed?: boolean;
|
|
17
|
+
/** No space between the number and `%`, whatever the locale's pattern: `12,5%`, not `12,5 %`. */
|
|
18
|
+
readonly tight?: boolean;
|
|
19
|
+
}
|
|
12
20
|
/** A `YYYY-MM-DD` day as `locale` writes it. Throws a `RangeError` for a malformed day. */
|
|
13
21
|
export declare function formatCalendarDay(day: string, locale: Locale, style?: CalendarDayStyle): string;
|
|
22
|
+
/** Whether `value` is a real calendar month written `YYYY-MM` (`2026-13` and `2026-1` are not). */
|
|
23
|
+
export declare function isCalendarMonth(value: unknown): value is string;
|
|
24
|
+
/**
|
|
25
|
+
* The month of a `YYYY-MM` month or a `YYYY-MM-DD` day, with its year, as `locale` writes it alone. Throws a
|
|
26
|
+
* `RangeError` for anything else.
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatCalendarMonth(month: string, locale: Locale, style?: CalendarMonthStyle): string;
|
|
29
|
+
/**
|
|
30
|
+
* Whole months as years and months in `locale`, with its plural forms: 38 is "3 years and 2 months"; a part that is
|
|
31
|
+
* zero is left out, and zero itself is "0 months". Throws a `RangeError` for a negative or fractional count.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatDuration(months: number, locale: Locale): string;
|
|
14
34
|
/**
|
|
15
35
|
* An amount in the currency's minor unit (2900 PLN = PLN 29.00) in `locale`'s notation, thousands always
|
|
16
36
|
* grouped (pl writes 1 234,56 where its default would leave four digits together), and zero is never signed (`-0`
|
|
@@ -19,6 +39,9 @@ export declare function formatCalendarDay(day: string, locale: Locale, style?: C
|
|
|
19
39
|
* `RangeError` for an amount that is not a whole number of minor units, or a code `Intl` refuses.
|
|
20
40
|
*/
|
|
21
41
|
export declare function formatMoney(minor: number, currency: string, locale: Locale, options?: FormatMoneyOptions): string;
|
|
22
|
-
/**
|
|
23
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Basis points as a percentage in `locale`: 1250 is 12.5%, at most two fraction digits, and zero is never signed (`-0`
|
|
44
|
+
* and a value that rounds to zero show as `0%`). Throws a `RangeError` for a non-finite value.
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatPercent(basisPoints: number, locale: Locale, options?: FormatPercentOptions): string;
|
|
24
47
|
//# sourceMappingURL=format.d.ts.map
|
package/dist/format.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAIA,OAAO,EAA+B,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAGrE,mIAAmI;AACnI,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,yKAAyK;IACzK,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,kIAAkI;AAClI,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,iHAAiH;IACjH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,iGAAiG;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAiBD,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,gBAAyB,GAAG,MAAM,CAGvG;AAED,mGAAmG;AACnG,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAM/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,kBAA2B,GAAG,MAAM,CAW7G;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAYrE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAarH;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAc7G"}
|
package/dist/format.js
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
// is formatted at UTC midnight in UTC, so neither the server's nor the reader's zone moves it.
|
|
3
3
|
import { isCalendarDay } from "./calendar-day.js";
|
|
4
4
|
import { CURRENCY_MINOR_UNIT_DIGITS } from "./currency-digits.js";
|
|
5
|
+
import { formatMessage, selectPlural } from "./i18n.js";
|
|
6
|
+
import { coreMessages } from "./messages/index.js";
|
|
7
|
+
const MONTHS_PER_YEAR = 12;
|
|
8
|
+
const MONTH_PATTERN = /^(\d{4})-(\d{2})$/;
|
|
9
|
+
const ROMAN_MONTHS = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"];
|
|
5
10
|
const BASIS_POINTS_PER_UNIT = 10_000;
|
|
6
11
|
const MAX_PERCENT_FRACTION_DIGITS = 2;
|
|
7
12
|
const dayFormatters = new Map();
|
|
@@ -15,13 +20,55 @@ const DAY_STYLE_OPTIONS = {
|
|
|
15
20
|
export function formatCalendarDay(day, locale, style = "long") {
|
|
16
21
|
if (!isCalendarDay(day))
|
|
17
22
|
throw new RangeError(`formatCalendarDay: "${String(day)}" is not a YYYY-MM-DD calendar day`);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
return getDayFormatter(`${locale}:${style}`, locale, DAY_STYLE_OPTIONS[style]).format(new Date(`${day}T00:00:00Z`));
|
|
24
|
+
}
|
|
25
|
+
/** Whether `value` is a real calendar month written `YYYY-MM` (`2026-13` and `2026-1` are not). */
|
|
26
|
+
export function isCalendarMonth(value) {
|
|
27
|
+
if (typeof value !== "string")
|
|
28
|
+
return false;
|
|
29
|
+
const match = MONTH_PATTERN.exec(value);
|
|
30
|
+
if (match === null)
|
|
31
|
+
return false;
|
|
32
|
+
const month = Number(match[2]);
|
|
33
|
+
return month >= 1 && month <= MONTHS_PER_YEAR;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The month of a `YYYY-MM` month or a `YYYY-MM-DD` day, with its year, as `locale` writes it alone. Throws a
|
|
37
|
+
* `RangeError` for anything else.
|
|
38
|
+
*/
|
|
39
|
+
export function formatCalendarMonth(month, locale, style = "long") {
|
|
40
|
+
const firstDay = isCalendarMonth(month) ? `${month}-01` : month;
|
|
41
|
+
if (!isCalendarDay(firstDay))
|
|
42
|
+
throw new RangeError(`formatCalendarMonth: "${String(month)}" is not a YYYY-MM month or a YYYY-MM-DD day`);
|
|
43
|
+
const date = new Date(`${firstDay}T00:00:00Z`);
|
|
44
|
+
const year = firstDay.slice(0, 4);
|
|
45
|
+
if (style === "roman")
|
|
46
|
+
return `${ROMAN_MONTHS[date.getUTCMonth()] ?? ""} ${year}`;
|
|
47
|
+
if (style === "long")
|
|
48
|
+
return getDayFormatter(`${locale}:month`, locale, { month: "long", year: "numeric" }).format(date);
|
|
49
|
+
// The genitive is the form a full date uses, so it is read from a day-month-year date's month part.
|
|
50
|
+
const parts = getDayFormatter(`${locale}:day-month`, locale, { day: "numeric", month: "long", year: "numeric" }).formatToParts(date);
|
|
51
|
+
const name = parts.find((part) => part.type === "month")?.value ?? "";
|
|
52
|
+
return `${name} ${year}`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whole months as years and months in `locale`, with its plural forms: 38 is "3 years and 2 months"; a part that is
|
|
56
|
+
* zero is left out, and zero itself is "0 months". Throws a `RangeError` for a negative or fractional count.
|
|
57
|
+
*/
|
|
58
|
+
export function formatDuration(months, locale) {
|
|
59
|
+
if (!Number.isSafeInteger(months) || months < 0) {
|
|
60
|
+
throw new RangeError(`formatDuration: ${String(months)} is not a whole, non-negative number of months`);
|
|
23
61
|
}
|
|
24
|
-
|
|
62
|
+
const copy = coreMessages[locale].duration;
|
|
63
|
+
const years = Math.floor(months / MONTHS_PER_YEAR);
|
|
64
|
+
const rest = months % MONTHS_PER_YEAR;
|
|
65
|
+
const yearsText = formatMessage(selectPlural(locale, years, copy.years), { count: years });
|
|
66
|
+
const monthsText = formatMessage(selectPlural(locale, rest, copy.months), { count: rest });
|
|
67
|
+
if (years === 0)
|
|
68
|
+
return monthsText;
|
|
69
|
+
if (rest === 0)
|
|
70
|
+
return yearsText;
|
|
71
|
+
return formatMessage(copy.both, { years: yearsText, months: monthsText });
|
|
25
72
|
}
|
|
26
73
|
/**
|
|
27
74
|
* An amount in the currency's minor unit (2900 PLN = PLN 29.00) in `locale`'s notation, thousands always
|
|
@@ -45,12 +92,37 @@ export function formatMoney(minor, currency, locale, options = {}) {
|
|
|
45
92
|
});
|
|
46
93
|
return format.format(minor / 10 ** digits);
|
|
47
94
|
}
|
|
48
|
-
/**
|
|
49
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Basis points as a percentage in `locale`: 1250 is 12.5%, at most two fraction digits, and zero is never signed (`-0`
|
|
97
|
+
* and a value that rounds to zero show as `0%`). Throws a `RangeError` for a non-finite value.
|
|
98
|
+
*/
|
|
99
|
+
export function formatPercent(basisPoints, locale, options = {}) {
|
|
50
100
|
if (!Number.isFinite(basisPoints))
|
|
51
101
|
throw new RangeError(`formatPercent: ${String(basisPoints)} is not a finite number of basis points`);
|
|
52
|
-
const format = getNumberFormatter(locale, {
|
|
53
|
-
|
|
102
|
+
const format = getNumberFormatter(locale, {
|
|
103
|
+
style: "percent",
|
|
104
|
+
maximumFractionDigits: MAX_PERCENT_FRACTION_DIGITS,
|
|
105
|
+
signDisplay: options.signed === true ? "exceptZero" : "negative",
|
|
106
|
+
});
|
|
107
|
+
const value = basisPoints / BASIS_POINTS_PER_UNIT;
|
|
108
|
+
if (options.tight !== true)
|
|
109
|
+
return format.format(value);
|
|
110
|
+
const parts = format.formatToParts(value);
|
|
111
|
+
return parts
|
|
112
|
+
.filter((part, index) => !(part.type === "literal" && part.value.trim() === "" && isNextToPercentSign(parts, index)))
|
|
113
|
+
.map((part) => part.value)
|
|
114
|
+
.join("");
|
|
115
|
+
}
|
|
116
|
+
function isNextToPercentSign(parts, index) {
|
|
117
|
+
return parts[index - 1]?.type === "percentSign" || parts[index + 1]?.type === "percentSign";
|
|
118
|
+
}
|
|
119
|
+
function getDayFormatter(key, locale, options) {
|
|
120
|
+
let format = dayFormatters.get(key);
|
|
121
|
+
if (format === undefined) {
|
|
122
|
+
format = new Intl.DateTimeFormat(locale, { ...options, timeZone: "UTC" });
|
|
123
|
+
dayFormatters.set(key, format);
|
|
124
|
+
}
|
|
125
|
+
return format;
|
|
54
126
|
}
|
|
55
127
|
function getNumberFormatter(locale, options) {
|
|
56
128
|
const key = `${locale}:${JSON.stringify(options)}`;
|
package/dist/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,+FAA+F;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { addCalendarDays, addCalendarMonths, calendarDaysBetween, getCalendarDay, isCalendarDay, toCalendarDay, wholeMonthsBetween, type EndOfMonth, } from "./calendar-day.js";
|
|
1
|
+
export { addCalendarDays, addCalendarMonths, calendarDaysBetween, calendarDaySchema, getCalendarDay, isCalendarDay, toCalendarDay, wholeMonthsBetween, type EndOfMonth, } from "./calendar-day.js";
|
|
2
2
|
export { CURRENCY_MINOR_UNIT_DIGITS } from "./currency-digits.js";
|
|
3
|
-
export { formatCalendarDay, formatMoney, formatPercent, type CalendarDayStyle, type FormatMoneyOptions } from "./format.js";
|
|
3
|
+
export { formatCalendarDay, formatCalendarMonth, formatDuration, formatMoney, formatPercent, isCalendarMonth, type CalendarDayStyle, type CalendarMonthStyle, type FormatMoneyOptions, type FormatPercentOptions, } from "./format.js";
|
|
4
|
+
export { memoizeByContent, type MemoizeByContentOptions, type MemoizedFunction } from "./memoize.js";
|
|
4
5
|
export { createTestClock, systemClock, type Clock, type TestClock } from "./clock.js";
|
|
5
6
|
export { formatMessage, getMessage, isLocale, LOCALES, mergeMessages, selectPlural, type DeepPartial, type Dictionaries, type Locale, type MessageOverrides, type MessageTree, type PluralForms, } from "./i18n.js";
|
|
6
7
|
export { coreMessages, type CoreMessages } from "./messages/index.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,WAAW,EACX,aAAa,EACb,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrG,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EACL,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,KAAK,EAAE,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC7H,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,yBAAyB,EACzB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,cAAc,EACnB,KAAK,mBAAmB,GACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Public API of @softure-ai/core: the contract every SOFTURE module stands on
|
|
2
2
|
// (docs/02-module-standard.md). The Next.js registry is a separate entry: `@softure-ai/core/next`.
|
|
3
|
-
export { addCalendarDays, addCalendarMonths, calendarDaysBetween, getCalendarDay, isCalendarDay, toCalendarDay, wholeMonthsBetween, } from "./calendar-day.js";
|
|
3
|
+
export { addCalendarDays, addCalendarMonths, calendarDaysBetween, calendarDaySchema, getCalendarDay, isCalendarDay, toCalendarDay, wholeMonthsBetween, } from "./calendar-day.js";
|
|
4
4
|
export { CURRENCY_MINOR_UNIT_DIGITS } from "./currency-digits.js";
|
|
5
|
-
export { formatCalendarDay, formatMoney, formatPercent } from "./format.js";
|
|
5
|
+
export { formatCalendarDay, formatCalendarMonth, formatDuration, formatMoney, formatPercent, isCalendarMonth, } from "./format.js";
|
|
6
|
+
export { memoizeByContent } from "./memoize.js";
|
|
6
7
|
export { createTestClock, systemClock } from "./clock.js";
|
|
7
8
|
export { formatMessage, getMessage, isLocale, LOCALES, mergeMessages, selectPlural, } from "./i18n.js";
|
|
8
9
|
export { coreMessages } from "./messages/index.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mGAAmG;AACnG,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,aAAa,EACb,kBAAkB,GAEnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mGAAmG;AACnG,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,aAAa,EACb,kBAAkB,GAEnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,WAAW,EACX,aAAa,EACb,eAAe,GAKhB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAuD,MAAM,cAAc,CAAC;AACrG,OAAO,EAAE,eAAe,EAAE,WAAW,EAA8B,MAAM,YAAY,CAAC;AACtF,OAAO,EACL,aAAa,EACb,UAAU,EACV,QAAQ,EACR,OAAO,EACP,aAAa,EACb,YAAY,GAOb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAkD,MAAM,aAAa,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAsB,MAAM,iBAAiB,CAAC;AAC7H,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,yBAAyB,GAQ1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAuB,MAAM,eAAe,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,GAUb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GAIjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAuC,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAyC,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAmC,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface MemoizeByContentOptions {
|
|
2
|
+
/** The most entries kept; the least recently used one goes first. */
|
|
3
|
+
readonly max: number;
|
|
4
|
+
}
|
|
5
|
+
/** `fn` with a cache, plus `clear()` to empty it. */
|
|
6
|
+
export type MemoizedFunction<Args extends readonly unknown[], Value> = ((...args: Args) => Value) & {
|
|
7
|
+
readonly clear: () => void;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* `fn` cached by the content of its arguments: primitives, arrays, `Date`s and plain objects (key order does not
|
|
11
|
+
* matter). An argument holding anything else (a function, a `Map`, a class instance, a cycle) throws a `TypeError`.
|
|
12
|
+
* A promise that rejects is dropped, so the next call tries again. Throws a `RangeError` for a `max` that is not a
|
|
13
|
+
* positive whole number.
|
|
14
|
+
*/
|
|
15
|
+
export declare function memoizeByContent<Args extends readonly unknown[], Value>(fn: (...args: Args) => Value, options: MemoizeByContentOptions): MemoizedFunction<Args, Value>;
|
|
16
|
+
//# sourceMappingURL=memoize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoize.d.ts","sourceRoot":"","sources":["../src/memoize.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,uBAAuB;IACtC,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,qDAAqD;AACrD,MAAM,MAAM,gBAAgB,CAAC,IAAI,SAAS,SAAS,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,CAAC,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAEnI;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,SAAS,SAAS,OAAO,EAAE,EAAE,KAAK,EACrE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,KAAK,EAC5B,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CA4B/B"}
|
package/dist/memoize.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// A cache for pure functions of plain data: the arguments' content is the key, so two equal objects built apart hit
|
|
2
|
+
// the same entry. Least recently used entries go beyond `max`; nothing expires by time.
|
|
3
|
+
/**
|
|
4
|
+
* `fn` cached by the content of its arguments: primitives, arrays, `Date`s and plain objects (key order does not
|
|
5
|
+
* matter). An argument holding anything else (a function, a `Map`, a class instance, a cycle) throws a `TypeError`.
|
|
6
|
+
* A promise that rejects is dropped, so the next call tries again. Throws a `RangeError` for a `max` that is not a
|
|
7
|
+
* positive whole number.
|
|
8
|
+
*/
|
|
9
|
+
export function memoizeByContent(fn, options) {
|
|
10
|
+
const { max } = options;
|
|
11
|
+
if (!Number.isSafeInteger(max) || max < 1)
|
|
12
|
+
throw new RangeError(`memoizeByContent: max must be a positive whole number, got ${String(max)}`);
|
|
13
|
+
const cache = new Map();
|
|
14
|
+
const memoized = (...args) => {
|
|
15
|
+
const key = toContentKey(args, new Set());
|
|
16
|
+
if (cache.has(key)) {
|
|
17
|
+
// Not `?? fn(...)`: a cached `undefined` is a hit too.
|
|
18
|
+
const hit = cache.get(key);
|
|
19
|
+
cache.delete(key);
|
|
20
|
+
cache.set(key, hit);
|
|
21
|
+
return hit;
|
|
22
|
+
}
|
|
23
|
+
const value = fn(...args);
|
|
24
|
+
cache.set(key, value);
|
|
25
|
+
if (cache.size > max) {
|
|
26
|
+
const oldest = cache.keys().next();
|
|
27
|
+
if (oldest.done !== true)
|
|
28
|
+
cache.delete(oldest.value);
|
|
29
|
+
}
|
|
30
|
+
if (value instanceof Promise) {
|
|
31
|
+
value.catch(() => {
|
|
32
|
+
if (cache.get(key) === value)
|
|
33
|
+
cache.delete(key);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
};
|
|
38
|
+
return Object.assign(memoized, { clear: () => cache.clear() });
|
|
39
|
+
}
|
|
40
|
+
function toContentKey(value, path) {
|
|
41
|
+
switch (typeof value) {
|
|
42
|
+
case "undefined":
|
|
43
|
+
return "u";
|
|
44
|
+
case "boolean":
|
|
45
|
+
return value ? "t" : "f";
|
|
46
|
+
case "number":
|
|
47
|
+
return `n${Object.is(value, -0) ? "-0" : String(value)}`;
|
|
48
|
+
case "bigint":
|
|
49
|
+
return `b${String(value)}`;
|
|
50
|
+
case "string":
|
|
51
|
+
return JSON.stringify(value);
|
|
52
|
+
case "object":
|
|
53
|
+
return value === null ? "null" : toObjectKey(value, path);
|
|
54
|
+
default:
|
|
55
|
+
throw new TypeError(`memoizeByContent: an argument holds a ${typeof value}, which has no content key`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function toObjectKey(value, path) {
|
|
59
|
+
if (value instanceof Date)
|
|
60
|
+
return `d${String(value.getTime())}`;
|
|
61
|
+
if (path.has(value))
|
|
62
|
+
throw new TypeError("memoizeByContent: an argument holds a cycle");
|
|
63
|
+
path.add(value);
|
|
64
|
+
let key;
|
|
65
|
+
if (Array.isArray(value)) {
|
|
66
|
+
key = `[${value.map((item) => toContentKey(item, path)).join(",")}]`;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const prototype = Object.getPrototypeOf(value);
|
|
70
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
71
|
+
throw new TypeError(`memoizeByContent: an argument holds a ${value.constructor.name}, which has no content key`);
|
|
72
|
+
}
|
|
73
|
+
const entries = Object.keys(value)
|
|
74
|
+
.sort()
|
|
75
|
+
.map((name) => `${JSON.stringify(name)}:${toContentKey(value[name], path)}`);
|
|
76
|
+
key = `{${entries.join(",")}}`;
|
|
77
|
+
}
|
|
78
|
+
path.delete(value);
|
|
79
|
+
return key;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=memoize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoize.js","sourceRoot":"","sources":["../src/memoize.ts"],"names":[],"mappings":"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"}
|