temporal-fmt 0.9.2 → 0.9.4

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 (103) hide show
  1. package/README.md +480 -9
  2. package/dist/calendarUtils.cjs +259 -4
  3. package/dist/calendarUtils.cjs.map +1 -1
  4. package/dist/calendarUtils.js +33 -1
  5. package/dist/chunk-4N3WCGEY.js +183 -0
  6. package/dist/{chunk-4JWGUR4O.js.map → chunk-4N3WCGEY.js.map} +1 -1
  7. package/dist/chunk-5UTV5VP6.js +984 -0
  8. package/dist/chunk-5UTV5VP6.js.map +1 -0
  9. package/dist/chunk-ACKKWH5Z.js +578 -0
  10. package/dist/{chunk-2JHEV7ZF.js.map → chunk-ACKKWH5Z.js.map} +1 -1
  11. package/dist/chunk-EGUUO6LE.js +439 -0
  12. package/dist/chunk-EGUUO6LE.js.map +1 -0
  13. package/dist/chunk-FBPHNRVW.js +2939 -0
  14. package/dist/chunk-FBPHNRVW.js.map +1 -0
  15. package/dist/chunk-GPB4JHGI.js +65 -0
  16. package/dist/chunk-GPB4JHGI.js.map +1 -0
  17. package/dist/chunk-H7YQX25T.js +170 -0
  18. package/dist/{chunk-J2AQNXF2.js.map → chunk-H7YQX25T.js.map} +1 -1
  19. package/dist/chunk-HXY2GUUM.js +182 -0
  20. package/dist/{chunk-EHLRZULM.js.map → chunk-HXY2GUUM.js.map} +1 -1
  21. package/dist/chunk-L24NPTAJ.js +328 -0
  22. package/dist/chunk-L24NPTAJ.js.map +1 -0
  23. package/dist/chunk-M3GDTHMT.js +169 -0
  24. package/dist/chunk-M3GDTHMT.js.map +1 -0
  25. package/dist/chunk-MKPDLQKD.js +51 -0
  26. package/dist/chunk-MKPDLQKD.js.map +1 -0
  27. package/dist/chunk-TSLPIURC.js +242 -0
  28. package/dist/{chunk-VQXUMFB2.js.map → chunk-TSLPIURC.js.map} +1 -1
  29. package/dist/chunk-UOPAV3WX.js +75 -0
  30. package/dist/chunk-UOPAV3WX.js.map +1 -0
  31. package/dist/chunk-VNIUIQA4.js +398 -0
  32. package/dist/chunk-VNIUIQA4.js.map +1 -0
  33. package/dist/chunk-YEUASGDK.js +9 -0
  34. package/dist/chunk-YEUASGDK.js.map +1 -0
  35. package/dist/chunk-ZQZF5EXW.js +29 -0
  36. package/dist/chunk-ZQZF5EXW.js.map +1 -0
  37. package/dist/config.d.cts +4 -2
  38. package/dist/config.d.ts +4 -2
  39. package/dist/duration.cjs +638 -26
  40. package/dist/duration.cjs.map +1 -1
  41. package/dist/duration.js +28 -1
  42. package/dist/format.cjs +833 -35
  43. package/dist/format.cjs.map +1 -1
  44. package/dist/format.js +20 -1
  45. package/dist/index.cjs +7698 -163
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +108 -24
  48. package/dist/index.d.ts +108 -24
  49. package/dist/index.js +1536 -58
  50. package/dist/index.js.map +1 -1
  51. package/dist/interval.cjs +5480 -35
  52. package/dist/interval.cjs.map +1 -1
  53. package/dist/interval.js +46 -1
  54. package/dist/localeRegistry.cjs +375 -32
  55. package/dist/localeRegistry.cjs.map +1 -1
  56. package/dist/localeRegistry.js +11 -1
  57. package/dist/modApi.d.cts +131 -0
  58. package/dist/modApi.d.ts +131 -0
  59. package/dist/parse.cjs +1797 -70
  60. package/dist/parse.cjs.map +1 -1
  61. package/dist/parse.js +20 -1
  62. package/dist/pattern.d.cts +1 -0
  63. package/dist/pattern.d.ts +1 -0
  64. package/dist/recurrence.cjs +452 -20
  65. package/dist/recurrence.cjs.map +1 -1
  66. package/dist/recurrence.js +19 -1
  67. package/dist/relativeTime.cjs +268 -21
  68. package/dist/relativeTime.cjs.map +1 -1
  69. package/dist/relativeTime.js +14 -1
  70. package/dist/runtime.d.cts +201 -0
  71. package/dist/runtime.d.ts +201 -0
  72. package/dist/timezone.cjs +387 -20
  73. package/dist/timezone.cjs.map +1 -1
  74. package/dist/timezone.js +26 -1
  75. package/package.json +4 -6
  76. package/scripts/cli.mjs +27 -5
  77. package/dist/chunk-2JHEV7ZF.js +0 -7
  78. package/dist/chunk-3MZLTVP3.js +0 -2
  79. package/dist/chunk-3MZLTVP3.js.map +0 -1
  80. package/dist/chunk-4JWGUR4O.js +0 -11
  81. package/dist/chunk-5U5WJ465.js +0 -36
  82. package/dist/chunk-5U5WJ465.js.map +0 -1
  83. package/dist/chunk-C5YESWFT.js +0 -2
  84. package/dist/chunk-C5YESWFT.js.map +0 -1
  85. package/dist/chunk-C6ZZ62ET.js +0 -2
  86. package/dist/chunk-C6ZZ62ET.js.map +0 -1
  87. package/dist/chunk-EHLRZULM.js +0 -5
  88. package/dist/chunk-F4RGUDA3.js +0 -2
  89. package/dist/chunk-F4RGUDA3.js.map +0 -1
  90. package/dist/chunk-J2AQNXF2.js +0 -2
  91. package/dist/chunk-NBXF7V5B.js +0 -2
  92. package/dist/chunk-NBXF7V5B.js.map +0 -1
  93. package/dist/chunk-R52YOKI3.js +0 -7
  94. package/dist/chunk-R52YOKI3.js.map +0 -1
  95. package/dist/chunk-UJR6DHXY.js +0 -2
  96. package/dist/chunk-UJR6DHXY.js.map +0 -1
  97. package/dist/chunk-VQXUMFB2.js +0 -21
  98. package/dist/chunk-XH46JNPK.js +0 -2
  99. package/dist/chunk-XH46JNPK.js.map +0 -1
  100. package/dist/chunk-YB6YAG7E.js +0 -35
  101. package/dist/chunk-YB6YAG7E.js.map +0 -1
  102. package/dist/chunk-ZGMTY52O.js +0 -2
  103. package/dist/chunk-ZGMTY52O.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/localeRegistry.ts","../src/errors.ts","../src/localeVocab.ts"],"sourcesContent":["// Locale registration and lookup. Extends the\n// existing registerLocaleVocab() surface in localeVocab.ts with\n// registerLocale() / getLocale() / hasLocale() and a richer LocaleVocab\n// that covers quarters, eras, ordinals, duration units, and relative-\n// time language.\n//\n// The existing localeVocab.ts stays as the implementation for months/\n// weekdays/day-periods (those are what tokens.ts's MMMM/MMM/EEEE/EEE/a\n// tokens read). This module wraps it and adds the extended fields.\n\nimport { registerLocaleVocab, getLocaleVocab, type LocaleVocab as BaseLocaleVocab } from './localeVocab.js';\nimport { InvalidLocaleError } from './errors.js';\n\nexport interface ExtendedLocaleVocab extends BaseLocaleVocab {\n // Quarters: Q1..Q4 long form (\"First quarter\", etc.). Default falls\n // back to \"Q1\"..\"Q4\" if not registered.\n quartersLong?: string[];\n quartersShort?: string[];\n // Eras: [\"BC\", \"AD\"] for gregory, etc. Default [\"BC\", \"AD\"].\n erasLong?: string[];\n erasShort?: string[];\n // Ordinal suffix rules: [\"st\", \"nd\", \"rd\", \"th\"] for English. Default\n // empty (the existing 'do' token has English-only ordinal logic baked\n // into tokens.ts; this field lets a custom locale override it).\n ordinals?: string[];\n // Duration unit names: long singular/plural for each unit. Used by\n // formatDuration's locale-aware path when Intl.NumberFormat isn't\n // desired (e.g. for a made-up locale Intl doesn't know about).\n durationUnits?: {\n years: [string, string];\n months: [string, string];\n weeks: [string, string];\n days: [string, string];\n hours: [string, string];\n minutes: [string, string];\n seconds: [string, string];\n milliseconds: [string, string];\n };\n // Relative-time language: words for \"ago\" / \"in\" / \"now\". Used by\n // formatRelative()'s locale-aware path when Intl.RelativeTimeFormat\n // isn't available or doesn't cover a registered locale.\n relativeTime?: {\n past: string;\n future: string;\n now: string;\n };\n}\n\n// Bounded indirectly: every entry here is added by registerLocale(), which\n// first passes registerLocaleVocab() — and THAT registry caps new locales\n// at 500 (MAX_CUSTOM_VOCABS, RangeError past it). So extendedVocabs can\n// never exceed 500 keys; no separate cap is needed (and an unreachable one\n// would only add dead branches).\nconst extendedVocabs = new Map<string, ExtendedLocaleVocab>();\nconst MAX_LOCALE_TAG_LENGTH = 256;\nconst MAX_VOCAB_STRING_LENGTH = 256;\n\nfunction canonicalKey(locale: string): string {\n try {\n return new Intl.Locale(locale.replace(/_/g, '-')).toString().toLowerCase();\n } catch {\n return locale;\n }\n}\n\nexport function registerLocale(locale: string, vocab: ExtendedLocaleVocab): void {\n if (typeof locale !== 'string' || locale.length === 0) {\n throw new InvalidLocaleError({ actual: String(locale), reason: 'locale string must be non-empty' });\n }\n if (locale.length > MAX_LOCALE_TAG_LENGTH) {\n throw new InvalidLocaleError({ actual: String(locale.length), reason: `locale tag must be at most ${MAX_LOCALE_TAG_LENGTH} characters` });\n }\n // Validate the base vocab fields (months/weekdays/day-periods) via\n // the existing registerLocaleVocab — it has the strict-shape checks.\n registerLocaleVocab(locale, vocab);\n // Extended fields are optional; only validate the ones that are present.\n validateExtended(vocab, locale);\n const key = canonicalKey(locale);\n extendedVocabs.set(key, { ...vocab });\n}\n\nfunction validateExtended(vocab: ExtendedLocaleVocab, locale: string): void {\n const checkArray = (val: unknown, key: string, length: number) => {\n if (val === undefined) return;\n if (!Array.isArray(val)) {\n throw new InvalidLocaleError({ actual: String(val), reason: `locale \"${locale}\": \"${key}\" must be an array` });\n }\n if (val.length !== length) {\n throw new InvalidLocaleError({ actual: String(val.length), reason: `locale \"${locale}\": \"${key}\" must have ${length} entries (got ${val.length})` });\n }\n for (let i = 0; i < val.length; i++) {\n if (typeof val[i] !== 'string' || val[i]!.length === 0) {\n throw new InvalidLocaleError({ actual: String(val[i]), reason: `locale \"${locale}\": \"${key}[${i}]\" must be a non-empty string` });\n }\n if (val[i]!.length > MAX_VOCAB_STRING_LENGTH) {\n throw new InvalidLocaleError({ actual: String(val[i]!.length), reason: `locale \"${locale}\": \"${key}[${i}]\" must be at most ${MAX_VOCAB_STRING_LENGTH} characters` });\n }\n }\n };\n checkArray(vocab.quartersLong, 'quartersLong', 4);\n checkArray(vocab.quartersShort, 'quartersShort', 4);\n checkArray(vocab.erasLong, 'erasLong', 2);\n checkArray(vocab.erasShort, 'erasShort', 2);\n checkArray(vocab.ordinals, 'ordinals', 4);\n}\n\nexport function getLocale(locale: string): ExtendedLocaleVocab | undefined {\n // Returns the extended vocab for a locale, OR undefined (falls back\n // to Intl). Combines the base vocab (from localeVocab.ts, which\n // includes Intl defaults) with any extended fields registered here.\n const key = canonicalKey(locale);\n const ext = extendedVocabs.get(key);\n if (ext) return ext;\n // Fall back to base vocab (Intl-derived) without extended fields.\n try {\n const base = getLocaleVocab(locale);\n return { ...base };\n } catch {\n return undefined;\n }\n}\n\nexport function hasLocale(locale: string): boolean {\n const key = canonicalKey(locale);\n return extendedVocabs.has(key);\n}\n\n// Re-export the base vocab types for callers that want them.\nexport type { LocaleVocab } from './localeVocab.js';\n","// Structured error classes for parse()/format() failures.\n//\n// As of 0.9.0, every throw site on the parse/format data path —\n// tokenize.ts, pattern.ts, format.ts, parse.ts (parse/safeParse/tryParse/\n// parseToParts/compileParser), and the two data-path throws in\n// localeVocab.ts (partValue/assertNoCollision on the getLocaleVocab side)\n// — throws these typed classes directly instead of plain\n// `new Error(message)`. Every migrated site kept its exact pre-0.9.0\n// message text — subclasses of TemporalFmtError still satisfy\n// `instanceof Error` and message-matching regexes (e.g.\n// `/token \"HH\" requires/`), so this was safe to do without a semver-major\n// bump for either check. What *is* a breaking change for 0.9.0: code that\n// specifically checked `err.constructor === Error` or `err.name ===\n// 'Error'` will see a different name now (e.g. 'FormatSyntaxError'). See\n// the 0.9.0 changelog entry.\n//\n// Not migrated, on purpose:\n// - localeVocab.ts's registration-time throws (assertValidVocab,\n// registerLocaleVocab itself) — these are config-time API-misuse\n// errors on data the developer supplies once at startup, not runtime\n// parse/format failures, so they don't fit this module's\n// TemporalFmtErrorCode taxonomy as-is. assertNoCollision is shared\n// between the registration path and the data path (getLocaleVocab), so\n// its throw stays plain `Error` for both until that split is done —\n// see the tracking note at its call site.\n//\n// wrapUntypedError() below still exists for localeVocab.ts's registration\n// throws and for anything a caller passes into safeParse()/tryParse() from\n// outside this package. On the data path, safeParse's `if (err instanceof\n// TemporalFmtError) return { ok: false, error: err }` now catches every\n// throw before it would reach the classifier, so the regex branches here\n// are effectively dead for parse/format/tokenize/pattern — left in place\n// as the fallback for anything not yet on a typed throw site.\n\nexport type TemporalFmtErrorCode =\n | 'FORMAT_SYNTAX_ERROR'\n | 'UNKNOWN_TOKEN'\n | 'PARSE_MISMATCH'\n | 'INVALID_DATE'\n | 'INVALID_TIME'\n | 'INVALID_OFFSET'\n | 'INVALID_TIME_ZONE'\n | 'INVALID_CALENDAR'\n | 'AMBIGUOUS_INPUT'\n | 'INVALID_LOCALE'\n | 'INVALID_DURATION';\n\nexport interface TemporalFmtErrorFields {\n code: TemporalFmtErrorCode;\n input?: string;\n format?: string;\n token?: string;\n position?: number;\n expected?: string;\n actual?: string;\n reason?: string;\n}\n\n// Base class. `message` is the human-readable summary; the structured\n// fields are the machine-readable parts a linter or codemod reports on.\n// `Error.captureStackTrace` is called manually (where available) so\n// the stack points at the call site, not at this constructor — same\n// pattern Node uses for its own error classes.\nexport class TemporalFmtError extends Error {\n readonly code: TemporalFmtErrorCode;\n readonly input?: string;\n readonly format?: string;\n readonly token?: string;\n readonly position?: number;\n readonly expected?: string;\n readonly actual?: string;\n readonly reason?: string;\n\n constructor(message: string, fields: TemporalFmtErrorFields) {\n super(message);\n this.name = 'TemporalFmtError';\n this.code = fields.code;\n this.input = fields.input;\n this.format = fields.format;\n this.token = fields.token;\n this.position = fields.position;\n this.expected = fields.expected;\n this.actual = fields.actual;\n this.reason = fields.reason;\n // Avoid setting the stack to point at this constructor — keeps it\n // useful. captureStackTrace is V8-only; on other engines the\n // default stack (this constructor line) is what callers get.\n const capture = (Error as unknown as { captureStackTrace?: (target: Error, ctor?: Function) => void }).captureStackTrace;\n if (typeof capture === 'function') {\n capture(this, this.constructor);\n }\n }\n\n // Lets callers do `err.toJSON()` for logging. Plain `Error` doesn't\n // serialize its non-enumerable fields; this picks them up explicitly.\n toJSON(): TemporalFmtErrorFields & { name: string; message: string } {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n input: this.input,\n format: this.format,\n token: this.token,\n position: this.position,\n expected: this.expected,\n actual: this.actual,\n reason: this.reason,\n };\n }\n}\n\n// Each subclass fixes `code` so callers can switch on it without\n// re-checking message text. The constructor takes only the fields\n// that vary per call; `code` and a default `message` template are\n// provided by the subclass.\n\nexport class FormatSyntaxError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `format string \"${fields.format ?? ''}\" has a syntax error${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'FORMAT_SYNTAX_ERROR', ...rest },\n );\n this.name = 'FormatSyntaxError';\n }\n}\n\nexport class UnknownTokenError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `token \"${fields.token ?? ''}\" is not a recognized temporal-fmt token${fields.format ? ` in format string \"${fields.format}\"` : ''}.`,\n { code: 'UNKNOWN_TOKEN', ...rest },\n );\n this.name = 'UnknownTokenError';\n }\n}\n\nexport class ParseMismatchError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" does not match format \"${fields.format ?? ''}\"${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'PARSE_MISMATCH', ...rest },\n );\n this.name = 'ParseMismatchError';\n }\n}\n\nexport class InvalidDateError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" does not describe a valid date${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_DATE', ...rest },\n );\n this.name = 'InvalidDateError';\n }\n}\n\n/* c8 ignore start @preserve -- InvalidTimeError is part of the public\n error-class surface (exported from index.ts, code 'INVALID_TIME')\n but nothing in this package constructs one. Investigated wiring it\n in the same way InvalidTimeZoneError was just wired (see parse.ts's\n zzz-validation loop): checked whether hour/minute/second have a\n post-match semantic range check the way zone ids do. They don't —\n pattern.ts's regex fragments for HH/H/hh/h/mm/m/ss/s already enforce\n their valid ranges at the regex level (e.g. HH is '(?:[01]\\d|2[0-3])',\n which can't match \"99\" in the first place), so an out-of-range time\n is rejected as a plain shape mismatch before any semantic check\n could run. There's no live gap to hook this into without inventing a\n redundant check purely to give this class a body. Left unconstructed\n until the library actually has a real invalid-time case to report. */\nexport class InvalidTimeError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" does not describe a valid time${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_TIME', ...rest },\n );\n this.name = 'InvalidTimeError';\n }\n}\n/* c8 ignore stop @preserve */\n\nexport class InvalidOffsetError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `offset \"${fields.actual ?? ''}\" is invalid${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_OFFSET', ...rest },\n );\n this.name = 'InvalidOffsetError';\n }\n}\n\nexport class InvalidTimeZoneError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `time zone \"${fields.actual ?? ''}\" is not a recognized IANA time zone or fixed offset${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_TIME_ZONE', ...rest },\n );\n this.name = 'InvalidTimeZoneError';\n }\n}\n\n/* c8 ignore start @preserve -- InvalidCalendarError is part of the\n public error-class surface (exported from index.ts, code\n 'INVALID_CALENDAR') but nothing in this package constructs one.\n Checked for a wiring opportunity the same way InvalidTimeZoneError\n got one: there's no user-supplied calendar identifier anywhere in\n the library to validate against a supported list. resolveCalendar()\n in parse.ts derives the calendar entirely from Intl's own resolution\n of the locale string — it's never handed an arbitrary \"calendar\"\n value a caller could get wrong. There's no live input to reject.\n Left unconstructed until the library actually accepts a calendar\n parameter that could be invalid. */\nexport class InvalidCalendarError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `calendar \"${fields.actual ?? ''}\" is not supported${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_CALENDAR', ...rest },\n );\n this.name = 'InvalidCalendarError';\n }\n}\n/* c8 ignore stop @preserve */\n\nexport class AmbiguousInputError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" is ambiguous${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'AMBIGUOUS_INPUT', ...rest },\n );\n this.name = 'AmbiguousInputError';\n }\n}\n\nexport class InvalidLocaleError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `locale \"${fields.actual ?? ''}\" is not a valid BCP-47 tag${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_LOCALE', ...rest },\n );\n this.name = 'InvalidLocaleError';\n }\n}\n\nexport class InvalidDurationError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `duration is invalid${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_DURATION', ...rest },\n );\n this.name = 'InvalidDurationError';\n }\n}\n\n// Wraps a plain Error thrown from a code path that hasn't been\n// migrated to typed errors yet. Carries the original message in\n// `reason` so callers reading the typed surface still see what\n// failed. Used by safeParse() in parse.ts.\n//\n// As of the 0.9.0 migration, every throw site on the parse/format data\n// path throws a TemporalFmtError directly, so safeParse's `instanceof\n// TemporalFmtError` check always passes before this function would be\n// called — nothing in the current test suite reaches any branch below.\n// Kept as the safety net for wrapping a future unmigrated throw site\n// (see the c8-ignored call in parse.ts's safeParse), same reasoning as\n// that call site: removing this would silently drop the \"safeParse\n// always returns a TemporalFmtError\" contract the moment anyone adds a\n// throw new Error(...) without wiring a typed class for it.\n/* c8 ignore start @preserve -- unreachable from the current test suite,\n see rationale above */\nexport function wrapUntypedError(err: Error, context: { input?: string; format?: string }): TemporalFmtError {\n // Try to classify by inspecting the message — covers the existing\n // parse()/format() throw sites without modifying them. Anything\n // that doesn't match a known pattern falls through to a generic\n // ParseMismatchError, which still has the structured fields.\n const msg = err.message;\n if (/unknown token|isn't a recognized token/.test(msg)) {\n return new UnknownTokenError({ input: context.input, format: context.format, reason: msg });\n }\n if (/ambiguous/i.test(msg)) {\n return new AmbiguousInputError({ input: context.input, format: context.format, reason: msg });\n }\n if (/offset/.test(msg) && /out of range|exceeds|doesn't match the shape/i.test(msg)) {\n return new InvalidOffsetError({ input: context.input, format: context.format, reason: msg });\n }\n if (/no valid pattern matches/i.test(msg)) {\n return new ParseMismatchError({ input: context.input, format: context.format, reason: msg });\n }\n if (/doesn't describe a valid date\\/time|incomplete date|weekday token|quarter token/.test(msg)) {\n return new InvalidDateError({ input: context.input, format: context.format, reason: msg });\n }\n const lowerMsg = msg.toLowerCase();\n const mentionsLocale = lowerMsg.includes('locale');\n if (\n (mentionsLocale && (lowerMsg.includes('produced no') || lowerMsg.includes('not a valid'))) ||\n lowerMsg.includes('cutoffs must be')\n ) {\n return new InvalidLocaleError({ input: context.input, format: context.format, reason: msg });\n }\n if (/format string exceeds maximum length|input exceeds maximum length|unterminated quote|isn't a recognized token/i.test(msg)) {\n return new FormatSyntaxError({ input: context.input, format: context.format, reason: msg });\n }\n return new ParseMismatchError({ input: context.input, format: context.format, reason: msg });\n}\n/* c8 ignore stop @preserve */","// Name lists for the locale-aware tokens (MMMM, MMM, EEEE, EEE, a). Each\n// list is small and fixed (12 months, 7 weekdays, 2 day periods), so we\n// generate the real Intl strings for a locale once and cache them.\n\nimport { InvalidLocaleError } from './errors.js';\n\nexport interface LocaleVocab {\n monthLong: string[]; // index 0 = January\n monthShort: string[];\n weekdayLong: string[]; // index 0 = Monday, per Temporal's dayOfWeek numbering\n weekdayShort: string[];\n dayPeriod: string[]; // typically [AM-ish, PM-ish], deduped\n}\n\n// Custom vocabs registered by callers for locales Intl doesn't cover well\n// (e.g. a 13-month Hebrew leap year, where Intl's 12-month vocabulary\n// silently loses a whole month). Keyed by canonical cache key so the\n// same locale string spelling variants fold together — same convention\n// as the Intl-derived vocab cache above.\nconst customVocabs = new Map<string, LocaleVocab>();\nconst MAX_CUSTOM_VOCABS = 500;\nconst MAX_LOCALE_TAG_LENGTH = 256;\nconst MAX_VOCAB_ENTRY_LENGTH = 256;\n\nfunction assertValidVocab(vocab: Partial<LocaleVocab>, locale: string): void {\n // Strict shape validation at registration time, not lazily on first\n // use — the README's promise is that a malformed registration throws\n // descriptively here, rather than failing later inside format()/parse()\n // with a confusing \"no month part\" or wrong-month error the caller\n // can't trace back to the bad registration.\n const required: Array<{ key: keyof LocaleVocab; length: number; label: string }> = [\n { key: 'monthLong', length: 12, label: 'long month names' },\n { key: 'monthShort', length: 12, label: 'short month names' },\n { key: 'weekdayLong', length: 7, label: 'long weekday names' },\n { key: 'weekdayShort', length: 7, label: 'short weekday names' },\n { key: 'dayPeriod', length: 2, label: 'day period markers (AM/PM-equivalent)' },\n ];\n\n for (const { key, length, label } of required) {\n const value = vocab[key];\n if (value === undefined) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\" is missing required field \"${key}\" (${label}).`\n );\n }\n if (!Array.isArray(value)) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}\" must be an array, got ${typeof value}.`\n );\n }\n if (value.length !== length) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}\" must have exactly ${length} entries (got ${value.length}) — ${label}.`\n );\n }\n value.forEach((entry, i) => {\n if (typeof entry !== 'string' || entry.length === 0) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}[${i}]\" must be a non-empty string, got ${String(entry)}.`\n );\n }\n if (entry.length > MAX_VOCAB_ENTRY_LENGTH) {\n throw new RangeError(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}[${i}]\" is too long (maximum ${MAX_VOCAB_ENTRY_LENGTH} characters).`\n );\n }\n });\n }\n\n // Reuse the same collision check the Intl-derived path uses — a\n // duplicate month name is just as ambiguous when supplied by a caller\n // as when produced by Intl.\n assertNoCollision(vocab.monthLong!, 'MMMM month', locale);\n assertNoCollision(vocab.monthShort!, 'MMM month', locale);\n assertNoCollision(vocab.weekdayLong!, 'EEEE weekday', locale);\n assertNoCollision(vocab.weekdayShort!, 'EEE weekday', locale);\n\n // dayPeriod entries must differ from each other, or parse()'s\n // isPM check (raw === vocab.dayPeriod[1]) can never return true and\n // every 12-hour parse silently resolves to AM. The Intl-derived path\n // dedupes a same-AM/PM collision to length 1, but a caller passing\n // both entries identical is a real bug to surface — not something to\n // dedupe around.\n if (vocab.dayPeriod![0] === vocab.dayPeriod![1]) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": dayPeriod entries must differ ` +\n `(both are \"${vocab.dayPeriod![0]}\"); otherwise parse() can't tell AM from PM.`\n );\n }\n}\n\n// Anything that caches a result derived from *which* vocabulary is\n// active for a locale (right now: parse.ts's compiled pattern cache,\n// whose MMMM/MMM/EEEE/EEE/a fragments embed the vocab's alternations)\n// subscribes here so it gets invalidated when a registration swaps the\n// vocab — mirrors temporalProvider.ts's subscribeToTemporalChanges.\nconst onVocabChanged: Array<() => void> = [];\n\nexport function subscribeToVocabChanges(listener: () => void): void {\n onVocabChanged.push(listener);\n}\n\n/**\n * Supply a custom month/weekday/day-period vocabulary for a locale key,\n * overriding the Intl-derived vocab this library would otherwise build\n * for that key. Useful for locales Intl doesn't cover well — the README's\n * known-limitations section calls out the Hebrew leap-month gap as a\n * specific case this addresses.\n *\n * Throws descriptively on malformed input (wrong array lengths, empty\n * strings, duplicate entries, missing fields) rather than failing later\n * during format/parse.\n *\n * Registered vocab takes precedence over the Intl-derived vocab for that\n * locale key, including for already-cached entries — registering\n * invalidates the prior cache entry for that locale so the next call\n * picks up the new vocab.\n *\n * @example\n * registerLocaleVocab('en-u-ca-hebrew-leap', {\n * monthLong: ['Nisan','Iyar','Sivan','Tammuz','Av','Elul','Tishrei','Marcheshvan','Kislev','Tevet','Shevat','Adar I','Adar II'],\n * monthShort: ['Nis','Iyy','Siv','Tam','Av','Elu','Tish','Chesh','Kis','Tev','Shv','Ad1','Ad2'],\n * weekdayLong: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],\n * weekdayShort: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],\n * dayPeriod: ['AM','PM'],\n * });\n */\nexport function registerLocaleVocab(locale: string, vocab: Partial<LocaleVocab>): void {\n if (typeof locale !== 'string' || locale.length === 0) {\n throw new Error(`temporal-fmt: registerLocaleVocab requires a non-empty locale string, got ${String(locale)}.`);\n }\n if (locale.length > MAX_LOCALE_TAG_LENGTH) {\n throw new RangeError(`temporal-fmt: registerLocaleVocab locale is too long (maximum ${MAX_LOCALE_TAG_LENGTH} characters).`);\n }\n assertValidVocab(vocab, locale);\n\n const cacheKey = canonicalCacheKey(locale);\n if (!customVocabs.has(cacheKey) && customVocabs.size >= MAX_CUSTOM_VOCABS) {\n throw new RangeError(`temporal-fmt: registerLocaleVocab reached the ${MAX_CUSTOM_VOCABS}-locale limit.`);\n }\n customVocabs.set(cacheKey, {\n monthLong: [...vocab.monthLong!],\n monthShort: [...vocab.monthShort!],\n weekdayLong: [...vocab.weekdayLong!],\n weekdayShort: [...vocab.weekdayShort!],\n dayPeriod: [...vocab.dayPeriod!],\n });\n // Invalidate the Intl-derived cache entry so any prior format/parse\n // result cached for this locale is rebuilt against the new vocab. Not\n // strictly necessary (getLocaleVocab checks customVocabs first), but\n // cheap and keeps the two caches from drifting out of sync.\n vocabCache.delete(cacheKey);\n // Also invalidate downstream caches that baked the previous vocab in\n // at build time (parse.ts's pattern cache is the one that matters:\n // without this, a cached pattern would keep matching the OLD month /\n // weekday names while format() renders the new ones, so the library's\n // own format() output would fail to parse back).\n for (const listener of onVocabChanged) listener();\n}\n\n// Every locale-keyed cache in this library (this one, formatterCache in\n// tokens.ts, patternCache/calendarCache in parse.ts) used to key on the\n// exact locale string a caller passed in. Intl treats spelling variants of\n// the same locale as equivalent ('en-US' / 'en-us' / 'en_US' all resolve\n// the same way), but a plain string-keyed Map doesn't — so callers mixing\n// spellings for what's really one locale would silently fragment across\n// separate cache entries instead of sharing one, making the bounded\n// eviction limits (MAX_*_CACHE_SIZE) less effective than they look. This\n// doesn't change any cache's *correctness* (each entry is still built from\n// -- and valid for -- whatever locale string produced it), only how many\n// distinct entries equivalent spellings end up costing. Falls back to the\n// original string on a malformed/unrecognized tag rather than throwing —\n// cache-key normalization shouldn't be where a bad locale first surfaces\n// as an error; whatever actually calls `new Intl.DateTimeFormat(locale)`\n// downstream is the right place for that.\n// Intl constructors (DateTimeFormat/NumberFormat/RelativeTimeFormat)\n// reject underscore-separated tags like 'en_US' outright, while\n// canonicalCacheKey and every locale-parsing path in this library\n// tolerates them by normalizing to BCP-47 hyphens. Centralize that\n// normalization so every `new Intl.*(locale)` construction site\n// accepts the same spellings the cache keys do. Genuinely malformed\n// tags still throw downstream, unchanged.\nexport function normalizeLocaleTag(locale: string): string {\n return locale.replace(/_/g, '-');\n}\n\n// Memoized so hot paths (parse()'s resolveCalendar keys off this on\n// every call, and every locale-keyed cache re-derives it) don't build a\n// fresh Intl.Locale per invocation — construction is comparatively\n// expensive. Bounded like every other cache in this library.\nconst canonicalKeyCache = new Map<string, string>();\nconst MAX_CANONICAL_KEY_CACHE = 500;\n\nexport function canonicalCacheKey(locale: string): string {\n const hit = canonicalKeyCache.get(locale);\n if (hit !== undefined) return hit;\n let key: string;\n try {\n // Intl.Locale requires BCP-47 hyphens and rejects underscore-separated\n // tags like 'en_US' outright (RangeError), rather than normalizing\n // them — so without this replace, that spelling would just fall\n // through to the catch below and never fold with 'en-US'.\n key = new Intl.Locale(locale.replace(/_/g, '-')).toString().toLowerCase();\n } catch {\n // Malformed tag: key on the raw string. Callers that must reject\n // malformed tags do it via assertValidLocaleTag() before/instead of\n // relying on this function — cache-key normalization isn't where a\n // bad locale should surface as an error (unchanged behavior).\n key = locale;\n }\n if (canonicalKeyCache.size >= MAX_CANONICAL_KEY_CACHE) {\n const oldestKey = canonicalKeyCache.keys().next().value;\n if (oldestKey !== undefined) canonicalKeyCache.delete(oldestKey);\n }\n canonicalKeyCache.set(locale, key);\n return key;\n}\n\n// Single validation choke point for locale tags at public boundaries.\n// Intl constructors reject malformed tags with a bare engine RangeError\n// (\"Incorrect locale information provided\") that carries none of the\n// library's structured error context; this rethrows as the typed\n// InvalidLocaleError with the offending tag in its fields. Accepts the\n// same spellings as canonicalCacheKey (underscore tags normalized).\nexport function assertValidLocaleTag(locale: string): void {\n try {\n new Intl.Locale(normalizeLocaleTag(locale));\n } catch {\n throw new InvalidLocaleError({\n actual: locale,\n reason: 'not a valid BCP-47 locale tag',\n });\n }\n}\n\nconst vocabCache = new Map<string, LocaleVocab>();\nconst MAX_VOCAB_CACHE_SIZE = 500;\n\n// Some locales (ja-JP) split a field across two parts — month \"8\" plus a\n// counter suffix \"月\" as a separate sibling \"literal\" — while format()'s\n// tokens go through toLocaleString(), which concatenates everything into\n// \"8月\". Reading only the type-tagged part used to drop that suffix, so\n// this locale's vocab never matched what format() actually produced.\n// Only merges *adjacent* literals, not the whole string, since the\n// dayPeriod/weekday formatters below carry an extra hour part that a\n// join-everything approach would wrongly absorb.\nfunction partValue(formatter: Intl.DateTimeFormat, date: Date, type: Intl.DateTimeFormatPartTypes): string {\n const parts = formatter.formatToParts(date);\n const index = parts.findIndex((p) => p.type === type);\n /* c8 ignore start @preserve -- defensive guard against a real but\n unreproducible failure mode: an Intl implementation that omits the\n requested part type entirely for some locale. Checked every locale\n with unusual dayPeriod/weekday/month rendering available in this\n runtime's ICU data (ja-JP, zh-CN, th-TH, he-IL, ar-SA, ko-KR, fa-IR)\n against the exact formatter options getLocaleVocab uses (notably\n hour12: true for the dayPeriod formatter, which is what makes every\n locale here actually emit a dayPeriod part — omitting it is what\n produced a false \"gap\" during investigation). None omit their part\n on this runtime. A different ICU version or a non-Node Intl\n implementation could plausibly behave differently, so this stays a\n real check rather than an assertion. */\n /* c8 ignore start @preserve */\n if (index === -1) {\n throw new InvalidLocaleError({\n message: `temporal-fmt: locale produced no \"${type}\" part while building match vocabulary.`,\n });\n }\n /* c8 ignore stop @preserve */\n let value = parts[index]!.value;\n const prev = parts[index - 1];\n const next = parts[index + 1];\n // skip whitespace literals (the separator before \"AM\") — only a\n // no-space suffix like ja-JP's \"月\" should get folded in\n if (prev?.type === 'literal' && !/\\s/.test(prev.value)) value = prev.value + value;\n if (next?.type === 'literal' && !/\\s/.test(next.value)) value = value + next.value;\n return value;\n}\n\n// Two entries rendering identically means parse()'s reverse lookup\n// (indexOf) can never tell them apart. Weekday collisions already surface\n// via parse()'s dayOfWeek cross-check, but with a confusing same-string\n// error; months have no equivalent cross-check, so a collision there would\n// otherwise resolve silently to the wrong month. Catching both here, once\n// at build time, gives one clear error instead.\nfunction assertNoCollision(names: string[], label: string, locale: string): void {\n const seen = new Map<string, number>();\n for (let i = 0; i < names.length; i++) {\n const prior = seen.get(names[i]!);\n if (prior !== undefined) {\n // Not migrated to a typed error: this function is shared between\n // getLocaleVocab's Intl-derived path (data-path error, would be a\n // good InvalidLocaleError candidate) and assertValidVocab's\n // registration-time check (out of scope for this pass — see the\n // localeVocab.ts registration-error follow-up). Splitting this into\n // two near-duplicate functions just to route error types\n // differently isn't worth it for one throw; revisit together with\n // the registration-error work instead.\n throw new Error(\n `temporal-fmt: locale \"${locale}\" renders ${label} index ${prior} and ${i} identically ` +\n `(\"${names[i]}\"). parse() can't reliably tell these apart for this locale/token, so this ` +\n `combination isn't supported.`\n );\n }\n seen.set(names[i]!, i);\n }\n}\n\n// Exposed for tokens.ts: when a custom vocab is registered for this\n// locale, format()'s locale-aware tokens (MMMM/MMM/EEEE/EEE/a) read\n// straight from the registered array instead of going through\n// Intl.DateTimeFormat. Without this override, format() would silently\n// keep producing Intl's strings while parse() matched against the\n// registered vocab — the two would round-trip-fail.\nexport function getCustomVocab(locale: string): LocaleVocab | undefined {\n const cacheKey = canonicalCacheKey(locale);\n return customVocabs.get(cacheKey);\n}\n\nexport function getLocaleVocab(locale: string): LocaleVocab {\n // Validate before building vocab: a malformed tag used to surface as a\n // raw RangeError from the first new Intl.DateTimeFormat below.\n assertValidLocaleTag(locale);\n const cacheKey = canonicalCacheKey(locale);\n // Registered vocabs take precedence over the Intl-derived one — this\n // is the override mechanism registerLocaleVocab() promises. Checking\n // here, before the Intl cache lookup, means a registration that\n // happens *after* the first Intl-derived vocab was built still takes\n // effect on the next call.\n const custom = customVocabs.get(cacheKey);\n if (custom) {\n return custom;\n }\n const cached = vocabCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const intlLocale = normalizeLocaleTag(locale);\n const monthLongFmt = new Intl.DateTimeFormat(intlLocale, { month: 'long', timeZone: 'UTC' });\n const monthShortFmt = new Intl.DateTimeFormat(intlLocale, { month: 'short', timeZone: 'UTC' });\n const monthLong: string[] = [];\n const monthShort: string[] = [];\n for (let m = 0; m < 12; m++) {\n const date = new Date(Date.UTC(2020, m, 1));\n monthLong.push(partValue(monthLongFmt, date, 'month'));\n monthShort.push(partValue(monthShortFmt, date, 'month'));\n }\n assertNoCollision(monthLong, 'MMMM month', locale);\n assertNoCollision(monthShort, 'MMM month', locale);\n\n const weekdayLongFmt = new Intl.DateTimeFormat(intlLocale, { weekday: 'long', timeZone: 'UTC' });\n const weekdayShortFmt = new Intl.DateTimeFormat(intlLocale, { weekday: 'short', timeZone: 'UTC' });\n const weekdayLong: string[] = [];\n const weekdayShort: string[] = [];\n // 2024-01-01 is a Monday (UTC) — walk 7 days from there for weekday names\n for (let d = 0; d < 7; d++) {\n const date = new Date(Date.UTC(2024, 0, 1 + d));\n weekdayLong.push(partValue(weekdayLongFmt, date, 'weekday'));\n weekdayShort.push(partValue(weekdayShortFmt, date, 'weekday'));\n }\n // redundant with parse()'s dayOfWeek cross-check, but gives a clearer error\n assertNoCollision(weekdayLong, 'EEEE weekday', locale);\n assertNoCollision(weekdayShort, 'EEE weekday', locale);\n\n const dayPeriodFmt = new Intl.DateTimeFormat(intlLocale, { hour: 'numeric', hour12: true, timeZone: 'UTC' });\n const am = partValue(dayPeriodFmt, new Date(Date.UTC(2020, 0, 1, 1)), 'dayPeriod');\n const pm = partValue(dayPeriodFmt, new Date(Date.UTC(2020, 0, 1, 13)), 'dayPeriod');\n const dayPeriod = [...new Set([am, pm])];\n\n const vocab: LocaleVocab = { monthLong, monthShort, weekdayLong, weekdayShort, dayPeriod };\n if (vocabCache.size >= MAX_VOCAB_CACHE_SIZE) {\n const oldestKey = vocabCache.keys().next().value;\n if (oldestKey !== undefined) vocabCache.delete(oldestKey);\n }\n vocabCache.set(cacheKey, vocab);\n return vocab;\n}"],"mappings":"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","names":["localeRegistry_exports","__export","getLocale","hasLocale","registerLocale","__toCommonJS","TemporalFmtError","message","fields","capture","InvalidLocaleError","TemporalFmtError","fields","message","rest","customVocabs","MAX_CUSTOM_VOCABS","MAX_LOCALE_TAG_LENGTH","MAX_VOCAB_ENTRY_LENGTH","assertValidVocab","vocab","locale","required","key","length","label","value","entry","i","assertNoCollision","onVocabChanged","registerLocaleVocab","locale","vocab","MAX_LOCALE_TAG_LENGTH","assertValidVocab","cacheKey","canonicalCacheKey","customVocabs","MAX_CUSTOM_VOCABS","vocabCache","listener","onVocabChanged","normalizeLocaleTag","canonicalKeyCache","MAX_CANONICAL_KEY_CACHE","hit","key","oldestKey","assertValidLocaleTag","InvalidLocaleError","MAX_VOCAB_CACHE_SIZE","partValue","formatter","date","type","parts","index","p","value","prev","next","assertNoCollision","names","label","seen","i","prior","getLocaleVocab","locale","assertValidLocaleTag","cacheKey","canonicalCacheKey","custom","customVocabs","cached","vocabCache","intlLocale","normalizeLocaleTag","monthLongFmt","monthShortFmt","monthLong","monthShort","date","partValue","assertNoCollision","weekdayLongFmt","weekdayShortFmt","weekdayLong","weekdayShort","d","dayPeriodFmt","am","pm","dayPeriod","vocab","MAX_VOCAB_CACHE_SIZE","oldestKey","extendedVocabs","MAX_LOCALE_TAG_LENGTH","MAX_VOCAB_STRING_LENGTH","canonicalKey","locale","registerLocale","vocab","InvalidLocaleError","registerLocaleVocab","validateExtended","key","checkArray","val","length","i","getLocale","ext","getLocaleVocab","hasLocale"]}
