cloudflare-next-intl 0.9.49 → 0.9.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -305,7 +305,8 @@ export default defineConfig({
305
305
  localeFiles: true, // Enable @locale-file & glob bundling (default: true)
306
306
  userAgentStub: true, // Enable regex-based user-agent stub (default: true)
307
307
  cfWorkersClientStub: true, // Enable client cloudflare:workers stub (default: true)
308
- vinextRouteWiringFix: true, // Enable vinext route wiring, matching, and prefetch fixes (default: true, or options object)
308
+ vinextRouteWiringFix: false, // ⚠️ DANGER: Monkey-patches vinext on disk (default: false, or options object)
309
+ experimentalRouteLoadingFixes: false, // ⚠️ DANGER: Unified switch enabling both vinextRouteWiringFix and SSG on loading.* (default: false)
309
310
  lucideOptimizer: true, // Auto-optimize lucide-react deep imports and normalize next/*.js (default: true, or options object)
310
311
  }),
311
312
  ],
@@ -9,6 +9,9 @@ export interface CheckDynamicPagesOptions {
9
9
  mode?: DynamicPagesCheckMode;
10
10
  target?: 'next' | 'vinext';
11
11
  skip?: readonly string[];
12
+ includeLoading?: boolean;
13
+ verifyVinextRouteWiring?: boolean;
14
+ projectRoot?: string;
12
15
  resolveImports?: boolean;
13
16
  aliases?: readonly AliasConfig[];
14
17
  extraChecks?: readonly DynamicApiCheck[];
@@ -28,5 +31,6 @@ export interface CheckDynamicPagesIo {
28
31
  readFile?: (file: string) => string;
29
32
  writeFile?: (file: string, contents: string) => void;
30
33
  isFile?: (file: string) => boolean;
34
+ isVinextRouteWiringSafe?: (root: string) => boolean;
31
35
  }
32
36
  export declare function checkDynamicPages(options: CheckDynamicPagesOptions, io?: CheckDynamicPagesIo): Promise<(CheckDynamicPagesReport | SyncErrorReportingAuthUserReport)[]>;
@@ -6,6 +6,7 @@ import { traceDynamicUsage } from './trace_dynamic_usage.js';
6
6
  import { insertDynamicExport } from './insert_dynamic_export.js';
7
7
  import { syncErrorReportingAuthUser } from './sync_error_reporting_auth_user.js';
8
8
  import { deriveRoute, isApiRoute, makePageLabeler } from './derive_page_label.js';
9
+ import { isVinextAppPageRouteWiringSafeOnDisk } from '../vite/vinext_route_wiring_fix.js';
9
10
  const LEGEND = 'λ API ƒ Dynamic (SSR) ○ Static (SSG) = Already declared - Unclear (framework decides) · Skipped';
10
11
  function actionGlyph(report, isApi) {
11
12
  if (isApi && report.action !== 'skipped')
@@ -81,12 +82,33 @@ function defaultIsFile(path) {
81
82
  return false;
82
83
  }
83
84
  }
85
+ function isSsgAction(report) {
86
+ if (report.action === 'added-force-static' || report.action === 'would-add-force-static') {
87
+ return true;
88
+ }
89
+ if (report.action === 'already-declared') {
90
+ return report.explicitValue === 'force-static';
91
+ }
92
+ return false;
93
+ }
84
94
  export async function checkDynamicPages(options, io = {}) {
85
95
  const mode = options.mode ?? 'report';
86
96
  if (mode === 'off')
87
97
  return [];
88
98
  const target = options.target ?? 'next';
89
99
  const resolveImports = options.resolveImports ?? true;
100
+ let includeLoading = options.includeLoading ?? false;
101
+ if (includeLoading && target === 'vinext' && options.verifyVinextRouteWiring !== false) {
102
+ const projectRoot = options.projectRoot ?? resolve(options.appDir, '..');
103
+ const checkSafe = io.isVinextRouteWiringSafe ?? isVinextAppPageRouteWiringSafeOnDisk;
104
+ if (!checkSafe(projectRoot)) {
105
+ console.warn('[cloudflare-next-intl] WARNING: Vinext route wiring fix is not verified on disk (vinext files may have changed, failed to patch, or patch is disabled). SSG was NOT added to loading.* files.');
106
+ includeLoading = false;
107
+ }
108
+ }
109
+ if (includeLoading) {
110
+ console.warn('[cloudflare-next-intl] WARNING: includeLoading is enabled. Forcing SSG on loading.* files is dangerous and can break route rendering, streaming, or hydration.');
111
+ }
90
112
  const findPageFiles = io.findPageFiles ?? findPageFilesImpl;
91
113
  const readFile = io.readFile ?? ((file) => readFileSync(file, 'utf8'));
92
114
  const writeFile = io.writeFile ?? ((file, contents) => writeFileSync(file, contents, 'utf8'));
@@ -98,6 +120,9 @@ export async function checkDynamicPages(options, io = {}) {
98
120
  const extraChecks = options.extraChecks ?? [];
99
121
  const reports = [];
100
122
  for (const file of findPageFiles(options.appDir)) {
123
+ if (!includeLoading && fileKind(file) === 'loading') {
124
+ continue;
125
+ }
101
126
  if (skipSet.has(file)) {
102
127
  reports.push({ file, action: 'skipped' });
103
128
  continue;
@@ -135,6 +160,14 @@ export async function checkDynamicPages(options, io = {}) {
135
160
  reports.push({ file, action: 'would-add-force-dynamic', signals });
136
161
  }
137
162
  }
163
+ if (includeLoading) {
164
+ for (const report of reports) {
165
+ const r = report;
166
+ if (fileKind(r.file) === 'loading' && !isSsgAction(r)) {
167
+ console.warn(`[cloudflare-next-intl] WARNING: Loading file is not static (SSG): ${displayPath(r.file)}`);
168
+ }
169
+ }
170
+ }
138
171
  if (options.verbose) {
139
172
  const pageLabelStyle = typeof options.verbose === 'object' ? options.verbose.pageLabel : undefined;
140
173
  const pageLabel = makePageLabeler(options.appDir, pageLabelStyle, displayPath);
@@ -6,6 +6,16 @@ export const defaultStaleDeployPatterns = [
6
6
  'connection closed',
7
7
  'rsc payload',
8
8
  'minified react error #412',
9
+ 'minified react error #418',
10
+ 'minified react error #419',
11
+ 'minified react error #421',
12
+ 'minified react error #422',
13
+ 'minified react error #423',
14
+ 'minified react error #425',
15
+ 'minified react error #426',
16
+ 'an error occurred in the server components render',
17
+ 'server components render',
18
+ 'digest property is included on this error instance',
9
19
  'the above error occurred in a react component',
10
20
  'the connection to the page was unexpectedly closed',
11
21
  'readablestream',
@@ -4,6 +4,8 @@ export interface AutoDynamicPagesPluginOptions {
4
4
  appDir?: string;
5
5
  mode?: DynamicPagesCheckMode;
6
6
  target?: 'next' | 'vinext';
7
+ includeLoading?: boolean;
8
+ verifyVinextRouteWiring?: boolean;
7
9
  syncErrorReportingAuthUser?: boolean;
8
10
  extraChecks?: readonly DynamicApiCheck[];
9
11
  verbose?: boolean | {
@@ -32,8 +32,11 @@ export function autoDynamicPagesPlugin(options = {}) {
32
32
  try {
33
33
  const reports = await checkDynamicPages({
34
34
  appDir,
35
+ projectRoot: root,
35
36
  mode: options.mode ?? "fix",
36
37
  target: options.target ?? "vinext",
38
+ includeLoading: options.includeLoading ?? false,
39
+ verifyVinextRouteWiring: options.verifyVinextRouteWiring ?? true,
37
40
  syncErrorReportingAuthUser: options.syncErrorReportingAuthUser ?? false,
38
41
  extraChecks: options.extraChecks ?? [],
39
42
  verbose: options.verbose ?? false,
@@ -3,7 +3,7 @@ export { autoLocaleParamsPlugin, type AutoLocaleParamsPluginOptions } from "./au
3
3
  export { buildIdAsset } from "./build_id_asset.js";
4
4
  export { userAgentStubPlugin, USER_AGENT_STUB_ID, USER_AGENT_STUB_CODE } from "./user_agent_stub.js";
5
5
  export { cfWorkersClientStubPlugin, CF_WORKERS_CLIENT_STUB_ID, CF_WORKERS_CLIENT_STUB_CODE } from "./cf_workers_client_stub.js";
6
- export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed, type VinextRouteWiringFixPluginOptions } from "./vinext_route_wiring_fix.js";
6
+ export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed, isVinextAppPageRouteWiringSafeOnDisk, type VinextRouteWiringFixPluginOptions } from "./vinext_route_wiring_fix.js";
7
7
  export { localeFilePlugin, resolveDefaultIntlConfigPath, type LocaleFilePluginOptions } from "./locale_file_plugin.js";
8
8
  export { lucideOptimizerPlugin, detectLucideReact, resolveLucideEsmEntry, parseLucideIconMap, transformLucideImports, transformNextJsImports, type LucideOptimizerPluginOptions, } from "./lucide_optimizer_plugin.js";
9
9
  export { cloudflareNextIntl, cloudflareNextIntlPlugin, type CloudflareNextIntlOptions, default } from "./plugin.js";
@@ -3,7 +3,7 @@ export { autoLocaleParamsPlugin } from "./auto_locale_params_plugin.js";
3
3
  export { buildIdAsset } from "./build_id_asset.js";
4
4
  export { userAgentStubPlugin, USER_AGENT_STUB_ID, USER_AGENT_STUB_CODE } from "./user_agent_stub.js";
5
5
  export { cfWorkersClientStubPlugin, CF_WORKERS_CLIENT_STUB_ID, CF_WORKERS_CLIENT_STUB_CODE } from "./cf_workers_client_stub.js";
6
- export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed } from "./vinext_route_wiring_fix.js";
6
+ export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed, isVinextAppPageRouteWiringSafeOnDisk } from "./vinext_route_wiring_fix.js";
7
7
  export { localeFilePlugin, resolveDefaultIntlConfigPath } from "./locale_file_plugin.js";
8
8
  export { lucideOptimizerPlugin, detectLucideReact, resolveLucideEsmEntry, parseLucideIconMap, transformLucideImports, transformNextJsImports, } from "./lucide_optimizer_plugin.js";
9
9
  export { cloudflareNextIntl, cloudflareNextIntlPlugin, default } from "./plugin.js";
@@ -15,6 +15,7 @@ export interface CloudflareNextIntlOptions extends LocaleFilePluginOptions {
15
15
  imageOptimizer?: boolean | ImageOptimizerPluginOptions;
16
16
  vinextRouteWiringFix?: boolean | VinextRouteWiringFixPluginOptions;
17
17
  autoLocaleParams?: boolean | AutoLocaleParamsPluginOptions;
18
+ experimentalRouteLoadingFixes?: boolean;
18
19
  }
19
20
  export declare function cloudflareNextIntl(options?: CloudflareNextIntlOptions): Plugin[];
20
21
  export declare const cloudflareNextIntlPlugin: typeof cloudflareNextIntl;
@@ -14,15 +14,24 @@ export function cloudflareNextIntl(options = {}) {
14
14
  ? options.lucideOptimizer
15
15
  : { root: options.root }));
16
16
  }
17
+ const enableRouteLoadingFixes = options.experimentalRouteLoadingFixes === true;
18
+ const shouldEnableVinextFix = options.vinextRouteWiringFix !== undefined
19
+ ? Boolean(options.vinextRouteWiringFix)
20
+ : enableRouteLoadingFixes;
21
+ if (shouldEnableVinextFix) {
22
+ plugins.push(vinextRouteWiringFixPlugin(typeof options.vinextRouteWiringFix === "object" ? options.vinextRouteWiringFix : {}));
23
+ }
17
24
  if (options.autoLocaleParams !== false) {
18
25
  plugins.push(autoLocaleParamsPlugin(typeof options.autoLocaleParams === "object"
19
26
  ? options.autoLocaleParams
20
27
  : undefined));
21
28
  }
22
29
  if (options.autoDynamicPages !== false) {
23
- plugins.push(autoDynamicPagesPlugin(typeof options.autoDynamicPages === "object"
24
- ? options.autoDynamicPages
25
- : undefined));
30
+ const autoDynamicPagesOptions = typeof options.autoDynamicPages === "object" ? { ...options.autoDynamicPages } : {};
31
+ if (enableRouteLoadingFixes && autoDynamicPagesOptions.includeLoading === undefined) {
32
+ autoDynamicPagesOptions.includeLoading = true;
33
+ }
34
+ plugins.push(autoDynamicPagesPlugin(autoDynamicPagesOptions));
26
35
  }
27
36
  if (options.imageOptimizer !== false) {
28
37
  plugins.push(imageOptimizerPlugin(typeof options.imageOptimizer === "object"
@@ -39,9 +48,6 @@ export function cloudflareNextIntl(options = {}) {
39
48
  if (options.userAgentStub !== false) {
40
49
  plugins.push(userAgentStubPlugin());
41
50
  }
42
- if (options.vinextRouteWiringFix !== false) {
43
- plugins.push(vinextRouteWiringFixPlugin(typeof options.vinextRouteWiringFix === "object" ? options.vinextRouteWiringFix : {}));
44
- }
45
51
  if (options.localeFiles !== false) {
46
52
  plugins.push(localeFilePlugin({
47
53
  messagesDir: options.messagesDir,
@@ -13,6 +13,7 @@ export declare function patchPrefetchLearning(code: string): string;
13
13
  export declare function resolveVinextBrowserEntryPath(root?: string): string | null;
14
14
  export declare function isAppPageRouteWiringFile(id: string): boolean;
15
15
  export declare function resolveVinextAppPageRouteWiringPath(root?: string): string | null;
16
+ export declare function isVinextAppPageRouteWiringSafeOnDisk(root?: string): boolean;
16
17
  export declare function resolveVinextRouteMatchingPath(root?: string): string | null;
17
18
  export declare function resolveVinextOptimisticRoutingPath(root?: string): string | null;
18
19
  export interface SyncPatchVinextOnDiskOptions {
@@ -28,11 +28,35 @@ const FIXED_PREFETCH_LOADING_FN = `function getPrefetchLoadingEntry(route) {
28
28
  }`;
29
29
  const ROUTE_LOADING_GUARD_RE = /if\s*\(\s*!isPrefetchLoadingShell\s*&&\s*treePosition\s*<\s*routeSegments\.length\s*\)\s*\{/g;
30
30
  const FIXED_ROUTE_LOADING_GUARD = "if (!isPrefetchLoadingShell && treePosition < routeSegments.length && !routeLoadingComponent) {";
31
+ const PAGE_LOADING_FALLBACK_RE = /fallback:\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*PageLoadingComponent\s*,\s*\{\s*\}\s*\)/;
32
+ const FIXED_PAGE_LOADING_FALLBACK = "fallback: /* @__PURE__ */ jsx(PageLoadingComponent, { params: options.makeThenableParams(options.matchedParams) })";
33
+ const ANCESTOR_LOADING_FALLBACK_RE = /fallback:\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*AncestorLoadingComponent\s*,\s*\{\s*\}\s*\)/;
34
+ const FIXED_ANCESTOR_LOADING_FALLBACK = "fallback: /* @__PURE__ */ jsx(AncestorLoadingComponent, { params: options.makeThenableParams(resolveAppPageSegmentParams(options.route.routeSegments, ancestorLoadingEntry.treePosition, options.matchedParams)) })";
35
+ const BRANCH_LOADING_FALLBACK_RE = /fallback:\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*(?<![A-Za-z0-9_$])LoadingComponent\s*,\s*\{\s*\}\s*\)/;
36
+ const FIXED_BRANCH_LOADING_FALLBACK = "fallback: /* @__PURE__ */ jsx(LoadingComponent, { params: options.makeThenableParams(slotParams) })";
37
+ const OWNER_LOADING_FALLBACK_RE = /fallback:\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*OwnerLoadingComponent\s*,\s*\{\s*\}\s*\)/;
38
+ const FIXED_OWNER_LOADING_FALLBACK = "fallback: /* @__PURE__ */ jsx(OwnerLoadingComponent, { params: options.makeThenableParams(resolveAppPageSegmentParams(options.route.routeSegments, ownerLoadingEntry.treePosition, options.matchedParams)) })";
39
+ const PREFETCH_LOADING_CALL_RE = /routeChildren\s*=\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*prefetchLoadingComponent\s*,\s*\{\s*\}\s*\)/;
40
+ const FIXED_PREFETCH_LOADING_CALL = "routeChildren = /* @__PURE__ */ jsx(prefetchLoadingComponent, { params: options.makeThenableParams(options.matchedParams) })";
41
+ const ROUTE_LOADING_FALLBACK_RE = /fallback:\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*routeLoadingComponent\s*,\s*\{\s*\}\s*\)/;
42
+ const FIXED_ROUTE_LOADING_FALLBACK = "fallback: /* @__PURE__ */ jsx(routeLoadingComponent, { params: options.makeThenableParams(options.matchedParams) })";
43
+ const SEGMENT_LOADING_FALLBACK_RE = /fallback:\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*segmentLoadingComponent\s*,\s*\{\s*\}\s*\)/;
44
+ const FIXED_SEGMENT_LOADING_FALLBACK = "fallback: /* @__PURE__ */ jsx(segmentLoadingComponent, { params: options.makeThenableParams(resolveAppPageSegmentParams(options.route.routeSegments, treePosition, options.matchedParams)) })";
45
+ const PREFETCH_SLOT_LOADING_CALL_RE = /slotElement\s*=\s*\/\*\s*@__PURE__\s*\*\/\s*jsx\s*\(\s*getDefaultExport\s*\(\s*prefetchSlotLoadingEntry\.loadingModule\s*\)\s*,\s*\{\s*\}\s*\)/;
46
+ const FIXED_PREFETCH_SLOT_LOADING_CALL = "slotElement = /* @__PURE__ */ jsx(getDefaultExport(prefetchSlotLoadingEntry.loadingModule), { params: options.makeThenableParams(slotParams) })";
31
47
  export function isAppPageRouteWiringAlreadyFixed(code) {
32
48
  const hasBuggyPrefetch = code.includes("firstNestedEntry") &&
33
49
  PREFETCH_LOADING_FN_RE.test(code);
34
50
  const hasBuggySuspense = !code.includes("!routeLoadingComponent") && ROUTE_LOADING_GUARD_RE.test(code);
35
- return !hasBuggyPrefetch && !hasBuggySuspense;
51
+ const hasEmptyLoadingProps = PAGE_LOADING_FALLBACK_RE.test(code) ||
52
+ ANCESTOR_LOADING_FALLBACK_RE.test(code) ||
53
+ BRANCH_LOADING_FALLBACK_RE.test(code) ||
54
+ OWNER_LOADING_FALLBACK_RE.test(code) ||
55
+ PREFETCH_LOADING_CALL_RE.test(code) ||
56
+ ROUTE_LOADING_FALLBACK_RE.test(code) ||
57
+ SEGMENT_LOADING_FALLBACK_RE.test(code) ||
58
+ PREFETCH_SLOT_LOADING_CALL_RE.test(code);
59
+ return !hasBuggyPrefetch && !hasBuggySuspense && !hasEmptyLoadingProps;
36
60
  }
37
61
  export function patchAppPageRouteWiring(code) {
38
62
  if (isAppPageRouteWiringAlreadyFixed(code)) {
@@ -49,6 +73,30 @@ export function patchAppPageRouteWiring(code) {
49
73
  if (hasBuggySuspense) {
50
74
  result = result.replace(ROUTE_LOADING_GUARD_RE, FIXED_ROUTE_LOADING_GUARD);
51
75
  }
76
+ if (PAGE_LOADING_FALLBACK_RE.test(result)) {
77
+ result = result.replace(PAGE_LOADING_FALLBACK_RE, FIXED_PAGE_LOADING_FALLBACK);
78
+ }
79
+ while (ANCESTOR_LOADING_FALLBACK_RE.test(result)) {
80
+ result = result.replace(ANCESTOR_LOADING_FALLBACK_RE, FIXED_ANCESTOR_LOADING_FALLBACK);
81
+ }
82
+ if (BRANCH_LOADING_FALLBACK_RE.test(result)) {
83
+ result = result.replace(BRANCH_LOADING_FALLBACK_RE, FIXED_BRANCH_LOADING_FALLBACK);
84
+ }
85
+ if (OWNER_LOADING_FALLBACK_RE.test(result)) {
86
+ result = result.replace(OWNER_LOADING_FALLBACK_RE, FIXED_OWNER_LOADING_FALLBACK);
87
+ }
88
+ if (PREFETCH_LOADING_CALL_RE.test(result)) {
89
+ result = result.replace(PREFETCH_LOADING_CALL_RE, FIXED_PREFETCH_LOADING_CALL);
90
+ }
91
+ if (ROUTE_LOADING_FALLBACK_RE.test(result)) {
92
+ result = result.replace(ROUTE_LOADING_FALLBACK_RE, FIXED_ROUTE_LOADING_FALLBACK);
93
+ }
94
+ if (SEGMENT_LOADING_FALLBACK_RE.test(result)) {
95
+ result = result.replace(SEGMENT_LOADING_FALLBACK_RE, FIXED_SEGMENT_LOADING_FALLBACK);
96
+ }
97
+ if (PREFETCH_SLOT_LOADING_CALL_RE.test(result)) {
98
+ result = result.replace(PREFETCH_SLOT_LOADING_CALL_RE, FIXED_PREFETCH_SLOT_LOADING_CALL);
99
+ }
52
100
  return result;
53
101
  }
54
102
  export function isRouteMatchingFile(id) {
@@ -296,6 +344,18 @@ export function resolveVinextAppPageRouteWiringPath(root = process.cwd()) {
296
344
  const directPath = resolve(root, "node_modules/vinext/dist/server/app-page-route-wiring.js");
297
345
  return existsSync(directPath) ? directPath : null;
298
346
  }
347
+ export function isVinextAppPageRouteWiringSafeOnDisk(root = process.cwd()) {
348
+ const filePath = resolveVinextAppPageRouteWiringPath(root);
349
+ if (!filePath)
350
+ return false;
351
+ try {
352
+ const content = readFileSync(filePath, "utf8");
353
+ return isAppPageRouteWiringAlreadyFixed(content);
354
+ }
355
+ catch {
356
+ return false;
357
+ }
358
+ }
299
359
  export function resolveVinextRouteMatchingPath(root = process.cwd()) {
300
360
  const directPath = resolve(root, "node_modules/vinext/dist/routing/route-matching.js");
301
361
  return existsSync(directPath) ? directPath : null;
@@ -397,6 +457,7 @@ export function bustVinextOptimizeDepsCache(cacheDir) {
397
457
  return removed;
398
458
  }
399
459
  export function vinextRouteWiringFixPlugin(options = {}) {
460
+ console.warn("[cloudflare-next-intl] WARNING: vinextRouteWiringFix is enabled. Monkey-patching vinext on disk is dangerous and can break routing or upstream compatibility.");
400
461
  const routeWiring = options.routeWiring !== false;
401
462
  const routeMatching = options.routeMatching !== false;
402
463
  const optimisticRouting = options.optimisticRouting !== false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.9.49",
3
+ "version": "0.9.50",
4
4
  "description": "Optimized Next Intl Package Special for App Router and Cloudflare",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",