diff --git a/.changeset/gold-mails-double.md b/.changeset/gold-mails-double.md new file mode 100644 index 0000000..c00c87b --- /dev/null +++ b/.changeset/gold-mails-double.md @@ -0,0 +1,8 @@ +--- +'@sumup-oss/intl': major +--- + +**This package is now pure ESM**. Please [read this](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). + +- If you use TypeScript, you need to use TypeScript 4.7 or later ([ref](https://github.com/microsoft/TypeScript/issues/46452)). +- If you use a bundler, make sure it supports ESM and that you have correctly configured it for ESM. (Next.js supports ESM packages out of the box since [v12](https://nextjs.org/blog/next-12#es-modules-support-and-url-imports)). diff --git a/.changeset/wicked-humans-deliver.md b/.changeset/wicked-humans-deliver.md new file mode 100644 index 0000000..e11ab5d --- /dev/null +++ b/.changeset/wicked-humans-deliver.md @@ -0,0 +1,5 @@ +--- +'@sumup-oss/intl': major +--- + +Raised the minimum Node.js version to 18+. This is the first maintained version with support for ES modules. diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 100% rename from .eslintrc.js rename to .eslintrc.cjs diff --git a/.huskyrc.js b/.huskyrc.cjs similarity index 100% rename from .huskyrc.js rename to .huskyrc.cjs diff --git a/README.md b/README.md index 23929c8..fe19e9b 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,10 @@ Creating instances of `Intl.*` formatters is an [expensive operation](https://bl ### Compatibility -`@sumup-oss/intl` works in [modern browsers](https://caniuse.com/mdn-javascript_builtins_intl_numberformat_numberformat,mdn-javascript_builtins_intl_datetimeformat_datetimeformat) as well as server runtimes with support for the `Intl` APIs (such as Node 10+[^1]). When the `Intl` APIs aren't (fully) available, `@sumup-oss/intl` tries to gracefully degrade. Please refer to the [API reference](#api-reference) to learn how certain functions behave when the runtime doesn't support the necessary APIs. If you need to support legacy browsers, consider including [polyfills](https://formatjs.io/docs/polyfills/). +`@sumup-oss/intl` works in [modern browsers](https://caniuse.com/mdn-javascript_builtins_intl_numberformat_numberformat,mdn-javascript_builtins_intl_datetimeformat_datetimeformat) as well as server runtimes with support for the `Intl` APIs (such as Node 13+). When the `Intl` APIs aren't (fully) available, `@sumup-oss/intl` tries to gracefully degrade. Please refer to the [API reference](#api-reference) to learn how certain functions behave when the runtime doesn't support the necessary APIs. If you need to support legacy browsers, consider including [polyfills](https://formatjs.io/docs/polyfills/). `@sumup-oss/intl` integrates [`temporal-polyfill`](https://www.npmjs.com/package/temporal-polyfill) to support formatting [`Temporal`](https://github.com/tc39/proposal-temporal) date-time objects. -[^1]: [Node](https://nodejs.org/en/) supports the `Intl` APIs since v8, however, it includes only the English localizations up to v12. Node v13 and above support all locales. If you're unable to use Node v13+, you can either include [polyfills](https://formatjs.io/docs/polyfills/) or use a [custom Node build](https://nodejs.org/docs/latest-v8.x/api/intl.html#intl_options_for_building_node_js). - ## Installation [`@sumup-oss/intl`](https://www.npmjs.com/package/@sumup-oss/intl) can be installed as a dependency via the [npm](https://www.npmjs.com) package manager. The [`temporal-polyfill`](https://www.npmjs.com/package/temporal-polyfill) package is a required peer dependency. @@ -42,7 +40,7 @@ Creating instances of `Intl.*` formatters is an [expensive operation](https://bl npm install @sumup-oss/intl temporal-polyfill ``` -`@sumup-oss/intl` requires Node v10+. +`@sumup-oss/intl` requires Node v18+. ## Usage diff --git a/lint-staged.config.js b/lint-staged.config.cjs similarity index 100% rename from lint-staged.config.js rename to lint-staged.config.cjs diff --git a/package-lock.json b/package-lock.json index 3d4c20d..90cb32c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sumup-oss/intl", - "version": "2.0.0", + "version": "2.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sumup-oss/intl", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "dependencies": { "intl-format-cache": "^4.2.27" diff --git a/package.json b/package.json index 4d30dc4..a2491ea 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,12 @@ "author": "Connor Bär ", "license": "Apache-2.0", "private": false, - "main": "dist/cjs/index.js", - "module": "dist/es/index.js", - "types": "dist/es/index.d.ts", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": "./dist/index.js" + }, "sideEffects": false, "files": [ "dist", @@ -23,9 +26,7 @@ "scripts": { "start": "tsc --watch", "dev": "npm run start", - "build": "npm run build:es && npm run build:cjs", - "build:es": "tsc", - "build:cjs": "tsc --project tsconfig.cjs.json", + "build": "tsc", "docs": "typedoc", "lint": "foundry run eslint . --ext .js,.jsx,.ts,.tsx", "lint:fix": "npm run lint -- --fix", @@ -37,7 +38,7 @@ "release": "changeset publish" }, "engines": { - "node": ">=10" + "node": ">=18" }, "dependencies": { "intl-format-cache": "^4.2.27" diff --git a/prettier.config.js b/prettier.config.cjs similarity index 100% rename from prettier.config.js rename to prettier.config.cjs diff --git a/src/data/currencies.ts b/src/data/currencies.ts index c514982..e8465de 100644 --- a/src/data/currencies.ts +++ b/src/data/currencies.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { Currency } from '../types'; +import { Currency } from '../types/index.js'; /** * An object that maps a 2 char country code to its official 3 char currency code. diff --git a/src/index.ts b/src/index.ts index e127962..34e883d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,7 +22,7 @@ export { resolveCurrencyFormat, isNumberFormatSupported, isNumberFormatToPartsSupported, -} from './lib/number-format'; +} from './lib/number-format/index.js'; export { formatDate, formatTime, @@ -31,5 +31,5 @@ export { resolveDateTimeFormat, isDateTimeFormatSupported, isDateTimeFormatToPartsSupported, -} from './lib/date-time-format'; -export { CURRENCIES } from './data/currencies'; +} from './lib/date-time-format/index.js'; +export { CURRENCIES } from './data/currencies.js'; diff --git a/src/lib/date-time-format/index.ts b/src/lib/date-time-format/index.ts index 8e9ce2b..933a337 100644 --- a/src/lib/date-time-format/index.ts +++ b/src/lib/date-time-format/index.ts @@ -18,15 +18,15 @@ import type { FormattableDateTime, FormattableTime, Locale, -} from '../../types'; -import { DATE_STYLES, TIME_STYLES } from '../../data/date-time-styles'; +} from '../../types/index.js'; +import { DATE_STYLES, TIME_STYLES } from '../../data/date-time-styles.js'; import { getDateTimeFormat, isDateTimeFormatSupported, isDateTimeFormatToPartsSupported, isDateTimeStyleSupported, -} from './intl'; +} from './intl.js'; export { isDateTimeFormatSupported, isDateTimeFormatToPartsSupported }; diff --git a/src/lib/date-time-format/intl.ts b/src/lib/date-time-format/intl.ts index 8b861a1..4c77d1f 100644 --- a/src/lib/date-time-format/intl.ts +++ b/src/lib/date-time-format/intl.ts @@ -16,7 +16,7 @@ import { Intl as IntlWithTemporal } from 'temporal-polyfill'; import memoizeFormatConstructor from 'intl-format-cache'; -import { Locale } from '../../types'; +import { Locale } from '../../types/index.js'; /** * Whether the `Intl` and `Intl.DateTimeFormat` APIs @@ -61,6 +61,7 @@ export const isDateTimeStyleSupported = (() => { } })(); +// @ts-expect-error intl-format-cache is bundled in a non-standard way. export const getDateTimeFormat = memoizeFormatConstructor( IntlWithTemporal.DateTimeFormat, ) as ( diff --git a/src/lib/date-time-format/tests/format-to-parts.spec.ts b/src/lib/date-time-format/tests/format-to-parts.spec.ts index b54d2ac..7d86c32 100644 --- a/src/lib/date-time-format/tests/format-to-parts.spec.ts +++ b/src/lib/date-time-format/tests/format-to-parts.spec.ts @@ -16,9 +16,9 @@ import { describe, it, expect } from 'vitest'; import { Intl } from 'temporal-polyfill'; -import { formatDateTimeToParts } from '..'; +import { formatDateTimeToParts } from '../index.js'; -import { datetimes, locales } from './shared'; +import { datetimes, locales } from './shared.js'; describe('Dates & times', () => { describe('formatDateTimeToParts', () => { diff --git a/src/lib/date-time-format/tests/format.spec.ts b/src/lib/date-time-format/tests/format.spec.ts index a7ff280..e116935 100644 --- a/src/lib/date-time-format/tests/format.spec.ts +++ b/src/lib/date-time-format/tests/format.spec.ts @@ -16,9 +16,9 @@ import { describe, it, expect } from 'vitest'; import { Intl } from 'temporal-polyfill'; -import { formatDateTime, formatDate, formatTime } from '..'; +import { formatDateTime, formatDate, formatTime } from '../index.js'; -import { locales, dates, times, datetimes } from './shared'; +import { locales, dates, times, datetimes } from './shared.js'; describe('Dates & times', () => { describe('formatDateTime', () => { diff --git a/src/lib/date-time-format/tests/resolve-format.spec.ts b/src/lib/date-time-format/tests/resolve-format.spec.ts index 458e2d1..7a4234a 100644 --- a/src/lib/date-time-format/tests/resolve-format.spec.ts +++ b/src/lib/date-time-format/tests/resolve-format.spec.ts @@ -16,9 +16,9 @@ import { describe, it, expect } from 'vitest'; import { Intl } from 'temporal-polyfill'; -import { resolveDateTimeFormat } from '..'; +import { resolveDateTimeFormat } from '../index.js'; -import { locales } from './shared'; +import { locales } from './shared.js'; describe('Dates & times', () => { describe('resolveDateTimeFormat', () => { diff --git a/src/lib/date-time-format/tests/unsupported-intl-api.spec.ts b/src/lib/date-time-format/tests/unsupported-intl-api.spec.ts index 93de65e..2c95b79 100644 --- a/src/lib/date-time-format/tests/unsupported-intl-api.spec.ts +++ b/src/lib/date-time-format/tests/unsupported-intl-api.spec.ts @@ -19,9 +19,9 @@ import { formatDateTime, formatDateTimeToParts, resolveDateTimeFormat, -} from '..'; +} from '../index.js'; -import { dates, datetimes, times } from './shared'; +import { dates, datetimes, times } from './shared.js'; vi.mock('../intl', async () => { const intl = await vi.importActual('../intl'); diff --git a/src/lib/date-time-format/tests/unsupported-styles.spec.ts b/src/lib/date-time-format/tests/unsupported-styles.spec.ts index c04b99e..4433bf2 100644 --- a/src/lib/date-time-format/tests/unsupported-styles.spec.ts +++ b/src/lib/date-time-format/tests/unsupported-styles.spec.ts @@ -16,9 +16,9 @@ import { vi, describe, it, expect } from 'vitest'; import { Intl } from 'temporal-polyfill'; -import { formatDateTime } from '..'; +import { formatDateTime } from '../index.js'; -import { dates, datetimes, times } from './shared'; +import { dates, datetimes, times } from './shared.js'; vi.mock('../intl', async () => { const intl = await vi.importActual('../intl'); diff --git a/src/lib/number-format/currencies.ts b/src/lib/number-format/currencies.ts index e508307..c715639 100644 --- a/src/lib/number-format/currencies.ts +++ b/src/lib/number-format/currencies.ts @@ -15,10 +15,13 @@ /* eslint-disable no-continue */ -import type { Locale, Currency, NumericOptions } from '../../types'; -import { CURRENCIES, CURRENCIES_WITHOUT_DECIMALS } from '../../data/currencies'; +import type { Locale, Currency, NumericOptions } from '../../types/index.js'; +import { + CURRENCIES, + CURRENCIES_WITHOUT_DECIMALS, +} from '../../data/currencies.js'; -import { resolveLocale } from './intl'; +import { resolveLocale } from './intl.js'; export function extractCountry(locale: string): string { if (locale.length === 2) { diff --git a/src/lib/number-format/index.ts b/src/lib/number-format/index.ts index e725a4b..3add3c9 100644 --- a/src/lib/number-format/index.ts +++ b/src/lib/number-format/index.ts @@ -18,16 +18,16 @@ import type { Locale, NumberFormat, NumericOptions, -} from '../../types'; -import { findIndex } from '../find-index'; +} from '../../types/index.js'; +import { findIndex } from '../find-index.js'; import { isNumberFormatSupported, isNumberFormatToPartsSupported, getNumberFormat, -} from './intl'; -import { getNumberOptions } from './numbers'; -import { getCurrencyOptions } from './currencies'; +} from './intl.js'; +import { getNumberOptions } from './numbers.js'; +import { getCurrencyOptions } from './currencies.js'; export { isNumberFormatSupported, isNumberFormatToPartsSupported }; diff --git a/src/lib/number-format/intl.ts b/src/lib/number-format/intl.ts index 9222c27..e493590 100644 --- a/src/lib/number-format/intl.ts +++ b/src/lib/number-format/intl.ts @@ -15,7 +15,7 @@ import memoizeFormatConstructor from 'intl-format-cache'; -import type { Locale } from '../../types'; +import type { Locale } from '../../types/index.js'; /** * Whether the `Intl` and `Intl.NumberFormat` APIs @@ -44,6 +44,7 @@ export const isNumberFormatToPartsSupported = (() => { } })(); +// @ts-expect-error intl-format-cache is bundled in a non-standard way. export const getNumberFormat = memoizeFormatConstructor(Intl.NumberFormat) as ( locales?: Locale | Locale[], options?: Intl.NumberFormatOptions, diff --git a/src/lib/number-format/numbers.ts b/src/lib/number-format/numbers.ts index 0f040f9..d6a1e16 100644 --- a/src/lib/number-format/numbers.ts +++ b/src/lib/number-format/numbers.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import type { Locale } from '../../types'; +import type { Locale } from '../../types/index.js'; export function getNumberOptions( locales?: Locale | Locale[], diff --git a/src/lib/number-format/tests/format-to-parts.spec.ts b/src/lib/number-format/tests/format-to-parts.spec.ts index 5399cb6..3d6dc26 100644 --- a/src/lib/number-format/tests/format-to-parts.spec.ts +++ b/src/lib/number-format/tests/format-to-parts.spec.ts @@ -15,10 +15,10 @@ import { describe, it, expect } from 'vitest'; -import { formatNumberToParts, formatCurrencyToParts } from '..'; -import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies'; +import { formatNumberToParts, formatCurrencyToParts } from '../index.js'; +import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies.js'; -import { locales, number } from './shared'; +import { locales, number } from './shared.js'; describe('Numbers', () => { describe('formatNumberToParts', () => { diff --git a/src/lib/number-format/tests/format.spec.ts b/src/lib/number-format/tests/format.spec.ts index 7148d4b..39ec8e2 100644 --- a/src/lib/number-format/tests/format.spec.ts +++ b/src/lib/number-format/tests/format.spec.ts @@ -15,10 +15,10 @@ import { describe, it, expect } from 'vitest'; -import { formatNumber, formatCurrency } from '..'; -import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies'; +import { formatNumber, formatCurrency } from '../index.js'; +import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies.js'; -import { locales, number } from './shared'; +import { locales, number } from './shared.js'; describe('Numbers', () => { describe('formatNumber', () => { diff --git a/src/lib/number-format/tests/resolve-format.spec.ts b/src/lib/number-format/tests/resolve-format.spec.ts index 6091579..a137ef7 100644 --- a/src/lib/number-format/tests/resolve-format.spec.ts +++ b/src/lib/number-format/tests/resolve-format.spec.ts @@ -15,10 +15,10 @@ import { describe, it, expect } from 'vitest'; -import { resolveNumberFormat, resolveCurrencyFormat } from '..'; -import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies'; +import { resolveNumberFormat, resolveCurrencyFormat } from '../index.js'; +import { CURRENCIES_WITHOUT_DECIMALS } from '../../../data/currencies.js'; -import { locales } from './shared'; +import { locales } from './shared.js'; describe('Numbers', () => { describe('resolveNumberFormat', () => { diff --git a/src/lib/number-format/tests/shared.ts b/src/lib/number-format/tests/shared.ts index b1ce052..cf420f5 100644 --- a/src/lib/number-format/tests/shared.ts +++ b/src/lib/number-format/tests/shared.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { CURRENCIES } from '../../..'; +import { CURRENCIES } from '../../../index.js'; export const locales: (string | string[])[] = [ ...Object.keys(CURRENCIES), diff --git a/src/lib/number-format/tests/unsupported-intl-api.spec.ts b/src/lib/number-format/tests/unsupported-intl-api.spec.ts index 04f1335..3c38236 100644 --- a/src/lib/number-format/tests/unsupported-intl-api.spec.ts +++ b/src/lib/number-format/tests/unsupported-intl-api.spec.ts @@ -22,9 +22,9 @@ import { formatNumberToParts, resolveCurrencyFormat, resolveNumberFormat, -} from '..'; +} from '../index.js'; -import { number } from './shared'; +import { number } from './shared.js'; vi.mock('../intl', async () => { const intl = await vi.importActual('../intl'); diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json deleted file mode 100644 index 8ae595f..0000000 --- a/tsconfig.cjs.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "CommonJS", - "target": "es5", - "outDir": "./dist/cjs" - } -} diff --git a/tsconfig.json b/tsconfig.json index 62923ad..c32c9c3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,17 @@ { "compilerOptions": { "target": "ES2017", - "module": "ES2020", + "module": "NodeNext", "lib": ["es2020", "es2017", "es7", "es6", "dom"], "declaration": true, "strict": true, "skipLibCheck": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "moduleResolution": "node", + "moduleResolution": "nodenext", "resolveJsonModule": true, "isolatedModules": true, - "outDir": "./dist/es" + "outDir": "./dist" }, "include": ["src/**/*"], "exclude": ["node_modules", "**.spec.*"],