1
+ {"version":3,"sources":["../src/localeRegistry.ts","../src/errors.ts","../src/localeVocab.ts"],"sourcesContent":["// locale registration + lookup. builds on the registerLocaleVocab()\n// stuff already in localeVocab.ts, adds registerLocale() / getLocale() /\n// hasLocale() plus a beefier LocaleVocab that covers quarters, eras,\n// ordinals, duration units, and relative-time words.\n//\n// localeVocab.ts itself is unchanged and still handles months/weekdays/\n// day-periods (what tokens.ts reads for MMMM/MMM/EEEE/EEE/a). this module\n// just wraps that and bolts the extra fields on top\n\nimport { registerLocaleVocab, getLocaleVocab, type LocaleVocab as BaseLocaleVocab } from './localeVocab.js';\nimport { InvalidLocaleError } from './errors.js';\n\nexport interface ExtendedLocaleVocab extends BaseLocaleVocab {\n // Q1-Q4 long form (\"First quarter\" etc). falls back to \"Q1\"..\"Q4\" if\n // nothing's registered\n quartersLong?: string[];\n quartersShort?: string[];\n // like [\"BC\", \"AD\"] for gregory. defaults to [\"BC\", \"AD\"]\n erasLong?: string[];\n erasShort?: string[];\n // suffixes like [\"st\", \"nd\", \"rd\", \"th\"] for English. empty by default —\n // the 'do' token already has English ordinal logic hardcoded in\n // tokens.ts, this just lets a custom locale override that\n ordinals?: string[];\n // long singular/plural names per unit. used by formatDuration's\n // locale-aware path for cases where Intl.NumberFormat won't cut it,\n // like a made-up locale Intl's never heard of\n durationUnits?: {\n years: [string, string];\n months: [string, string];\n weeks: [string, string];\n days: [string, string];\n hours: [string, string];\n minutes: [string, string];\n seconds: [string, string];\n milliseconds: [string, string];\n };\n // words for \"ago\" / \"in\" / \"now\". used by formatRelative()'s\n // locale-aware path when Intl.RelativeTimeFormat isn't around or\n // doesn't know about a locale someone registered\n relativeTime?: {\n past: string;\n future: string;\n now: string;\n };\n}\n\n// bounded indirectly — everything added here goes through registerLocale(),\n// which calls registerLocaleVocab() first, and THAT registry already caps\n// out at 500 new locales (MAX_CUSTOM_VOCABS, throws RangeError past it).\n// so extendedVocabs can never actually exceed 500 keys, no need for a\n// separate cap here (would just be dead code anyway)\nconst extendedVocabs = new Map<string, ExtendedLocaleVocab>();\nconst MAX_LOCALE_TAG_LENGTH = 256;\nconst MAX_VOCAB_STRING_LENGTH = 256;\n\nfunction canonicalKey(locale: string): string {\n try {\n return new Intl.Locale(locale.replace(/_/g, '-')).toString().toLowerCase();\n } catch {\n return locale;\n }\n}\n\nexport function registerLocale(locale: string, vocab: ExtendedLocaleVocab): void {\n if (typeof locale !== 'string' || locale.length === 0) {\n throw new InvalidLocaleError({ actual: String(locale), reason: 'locale string must be non-empty' });\n }\n if (locale.length > MAX_LOCALE_TAG_LENGTH) {\n throw new InvalidLocaleError({ actual: String(locale.length), reason: `locale tag must be at most ${MAX_LOCALE_TAG_LENGTH} characters` });\n }\n // base vocab fields (months/weekdays/day-periods) get validated by\n // registerLocaleVocab already, it's got the strict shape checks\n registerLocaleVocab(locale, vocab);\n // extended fields are all optional, only check the ones actually there\n validateExtended(vocab, locale);\n const key = canonicalKey(locale);\n extendedVocabs.set(key, { ...vocab });\n}\n\nfunction validateExtended(vocab: ExtendedLocaleVocab, locale: string): void {\n const checkArray = (val: unknown, key: string, length: number) => {\n if (val === undefined) return;\n if (!Array.isArray(val)) {\n throw new InvalidLocaleError({ actual: String(val), reason: `locale \"${locale}\": \"${key}\" must be an array` });\n }\n if (val.length !== length) {\n throw new InvalidLocaleError({ actual: String(val.length), reason: `locale \"${locale}\": \"${key}\" must have ${length} entries (got ${val.length})` });\n }\n for (let i = 0; i < val.length; i++) {\n if (typeof val[i] !== 'string' || val[i]!.length === 0) {\n throw new InvalidLocaleError({ actual: String(val[i]), reason: `locale \"${locale}\": \"${key}[${i}]\" must be a non-empty string` });\n }\n if (val[i]!.length > MAX_VOCAB_STRING_LENGTH) {\n throw new InvalidLocaleError({ actual: String(val[i]!.length), reason: `locale \"${locale}\": \"${key}[${i}]\" must be at most ${MAX_VOCAB_STRING_LENGTH} characters` });\n }\n }\n };\n checkArray(vocab.quartersLong, 'quartersLong', 4);\n checkArray(vocab.quartersShort, 'quartersShort', 4);\n checkArray(vocab.erasLong, 'erasLong', 2);\n checkArray(vocab.erasShort, 'erasShort', 2);\n checkArray(vocab.ordinals, 'ordinals', 4);\n}\n\nexport function getLocale(locale: string): ExtendedLocaleVocab | undefined {\n // gives back the extended vocab for a locale, or undefined if there's\n // nothing (falls back to Intl at that point). combines the base vocab\n // (from localeVocab.ts, Intl-derived) with whatever extended fields\n // got registered here\n const key = canonicalKey(locale);\n const ext = extendedVocabs.get(key);\n if (ext) return ext;\n // nothing extended registered — just fall back to the base Intl vocab\n try {\n const base = getLocaleVocab(locale);\n return { ...base };\n } catch {\n return undefined;\n }\n}\n\nexport function hasLocale(locale: string): boolean {\n const key = canonicalKey(locale);\n return extendedVocabs.has(key);\n}\n\n// re-exporting the base vocab types in case anyone wants them\nexport type { LocaleVocab } from './localeVocab.js';\n","// structured error classes for parse()/format() failures.\n//\n// as of 0.9.0 every throw site on the parse/format data path —\n// tokenize.ts, pattern.ts, format.ts, parse.ts (parse/safeParse/tryParse/\n// parseToParts/compileParser), plus the two data-path throws in\n// localeVocab.ts (partValue/assertNoCollision on the getLocaleVocab side)\n// — throws one of these typed classes directly instead of a plain\n// `new Error(message)`. every site we migrated kept its exact pre-0.9.0\n// message text, and since subclasses of TemporalFmtError still pass\n// `instanceof Error` and match the same message regexes (e.g.\n// `/token \"HH\" requires/`), this didn't need a semver-major bump for\n// either of those checks. what DOES break in 0.9.0: if anyone was\n// specifically checking `err.constructor === Error` or `err.name ===\n// 'Error'`, that'll now see a different name (e.g. 'FormatSyntaxError').\n// noted in the 0.9.0 changelog.\n//\n// deliberately did NOT migrate:\n// - localeVocab.ts's registration-time throws (assertValidVocab,\n// registerLocaleVocab itself) — these are config-time API-misuse\n// errors on data a developer hands in once at startup, not runtime\n// parse/format failures, so they don't really fit this module's\n// TemporalFmtErrorCode taxonomy as-is. assertNoCollision is shared\n// between the registration path and the data path (getLocaleVocab)\n// though, so its throw stays a plain Error for both until that gets\n// split apart — see the tracking note where it's called.\n//\n// wrapUntypedError() below is still around for localeVocab.ts's\n// registration throws, and for anything a caller passes into\n// safeParse()/tryParse() from outside this package. on the data path\n// itself, safeParse's `if (err instanceof TemporalFmtError) return { ok:\n// false, error: err }` catches everything before it'd even reach the\n// classifier here, so honestly the regex branches below are dead for\n// parse/format/tokenize/pattern at this point — kept as the fallback for\n// whatever hasn't been migrated to a typed throw site yet\n\nexport type TemporalFmtErrorCode =\n | 'FORMAT_SYNTAX_ERROR'\n | 'UNKNOWN_TOKEN'\n | 'PARSE_MISMATCH'\n | 'INVALID_DATE'\n | 'INVALID_TIME'\n | 'INVALID_OFFSET'\n | 'INVALID_TIME_ZONE'\n | 'INVALID_CALENDAR'\n | 'AMBIGUOUS_INPUT'\n | 'INVALID_LOCALE'\n | 'INVALID_DURATION';\n\nexport interface TemporalFmtErrorFields {\n code: TemporalFmtErrorCode;\n input?: string;\n format?: string;\n token?: string;\n position?: number;\n expected?: string;\n actual?: string;\n reason?: string;\n}\n\n// base class. `message` is the human-readable summary, the structured\n// fields are the machine-readable bits a linter or codemod would report\n// on. calling Error.captureStackTrace manually (where it exists) so the\n// stack points at wherever this got thrown from, not at this constructor\n// — same trick Node uses for its own error classes\nexport class TemporalFmtError extends Error {\n readonly code: TemporalFmtErrorCode;\n readonly input?: string;\n readonly format?: string;\n readonly token?: string;\n readonly position?: number;\n readonly expected?: string;\n readonly actual?: string;\n readonly reason?: string;\n\n constructor(message: string, fields: TemporalFmtErrorFields) {\n super(message);\n this.name = 'TemporalFmtError';\n this.code = fields.code;\n this.input = fields.input;\n this.format = fields.format;\n this.token = fields.token;\n this.position = fields.position;\n this.expected = fields.expected;\n this.actual = fields.actual;\n this.reason = fields.reason;\n // don't want the stack pointing at this constructor line — captureStackTrace\n // is V8-only though, so on other engines callers just get the default\n // stack (pointing here) since there's nothing better to do about it\n const capture = (Error as unknown as { captureStackTrace?: (target: Error, ctor?: Function) => void }).captureStackTrace;\n if (typeof capture === 'function') {\n capture(this, this.constructor);\n }\n }\n\n // lets callers just call err.toJSON() for logging. plain Error doesn't\n // serialize its non-enumerable fields on its own, so this picks them\n // up explicitly\n toJSON(): TemporalFmtErrorFields & { name: string; message: string } {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n input: this.input,\n format: this.format,\n token: this.token,\n position: this.position,\n expected: this.expected,\n actual: this.actual,\n reason: this.reason,\n };\n }\n}\n\n// each subclass just fixes `code` so callers can switch on it without\n// having to re-check message text. the constructor only takes the\n// fields that actually vary per call; `code` and the default message\n// template come from the subclass itself\n\nexport class FormatSyntaxError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `format string \"${fields.format ?? ''}\" has a syntax error${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'FORMAT_SYNTAX_ERROR', ...rest },\n );\n this.name = 'FormatSyntaxError';\n }\n}\n\nexport class UnknownTokenError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `token \"${fields.token ?? ''}\" is not a recognized temporal-fmt token${fields.format ? ` in format string \"${fields.format}\"` : ''}.`,\n { code: 'UNKNOWN_TOKEN', ...rest },\n );\n this.name = 'UnknownTokenError';\n }\n}\n\nexport class ParseMismatchError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" does not match format \"${fields.format ?? ''}\"${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'PARSE_MISMATCH', ...rest },\n );\n this.name = 'ParseMismatchError';\n }\n}\n\nexport class InvalidDateError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" does not describe a valid date${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_DATE', ...rest },\n );\n this.name = 'InvalidDateError';\n }\n}\n\n/* c8 ignore start @preserve -- InvalidTimeError is part of the public\n error-class surface (exported from index.ts, code 'INVALID_TIME') but\n nothing in this package actually constructs one. went and checked\n whether it could get wired in the same way InvalidTimeZoneError just\n was (see parse.ts's zzz-validation loop) — does hour/minute/second have\n a post-match semantic range check the way zone ids do? nope.\n pattern.ts's regex fragments for HH/H/hh/h/mm/m/ss/s already enforce\n their valid ranges right at the regex level (e.g. HH is\n '(?:[01]\\d|2[0-3])', which literally can't match \"99\"), so an\n out-of-range time just gets rejected as a plain shape mismatch before\n any semantic check would even run. no live gap to hook this into\n without inventing a redundant check purely to give this class a body.\n leaving it unconstructed until the library actually hits a real\n invalid-time case worth reporting */\nexport class InvalidTimeError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" does not describe a valid time${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_TIME', ...rest },\n );\n this.name = 'InvalidTimeError';\n }\n}\n/* c8 ignore stop @preserve */\n\nexport class InvalidOffsetError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `offset \"${fields.actual ?? ''}\" is invalid${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_OFFSET', ...rest },\n );\n this.name = 'InvalidOffsetError';\n }\n}\n\nexport class InvalidTimeZoneError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `time zone \"${fields.actual ?? ''}\" is not a recognized IANA time zone or fixed offset${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_TIME_ZONE', ...rest },\n );\n this.name = 'InvalidTimeZoneError';\n }\n}\n\n/* c8 ignore start @preserve -- InvalidCalendarError is part of the\n public error-class surface (exported from index.ts, code\n 'INVALID_CALENDAR') but same story as InvalidTimeError above — nothing\n in this package constructs one. checked for a wiring opportunity the\n same way: there's no user-supplied calendar identifier anywhere in the\n library that we'd validate against a supported list. resolveCalendar()\n in parse.ts derives the calendar entirely from Intl's own resolution\n of the locale string — it's never handed an arbitrary \"calendar\" value\n a caller could actually get wrong. no live input to reject here.\n leaving it unconstructed until the library accepts an actual calendar\n parameter that could be invalid */\nexport class InvalidCalendarError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `calendar \"${fields.actual ?? ''}\" is not supported${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_CALENDAR', ...rest },\n );\n this.name = 'InvalidCalendarError';\n }\n}\n/* c8 ignore stop @preserve */\n\nexport class AmbiguousInputError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `input \"${fields.input ?? ''}\" is ambiguous${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'AMBIGUOUS_INPUT', ...rest },\n );\n this.name = 'AmbiguousInputError';\n }\n}\n\nexport class InvalidLocaleError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `locale \"${fields.actual ?? ''}\" is not a valid BCP-47 tag${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_LOCALE', ...rest },\n );\n this.name = 'InvalidLocaleError';\n }\n}\n\nexport class InvalidDurationError extends TemporalFmtError {\n constructor(fields: Omit<TemporalFmtErrorFields, 'code'> & { message?: string }) {\n const { message, ...rest } = fields;\n super(\n message ?? `duration is invalid${fields.reason ? `: ${fields.reason}` : ''}.`,\n { code: 'INVALID_DURATION', ...rest },\n );\n this.name = 'InvalidDurationError';\n }\n}\n\n// wraps a plain Error thrown from a code path that hasn't been migrated\n// to typed errors yet. keeps the original message around in `reason` so\n// callers reading the typed surface still see what actually failed.\n// used by safeParse() in parse.ts.\n//\n// after the 0.9.0 migration, every throw site on the parse/format data\n// path throws a TemporalFmtError directly, so safeParse's `instanceof\n// TemporalFmtError` check always passes before this function would even\n// get called — nothing in the current test suite actually reaches any\n// branch below. kept as the safety net for whenever someone adds an\n// unmigrated throw site down the line (see the c8-ignored call in\n// parse.ts's safeParse) — same reasoning as that call site: removing\n// this would silently break the \"safeParse always returns a\n// TemporalFmtError\" contract the moment anyone adds a bare\n// `throw new Error(...)` without wiring up a typed class for it\n/* c8 ignore start @preserve -- unreachable from the current test suite,\n see rationale above */\nexport function wrapUntypedError(err: Error, context: { input?: string; format?: string }): TemporalFmtError {\n // try to classify by looking at the message — covers the existing\n // parse()/format() throw sites without having to touch them. anything\n // that doesn't match a known pattern falls through to a generic\n // ParseMismatchError, still with the structured fields intact\n const msg = err.message;\n if (/unknown token|isn't a recognized token/.test(msg)) {\n return new UnknownTokenError({ input: context.input, format: context.format, reason: msg });\n }\n if (/ambiguous/i.test(msg)) {\n return new AmbiguousInputError({ input: context.input, format: context.format, reason: msg });\n }\n if (/offset/.test(msg) && /out of range|exceeds|doesn't match the shape/i.test(msg)) {\n return new InvalidOffsetError({ input: context.input, format: context.format, reason: msg });\n }\n if (/no valid pattern matches/i.test(msg)) {\n return new ParseMismatchError({ input: context.input, format: context.format, reason: msg });\n }\n if (/doesn't describe a valid date\\/time|incomplete date|weekday token|quarter token/.test(msg)) {\n return new InvalidDateError({ input: context.input, format: context.format, reason: msg });\n }\n const lowerMsg = msg.toLowerCase();\n const mentionsLocale = lowerMsg.includes('locale');\n if (\n (mentionsLocale && (lowerMsg.includes('produced no') || lowerMsg.includes('not a valid'))) ||\n lowerMsg.includes('cutoffs must be')\n ) {\n return new InvalidLocaleError({ input: context.input, format: context.format, reason: msg });\n }\n if (/format string exceeds maximum length|input exceeds maximum length|unterminated quote|isn't a recognized token/i.test(msg)) {\n return new FormatSyntaxError({ input: context.input, format: context.format, reason: msg });\n }\n return new ParseMismatchError({ input: context.input, format: context.format, reason: msg });\n}\n/* c8 ignore stop @preserve */","// Name lists for the locale-aware tokens (MMMM, MMM, EEEE, EEE, a). Each\n// list is small and fixed (12 months, 7 weekdays, 2 day periods), so we\n// generate the real Intl strings for a locale once and cache them.\n\nimport { InvalidLocaleError } from './errors.js';\n\nexport interface LocaleVocab {\n monthLong: string[]; // index 0 = January\n monthShort: string[];\n weekdayLong: string[]; // index 0 = Monday, per Temporal's dayOfWeek numbering\n weekdayShort: string[];\n dayPeriod: string[]; // typically [AM-ish, PM-ish], deduped\n}\n\n// Custom vocabs registered by callers for locales Intl doesn't cover well\n// (e.g. a 13-month Hebrew leap year, where Intl's 12-month vocabulary\n// silently loses a whole month). Keyed by canonical cache key so the\n// same locale string spelling variants fold together — same convention\n// as the Intl-derived vocab cache above.\nconst customVocabs = new Map<string, LocaleVocab>();\nconst MAX_CUSTOM_VOCABS = 500;\nconst MAX_LOCALE_TAG_LENGTH = 256;\nconst MAX_VOCAB_ENTRY_LENGTH = 256;\n\nfunction assertValidVocab(vocab: Partial<LocaleVocab>, locale: string): void {\n // Strict shape validation at registration time, not lazily on first\n // use — the README's promise is that a malformed registration throws\n // descriptively here, rather than failing later inside format()/parse()\n // with a confusing \"no month part\" or wrong-month error the caller\n // can't trace back to the bad registration.\n const required: Array<{ key: keyof LocaleVocab; length: number; label: string }> = [\n { key: 'monthLong', length: 12, label: 'long month names' },\n { key: 'monthShort', length: 12, label: 'short month names' },\n { key: 'weekdayLong', length: 7, label: 'long weekday names' },\n { key: 'weekdayShort', length: 7, label: 'short weekday names' },\n { key: 'dayPeriod', length: 2, label: 'day period markers (AM/PM-equivalent)' },\n ];\n\n for (const { key, length, label } of required) {\n const value = vocab[key];\n if (value === undefined) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\" is missing required field \"${key}\" (${label}).`\n );\n }\n if (!Array.isArray(value)) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}\" must be an array, got ${typeof value}.`\n );\n }\n if (value.length !== length) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}\" must have exactly ${length} entries (got ${value.length}) — ${label}.`\n );\n }\n value.forEach((entry, i) => {\n if (typeof entry !== 'string' || entry.length === 0) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}[${i}]\" must be a non-empty string, got ${String(entry)}.`\n );\n }\n if (entry.length > MAX_VOCAB_ENTRY_LENGTH) {\n throw new RangeError(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": \"${key}[${i}]\" is too long (maximum ${MAX_VOCAB_ENTRY_LENGTH} characters).`\n );\n }\n });\n }\n\n // Reuse the same collision check the Intl-derived path uses — a\n // duplicate month name is just as ambiguous when supplied by a caller\n // as when produced by Intl.\n assertNoCollision(vocab.monthLong!, 'MMMM month', locale);\n assertNoCollision(vocab.monthShort!, 'MMM month', locale);\n assertNoCollision(vocab.weekdayLong!, 'EEEE weekday', locale);\n assertNoCollision(vocab.weekdayShort!, 'EEE weekday', locale);\n\n // dayPeriod entries must differ from each other, or parse()'s\n // isPM check (raw === vocab.dayPeriod[1]) can never return true and\n // every 12-hour parse silently resolves to AM. The Intl-derived path\n // dedupes a same-AM/PM collision to length 1, but a caller passing\n // both entries identical is a real bug to surface — not something to\n // dedupe around.\n if (vocab.dayPeriod![0] === vocab.dayPeriod![1]) {\n throw new Error(\n `temporal-fmt: registerLocaleVocab for locale \"${locale}\": dayPeriod entries must differ ` +\n `(both are \"${vocab.dayPeriod![0]}\"); otherwise parse() can't tell AM from PM.`\n );\n }\n}\n\n// Anything that caches a result derived from *which* vocabulary is\n// active for a locale (right now: parse.ts's compiled pattern cache,\n// whose MMMM/MMM/EEEE/EEE/a fragments embed the vocab's alternations)\n// subscribes here so it gets invalidated when a registration swaps the\n// vocab — mirrors temporalProvider.ts's subscribeToTemporalChanges.\nconst onVocabChanged: Array<() => void> = [];\n\nexport function subscribeToVocabChanges(listener: () => void): void {\n onVocabChanged.push(listener);\n}\n\n/**\n * Supply a custom month/weekday/day-period vocabulary for a locale key,\n * overriding the Intl-derived vocab this library would otherwise build\n * for that key. Useful for locales Intl doesn't cover well — the README's\n * known-limitations section calls out the Hebrew leap-month gap as a\n * specific case this addresses.\n *\n * Throws descriptively on malformed input (wrong array lengths, empty\n * strings, duplicate entries, missing fields) rather than failing later\n * during format/parse.\n *\n * Registered vocab takes precedence over the Intl-derived vocab for that\n * locale key, including for already-cached entries — registering\n * invalidates the prior cache entry for that locale so the next call\n * picks up the new vocab.\n *\n * @example\n * registerLocaleVocab('en-u-ca-hebrew-leap', {\n * monthLong: ['Nisan','Iyar','Sivan','Tammuz','Av','Elul','Tishrei','Marcheshvan','Kislev','Tevet','Shevat','Adar I','Adar II'],\n * monthShort: ['Nis','Iyy','Siv','Tam','Av','Elu','Tish','Chesh','Kis','Tev','Shv','Ad1','Ad2'],\n * weekdayLong: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],\n * weekdayShort: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],\n * dayPeriod: ['AM','PM'],\n * });\n */\nexport function registerLocaleVocab(locale: string, vocab: Partial<LocaleVocab>): void {\n if (typeof locale !== 'string' || locale.length === 0) {\n throw new Error(`temporal-fmt: registerLocaleVocab requires a non-empty locale string, got ${String(locale)}.`);\n }\n if (locale.length > MAX_LOCALE_TAG_LENGTH) {\n throw new RangeError(`temporal-fmt: registerLocaleVocab locale is too long (maximum ${MAX_LOCALE_TAG_LENGTH} characters).`);\n }\n assertValidVocab(vocab, locale);\n\n const cacheKey = canonicalCacheKey(locale);\n if (!customVocabs.has(cacheKey) && customVocabs.size >= MAX_CUSTOM_VOCABS) {\n throw new RangeError(`temporal-fmt: registerLocaleVocab reached the ${MAX_CUSTOM_VOCABS}-locale limit.`);\n }\n customVocabs.set(cacheKey, {\n monthLong: [...vocab.monthLong!],\n monthShort: [...vocab.monthShort!],\n weekdayLong: [...vocab.weekdayLong!],\n weekdayShort: [...vocab.weekdayShort!],\n dayPeriod: [...vocab.dayPeriod!],\n });\n // Invalidate the Intl-derived cache entry so any prior format/parse\n // result cached for this locale is rebuilt against the new vocab. Not\n // strictly necessary (getLocaleVocab checks customVocabs first), but\n // cheap and keeps the two caches from drifting out of sync.\n vocabCache.delete(cacheKey);\n // Also invalidate downstream caches that baked the previous vocab in\n // at build time (parse.ts's pattern cache is the one that matters:\n // without this, a cached pattern would keep matching the OLD month /\n // weekday names while format() renders the new ones, so the library's\n // own format() output would fail to parse back).\n for (const listener of onVocabChanged) listener();\n}\n\n// Every locale-keyed cache in this library (this one, formatterCache in\n// tokens.ts, patternCache/calendarCache in parse.ts) used to key on the\n// exact locale string a caller passed in. Intl treats spelling variants of\n// the same locale as equivalent ('en-US' / 'en-us' / 'en_US' all resolve\n// the same way), but a plain string-keyed Map doesn't — so callers mixing\n// spellings for what's really one locale would silently fragment across\n// separate cache entries instead of sharing one, making the bounded\n// eviction limits (MAX_*_CACHE_SIZE) less effective than they look. This\n// doesn't change any cache's *correctness* (each entry is still built from\n// -- and valid for -- whatever locale string produced it), only how many\n// distinct entries equivalent spellings end up costing. Falls back to the\n// original string on a malformed/unrecognized tag rather than throwing —\n// cache-key normalization shouldn't be where a bad locale first surfaces\n// as an error; whatever actually calls `new Intl.DateTimeFormat(locale)`\n// downstream is the right place for that.\n// Intl constructors (DateTimeFormat/NumberFormat/RelativeTimeFormat)\n// reject underscore-separated tags like 'en_US' outright, while\n// canonicalCacheKey and every locale-parsing path in this library\n// tolerates them by normalizing to BCP-47 hyphens. Centralize that\n// normalization so every `new Intl.*(locale)` construction site\n// accepts the same spellings the cache keys do. Genuinely malformed\n// tags still throw downstream, unchanged.\nexport function normalizeLocaleTag(locale: string): string {\n return locale.replace(/_/g, '-');\n}\n\n// Memoized so hot paths (parse()'s resolveCalendar keys off this on\n// every call, and every locale-keyed cache re-derives it) don't build a\n// fresh Intl.Locale per invocation — construction is comparatively\n// expensive. Bounded like every other cache in this library.\nconst canonicalKeyCache = new Map<string, string>();\nconst MAX_CANONICAL_KEY_CACHE = 500;\n\nexport function canonicalCacheKey(locale: string): string {\n const hit = canonicalKeyCache.get(locale);\n if (hit !== undefined) return hit;\n let key: string;\n try {\n // Intl.Locale requires BCP-47 hyphens and rejects underscore-separated\n // tags like 'en_US' outright (RangeError), rather than normalizing\n // them — so without this replace, that spelling would just fall\n // through to the catch below and never fold with 'en-US'.\n key = new Intl.Locale(locale.replace(/_/g, '-')).toString().toLowerCase();\n } catch {\n // Malformed tag: key on the raw string. Callers that must reject\n // malformed tags do it via assertValidLocaleTag() before/instead of\n // relying on this function — cache-key normalization isn't where a\n // bad locale should surface as an error (unchanged behavior).\n key = locale;\n }\n if (canonicalKeyCache.size >= MAX_CANONICAL_KEY_CACHE) {\n const oldestKey = canonicalKeyCache.keys().next().value;\n if (oldestKey !== undefined) canonicalKeyCache.delete(oldestKey);\n }\n canonicalKeyCache.set(locale, key);\n return key;\n}\n\n// Single validation choke point for locale tags at public boundaries.\n// Intl constructors reject malformed tags with a bare engine RangeError\n// (\"Incorrect locale information provided\") that carries none of the\n// library's structured error context; this rethrows as the typed\n// InvalidLocaleError with the offending tag in its fields. Accepts the\n// same spellings as canonicalCacheKey (underscore tags normalized).\nexport function assertValidLocaleTag(locale: string): void {\n try {\n new Intl.Locale(normalizeLocaleTag(locale));\n } catch {\n throw new InvalidLocaleError({\n actual: locale,\n reason: 'not a valid BCP-47 locale tag',\n });\n }\n}\n\nconst vocabCache = new Map<string, LocaleVocab>();\nconst MAX_VOCAB_CACHE_SIZE = 500;\n\n// Some locales (ja-JP) split a field across two parts — month \"8\" plus a\n// counter suffix \"月\" as a separate sibling \"literal\" — while format()'s\n// tokens go through toLocaleString(), which concatenates everything into\n// \"8月\". Reading only the type-tagged part used to drop that suffix, so\n// this locale's vocab never matched what format() actually produced.\n// Only merges *adjacent* literals, not the whole string, since the\n// dayPeriod/weekday formatters below carry an extra hour part that a\n// join-everything approach would wrongly absorb.\nfunction partValue(formatter: Intl.DateTimeFormat, date: Date, type: Intl.DateTimeFormatPartTypes): string {\n const parts = formatter.formatToParts(date);\n const index = parts.findIndex((p) => p.type === type);\n /* c8 ignore start @preserve -- defensive guard against a real but\n unreproducible failure mode: an Intl implementation that omits the\n requested part type entirely for some locale. Checked every locale\n with unusual dayPeriod/weekday/month rendering available in this\n runtime's ICU data (ja-JP, zh-CN, th-TH, he-IL, ar-SA, ko-KR, fa-IR)\n against the exact formatter options getLocaleVocab uses (notably\n hour12: true for the dayPeriod formatter, which is what makes every\n locale here actually emit a dayPeriod part — omitting it is what\n produced a false \"gap\" during investigation). None omit their part\n on this runtime. A different ICU version or a non-Node Intl\n implementation could plausibly behave differently, so this stays a\n real check rather than an assertion. */\n /* c8 ignore start @preserve */\n if (index === -1) {\n throw new InvalidLocaleError({\n message: `temporal-fmt: locale produced no \"${type}\" part while building match vocabulary.`,\n });\n }\n /* c8 ignore stop @preserve */\n let value = parts[index]!.value;\n const prev = parts[index - 1];\n const next = parts[index + 1];\n // skip whitespace literals (the separator before \"AM\") — only a\n // no-space suffix like ja-JP's \"月\" should get folded in\n if (prev?.type === 'literal' && !/\\s/.test(prev.value)) value = prev.value + value;\n if (next?.type === 'literal' && !/\\s/.test(next.value)) value = value + next.value;\n return value;\n}\n\n// Two entries rendering identically means parse()'s reverse lookup\n// (indexOf) can never tell them apart. Weekday collisions already surface\n// via parse()'s dayOfWeek cross-check, but with a confusing same-string\n// error; months have no equivalent cross-check, so a collision there would\n// otherwise resolve silently to the wrong month. Catching both here, once\n// at build time, gives one clear error instead.\nfunction assertNoCollision(names: string[], label: string, locale: string): void {\n const seen = new Map<string, number>();\n for (let i = 0; i < names.length; i++) {\n const prior = seen.get(names[i]!);\n if (prior !== undefined) {\n // Not migrated to a typed error: this function is shared between\n // getLocaleVocab's Intl-derived path (data-path error, would be a\n // good InvalidLocaleError candidate) and assertValidVocab's\n // registration-time check (out of scope for this pass — see the\n // localeVocab.ts registration-error follow-up). Splitting this into\n // two near-duplicate functions just to route error types\n // differently isn't worth it for one throw; revisit together with\n // the registration-error work instead.\n throw new Error(\n `temporal-fmt: locale \"${locale}\" renders ${label} index ${prior} and ${i} identically ` +\n `(\"${names[i]}\"). parse() can't reliably tell these apart for this locale/token, so this ` +\n `combination isn't supported.`\n );\n }\n seen.set(names[i]!, i);\n }\n}\n\n// Exposed for tokens.ts: when a custom vocab is registered for this\n// locale, format()'s locale-aware tokens (MMMM/MMM/EEEE/EEE/a) read\n// straight from the registered array instead of going through\n// Intl.DateTimeFormat. Without this override, format() would silently\n// keep producing Intl's strings while parse() matched against the\n// registered vocab — the two would round-trip-fail.\nexport function getCustomVocab(locale: string): LocaleVocab | undefined {\n const cacheKey = canonicalCacheKey(locale);\n return customVocabs.get(cacheKey);\n}\n\nexport function getLocaleVocab(locale: string): LocaleVocab {\n // Validate before building vocab: a malformed tag used to surface as a\n // raw RangeError from the first new Intl.DateTimeFormat below.\n assertValidLocaleTag(locale);\n const cacheKey = canonicalCacheKey(locale);\n // Registered vocabs take precedence over the Intl-derived one — this\n // is the override mechanism registerLocaleVocab() promises. Checking\n // here, before the Intl cache lookup, means a registration that\n // happens *after* the first Intl-derived vocab was built still takes\n // effect on the next call.\n const custom = customVocabs.get(cacheKey);\n if (custom) {\n return custom;\n }\n const cached = vocabCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const intlLocale = normalizeLocaleTag(locale);\n const monthLongFmt = new Intl.DateTimeFormat(intlLocale, { month: 'long', timeZone: 'UTC' });\n const monthShortFmt = new Intl.DateTimeFormat(intlLocale, { month: 'short', timeZone: 'UTC' });\n const monthLong: string[] = [];\n const monthShort: string[] = [];\n for (let m = 0; m < 12; m++) {\n const date = new Date(Date.UTC(2020, m, 1));\n monthLong.push(partValue(monthLongFmt, date, 'month'));\n monthShort.push(partValue(monthShortFmt, date, 'month'));\n }\n assertNoCollision(monthLong, 'MMMM month', locale);\n assertNoCollision(monthShort, 'MMM month', locale);\n\n const weekdayLongFmt = new Intl.DateTimeFormat(intlLocale, { weekday: 'long', timeZone: 'UTC' });\n const weekdayShortFmt = new Intl.DateTimeFormat(intlLocale, { weekday: 'short', timeZone: 'UTC' });\n const weekdayLong: string[] = [];\n const weekdayShort: string[] = [];\n // 2024-01-01 is a Monday (UTC) — walk 7 days from there for weekday names\n for (let d = 0; d < 7; d++) {\n const date = new Date(Date.UTC(2024, 0, 1 + d));\n weekdayLong.push(partValue(weekdayLongFmt, date, 'weekday'));\n weekdayShort.push(partValue(weekdayShortFmt, date, 'weekday'));\n }\n // redundant with parse()'s dayOfWeek cross-check, but gives a clearer error\n assertNoCollision(weekdayLong, 'EEEE weekday', locale);\n assertNoCollision(weekdayShort, 'EEE weekday', locale);\n\n const dayPeriodFmt = new Intl.DateTimeFormat(intlLocale, { hour: 'numeric', hour12: true, timeZone: 'UTC' });\n const am = partValue(dayPeriodFmt, new Date(Date.UTC(2020, 0, 1, 1)), 'dayPeriod');\n const pm = partValue(dayPeriodFmt, new Date(Date.UTC(2020, 0, 1, 13)), 'dayPeriod');\n const dayPeriod = [...new Set([am, pm])];\n\n const vocab: LocaleVocab = { monthLong, monthShort, weekdayLong, weekdayShort, dayPeriod };\n if (vocabCache.size >= MAX_VOCAB_CACHE_SIZE) {\n const oldestKey = vocabCache.keys().next().value;\n if (oldestKey !== undefined) vocabCache.delete(oldestKey);\n }\n vocabCache.set(cacheKey, vocab);\n return vocab;\n}"],"mappings":"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","names":["MAX_LOCALE_TAG_LENGTH"]}
@@ -1,2 +1,12 @@
1
- import{a,b,c}from"./chunk-XH46JNPK.js";import"./chunk-5U5WJ465.js";export{b as getLocale,c as hasLocale,a as registerLocale};
1
+ import {
2
+ getLocale,
3
+ hasLocale,
4
+ registerLocale
5
+ } from "./chunk-UOPAV3WX.js";
6
+ import "./chunk-EGUUO6LE.js";
7
+ export {
8
+ getLocale,
9
+ hasLocale,
10
+ registerLocale
11
+ };
2
12
  //# sourceMappingURL=localeRegistry.js.map
