diff --git a/packages/nuqs/package.json b/packages/nuqs/package.json index 86d9ca6d..ac3fa6c0 100644 --- a/packages/nuqs/package.json +++ b/packages/nuqs/package.json @@ -175,7 +175,8 @@ "size-limit": "^11.1.6", "tsup": "^8.3.6", "typescript": "^5.7.3", - "vitest": "^3.0.5" + "vitest": "^3.0.5", + "vitest-package-exports": "^0.1.0" }, "size-limit": [ { diff --git a/packages/nuqs/src/api.test.ts b/packages/nuqs/src/api.test.ts new file mode 100644 index 00000000..6407c549 --- /dev/null +++ b/packages/nuqs/src/api.test.ts @@ -0,0 +1,109 @@ +import { fileURLToPath } from 'node:url' +import { expect, it } from 'vitest' +import { getPackageExportsManifest } from 'vitest-package-exports' + +// Update the snapshot when updating the API +// (and adjust the documentation accordingly). +const exports = ` +{ + ".": { + "createLoader": "function", + "createParser": "function", + "createSerializer": "function", + "parseAsArrayOf": "function", + "parseAsBoolean": "object", + "parseAsFloat": "object", + "parseAsHex": "object", + "parseAsIndex": "object", + "parseAsInteger": "object", + "parseAsIsoDate": "object", + "parseAsIsoDateTime": "object", + "parseAsJson": "function", + "parseAsNumberLiteral": "function", + "parseAsString": "object", + "parseAsStringEnum": "function", + "parseAsStringLiteral": "function", + "parseAsTimestamp": "object", + "useQueryState": "function", + "useQueryStates": "function", + }, + "./adapters/custom": { + "renderQueryString": "function", + "unstable_createAdapterProvider": "function", + }, + "./adapters/next": { + "NuqsAdapter": "function", + }, + "./adapters/next/app": { + "NuqsAdapter": "function", + }, + "./adapters/next/pages": { + "NuqsAdapter": "function", + }, + "./adapters/react": { + "NuqsAdapter": "function", + "enableHistorySync": "function", + }, + "./adapters/react-router": { + "NuqsAdapter": "function", + "useOptimisticSearchParams": "function", + }, + "./adapters/react-router/v6": { + "NuqsAdapter": "function", + "useOptimisticSearchParams": "function", + }, + "./adapters/react-router/v7": { + "NuqsAdapter": "function", + "useOptimisticSearchParams": "function", + }, + "./adapters/remix": { + "NuqsAdapter": "function", + "useOptimisticSearchParams": "function", + }, + "./adapters/testing": { + "NuqsTestingAdapter": "function", + "withNuqsTestingAdapter": "function", + }, + "./server": { + "createLoader": "function", + "createParser": "function", + "createSearchParamsCache": "function", + "createSerializer": "function", + "parseAsArrayOf": "function", + "parseAsBoolean": "object", + "parseAsFloat": "object", + "parseAsHex": "object", + "parseAsIndex": "object", + "parseAsInteger": "object", + "parseAsIsoDate": "object", + "parseAsIsoDateTime": "object", + "parseAsJson": "function", + "parseAsNumberLiteral": "function", + "parseAsString": "object", + "parseAsStringEnum": "function", + "parseAsStringLiteral": "function", + "parseAsTimestamp": "object", + }, + "./testing": { + "isParserBijective": "function", + "testParseThenSerialize": "function", + "testSerializeThenParse": "function", + }, +} +` + +it('has a stable exported API (package.json)', async () => { + const manifest = await getPackageExportsManifest({ + importMode: 'package', + cwd: fileURLToPath(import.meta.url) + }) + expect(manifest.exports).toMatchInlineSnapshot(exports) +}) + +it('has a stable exported API (dist)', async () => { + const manifest = await getPackageExportsManifest({ + importMode: 'dist', + cwd: fileURLToPath(import.meta.url) + }) + expect(manifest.exports).toMatchInlineSnapshot(exports) +}) diff --git a/packages/nuqs/vitest.config.ts b/packages/nuqs/vitest.config.ts index 177221af..159e4bd0 100644 --- a/packages/nuqs/vitest.config.ts +++ b/packages/nuqs/vitest.config.ts @@ -7,6 +7,11 @@ export default defineConfig({ include: ['**/*.test.?(c|m)[jt]s?(x)'], env: { IS_REACT_ACT_ENVIRONMENT: 'true' + }, + server: { + deps: { + inline: ['vitest-package-exports'] + } } } }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 72df7b62..4ce20bb7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -576,6 +576,9 @@ importers: vitest: specifier: ^3.0.5 version: 3.0.5(@types/debug@4.1.12)(@types/node@22.13.1)(jiti@2.4.2)(jsdom@26.0.0)(terser@5.37.0)(yaml@2.7.0) + vitest-package-exports: + specifier: ^0.1.0 + version: 0.1.0 packages/res: {} @@ -6193,6 +6196,9 @@ packages: pathe@2.0.2: resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@2.0.0: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} @@ -7867,6 +7873,9 @@ packages: yaml: optional: true + vitest-package-exports@0.1.0: + resolution: {integrity: sha512-h83R5dqOstC0xNPLJUqvtu4yx83l7Eu4gMQJZfTYjP7eqvOoVUPK3hMBEQMzndleUygRatr7/kBHOeINEvz1OQ==} + vitest@3.0.5: resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -14567,6 +14576,8 @@ snapshots: pathe@2.0.2: {} + pathe@2.0.3: {} + pathval@2.0.0: {} pause-stream@0.0.11: @@ -16377,6 +16388,11 @@ snapshots: terser: 5.37.0 yaml: 2.7.0 + vitest-package-exports@0.1.0: + dependencies: + find-up-simple: 1.0.0 + pathe: 2.0.3 + vitest@3.0.5(@types/debug@4.1.12)(@types/node@22.13.1)(jiti@2.4.2)(jsdom@26.0.0)(terser@5.37.0)(yaml@2.7.0): dependencies: '@vitest/expect': 3.0.5