Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@tanstack/router-utils

Package Overview
Dependencies
Maintainers
7
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/router-utils - npm Package Compare versions

Comparing version
1.161.7
to
1.161.8
+19
-10
dist/cjs/ast.cjs

@@ -9,17 +9,26 @@ const require_runtime = require("./_virtual/_rolldown/runtime.cjs");

//#region src/ast.ts
function parseAst({ code, ...opts }) {
function parseAst({ code, filename, sourceFilename, plugins, ...opts }) {
return (0, _babel_parser.parse)(code, {
plugins: [
"jsx",
"typescript",
"explicitResourceManagement",
"importAttributes",
"deprecatedImportAssert",
["decorators", { decoratorsBeforeExport: true }],
"decoratorAutoAccessors"
],
plugins: plugins ?? getDefaultParserPluginsForFilename(filename ?? sourceFilename),
sourceType: "module",
sourceFilename,
...opts
});
}
function getDefaultParserPluginsForFilename(filename) {
const plugins = [
"typescript",
"explicitResourceManagement",
"importAttributes",
"deprecatedImportAssert",
["decorators", { decoratorsBeforeExport: true }],
"decoratorAutoAccessors"
];
if (!isPlainTypeScriptFile(filename)) plugins.unshift("jsx");
return plugins;
}
function isPlainTypeScriptFile(filename) {
if (!filename) return false;
return /\.[cm]?ts(?:$|[?#])/.test(filename);
}
var generate = _babel_generator.default;

@@ -26,0 +35,0 @@ if ("default" in generate) generate = generate.default;

@@ -1,1 +0,1 @@

{"version":3,"file":"ast.cjs","names":[],"sources":["../../src/ast.ts"],"sourcesContent":["import { parse } from '@babel/parser'\nimport _generate from '@babel/generator'\nimport * as t from '@babel/types'\nimport {\n deadCodeElimination as _deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport type { GeneratorOptions, GeneratorResult } from '@babel/generator'\nimport type { ParseResult, ParserOptions } from '@babel/parser'\nimport type * as _babel_types from '@babel/types'\n\nexport type ParseAstOptions = ParserOptions & {\n code: string\n}\n\nexport type ParseAstResult = ParseResult<_babel_types.File>\nexport function parseAst({ code, ...opts }: ParseAstOptions): ParseAstResult {\n return parse(code, {\n plugins: [\n 'jsx',\n 'typescript',\n 'explicitResourceManagement',\n 'importAttributes',\n 'deprecatedImportAssert',\n ['decorators', { decoratorsBeforeExport: true }],\n 'decoratorAutoAccessors',\n ],\n sourceType: 'module',\n ...opts,\n })\n}\n\nlet generate = _generate\n\nif ('default' in generate) {\n generate = generate.default as typeof generate\n}\ntype GenerateFromAstOptions = GeneratorOptions &\n Required<Pick<GeneratorOptions, 'sourceFileName' | 'filename'>>\nexport function generateFromAst(\n ast: _babel_types.Node,\n opts?: GenerateFromAstOptions,\n): GeneratorResult {\n return generate(\n ast,\n opts\n ? { importAttributesKeyword: 'with', sourceMaps: true, ...opts }\n : undefined,\n )\n}\nexport type { GeneratorResult } from '@babel/generator'\n\n/**\n * Strips TypeScript type-only exports and imports from an AST.\n *\n * This is necessary because babel-dead-code-elimination doesn't handle\n * TypeScript type exports/imports. When a type export references an import\n * that pulls in server-only code, the dead code elimination won't remove\n * that import because it sees the type as still referencing it.\n *\n * This function removes:\n * - `export type Foo = ...`\n * - `export interface Foo { ... }`\n * - `export type { Foo } from './module'`\n * - `export type * from './module'`\n * - Type specifiers in mixed exports: `export { value, type Foo }` -> `export { value }`\n * - `import type { Foo } from './module'`\n * - Type specifiers in mixed imports: `import { value, type Foo } from './module'` -> `import { value }`\n *\n * Note: Non-exported type/interface declarations are preserved as they may be\n * used as type annotations within the code.\n *\n * @param ast - The Babel AST (or ParseResult) to mutate\n */\nexport function stripTypeExports(ast: ParseResult<_babel_types.File>): void {\n // Filter the program body to remove type-only nodes\n ast.program.body = ast.program.body.filter((node) => {\n // Handle export declarations\n if (t.isExportNamedDeclaration(node)) {\n // Remove entire export if it's a type-only export\n // e.g., `export type Foo = string`, `export interface Bar {}`, `export type { X } from './y'`\n if (node.exportKind === 'type') {\n return false\n }\n\n // For value exports with mixed specifiers, filter out type-only specifiers\n // e.g., `export { value, type TypeOnly }` -> `export { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isExportSpecifier(specifier)) {\n return specifier.exportKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire export declaration\n // (unless it has a declaration like `export const x = 1`)\n if (node.specifiers.length === 0 && !node.declaration) {\n return false\n }\n }\n }\n\n // Handle type-only export-all declarations\n // e.g., `export type * from './module'`\n if (t.isExportAllDeclaration(node)) {\n if (node.exportKind === 'type') {\n return false\n }\n }\n\n // Handle import declarations\n if (t.isImportDeclaration(node)) {\n // Remove entire import if it's a type-only import\n // e.g., `import type { Foo } from './module'`\n if (node.importKind === 'type') {\n return false\n }\n\n // For value imports with mixed specifiers, filter out type-only specifiers\n // e.g., `import { value, type TypeOnly } from './module'` -> `import { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isImportSpecifier(specifier)) {\n return specifier.importKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire import declaration\n if (node.specifiers.length === 0) {\n return false\n }\n }\n }\n\n return true\n })\n}\n\n// Re-export findReferencedIdentifiers from babel-dead-code-elimination\nexport { findReferencedIdentifiers }\n\n/**\n * Performs dead code elimination on the AST, with TypeScript type stripping.\n *\n * This is a wrapper around babel-dead-code-elimination that first strips\n * TypeScript type-only exports and imports. This is necessary because\n * babel-dead-code-elimination doesn't handle type exports, which can cause\n * imports to be retained when they're only referenced by type exports.\n *\n * @param ast - The Babel AST to mutate\n * @param candidates - Optional set of identifier paths to consider for removal.\n * If provided, only these identifiers will be candidates for removal.\n * This should be the result of `findReferencedIdentifiers(ast)` called\n * before any AST transformations.\n */\nexport function deadCodeElimination(\n ast: ParseResult<_babel_types.File>,\n candidates?: ReturnType<typeof findReferencedIdentifiers>,\n): void {\n // First strip TypeScript type-only exports and imports\n stripTypeExports(ast)\n\n // Then run the original dead code elimination\n _deadCodeElimination(ast, candidates)\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,SAAS,EAAE,MAAM,GAAG,QAAyC;AAC3E,SAAA,GAAA,cAAA,OAAa,MAAM;EACjB,SAAS;GACP;GACA;GACA;GACA;GACA;GACA,CAAC,cAAc,EAAE,wBAAwB,MAAM,CAAC;GAChD;GACD;EACD,YAAY;EACZ,GAAG;EACJ,CAAC;;AAGJ,IAAI,WAAW,iBAAA;AAEf,IAAI,aAAa,SACf,YAAW,SAAS;AAItB,SAAgB,gBACd,KACA,MACiB;AACjB,QAAO,SACL,KACA,OACI;EAAE,yBAAyB;EAAQ,YAAY;EAAM,GAAG;EAAM,GAC9D,KAAA,EACL;;;;;;;;;;;;;;;;;;;;;;;;AA0BH,SAAgB,iBAAiB,KAA2C;AAE1E,KAAI,QAAQ,OAAO,IAAI,QAAQ,KAAK,QAAQ,SAAS;AAEnD,MAAI,aAAE,yBAAyB,KAAK,EAAE;AAGpC,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,aAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAIF,QAAI,KAAK,WAAW,WAAW,KAAK,CAAC,KAAK,YACxC,QAAO;;;AAOb,MAAI,aAAE,uBAAuB,KAAK;OAC5B,KAAK,eAAe,OACtB,QAAO;;AAKX,MAAI,aAAE,oBAAoB,KAAK,EAAE;AAG/B,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,aAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAGF,QAAI,KAAK,WAAW,WAAW,EAC7B,QAAO;;;AAKb,SAAO;GACP;;;;;;;;;;;;;;;;AAoBJ,SAAgB,oBACd,KACA,YACM;AAEN,kBAAiB,IAAI;AAGrB,EAAA,GAAA,4BAAA,qBAAqB,KAAK,WAAW"}
{"version":3,"file":"ast.cjs","names":[],"sources":["../../src/ast.ts"],"sourcesContent":["import { parse } from '@babel/parser'\nimport _generate from '@babel/generator'\nimport * as t from '@babel/types'\nimport {\n deadCodeElimination as _deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport type { GeneratorOptions, GeneratorResult } from '@babel/generator'\nimport type { ParseResult, ParserOptions } from '@babel/parser'\nimport type * as _babel_types from '@babel/types'\n\nexport type ParseAstOptions = ParserOptions & {\n code: string\n filename?: string\n}\n\nexport type ParseAstResult = ParseResult<_babel_types.File>\nexport function parseAst({\n code,\n filename,\n sourceFilename,\n plugins,\n ...opts\n}: ParseAstOptions): ParseAstResult {\n const inferredFilename = filename ?? sourceFilename\n return parse(code, {\n plugins: plugins ?? getDefaultParserPluginsForFilename(inferredFilename),\n sourceType: 'module',\n sourceFilename,\n ...opts,\n })\n}\n\nfunction getDefaultParserPluginsForFilename(\n filename: string | undefined,\n): NonNullable<ParserOptions['plugins']> {\n const plugins: NonNullable<ParserOptions['plugins']> = [\n 'typescript',\n 'explicitResourceManagement',\n 'importAttributes',\n 'deprecatedImportAssert',\n ['decorators', { decoratorsBeforeExport: true }],\n 'decoratorAutoAccessors',\n ]\n\n if (!isPlainTypeScriptFile(filename)) {\n plugins.unshift('jsx')\n }\n\n return plugins\n}\n\nfunction isPlainTypeScriptFile(filename: string | undefined): boolean {\n if (!filename) {\n return false\n }\n\n return /\\.[cm]?ts(?:$|[?#])/.test(filename)\n}\n\nlet generate = _generate\n\nif ('default' in generate) {\n generate = generate.default as typeof generate\n}\ntype GenerateFromAstOptions = GeneratorOptions &\n Required<Pick<GeneratorOptions, 'sourceFileName' | 'filename'>>\nexport function generateFromAst(\n ast: _babel_types.Node,\n opts?: GenerateFromAstOptions,\n): GeneratorResult {\n return generate(\n ast,\n opts\n ? { importAttributesKeyword: 'with', sourceMaps: true, ...opts }\n : undefined,\n )\n}\nexport type { GeneratorResult } from '@babel/generator'\n\n/**\n * Strips TypeScript type-only exports and imports from an AST.\n *\n * This is necessary because babel-dead-code-elimination doesn't handle\n * TypeScript type exports/imports. When a type export references an import\n * that pulls in server-only code, the dead code elimination won't remove\n * that import because it sees the type as still referencing it.\n *\n * This function removes:\n * - `export type Foo = ...`\n * - `export interface Foo { ... }`\n * - `export type { Foo } from './module'`\n * - `export type * from './module'`\n * - Type specifiers in mixed exports: `export { value, type Foo }` -> `export { value }`\n * - `import type { Foo } from './module'`\n * - Type specifiers in mixed imports: `import { value, type Foo } from './module'` -> `import { value }`\n *\n * Note: Non-exported type/interface declarations are preserved as they may be\n * used as type annotations within the code.\n *\n * @param ast - The Babel AST (or ParseResult) to mutate\n */\nexport function stripTypeExports(ast: ParseResult<_babel_types.File>): void {\n // Filter the program body to remove type-only nodes\n ast.program.body = ast.program.body.filter((node) => {\n // Handle export declarations\n if (t.isExportNamedDeclaration(node)) {\n // Remove entire export if it's a type-only export\n // e.g., `export type Foo = string`, `export interface Bar {}`, `export type { X } from './y'`\n if (node.exportKind === 'type') {\n return false\n }\n\n // For value exports with mixed specifiers, filter out type-only specifiers\n // e.g., `export { value, type TypeOnly }` -> `export { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isExportSpecifier(specifier)) {\n return specifier.exportKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire export declaration\n // (unless it has a declaration like `export const x = 1`)\n if (node.specifiers.length === 0 && !node.declaration) {\n return false\n }\n }\n }\n\n // Handle type-only export-all declarations\n // e.g., `export type * from './module'`\n if (t.isExportAllDeclaration(node)) {\n if (node.exportKind === 'type') {\n return false\n }\n }\n\n // Handle import declarations\n if (t.isImportDeclaration(node)) {\n // Remove entire import if it's a type-only import\n // e.g., `import type { Foo } from './module'`\n if (node.importKind === 'type') {\n return false\n }\n\n // For value imports with mixed specifiers, filter out type-only specifiers\n // e.g., `import { value, type TypeOnly } from './module'` -> `import { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isImportSpecifier(specifier)) {\n return specifier.importKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire import declaration\n if (node.specifiers.length === 0) {\n return false\n }\n }\n }\n\n return true\n })\n}\n\n// Re-export findReferencedIdentifiers from babel-dead-code-elimination\nexport { findReferencedIdentifiers }\n\n/**\n * Performs dead code elimination on the AST, with TypeScript type stripping.\n *\n * This is a wrapper around babel-dead-code-elimination that first strips\n * TypeScript type-only exports and imports. This is necessary because\n * babel-dead-code-elimination doesn't handle type exports, which can cause\n * imports to be retained when they're only referenced by type exports.\n *\n * @param ast - The Babel AST to mutate\n * @param candidates - Optional set of identifier paths to consider for removal.\n * If provided, only these identifiers will be candidates for removal.\n * This should be the result of `findReferencedIdentifiers(ast)` called\n * before any AST transformations.\n */\nexport function deadCodeElimination(\n ast: ParseResult<_babel_types.File>,\n candidates?: ReturnType<typeof findReferencedIdentifiers>,\n): void {\n // First strip TypeScript type-only exports and imports\n stripTypeExports(ast)\n\n // Then run the original dead code elimination\n _deadCodeElimination(ast, candidates)\n}\n"],"mappings":";;;;;;;;AAiBA,SAAgB,SAAS,EACvB,MACA,UACA,gBACA,SACA,GAAG,QAC+B;AAElC,SAAA,GAAA,cAAA,OAAa,MAAM;EACjB,SAAS,WAAW,mCAFG,YAAY,eAEqC;EACxE,YAAY;EACZ;EACA,GAAG;EACJ,CAAC;;AAGJ,SAAS,mCACP,UACuC;CACvC,MAAM,UAAiD;EACrD;EACA;EACA;EACA;EACA,CAAC,cAAc,EAAE,wBAAwB,MAAM,CAAC;EAChD;EACD;AAED,KAAI,CAAC,sBAAsB,SAAS,CAClC,SAAQ,QAAQ,MAAM;AAGxB,QAAO;;AAGT,SAAS,sBAAsB,UAAuC;AACpE,KAAI,CAAC,SACH,QAAO;AAGT,QAAO,sBAAsB,KAAK,SAAS;;AAG7C,IAAI,WAAW,iBAAA;AAEf,IAAI,aAAa,SACf,YAAW,SAAS;AAItB,SAAgB,gBACd,KACA,MACiB;AACjB,QAAO,SACL,KACA,OACI;EAAE,yBAAyB;EAAQ,YAAY;EAAM,GAAG;EAAM,GAC9D,KAAA,EACL;;;;;;;;;;;;;;;;;;;;;;;;AA0BH,SAAgB,iBAAiB,KAA2C;AAE1E,KAAI,QAAQ,OAAO,IAAI,QAAQ,KAAK,QAAQ,SAAS;AAEnD,MAAI,aAAE,yBAAyB,KAAK,EAAE;AAGpC,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,aAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAIF,QAAI,KAAK,WAAW,WAAW,KAAK,CAAC,KAAK,YACxC,QAAO;;;AAOb,MAAI,aAAE,uBAAuB,KAAK;OAC5B,KAAK,eAAe,OACtB,QAAO;;AAKX,MAAI,aAAE,oBAAoB,KAAK,EAAE;AAG/B,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,aAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAGF,QAAI,KAAK,WAAW,WAAW,EAC7B,QAAO;;;AAKb,SAAO;GACP;;;;;;;;;;;;;;;;AAoBJ,SAAgB,oBACd,KACA,YACM;AAEN,kBAAiB,IAAI;AAGrB,EAAA,GAAA,4BAAA,qBAAqB,KAAK,WAAW"}

@@ -7,5 +7,6 @@ import { findReferencedIdentifiers } from 'babel-dead-code-elimination';

code: string;
filename?: string;
};
export type ParseAstResult = ParseResult<_babel_types.File>;
export declare function parseAst({ code, ...opts }: ParseAstOptions): ParseAstResult;
export declare function parseAst({ code, filename, sourceFilename, plugins, ...opts }: ParseAstOptions): ParseAstResult;
type GenerateFromAstOptions = GeneratorOptions & Required<Pick<GeneratorOptions, 'sourceFileName' | 'filename'>>;

@@ -12,0 +13,0 @@ export declare function generateFromAst(ast: _babel_types.Node, opts?: GenerateFromAstOptions): GeneratorResult;

@@ -7,5 +7,6 @@ import { findReferencedIdentifiers } from 'babel-dead-code-elimination';

code: string;
filename?: string;
};
export type ParseAstResult = ParseResult<_babel_types.File>;
export declare function parseAst({ code, ...opts }: ParseAstOptions): ParseAstResult;
export declare function parseAst({ code, filename, sourceFilename, plugins, ...opts }: ParseAstOptions): ParseAstResult;
type GenerateFromAstOptions = GeneratorOptions & Required<Pick<GeneratorOptions, 'sourceFileName' | 'filename'>>;

@@ -12,0 +13,0 @@ export declare function generateFromAst(ast: _babel_types.Node, opts?: GenerateFromAstOptions): GeneratorResult;

@@ -6,17 +6,26 @@ import { parse } from "@babel/parser";

//#region src/ast.ts
function parseAst({ code, ...opts }) {
function parseAst({ code, filename, sourceFilename, plugins, ...opts }) {
return parse(code, {
plugins: [
"jsx",
"typescript",
"explicitResourceManagement",
"importAttributes",
"deprecatedImportAssert",
["decorators", { decoratorsBeforeExport: true }],
"decoratorAutoAccessors"
],
plugins: plugins ?? getDefaultParserPluginsForFilename(filename ?? sourceFilename),
sourceType: "module",
sourceFilename,
...opts
});
}
function getDefaultParserPluginsForFilename(filename) {
const plugins = [
"typescript",
"explicitResourceManagement",
"importAttributes",
"deprecatedImportAssert",
["decorators", { decoratorsBeforeExport: true }],
"decoratorAutoAccessors"
];
if (!isPlainTypeScriptFile(filename)) plugins.unshift("jsx");
return plugins;
}
function isPlainTypeScriptFile(filename) {
if (!filename) return false;
return /\.[cm]?ts(?:$|[?#])/.test(filename);
}
var generate = _generate;

@@ -23,0 +32,0 @@ if ("default" in generate) generate = generate.default;

@@ -1,1 +0,1 @@

{"version":3,"file":"ast.js","names":[],"sources":["../../src/ast.ts"],"sourcesContent":["import { parse } from '@babel/parser'\nimport _generate from '@babel/generator'\nimport * as t from '@babel/types'\nimport {\n deadCodeElimination as _deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport type { GeneratorOptions, GeneratorResult } from '@babel/generator'\nimport type { ParseResult, ParserOptions } from '@babel/parser'\nimport type * as _babel_types from '@babel/types'\n\nexport type ParseAstOptions = ParserOptions & {\n code: string\n}\n\nexport type ParseAstResult = ParseResult<_babel_types.File>\nexport function parseAst({ code, ...opts }: ParseAstOptions): ParseAstResult {\n return parse(code, {\n plugins: [\n 'jsx',\n 'typescript',\n 'explicitResourceManagement',\n 'importAttributes',\n 'deprecatedImportAssert',\n ['decorators', { decoratorsBeforeExport: true }],\n 'decoratorAutoAccessors',\n ],\n sourceType: 'module',\n ...opts,\n })\n}\n\nlet generate = _generate\n\nif ('default' in generate) {\n generate = generate.default as typeof generate\n}\ntype GenerateFromAstOptions = GeneratorOptions &\n Required<Pick<GeneratorOptions, 'sourceFileName' | 'filename'>>\nexport function generateFromAst(\n ast: _babel_types.Node,\n opts?: GenerateFromAstOptions,\n): GeneratorResult {\n return generate(\n ast,\n opts\n ? { importAttributesKeyword: 'with', sourceMaps: true, ...opts }\n : undefined,\n )\n}\nexport type { GeneratorResult } from '@babel/generator'\n\n/**\n * Strips TypeScript type-only exports and imports from an AST.\n *\n * This is necessary because babel-dead-code-elimination doesn't handle\n * TypeScript type exports/imports. When a type export references an import\n * that pulls in server-only code, the dead code elimination won't remove\n * that import because it sees the type as still referencing it.\n *\n * This function removes:\n * - `export type Foo = ...`\n * - `export interface Foo { ... }`\n * - `export type { Foo } from './module'`\n * - `export type * from './module'`\n * - Type specifiers in mixed exports: `export { value, type Foo }` -> `export { value }`\n * - `import type { Foo } from './module'`\n * - Type specifiers in mixed imports: `import { value, type Foo } from './module'` -> `import { value }`\n *\n * Note: Non-exported type/interface declarations are preserved as they may be\n * used as type annotations within the code.\n *\n * @param ast - The Babel AST (or ParseResult) to mutate\n */\nexport function stripTypeExports(ast: ParseResult<_babel_types.File>): void {\n // Filter the program body to remove type-only nodes\n ast.program.body = ast.program.body.filter((node) => {\n // Handle export declarations\n if (t.isExportNamedDeclaration(node)) {\n // Remove entire export if it's a type-only export\n // e.g., `export type Foo = string`, `export interface Bar {}`, `export type { X } from './y'`\n if (node.exportKind === 'type') {\n return false\n }\n\n // For value exports with mixed specifiers, filter out type-only specifiers\n // e.g., `export { value, type TypeOnly }` -> `export { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isExportSpecifier(specifier)) {\n return specifier.exportKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire export declaration\n // (unless it has a declaration like `export const x = 1`)\n if (node.specifiers.length === 0 && !node.declaration) {\n return false\n }\n }\n }\n\n // Handle type-only export-all declarations\n // e.g., `export type * from './module'`\n if (t.isExportAllDeclaration(node)) {\n if (node.exportKind === 'type') {\n return false\n }\n }\n\n // Handle import declarations\n if (t.isImportDeclaration(node)) {\n // Remove entire import if it's a type-only import\n // e.g., `import type { Foo } from './module'`\n if (node.importKind === 'type') {\n return false\n }\n\n // For value imports with mixed specifiers, filter out type-only specifiers\n // e.g., `import { value, type TypeOnly } from './module'` -> `import { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isImportSpecifier(specifier)) {\n return specifier.importKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire import declaration\n if (node.specifiers.length === 0) {\n return false\n }\n }\n }\n\n return true\n })\n}\n\n// Re-export findReferencedIdentifiers from babel-dead-code-elimination\nexport { findReferencedIdentifiers }\n\n/**\n * Performs dead code elimination on the AST, with TypeScript type stripping.\n *\n * This is a wrapper around babel-dead-code-elimination that first strips\n * TypeScript type-only exports and imports. This is necessary because\n * babel-dead-code-elimination doesn't handle type exports, which can cause\n * imports to be retained when they're only referenced by type exports.\n *\n * @param ast - The Babel AST to mutate\n * @param candidates - Optional set of identifier paths to consider for removal.\n * If provided, only these identifiers will be candidates for removal.\n * This should be the result of `findReferencedIdentifiers(ast)` called\n * before any AST transformations.\n */\nexport function deadCodeElimination(\n ast: ParseResult<_babel_types.File>,\n candidates?: ReturnType<typeof findReferencedIdentifiers>,\n): void {\n // First strip TypeScript type-only exports and imports\n stripTypeExports(ast)\n\n // Then run the original dead code elimination\n _deadCodeElimination(ast, candidates)\n}\n"],"mappings":";;;;;AAgBA,SAAgB,SAAS,EAAE,MAAM,GAAG,QAAyC;AAC3E,QAAO,MAAM,MAAM;EACjB,SAAS;GACP;GACA;GACA;GACA;GACA;GACA,CAAC,cAAc,EAAE,wBAAwB,MAAM,CAAC;GAChD;GACD;EACD,YAAY;EACZ,GAAG;EACJ,CAAC;;AAGJ,IAAI,WAAW;AAEf,IAAI,aAAa,SACf,YAAW,SAAS;AAItB,SAAgB,gBACd,KACA,MACiB;AACjB,QAAO,SACL,KACA,OACI;EAAE,yBAAyB;EAAQ,YAAY;EAAM,GAAG;EAAM,GAC9D,KAAA,EACL;;;;;;;;;;;;;;;;;;;;;;;;AA0BH,SAAgB,iBAAiB,KAA2C;AAE1E,KAAI,QAAQ,OAAO,IAAI,QAAQ,KAAK,QAAQ,SAAS;AAEnD,MAAI,EAAE,yBAAyB,KAAK,EAAE;AAGpC,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,EAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAIF,QAAI,KAAK,WAAW,WAAW,KAAK,CAAC,KAAK,YACxC,QAAO;;;AAOb,MAAI,EAAE,uBAAuB,KAAK;OAC5B,KAAK,eAAe,OACtB,QAAO;;AAKX,MAAI,EAAE,oBAAoB,KAAK,EAAE;AAG/B,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,EAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAGF,QAAI,KAAK,WAAW,WAAW,EAC7B,QAAO;;;AAKb,SAAO;GACP;;;;;;;;;;;;;;;;AAoBJ,SAAgB,sBACd,KACA,YACM;AAEN,kBAAiB,IAAI;AAGrB,qBAAqB,KAAK,WAAW"}
{"version":3,"file":"ast.js","names":[],"sources":["../../src/ast.ts"],"sourcesContent":["import { parse } from '@babel/parser'\nimport _generate from '@babel/generator'\nimport * as t from '@babel/types'\nimport {\n deadCodeElimination as _deadCodeElimination,\n findReferencedIdentifiers,\n} from 'babel-dead-code-elimination'\nimport type { GeneratorOptions, GeneratorResult } from '@babel/generator'\nimport type { ParseResult, ParserOptions } from '@babel/parser'\nimport type * as _babel_types from '@babel/types'\n\nexport type ParseAstOptions = ParserOptions & {\n code: string\n filename?: string\n}\n\nexport type ParseAstResult = ParseResult<_babel_types.File>\nexport function parseAst({\n code,\n filename,\n sourceFilename,\n plugins,\n ...opts\n}: ParseAstOptions): ParseAstResult {\n const inferredFilename = filename ?? sourceFilename\n return parse(code, {\n plugins: plugins ?? getDefaultParserPluginsForFilename(inferredFilename),\n sourceType: 'module',\n sourceFilename,\n ...opts,\n })\n}\n\nfunction getDefaultParserPluginsForFilename(\n filename: string | undefined,\n): NonNullable<ParserOptions['plugins']> {\n const plugins: NonNullable<ParserOptions['plugins']> = [\n 'typescript',\n 'explicitResourceManagement',\n 'importAttributes',\n 'deprecatedImportAssert',\n ['decorators', { decoratorsBeforeExport: true }],\n 'decoratorAutoAccessors',\n ]\n\n if (!isPlainTypeScriptFile(filename)) {\n plugins.unshift('jsx')\n }\n\n return plugins\n}\n\nfunction isPlainTypeScriptFile(filename: string | undefined): boolean {\n if (!filename) {\n return false\n }\n\n return /\\.[cm]?ts(?:$|[?#])/.test(filename)\n}\n\nlet generate = _generate\n\nif ('default' in generate) {\n generate = generate.default as typeof generate\n}\ntype GenerateFromAstOptions = GeneratorOptions &\n Required<Pick<GeneratorOptions, 'sourceFileName' | 'filename'>>\nexport function generateFromAst(\n ast: _babel_types.Node,\n opts?: GenerateFromAstOptions,\n): GeneratorResult {\n return generate(\n ast,\n opts\n ? { importAttributesKeyword: 'with', sourceMaps: true, ...opts }\n : undefined,\n )\n}\nexport type { GeneratorResult } from '@babel/generator'\n\n/**\n * Strips TypeScript type-only exports and imports from an AST.\n *\n * This is necessary because babel-dead-code-elimination doesn't handle\n * TypeScript type exports/imports. When a type export references an import\n * that pulls in server-only code, the dead code elimination won't remove\n * that import because it sees the type as still referencing it.\n *\n * This function removes:\n * - `export type Foo = ...`\n * - `export interface Foo { ... }`\n * - `export type { Foo } from './module'`\n * - `export type * from './module'`\n * - Type specifiers in mixed exports: `export { value, type Foo }` -> `export { value }`\n * - `import type { Foo } from './module'`\n * - Type specifiers in mixed imports: `import { value, type Foo } from './module'` -> `import { value }`\n *\n * Note: Non-exported type/interface declarations are preserved as they may be\n * used as type annotations within the code.\n *\n * @param ast - The Babel AST (or ParseResult) to mutate\n */\nexport function stripTypeExports(ast: ParseResult<_babel_types.File>): void {\n // Filter the program body to remove type-only nodes\n ast.program.body = ast.program.body.filter((node) => {\n // Handle export declarations\n if (t.isExportNamedDeclaration(node)) {\n // Remove entire export if it's a type-only export\n // e.g., `export type Foo = string`, `export interface Bar {}`, `export type { X } from './y'`\n if (node.exportKind === 'type') {\n return false\n }\n\n // For value exports with mixed specifiers, filter out type-only specifiers\n // e.g., `export { value, type TypeOnly }` -> `export { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isExportSpecifier(specifier)) {\n return specifier.exportKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire export declaration\n // (unless it has a declaration like `export const x = 1`)\n if (node.specifiers.length === 0 && !node.declaration) {\n return false\n }\n }\n }\n\n // Handle type-only export-all declarations\n // e.g., `export type * from './module'`\n if (t.isExportAllDeclaration(node)) {\n if (node.exportKind === 'type') {\n return false\n }\n }\n\n // Handle import declarations\n if (t.isImportDeclaration(node)) {\n // Remove entire import if it's a type-only import\n // e.g., `import type { Foo } from './module'`\n if (node.importKind === 'type') {\n return false\n }\n\n // For value imports with mixed specifiers, filter out type-only specifiers\n // e.g., `import { value, type TypeOnly } from './module'` -> `import { value }`\n if (node.specifiers.length > 0) {\n node.specifiers = node.specifiers.filter((specifier) => {\n if (t.isImportSpecifier(specifier)) {\n return specifier.importKind !== 'type'\n }\n return true\n })\n\n // If all specifiers were removed, remove the entire import declaration\n if (node.specifiers.length === 0) {\n return false\n }\n }\n }\n\n return true\n })\n}\n\n// Re-export findReferencedIdentifiers from babel-dead-code-elimination\nexport { findReferencedIdentifiers }\n\n/**\n * Performs dead code elimination on the AST, with TypeScript type stripping.\n *\n * This is a wrapper around babel-dead-code-elimination that first strips\n * TypeScript type-only exports and imports. This is necessary because\n * babel-dead-code-elimination doesn't handle type exports, which can cause\n * imports to be retained when they're only referenced by type exports.\n *\n * @param ast - The Babel AST to mutate\n * @param candidates - Optional set of identifier paths to consider for removal.\n * If provided, only these identifiers will be candidates for removal.\n * This should be the result of `findReferencedIdentifiers(ast)` called\n * before any AST transformations.\n */\nexport function deadCodeElimination(\n ast: ParseResult<_babel_types.File>,\n candidates?: ReturnType<typeof findReferencedIdentifiers>,\n): void {\n // First strip TypeScript type-only exports and imports\n stripTypeExports(ast)\n\n // Then run the original dead code elimination\n _deadCodeElimination(ast, candidates)\n}\n"],"mappings":";;;;;AAiBA,SAAgB,SAAS,EACvB,MACA,UACA,gBACA,SACA,GAAG,QAC+B;AAElC,QAAO,MAAM,MAAM;EACjB,SAAS,WAAW,mCAFG,YAAY,eAEqC;EACxE,YAAY;EACZ;EACA,GAAG;EACJ,CAAC;;AAGJ,SAAS,mCACP,UACuC;CACvC,MAAM,UAAiD;EACrD;EACA;EACA;EACA;EACA,CAAC,cAAc,EAAE,wBAAwB,MAAM,CAAC;EAChD;EACD;AAED,KAAI,CAAC,sBAAsB,SAAS,CAClC,SAAQ,QAAQ,MAAM;AAGxB,QAAO;;AAGT,SAAS,sBAAsB,UAAuC;AACpE,KAAI,CAAC,SACH,QAAO;AAGT,QAAO,sBAAsB,KAAK,SAAS;;AAG7C,IAAI,WAAW;AAEf,IAAI,aAAa,SACf,YAAW,SAAS;AAItB,SAAgB,gBACd,KACA,MACiB;AACjB,QAAO,SACL,KACA,OACI;EAAE,yBAAyB;EAAQ,YAAY;EAAM,GAAG;EAAM,GAC9D,KAAA,EACL;;;;;;;;;;;;;;;;;;;;;;;;AA0BH,SAAgB,iBAAiB,KAA2C;AAE1E,KAAI,QAAQ,OAAO,IAAI,QAAQ,KAAK,QAAQ,SAAS;AAEnD,MAAI,EAAE,yBAAyB,KAAK,EAAE;AAGpC,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,EAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAIF,QAAI,KAAK,WAAW,WAAW,KAAK,CAAC,KAAK,YACxC,QAAO;;;AAOb,MAAI,EAAE,uBAAuB,KAAK;OAC5B,KAAK,eAAe,OACtB,QAAO;;AAKX,MAAI,EAAE,oBAAoB,KAAK,EAAE;AAG/B,OAAI,KAAK,eAAe,OACtB,QAAO;AAKT,OAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,SAAK,aAAa,KAAK,WAAW,QAAQ,cAAc;AACtD,SAAI,EAAE,kBAAkB,UAAU,CAChC,QAAO,UAAU,eAAe;AAElC,YAAO;MACP;AAGF,QAAI,KAAK,WAAW,WAAW,EAC7B,QAAO;;;AAKb,SAAO;GACP;;;;;;;;;;;;;;;;AAoBJ,SAAgB,sBACd,KACA,YACM;AAEN,kBAAiB,IAAI;AAGrB,qBAAqB,KAAK,WAAW"}
{
"name": "@tanstack/router-utils",
"version": "1.161.7",
"version": "1.161.8",
"description": "Modern and scalable routing for React applications",

@@ -5,0 +5,0 @@ "author": "Tanner Linsley",

@@ -14,17 +14,18 @@ import { parse } from '@babel/parser'

code: string
filename?: string
}
export type ParseAstResult = ParseResult<_babel_types.File>
export function parseAst({ code, ...opts }: ParseAstOptions): ParseAstResult {
export function parseAst({
code,
filename,
sourceFilename,
plugins,
...opts
}: ParseAstOptions): ParseAstResult {
const inferredFilename = filename ?? sourceFilename
return parse(code, {
plugins: [
'jsx',
'typescript',
'explicitResourceManagement',
'importAttributes',
'deprecatedImportAssert',
['decorators', { decoratorsBeforeExport: true }],
'decoratorAutoAccessors',
],
plugins: plugins ?? getDefaultParserPluginsForFilename(inferredFilename),
sourceType: 'module',
sourceFilename,
...opts,

@@ -34,2 +35,29 @@ })

function getDefaultParserPluginsForFilename(
filename: string | undefined,
): NonNullable<ParserOptions['plugins']> {
const plugins: NonNullable<ParserOptions['plugins']> = [
'typescript',
'explicitResourceManagement',
'importAttributes',
'deprecatedImportAssert',
['decorators', { decoratorsBeforeExport: true }],
'decoratorAutoAccessors',
]
if (!isPlainTypeScriptFile(filename)) {
plugins.unshift('jsx')
}
return plugins
}
function isPlainTypeScriptFile(filename: string | undefined): boolean {
if (!filename) {
return false
}
return /\.[cm]?ts(?:$|[?#])/.test(filename)
}
let generate = _generate

@@ -36,0 +64,0 @@