@@ -0,0 +1,131 @@
1
+ import { type ExtendedLocaleVocab } from './localeRegistry.cjs';
2
+ import { type LocaleVocab } from './localeVocab.cjs';
3
+ import { type RelativeGrammar } from './relativeGrammar.cjs';
4
+ import { type FormatterOptions, type Formatter } from './extensibility.cjs';
5
+ import { type HolidaySpec, type HolidayCalendar } from './holidays.cjs';
6
+ import type { compileFormat as compileFormatBase } from './format.cjs';
7
+ import type { compileParser as compileParserBase } from './parse.cjs';
8
+ import type { parseRelative as parseRelativeBase } from './parseRelative.cjs';
9
+ import type { explainFormat as explainFormatBase, tokenizeFormat as tokenizeFormatBase, listTokens as listTokensBase, tokenInfo as tokenInfoBase, isValidFormat as isValidFormatBase, validateFormat as validateFormatBase, fieldForToken as fieldForTokenBase } from './analyze.cjs';
10
+ import type { monthsInYear as monthsInYearBase, isLeapYear as isLeapYearBase, isLeapMonth as isLeapMonthBase, weekOfYear as weekOfYearBase, weekYear as weekYearBase, getMonth as getMonthBase, getWeekday as getWeekdayBase } from './calendarUtils.cjs';
11
+ import type { isEqual as isEqualBase, isBefore as isBeforeBase, isAfter as isAfterBase, clamp as clampBase, isBetween as isBetweenBase, isToday as isTodayBase, isTomorrow as isTomorrowBase, isYesterday as isYesterdayBase, isSameDay as isSameDayBase, isSameWeek as isSameWeekBase, isSameMonth as isSameMonthBase, isSameQuarter as isSameQuarterBase, isSameYear as isSameYearBase, isWeekday as isWeekdayBase } from './comparison.cjs';
12
+ import type { floor as floorBase, ceil as ceilBase, truncate as truncateBase } from './rounding.cjs';
13
+ import type { parseRFC3339 as parseRFC3339Base, formatRFC3339 as formatRFC3339Base, parseRFC2822 as parseRFC2822Base, parseHTTPDate as parseHTTPDateBase, fromUnixMicroseconds as fromUnixMicrosecondsBase, fromUnixNanoseconds as fromUnixNanosecondsBase, toUnixSeconds as toUnixSecondsBase, toUnixMilliseconds as toUnixMillisecondsBase, toUnixMicroseconds as toUnixMicrosecondsBase, toUnixNanoseconds as toUnixNanosecondsBase, parseSQL as parseSQLBase, formatSQL as formatSQLBase } from './serialization.cjs';
14
+ import type { formatDurationToParts as formatDurationToPartsBase, parseDuration as parseDurationBase, parseISODuration as parseISODurationBase, formatISODuration as formatISODurationBase, balanceDuration as balanceDurationBase, compareDuration as compareDurationBase, subtractDuration as subtractDurationBase } from './duration.cjs';
15
+ import type { getLocale as getLocaleBase, hasLocale as hasLocaleBase } from './localeRegistry.cjs';
16
+ import type { createConfig as createConfigBase, mergeWithConfig as mergeWithConfigBase } from './config.cjs';
17
+ import type { listRegisteredGrammars as listRegisteredGrammarsBase } from './relativeGrammar.cjs';
18
+ import type { interval as intervalBase, overlaps as overlapsBase, intersection as intersectionBase, union as unionBase, mergeIntervals as mergeIntervalsBase, formatRangeToParts as formatRangeToPartsBase } from './interval.cjs';
19
+ import type { between as betweenBase, parseRRule as parseRRuleBase, formatRRule as formatRRuleBase } from './recurrence.cjs';
20
+ import type { createBusinessCalendar as createBusinessCalendarBase, subtractBusinessDays as subtractBusinessDaysBase } from './businessCalendar.cjs';
21
+ import type { nextHoliday as nextHolidayBase, previousHoliday as previousHolidayBase } from './holidays.cjs';
22
+ import type { resolveZoned as resolveZonedBase, getNextTransition as getNextTransitionBase, getPreviousTransition as getPreviousTransitionBase, possibleInstantsFor as possibleInstantsForBase } from './timezone.cjs';
23
+ import type { getAutocompleteData as getAutocompleteDataBase, getHoverDocs as getHoverDocsBase, getInlineDiagnostics as getInlineDiagnosticsBase, previewFormat as previewFormatBase, getDocUrl as getDocUrlBase } from './ideData.cjs';
24
+ import type { translateDateFnsFormatString as translateDateFnsFormatStringBase } from './codemod.cjs';
25
+ import type { format as FormatFn } from './format.cjs';
26
+ import type { parse as ParseFn } from './parse.cjs';
27
+ export interface ModContext {
28
+ registerLocale(locale: string, vocab: ExtendedLocaleVocab): void;
29
+ registerLocaleVocab(locale: string, vocab: LocaleVocab): void;
30
+ registerRelativeGrammar(grammar: RelativeGrammar): void;
31
+ createFormatter(options?: FormatterOptions): Formatter;
32
+ createHolidayCalendar(specs: HolidaySpec[]): HolidayCalendar;
33
+ overrideFormat(impl: (original: typeof FormatFn, ...args: Parameters<typeof FormatFn>) => ReturnType<typeof FormatFn>): void;
34
+ overrideParse(impl: (original: typeof ParseFn, ...args: Parameters<typeof ParseFn>) => ReturnType<typeof ParseFn>): void;
35
+ overrideCompileFormat(impl: (original: typeof compileFormatBase, ...args: Parameters<typeof compileFormatBase>) => ReturnType<typeof compileFormatBase>): void;
36
+ overrideCompileParser(impl: (original: typeof compileParserBase, ...args: Parameters<typeof compileParserBase>) => ReturnType<typeof compileParserBase>): void;
37
+ overrideParseRelative(impl: (original: typeof parseRelativeBase, ...args: Parameters<typeof parseRelativeBase>) => ReturnType<typeof parseRelativeBase>): void;
38
+ overrideExplainFormat(impl: (original: typeof explainFormatBase, ...args: Parameters<typeof explainFormatBase>) => ReturnType<typeof explainFormatBase>): void;
39
+ overrideTokenizeFormat(impl: (original: typeof tokenizeFormatBase, ...args: Parameters<typeof tokenizeFormatBase>) => ReturnType<typeof tokenizeFormatBase>): void;
40
+ overrideListTokens(impl: (original: typeof listTokensBase, ...args: Parameters<typeof listTokensBase>) => ReturnType<typeof listTokensBase>): void;
41
+ overrideTokenInfo(impl: (original: typeof tokenInfoBase, ...args: Parameters<typeof tokenInfoBase>) => ReturnType<typeof tokenInfoBase>): void;
42
+ overrideIsValidFormat(impl: (original: typeof isValidFormatBase, ...args: Parameters<typeof isValidFormatBase>) => ReturnType<typeof isValidFormatBase>): void;
43
+ overrideValidateFormat(impl: (original: typeof validateFormatBase, ...args: Parameters<typeof validateFormatBase>) => ReturnType<typeof validateFormatBase>): void;
44
+ overrideFieldForToken(impl: (original: typeof fieldForTokenBase, ...args: Parameters<typeof fieldForTokenBase>) => ReturnType<typeof fieldForTokenBase>): void;
45
+ overrideMonthsInYear(impl: (original: typeof monthsInYearBase, ...args: Parameters<typeof monthsInYearBase>) => ReturnType<typeof monthsInYearBase>): void;
46
+ overrideIsLeapYear(impl: (original: typeof isLeapYearBase, ...args: Parameters<typeof isLeapYearBase>) => ReturnType<typeof isLeapYearBase>): void;
47
+ overrideIsLeapMonth(impl: (original: typeof isLeapMonthBase, ...args: Parameters<typeof isLeapMonthBase>) => ReturnType<typeof isLeapMonthBase>): void;
48
+ overrideWeekOfYear(impl: (original: typeof weekOfYearBase, ...args: Parameters<typeof weekOfYearBase>) => ReturnType<typeof weekOfYearBase>): void;
49
+ overrideWeekYear(impl: (original: typeof weekYearBase, ...args: Parameters<typeof weekYearBase>) => ReturnType<typeof weekYearBase>): void;
50
+ overrideGetMonth(impl: (original: typeof getMonthBase, ...args: Parameters<typeof getMonthBase>) => ReturnType<typeof getMonthBase>): void;
51
+ overrideGetWeekday(impl: (original: typeof getWeekdayBase, ...args: Parameters<typeof getWeekdayBase>) => ReturnType<typeof getWeekdayBase>): void;
52
+ overrideIsEqual(impl: (original: typeof isEqualBase, ...args: Parameters<typeof isEqualBase>) => ReturnType<typeof isEqualBase>): void;
53
+ overrideIsBefore(impl: (original: typeof isBeforeBase, ...args: Parameters<typeof isBeforeBase>) => ReturnType<typeof isBeforeBase>): void;
54
+ overrideIsAfter(impl: (original: typeof isAfterBase, ...args: Parameters<typeof isAfterBase>) => ReturnType<typeof isAfterBase>): void;
55
+ overrideClamp(impl: (original: typeof clampBase, ...args: Parameters<typeof clampBase>) => ReturnType<typeof clampBase>): void;
56
+ overrideIsBetween(impl: (original: typeof isBetweenBase, ...args: Parameters<typeof isBetweenBase>) => ReturnType<typeof isBetweenBase>): void;
57
+ overrideIsToday(impl: (original: typeof isTodayBase, ...args: Parameters<typeof isTodayBase>) => ReturnType<typeof isTodayBase>): void;
58
+ overrideIsTomorrow(impl: (original: typeof isTomorrowBase, ...args: Parameters<typeof isTomorrowBase>) => ReturnType<typeof isTomorrowBase>): void;
59
+ overrideIsYesterday(impl: (original: typeof isYesterdayBase, ...args: Parameters<typeof isYesterdayBase>) => ReturnType<typeof isYesterdayBase>): void;
60
+ overrideIsSameDay(impl: (original: typeof isSameDayBase, ...args: Parameters<typeof isSameDayBase>) => ReturnType<typeof isSameDayBase>): void;
61
+ overrideIsSameWeek(impl: (original: typeof isSameWeekBase, ...args: Parameters<typeof isSameWeekBase>) => ReturnType<typeof isSameWeekBase>): void;
62
+ overrideIsSameMonth(impl: (original: typeof isSameMonthBase, ...args: Parameters<typeof isSameMonthBase>) => ReturnType<typeof isSameMonthBase>): void;
63
+ overrideIsSameQuarter(impl: (original: typeof isSameQuarterBase, ...args: Parameters<typeof isSameQuarterBase>) => ReturnType<typeof isSameQuarterBase>): void;
64
+ overrideIsSameYear(impl: (original: typeof isSameYearBase, ...args: Parameters<typeof isSameYearBase>) => ReturnType<typeof isSameYearBase>): void;
65
+ overrideIsWeekday(impl: (original: typeof isWeekdayBase, ...args: Parameters<typeof isWeekdayBase>) => ReturnType<typeof isWeekdayBase>): void;
66
+ overrideFloor(impl: (original: typeof floorBase, ...args: Parameters<typeof floorBase>) => ReturnType<typeof floorBase>): void;
67
+ overrideCeil(impl: (original: typeof ceilBase, ...args: Parameters<typeof ceilBase>) => ReturnType<typeof ceilBase>): void;
68
+ overrideTruncate(impl: (original: typeof truncateBase, ...args: Parameters<typeof truncateBase>) => ReturnType<typeof truncateBase>): void;
69
+ overrideParseRFC3339(impl: (original: typeof parseRFC3339Base, ...args: Parameters<typeof parseRFC3339Base>) => ReturnType<typeof parseRFC3339Base>): void;
70
+ overrideFormatRFC3339(impl: (original: typeof formatRFC3339Base, ...args: Parameters<typeof formatRFC3339Base>) => ReturnType<typeof formatRFC3339Base>): void;
71
+ overrideParseRFC2822(impl: (original: typeof parseRFC2822Base, ...args: Parameters<typeof parseRFC2822Base>) => ReturnType<typeof parseRFC2822Base>): void;
72
+ overrideParseHTTPDate(impl: (original: typeof parseHTTPDateBase, ...args: Parameters<typeof parseHTTPDateBase>) => ReturnType<typeof parseHTTPDateBase>): void;
73
+ overrideFromUnixMicroseconds(impl: (original: typeof fromUnixMicrosecondsBase, ...args: Parameters<typeof fromUnixMicrosecondsBase>) => ReturnType<typeof fromUnixMicrosecondsBase>): void;
74
+ overrideFromUnixNanoseconds(impl: (original: typeof fromUnixNanosecondsBase, ...args: Parameters<typeof fromUnixNanosecondsBase>) => ReturnType<typeof fromUnixNanosecondsBase>): void;
75
+ overrideToUnixSeconds(impl: (original: typeof toUnixSecondsBase, ...args: Parameters<typeof toUnixSecondsBase>) => ReturnType<typeof toUnixSecondsBase>): void;
76
+ overrideToUnixMilliseconds(impl: (original: typeof toUnixMillisecondsBase, ...args: Parameters<typeof toUnixMillisecondsBase>) => ReturnType<typeof toUnixMillisecondsBase>): void;
77
+ overrideToUnixMicroseconds(impl: (original: typeof toUnixMicrosecondsBase, ...args: Parameters<typeof toUnixMicrosecondsBase>) => ReturnType<typeof toUnixMicrosecondsBase>): void;
78
+ overrideToUnixNanoseconds(impl: (original: typeof toUnixNanosecondsBase, ...args: Parameters<typeof toUnixNanosecondsBase>) => ReturnType<typeof toUnixNanosecondsBase>): void;
79
+ overrideParseSQL(impl: (original: typeof parseSQLBase, ...args: Parameters<typeof parseSQLBase>) => ReturnType<typeof parseSQLBase>): void;
80
+ overrideFormatSQL(impl: (original: typeof formatSQLBase, ...args: Parameters<typeof formatSQLBase>) => ReturnType<typeof formatSQLBase>): void;
81
+ overrideFormatDurationToParts(impl: (original: typeof formatDurationToPartsBase, ...args: Parameters<typeof formatDurationToPartsBase>) => ReturnType<typeof formatDurationToPartsBase>): void;
82
+ overrideParseDuration(impl: (original: typeof parseDurationBase, ...args: Parameters<typeof parseDurationBase>) => ReturnType<typeof parseDurationBase>): void;
83
+ overrideParseISODuration(impl: (original: typeof parseISODurationBase, ...args: Parameters<typeof parseISODurationBase>) => ReturnType<typeof parseISODurationBase>): void;
84
+ overrideFormatISODuration(impl: (original: typeof formatISODurationBase, ...args: Parameters<typeof formatISODurationBase>) => ReturnType<typeof formatISODurationBase>): void;
85
+ overrideBalanceDuration(impl: (original: typeof balanceDurationBase, ...args: Parameters<typeof balanceDurationBase>) => ReturnType<typeof balanceDurationBase>): void;
86
+ overrideCompareDuration(impl: (original: typeof compareDurationBase, ...args: Parameters<typeof compareDurationBase>) => ReturnType<typeof compareDurationBase>): void;
87
+ overrideSubtractDuration(impl: (original: typeof subtractDurationBase, ...args: Parameters<typeof subtractDurationBase>) => ReturnType<typeof subtractDurationBase>): void;
88
+ overrideGetLocale(impl: (original: typeof getLocaleBase, ...args: Parameters<typeof getLocaleBase>) => ReturnType<typeof getLocaleBase>): void;
89
+ overrideHasLocale(impl: (original: typeof hasLocaleBase, ...args: Parameters<typeof hasLocaleBase>) => ReturnType<typeof hasLocaleBase>): void;
90
+ overrideCreateConfig(impl: (original: typeof createConfigBase, ...args: Parameters<typeof createConfigBase>) => ReturnType<typeof createConfigBase>): void;
91
+ overrideMergeWithConfig(impl: (original: typeof mergeWithConfigBase, ...args: Parameters<typeof mergeWithConfigBase>) => ReturnType<typeof mergeWithConfigBase>): void;
92
+ overrideListRegisteredGrammars(impl: (original: typeof listRegisteredGrammarsBase, ...args: Parameters<typeof listRegisteredGrammarsBase>) => ReturnType<typeof listRegisteredGrammarsBase>): void;
93
+ overrideInterval(impl: (original: typeof intervalBase, ...args: Parameters<typeof intervalBase>) => ReturnType<typeof intervalBase>): void;
94
+ overrideOverlaps(impl: (original: typeof overlapsBase, ...args: Parameters<typeof overlapsBase>) => ReturnType<typeof overlapsBase>): void;
95
+ overrideIntersection(impl: (original: typeof intersectionBase, ...args: Parameters<typeof intersectionBase>) => ReturnType<typeof intersectionBase>): void;
96
+ overrideUnion(impl: (original: typeof unionBase, ...args: Parameters<typeof unionBase>) => ReturnType<typeof unionBase>): void;
97
+ overrideMergeIntervals(impl: (original: typeof mergeIntervalsBase, ...args: Parameters<typeof mergeIntervalsBase>) => ReturnType<typeof mergeIntervalsBase>): void;
98
+ overrideFormatRangeToParts(impl: (original: typeof formatRangeToPartsBase, ...args: Parameters<typeof formatRangeToPartsBase>) => ReturnType<typeof formatRangeToPartsBase>): void;
99
+ overrideBetween(impl: (original: typeof betweenBase, ...args: Parameters<typeof betweenBase>) => ReturnType<typeof betweenBase>): void;
100
+ overrideParseRRule(impl: (original: typeof parseRRuleBase, ...args: Parameters<typeof parseRRuleBase>) => ReturnType<typeof parseRRuleBase>): void;
101
+ overrideFormatRRule(impl: (original: typeof formatRRuleBase, ...args: Parameters<typeof formatRRuleBase>) => ReturnType<typeof formatRRuleBase>): void;
102
+ overrideCreateBusinessCalendar(impl: (original: typeof createBusinessCalendarBase, ...args: Parameters<typeof createBusinessCalendarBase>) => ReturnType<typeof createBusinessCalendarBase>): void;
103
+ overrideSubtractBusinessDays(impl: (original: typeof subtractBusinessDaysBase, ...args: Parameters<typeof subtractBusinessDaysBase>) => ReturnType<typeof subtractBusinessDaysBase>): void;
104
+ overrideNextHoliday(impl: (original: typeof nextHolidayBase, ...args: Parameters<typeof nextHolidayBase>) => ReturnType<typeof nextHolidayBase>): void;
105
+ overridePreviousHoliday(impl: (original: typeof previousHolidayBase, ...args: Parameters<typeof previousHolidayBase>) => ReturnType<typeof previousHolidayBase>): void;
106
+ overrideResolveZoned(impl: (original: typeof resolveZonedBase, ...args: Parameters<typeof resolveZonedBase>) => ReturnType<typeof resolveZonedBase>): void;
107
+ overrideGetNextTransition(impl: (original: typeof getNextTransitionBase, ...args: Parameters<typeof getNextTransitionBase>) => ReturnType<typeof getNextTransitionBase>): void;
108
+ overrideGetPreviousTransition(impl: (original: typeof getPreviousTransitionBase, ...args: Parameters<typeof getPreviousTransitionBase>) => ReturnType<typeof getPreviousTransitionBase>): void;
109
+ overridePossibleInstantsFor(impl: (original: typeof possibleInstantsForBase, ...args: Parameters<typeof possibleInstantsForBase>) => ReturnType<typeof possibleInstantsForBase>): void;
110
+ overrideGetAutocompleteData(impl: (original: typeof getAutocompleteDataBase, ...args: Parameters<typeof getAutocompleteDataBase>) => ReturnType<typeof getAutocompleteDataBase>): void;
111
+ overrideGetHoverDocs(impl: (original: typeof getHoverDocsBase, ...args: Parameters<typeof getHoverDocsBase>) => ReturnType<typeof getHoverDocsBase>): void;
112
+ overrideGetInlineDiagnostics(impl: (original: typeof getInlineDiagnosticsBase, ...args: Parameters<typeof getInlineDiagnosticsBase>) => ReturnType<typeof getInlineDiagnosticsBase>): void;
113
+ overridePreviewFormat(impl: (original: typeof previewFormatBase, ...args: Parameters<typeof previewFormatBase>) => ReturnType<typeof previewFormatBase>): void;
114
+ overrideGetDocUrl(impl: (original: typeof getDocUrlBase, ...args: Parameters<typeof getDocUrlBase>) => ReturnType<typeof getDocUrlBase>): void;
115
+ overrideTranslateDateFnsFormatString(impl: (original: typeof translateDateFnsFormatStringBase, ...args: Parameters<typeof translateDateFnsFormatStringBase>) => ReturnType<typeof translateDateFnsFormatStringBase>): void;
116
+ }
117
+ export declare function buildModContextFor(modName: string): ModContext;
118
+ export declare function buildModContext(): ModContext;
119
+ export interface ModRegistrationKey {
120
+ kind: 'locale' | 'localeVocab' | 'relativeGrammar' | 'formatterTokens' | 'overrideFormat' | 'overrideParse';
121
+ key: string;
122
+ }
123
+ export declare function buildTrackedModContext(modName: string, onRegister: (key: ModRegistrationKey) => void): ModContext;
124
+ export interface Mod {
125
+ name: string;
126
+ version?: string;
127
+ requires?: string[];
128
+ priority?: number;
129
+ register(ctx: ModContext, config: Record<string, unknown>): void | Promise<void>;
130
+ }
131
+ export declare function isMod(value: unknown): value is Mod;
@@ -0,0 +1,131 @@
1
+ import { type ExtendedLocaleVocab } from './localeRegistry.js';
2
+ import { type LocaleVocab } from './localeVocab.js';
3
+ import { type RelativeGrammar } from './relativeGrammar.js';
4
+ import { type FormatterOptions, type Formatter } from './extensibility.js';
5
+ import { type HolidaySpec, type HolidayCalendar } from './holidays.js';
6
+ import type { compileFormat as compileFormatBase } from './format.js';
7
+ import type { compileParser as compileParserBase } from './parse.js';
8
+ import type { parseRelative as parseRelativeBase } from './parseRelative.js';
9
+ import type { explainFormat as explainFormatBase, tokenizeFormat as tokenizeFormatBase, listTokens as listTokensBase, tokenInfo as tokenInfoBase, isValidFormat as isValidFormatBase, validateFormat as validateFormatBase, fieldForToken as fieldForTokenBase } from './analyze.js';
10
+ import type { monthsInYear as monthsInYearBase, isLeapYear as isLeapYearBase, isLeapMonth as isLeapMonthBase, weekOfYear as weekOfYearBase, weekYear as weekYearBase, getMonth as getMonthBase, getWeekday as getWeekdayBase } from './calendarUtils.js';
11
+ import type { isEqual as isEqualBase, isBefore as isBeforeBase, isAfter as isAfterBase, clamp as clampBase, isBetween as isBetweenBase, isToday as isTodayBase, isTomorrow as isTomorrowBase, isYesterday as isYesterdayBase, isSameDay as isSameDayBase, isSameWeek as isSameWeekBase, isSameMonth as isSameMonthBase, isSameQuarter as isSameQuarterBase, isSameYear as isSameYearBase, isWeekday as isWeekdayBase } from './comparison.js';
12
+ import type { floor as floorBase, ceil as ceilBase, truncate as truncateBase } from './rounding.js';
13
+ import type { parseRFC3339 as parseRFC3339Base, formatRFC3339 as formatRFC3339Base, parseRFC2822 as parseRFC2822Base, parseHTTPDate as parseHTTPDateBase, fromUnixMicroseconds as fromUnixMicrosecondsBase, fromUnixNanoseconds as fromUnixNanosecondsBase, toUnixSeconds as toUnixSecondsBase, toUnixMilliseconds as toUnixMillisecondsBase, toUnixMicroseconds as toUnixMicrosecondsBase, toUnixNanoseconds as toUnixNanosecondsBase, parseSQL as parseSQLBase, formatSQL as formatSQLBase } from './serialization.js';
14
+ import type { formatDurationToParts as formatDurationToPartsBase, parseDuration as parseDurationBase, parseISODuration as parseISODurationBase, formatISODuration as formatISODurationBase, balanceDuration as balanceDurationBase, compareDuration as compareDurationBase, subtractDuration as subtractDurationBase } from './duration.js';
15
+ import type { getLocale as getLocaleBase, hasLocale as hasLocaleBase } from './localeRegistry.js';
16
+ import type { createConfig as createConfigBase, mergeWithConfig as mergeWithConfigBase } from './config.js';
17
+ import type { listRegisteredGrammars as listRegisteredGrammarsBase } from './relativeGrammar.js';
18
+ import type { interval as intervalBase, overlaps as overlapsBase, intersection as intersectionBase, union as unionBase, mergeIntervals as mergeIntervalsBase, formatRangeToParts as formatRangeToPartsBase } from './interval.js';
19
+ import type { between as betweenBase, parseRRule as parseRRuleBase, formatRRule as formatRRuleBase } from './recurrence.js';
20
+ import type { createBusinessCalendar as createBusinessCalendarBase, subtractBusinessDays as subtractBusinessDaysBase } from './businessCalendar.js';
21
+ import type { nextHoliday as nextHolidayBase, previousHoliday as previousHolidayBase } from './holidays.js';
22
+ import type { resolveZoned as resolveZonedBase, getNextTransition as getNextTransitionBase, getPreviousTransition as getPreviousTransitionBase, possibleInstantsFor as possibleInstantsForBase } from './timezone.js';
23
+ import type { getAutocompleteData as getAutocompleteDataBase, getHoverDocs as getHoverDocsBase, getInlineDiagnostics as getInlineDiagnosticsBase, previewFormat as previewFormatBase, getDocUrl as getDocUrlBase } from './ideData.js';
24
+ import type { translateDateFnsFormatString as translateDateFnsFormatStringBase } from './codemod.js';
25
+ import type { format as FormatFn } from './format.js';
26
+ import type { parse as ParseFn } from './parse.js';
27
+ export interface ModContext {
28
+ registerLocale(locale: string, vocab: ExtendedLocaleVocab): void;
29
+ registerLocaleVocab(locale: string, vocab: LocaleVocab): void;
30
+ registerRelativeGrammar(grammar: RelativeGrammar): void;
31
+ createFormatter(options?: FormatterOptions): Formatter;
32
+ createHolidayCalendar(specs: HolidaySpec[]): HolidayCalendar;
33
+ overrideFormat(impl: (original: typeof FormatFn, ...args: Parameters<typeof FormatFn>) => ReturnType<typeof FormatFn>): void;
34
+ overrideParse(impl: (original: typeof ParseFn, ...args: Parameters<typeof ParseFn>) => ReturnType<typeof ParseFn>): void;
35
+ overrideCompileFormat(impl: (original: typeof compileFormatBase, ...args: Parameters<typeof compileFormatBase>) => ReturnType<typeof compileFormatBase>): void;
36
+ overrideCompileParser(impl: (original: typeof compileParserBase, ...args: Parameters<typeof compileParserBase>) => ReturnType<typeof compileParserBase>): void;
37
+ overrideParseRelative(impl: (original: typeof parseRelativeBase, ...args: Parameters<typeof parseRelativeBase>) => ReturnType<typeof parseRelativeBase>): void;
38
+ overrideExplainFormat(impl: (original: typeof explainFormatBase, ...args: Parameters<typeof explainFormatBase>) => ReturnType<typeof explainFormatBase>): void;
39
+ overrideTokenizeFormat(impl: (original: typeof tokenizeFormatBase, ...args: Parameters<typeof tokenizeFormatBase>) => ReturnType<typeof tokenizeFormatBase>): void;
40
+ overrideListTokens(impl: (original: typeof listTokensBase, ...args: Parameters<typeof listTokensBase>) => ReturnType<typeof listTokensBase>): void;
41
+ overrideTokenInfo(impl: (original: typeof tokenInfoBase, ...args: Parameters<typeof tokenInfoBase>) => ReturnType<typeof tokenInfoBase>): void;
42
+ overrideIsValidFormat(impl: (original: typeof isValidFormatBase, ...args: Parameters<typeof isValidFormatBase>) => ReturnType<typeof isValidFormatBase>): void;
43
+ overrideValidateFormat(impl: (original: typeof validateFormatBase, ...args: Parameters<typeof validateFormatBase>) => ReturnType<typeof validateFormatBase>): void;
44
+ overrideFieldForToken(impl: (original: typeof fieldForTokenBase, ...args: Parameters<typeof fieldForTokenBase>) => ReturnType<typeof fieldForTokenBase>): void;
45
+ overrideMonthsInYear(impl: (original: typeof monthsInYearBase, ...args: Parameters<typeof monthsInYearBase>) => ReturnType<typeof monthsInYearBase>): void;
46
+ overrideIsLeapYear(impl: (original: typeof isLeapYearBase, ...args: Parameters<typeof isLeapYearBase>) => ReturnType<typeof isLeapYearBase>): void;
47
+ overrideIsLeapMonth(impl: (original: typeof isLeapMonthBase, ...args: Parameters<typeof isLeapMonthBase>) => ReturnType<typeof isLeapMonthBase>): void;
48
+ overrideWeekOfYear(impl: (original: typeof weekOfYearBase, ...args: Parameters<typeof weekOfYearBase>) => ReturnType<typeof weekOfYearBase>): void;
49
+ overrideWeekYear(impl: (original: typeof weekYearBase, ...args: Parameters<typeof weekYearBase>) => ReturnType<typeof weekYearBase>): void;
50
+ overrideGetMonth(impl: (original: typeof getMonthBase, ...args: Parameters<typeof getMonthBase>) => ReturnType<typeof getMonthBase>): void;
51
+ overrideGetWeekday(impl: (original: typeof getWeekdayBase, ...args: Parameters<typeof getWeekdayBase>) => ReturnType<typeof getWeekdayBase>): void;
52
+ overrideIsEqual(impl: (original: typeof isEqualBase, ...args: Parameters<typeof isEqualBase>) => ReturnType<typeof isEqualBase>): void;
53
+ overrideIsBefore(impl: (original: typeof isBeforeBase, ...args: Parameters<typeof isBeforeBase>) => ReturnType<typeof isBeforeBase>): void;
54
+ overrideIsAfter(impl: (original: typeof isAfterBase, ...args: Parameters<typeof isAfterBase>) => ReturnType<typeof isAfterBase>): void;
55
+ overrideClamp(impl: (original: typeof clampBase, ...args: Parameters<typeof clampBase>) => ReturnType<typeof clampBase>): void;
56
+ overrideIsBetween(impl: (original: typeof isBetweenBase, ...args: Parameters<typeof isBetweenBase>) => ReturnType<typeof isBetweenBase>): void;
57
+ overrideIsToday(impl: (original: typeof isTodayBase, ...args: Parameters<typeof isTodayBase>) => ReturnType<typeof isTodayBase>): void;
58
+ overrideIsTomorrow(impl: (original: typeof isTomorrowBase, ...args: Parameters<typeof isTomorrowBase>) => ReturnType<typeof isTomorrowBase>): void;
59
+ overrideIsYesterday(impl: (original: typeof isYesterdayBase, ...args: Parameters<typeof isYesterdayBase>) => ReturnType<typeof isYesterdayBase>): void;
60
+ overrideIsSameDay(impl: (original: typeof isSameDayBase, ...args: Parameters<typeof isSameDayBase>) => ReturnType<typeof isSameDayBase>): void;
61
+ overrideIsSameWeek(impl: (original: typeof isSameWeekBase, ...args: Parameters<typeof isSameWeekBase>) => ReturnType<typeof isSameWeekBase>): void;
62
+ overrideIsSameMonth(impl: (original: typeof isSameMonthBase, ...args: Parameters<typeof isSameMonthBase>) => ReturnType<typeof isSameMonthBase>): void;
63
+ overrideIsSameQuarter(impl: (original: typeof isSameQuarterBase, ...args: Parameters<typeof isSameQuarterBase>) => ReturnType<typeof isSameQuarterBase>): void;
64
+ overrideIsSameYear(impl: (original: typeof isSameYearBase, ...args: Parameters<typeof isSameYearBase>) => ReturnType<typeof isSameYearBase>): void;
65
+ overrideIsWeekday(impl: (original: typeof isWeekdayBase, ...args: Parameters<typeof isWeekdayBase>) => ReturnType<typeof isWeekdayBase>): void;
66
+ overrideFloor(impl: (original: typeof floorBase, ...args: Parameters<typeof floorBase>) => ReturnType<typeof floorBase>): void;
67
+ overrideCeil(impl: (original: typeof ceilBase, ...args: Parameters<typeof ceilBase>) => ReturnType<typeof ceilBase>): void;
68
+ overrideTruncate(impl: (original: typeof truncateBase, ...args: Parameters<typeof truncateBase>) => ReturnType<typeof truncateBase>): void;
69
+ overrideParseRFC3339(impl: (original: typeof parseRFC3339Base, ...args: Parameters<typeof parseRFC3339Base>) => ReturnType<typeof parseRFC3339Base>): void;
70
+ overrideFormatRFC3339(impl: (original: typeof formatRFC3339Base, ...args: Parameters<typeof formatRFC3339Base>) => ReturnType<typeof formatRFC3339Base>): void;
71
+ overrideParseRFC2822(impl: (original: typeof parseRFC2822Base, ...args: Parameters<typeof parseRFC2822Base>) => ReturnType<typeof parseRFC2822Base>): void;
72
+ overrideParseHTTPDate(impl: (original: typeof parseHTTPDateBase, ...args: Parameters<typeof parseHTTPDateBase>) => ReturnType<typeof parseHTTPDateBase>): void;
73
+ overrideFromUnixMicroseconds(impl: (original: typeof fromUnixMicrosecondsBase, ...args: Parameters<typeof fromUnixMicrosecondsBase>) => ReturnType<typeof fromUnixMicrosecondsBase>): void;
74
+ overrideFromUnixNanoseconds(impl: (original: typeof fromUnixNanosecondsBase, ...args: Parameters<typeof fromUnixNanosecondsBase>) => ReturnType<typeof fromUnixNanosecondsBase>): void;
75
+ overrideToUnixSeconds(impl: (original: typeof toUnixSecondsBase, ...args: Parameters<typeof toUnixSecondsBase>) => ReturnType<typeof toUnixSecondsBase>): void;
76
+ overrideToUnixMilliseconds(impl: (original: typeof toUnixMillisecondsBase, ...args: Parameters<typeof toUnixMillisecondsBase>) => ReturnType<typeof toUnixMillisecondsBase>): void;
77
+ overrideToUnixMicroseconds(impl: (original: typeof toUnixMicrosecondsBase, ...args: Parameters<typeof toUnixMicrosecondsBase>) => ReturnType<typeof toUnixMicrosecondsBase>): void;
78
+ overrideToUnixNanoseconds(impl: (original: typeof toUnixNanosecondsBase, ...args: Parameters<typeof toUnixNanosecondsBase>) => ReturnType<typeof toUnixNanosecondsBase>): void;
79
+ overrideParseSQL(impl: (original: typeof parseSQLBase, ...args: Parameters<typeof parseSQLBase>) => ReturnType<typeof parseSQLBase>): void;
80
+ overrideFormatSQL(impl: (original: typeof formatSQLBase, ...args: Parameters<typeof formatSQLBase>) => ReturnType<typeof formatSQLBase>): void;
81
+ overrideFormatDurationToParts(impl: (original: typeof formatDurationToPartsBase, ...args: Parameters<typeof formatDurationToPartsBase>) => ReturnType<typeof formatDurationToPartsBase>): void;
82
+ overrideParseDuration(impl: (original: typeof parseDurationBase, ...args: Parameters<typeof parseDurationBase>) => ReturnType<typeof parseDurationBase>): void;
83
+ overrideParseISODuration(impl: (original: typeof parseISODurationBase, ...args: Parameters<typeof parseISODurationBase>) => ReturnType<typeof parseISODurationBase>): void;
84
+ overrideFormatISODuration(impl: (original: typeof formatISODurationBase, ...args: Parameters<typeof formatISODurationBase>) => ReturnType<typeof formatISODurationBase>): void;
85
+ overrideBalanceDuration(impl: (original: typeof balanceDurationBase, ...args: Parameters<typeof balanceDurationBase>) => ReturnType<typeof balanceDurationBase>): void;
86
+ overrideCompareDuration(impl: (original: typeof compareDurationBase, ...args: Parameters<typeof compareDurationBase>) => ReturnType<typeof compareDurationBase>): void;
87
+ overrideSubtractDuration(impl: (original: typeof subtractDurationBase, ...args: Parameters<typeof subtractDurationBase>) => ReturnType<typeof subtractDurationBase>): void;
88
+ overrideGetLocale(impl: (original: typeof getLocaleBase, ...args: Parameters<typeof getLocaleBase>) => ReturnType<typeof getLocaleBase>): void;
89
+ overrideHasLocale(impl: (original: typeof hasLocaleBase, ...args: Parameters<typeof hasLocaleBase>) => ReturnType<typeof hasLocaleBase>): void;
90
+ overrideCreateConfig(impl: (original: typeof createConfigBase, ...args: Parameters<typeof createConfigBase>) => ReturnType<typeof createConfigBase>): void;
91
+ overrideMergeWithConfig(impl: (original: typeof mergeWithConfigBase, ...args: Parameters<typeof mergeWithConfigBase>) => ReturnType<typeof mergeWithConfigBase>): void;
92
+ overrideListRegisteredGrammars(impl: (original: typeof listRegisteredGrammarsBase, ...args: Parameters<typeof listRegisteredGrammarsBase>) => ReturnType<typeof listRegisteredGrammarsBase>): void;
93
+ overrideInterval(impl: (original: typeof intervalBase, ...args: Parameters<typeof intervalBase>) => ReturnType<typeof intervalBase>): void;
94
+ overrideOverlaps(impl: (original: typeof overlapsBase, ...args: Parameters<typeof overlapsBase>) => ReturnType<typeof overlapsBase>): void;
95
+ overrideIntersection(impl: (original: typeof intersectionBase, ...args: Parameters<typeof intersectionBase>) => ReturnType<typeof intersectionBase>): void;
96
+ overrideUnion(impl: (original: typeof unionBase, ...args: Parameters<typeof unionBase>) => ReturnType<typeof unionBase>): void;
97
+ overrideMergeIntervals(impl: (original: typeof mergeIntervalsBase, ...args: Parameters<typeof mergeIntervalsBase>) => ReturnType<typeof mergeIntervalsBase>): void;
98
+ overrideFormatRangeToParts(impl: (original: typeof formatRangeToPartsBase, ...args: Parameters<typeof formatRangeToPartsBase>) => ReturnType<typeof formatRangeToPartsBase>): void;
99
+ overrideBetween(impl: (original: typeof betweenBase, ...args: Parameters<typeof betweenBase>) => ReturnType<typeof betweenBase>): void;
100
+ overrideParseRRule(impl: (original: typeof parseRRuleBase, ...args: Parameters<typeof parseRRuleBase>) => ReturnType<typeof parseRRuleBase>): void;
101
+ overrideFormatRRule(impl: (original: typeof formatRRuleBase, ...args: Parameters<typeof formatRRuleBase>) => ReturnType<typeof formatRRuleBase>): void;
102
+ overrideCreateBusinessCalendar(impl: (original: typeof createBusinessCalendarBase, ...args: Parameters<typeof createBusinessCalendarBase>) => ReturnType<typeof createBusinessCalendarBase>): void;
103
+ overrideSubtractBusinessDays(impl: (original: typeof subtractBusinessDaysBase, ...args: Parameters<typeof subtractBusinessDaysBase>) => ReturnType<typeof subtractBusinessDaysBase>): void;
104
+ overrideNextHoliday(impl: (original: typeof nextHolidayBase, ...args: Parameters<typeof nextHolidayBase>) => ReturnType<typeof nextHolidayBase>): void;
105
+ overridePreviousHoliday(impl: (original: typeof previousHolidayBase, ...args: Parameters<typeof previousHolidayBase>) => ReturnType<typeof previousHolidayBase>): void;
106
+ overrideResolveZoned(impl: (original: typeof resolveZonedBase, ...args: Parameters<typeof resolveZonedBase>) => ReturnType<typeof resolveZonedBase>): void;
107
+ overrideGetNextTransition(impl: (original: typeof getNextTransitionBase, ...args: Parameters<typeof getNextTransitionBase>) => ReturnType<typeof getNextTransitionBase>): void;
108
+ overrideGetPreviousTransition(impl: (original: typeof getPreviousTransitionBase, ...args: Parameters<typeof getPreviousTransitionBase>) => ReturnType<typeof getPreviousTransitionBase>): void;
109
+ overridePossibleInstantsFor(impl: (original: typeof possibleInstantsForBase, ...args: Parameters<typeof possibleInstantsForBase>) => ReturnType<typeof possibleInstantsForBase>): void;
110
+ overrideGetAutocompleteData(impl: (original: typeof getAutocompleteDataBase, ...args: Parameters<typeof getAutocompleteDataBase>) => ReturnType<typeof getAutocompleteDataBase>): void;
111
+ overrideGetHoverDocs(impl: (original: typeof getHoverDocsBase, ...args: Parameters<typeof getHoverDocsBase>) => ReturnType<typeof getHoverDocsBase>): void;
112
+ overrideGetInlineDiagnostics(impl: (original: typeof getInlineDiagnosticsBase, ...args: Parameters<typeof getInlineDiagnosticsBase>) => ReturnType<typeof getInlineDiagnosticsBase>): void;
113
+ overridePreviewFormat(impl: (original: typeof previewFormatBase, ...args: Parameters<typeof previewFormatBase>) => ReturnType<typeof previewFormatBase>): void;
114
+ overrideGetDocUrl(impl: (original: typeof getDocUrlBase, ...args: Parameters<typeof getDocUrlBase>) => ReturnType<typeof getDocUrlBase>): void;
115
+ overrideTranslateDateFnsFormatString(impl: (original: typeof translateDateFnsFormatStringBase, ...args: Parameters<typeof translateDateFnsFormatStringBase>) => ReturnType<typeof translateDateFnsFormatStringBase>): void;
116
+ }
117
+ export declare function buildModContextFor(modName: string): ModContext;
118
+ export declare function buildModContext(): ModContext;
119
+ export interface ModRegistrationKey {
120
+ kind: 'locale' | 'localeVocab' | 'relativeGrammar' | 'formatterTokens' | 'overrideFormat' | 'overrideParse';
121
+ key: string;
122
+ }
123
+ export declare function buildTrackedModContext(modName: string, onRegister: (key: ModRegistrationKey) => void): ModContext;
124
+ export interface Mod {
125
+ name: string;
126
+ version?: string;
127
+ requires?: string[];
128
+ priority?: number;
129
+ register(ctx: ModContext, config: Record<string, unknown>): void | Promise<void>;
130
+ }
131
+ export declare function isMod(value: unknown): value is Mod;