Bugfix. Update Tsx server stripping function to have absolute paths. Run the rewrite function on dev and build commands.
This commit is contained in:
parent
a9af20a8b2
commit
3d044ee79e
4
.gitignore
vendored
4
.gitignore
vendored
@ -178,4 +178,6 @@ out
|
|||||||
/build
|
/build
|
||||||
__fixtures__
|
__fixtures__
|
||||||
/public
|
/public
|
||||||
/.*
|
/.data
|
||||||
|
/.dump
|
||||||
|
/.vscode
|
||||||
2
dist/commands/build/index.js
vendored
2
dist/commands/build/index.js
vendored
@ -2,12 +2,14 @@ import { Command } from "commander";
|
|||||||
import allPagesBundler from "../../functions/bundler/all-pages-bundler";
|
import allPagesBundler from "../../functions/bundler/all-pages-bundler";
|
||||||
import { log } from "../../utils/log";
|
import { log } from "../../utils/log";
|
||||||
import init from "../../functions/init";
|
import init from "../../functions/init";
|
||||||
|
import rewritePagesModule from "../../utils/rewrite-pages-module";
|
||||||
export default function () {
|
export default function () {
|
||||||
return new Command("build")
|
return new Command("build")
|
||||||
.description("Build Project")
|
.description("Build Project")
|
||||||
.action(async () => {
|
.action(async () => {
|
||||||
process.env.NODE_ENV = "production";
|
process.env.NODE_ENV = "production";
|
||||||
process.env.BUILD = "true";
|
process.env.BUILD = "true";
|
||||||
|
await rewritePagesModule();
|
||||||
await init();
|
await init();
|
||||||
log.banner();
|
log.banner();
|
||||||
log.build("Building Project ...");
|
log.build("Building Project ...");
|
||||||
|
|||||||
2
dist/commands/dev/index.js
vendored
2
dist/commands/dev/index.js
vendored
@ -2,12 +2,14 @@ import { Command } from "commander";
|
|||||||
import startServer from "../../functions/server/start-server";
|
import startServer from "../../functions/server/start-server";
|
||||||
import { log } from "../../utils/log";
|
import { log } from "../../utils/log";
|
||||||
import bunextInit from "../../functions/bunext-init";
|
import bunextInit from "../../functions/bunext-init";
|
||||||
|
import rewritePagesModule from "../../utils/rewrite-pages-module";
|
||||||
export default function () {
|
export default function () {
|
||||||
return new Command("dev")
|
return new Command("dev")
|
||||||
.description("Run development server")
|
.description("Run development server")
|
||||||
.action(async () => {
|
.action(async () => {
|
||||||
process.env.NODE_ENV == "development";
|
process.env.NODE_ENV == "development";
|
||||||
log.info("Running development server ...");
|
log.info("Running development server ...");
|
||||||
|
await rewritePagesModule();
|
||||||
await bunextInit();
|
await bunextInit();
|
||||||
await startServer();
|
await startServer();
|
||||||
});
|
});
|
||||||
|
|||||||
5
dist/functions/bundler/all-pages-bundler.js
vendored
5
dist/functions/bundler/all-pages-bundler.js
vendored
@ -44,7 +44,10 @@ export default async function allPagesBundler(params) {
|
|||||||
if (!source.includes("server")) {
|
if (!source.includes("server")) {
|
||||||
return { contents: source, loader: "tsx" };
|
return { contents: source, loader: "tsx" };
|
||||||
}
|
}
|
||||||
const strippedCode = stripServerSideLogic({ txt_code: source });
|
const strippedCode = stripServerSideLogic({
|
||||||
|
txt_code: source,
|
||||||
|
file_path: args.path,
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
contents: strippedCode,
|
contents: strippedCode,
|
||||||
loader: "tsx",
|
loader: "tsx",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
type Params = {
|
type Params = {
|
||||||
txt_code: string;
|
txt_code: string;
|
||||||
|
file_path: string;
|
||||||
};
|
};
|
||||||
export default function stripServerSideLogic({ txt_code }: Params): string;
|
export default function stripServerSideLogic({ txt_code, file_path }: Params): string;
|
||||||
export {};
|
export {};
|
||||||
|
|||||||
@ -1,53 +1,55 @@
|
|||||||
|
import path from "path";
|
||||||
import ts from "typescript";
|
import ts from "typescript";
|
||||||
export default function stripServerSideLogic({ txt_code }) {
|
export default function stripServerSideLogic({ txt_code, file_path }) {
|
||||||
const sourceFile = ts.createSourceFile("temp.tsx", txt_code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
const sourceFile = ts.createSourceFile("file.tsx", txt_code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
||||||
const transformer = (context) => {
|
const printer = ts.createPrinter();
|
||||||
return (rootNode) => {
|
const file_fir_name = path.dirname(file_path);
|
||||||
|
const transformer = (context) => (rootNode) => {
|
||||||
const visitor = (node) => {
|
const visitor = (node) => {
|
||||||
|
// 1. Strip the 'server' export
|
||||||
if (ts.isVariableStatement(node) &&
|
if (ts.isVariableStatement(node) &&
|
||||||
node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
|
node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {
|
||||||
const isServerExport = node.declarationList.declarations.some((d) => ts.isIdentifier(d.name) &&
|
const isServer = node.declarationList.declarations.some((d) => ts.isIdentifier(d.name) && d.name.text === "server");
|
||||||
d.name.text === "server");
|
if (isServer)
|
||||||
if (isServerExport)
|
return undefined;
|
||||||
return undefined; // Remove it
|
}
|
||||||
|
// 2. Convert relative imports to absolute imports
|
||||||
|
if (ts.isImportDeclaration(node)) {
|
||||||
|
const moduleSpecifier = node.moduleSpecifier;
|
||||||
|
if (ts.isStringLiteral(moduleSpecifier) &&
|
||||||
|
moduleSpecifier.text.startsWith(".")) {
|
||||||
|
// Resolve the relative path to an absolute filesystem path
|
||||||
|
const absolutePath = path.resolve(file_fir_name, moduleSpecifier.text);
|
||||||
|
return ts.factory.updateImportDeclaration(node, node.modifiers, node.importClause, ts.factory.createStringLiteral(absolutePath), node.attributes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ts.visitEachChild(node, visitor, context);
|
return ts.visitEachChild(node, visitor, context);
|
||||||
};
|
};
|
||||||
return ts.visitNode(rootNode, visitor);
|
return ts.visitNode(rootNode, visitor);
|
||||||
};
|
};
|
||||||
};
|
|
||||||
const result = ts.transform(sourceFile, [transformer]);
|
const result = ts.transform(sourceFile, [transformer]);
|
||||||
const printer = ts.createPrinter();
|
const intermediate = printer.printFile(result.transformed[0]);
|
||||||
const strippedCode = printer.printFile(result.transformed[0]);
|
// Pass 2: Cleanup unused imports (Same logic as before)
|
||||||
const cleanSourceFile = ts.createSourceFile("clean.tsx", strippedCode, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
const cleanSource = ts.createSourceFile("clean.tsx", intermediate, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
||||||
// Simple reference check: if a named import isn't found in the text, drop it
|
const cleanup = (context) => (rootNode) => {
|
||||||
const cleanupTransformer = (context) => {
|
|
||||||
return (rootNode) => {
|
|
||||||
const visitor = (node) => {
|
const visitor = (node) => {
|
||||||
if (ts.isImportDeclaration(node)) {
|
if (ts.isImportDeclaration(node)) {
|
||||||
const clause = node.importClause;
|
const clause = node.importClause;
|
||||||
if (!clause)
|
if (!clause)
|
||||||
return node;
|
return node;
|
||||||
// Handle named imports like { BunextPageProps, BunextPageServerFn }
|
|
||||||
if (clause.namedBindings &&
|
if (clause.namedBindings &&
|
||||||
ts.isNamedImports(clause.namedBindings)) {
|
ts.isNamedImports(clause.namedBindings)) {
|
||||||
const activeElements = clause.namedBindings.elements.filter((el) => {
|
const used = clause.namedBindings.elements.filter((el) => {
|
||||||
const name = el.name.text;
|
const regex = new RegExp(`\\b${el.name.text}\\b`, "g");
|
||||||
// Check if the name appears anywhere else in the file
|
return ((intermediate.match(regex) || []).length > 1);
|
||||||
const regex = new RegExp(`\\b${name}\\b`, "g");
|
|
||||||
const matches = strippedCode.match(regex);
|
|
||||||
return matches && matches.length > 1; // 1 for the import itself, >1 for usage
|
|
||||||
});
|
});
|
||||||
if (activeElements.length === 0)
|
if (used.length === 0)
|
||||||
return undefined;
|
return undefined;
|
||||||
return ts.factory.updateImportDeclaration(node, node.modifiers, ts.factory.updateImportClause(clause, clause.isTypeOnly, clause.name, ts.factory.createNamedImports(activeElements)), node.moduleSpecifier, node.attributes);
|
return ts.factory.updateImportDeclaration(node, node.modifiers, ts.factory.updateImportClause(clause, clause.isTypeOnly, clause.name, ts.factory.createNamedImports(used)), node.moduleSpecifier, node.attributes);
|
||||||
}
|
}
|
||||||
// Handle default imports like 'import BunSQLite'
|
|
||||||
if (clause.name) {
|
if (clause.name) {
|
||||||
const name = clause.name.text;
|
const regex = new RegExp(`\\b${clause.name.text}\\b`, "g");
|
||||||
const regex = new RegExp(`\\b${name}\\b`, "g");
|
if ((intermediate.match(regex) || []).length <= 1)
|
||||||
const matches = strippedCode.match(regex);
|
|
||||||
if (!matches || matches.length <= 1)
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +57,6 @@ export default function stripServerSideLogic({ txt_code }) {
|
|||||||
};
|
};
|
||||||
return ts.visitNode(rootNode, visitor);
|
return ts.visitNode(rootNode, visitor);
|
||||||
};
|
};
|
||||||
};
|
const final = ts.transform(cleanSource, [cleanup]);
|
||||||
const finalResult = ts.transform(cleanSourceFile, [cleanupTransformer]);
|
return printer.printFile(final.transformed[0]);
|
||||||
return printer.printFile(finalResult.transformed[0]);
|
|
||||||
}
|
}
|
||||||
|
|||||||
1
dist/utils/rewrite-pages-module.js
vendored
1
dist/utils/rewrite-pages-module.js
vendored
@ -17,6 +17,7 @@ export default async function rewritePagesModule(params) {
|
|||||||
const origin_page_content = await Bun.file(page_path).text();
|
const origin_page_content = await Bun.file(page_path).text();
|
||||||
const dst_page_content = stripServerSideLogic({
|
const dst_page_content = stripServerSideLogic({
|
||||||
txt_code: origin_page_content,
|
txt_code: origin_page_content,
|
||||||
|
file_path: page_path,
|
||||||
});
|
});
|
||||||
await Bun.write(dst_path, dst_page_content, {
|
await Bun.write(dst_path, dst_page_content, {
|
||||||
createPath: true,
|
createPath: true,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"name": "@moduletrace/bunext",
|
"name": "@moduletrace/bunext",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.10",
|
"version": "1.0.11",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Command } from "commander";
|
|||||||
import allPagesBundler from "../../functions/bundler/all-pages-bundler";
|
import allPagesBundler from "../../functions/bundler/all-pages-bundler";
|
||||||
import { log } from "../../utils/log";
|
import { log } from "../../utils/log";
|
||||||
import init from "../../functions/init";
|
import init from "../../functions/init";
|
||||||
|
import rewritePagesModule from "../../utils/rewrite-pages-module";
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
return new Command("build")
|
return new Command("build")
|
||||||
@ -10,6 +11,7 @@ export default function () {
|
|||||||
process.env.NODE_ENV = "production";
|
process.env.NODE_ENV = "production";
|
||||||
process.env.BUILD = "true";
|
process.env.BUILD = "true";
|
||||||
|
|
||||||
|
await rewritePagesModule();
|
||||||
await init();
|
await init();
|
||||||
|
|
||||||
log.banner();
|
log.banner();
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Command } from "commander";
|
|||||||
import startServer from "../../functions/server/start-server";
|
import startServer from "../../functions/server/start-server";
|
||||||
import { log } from "../../utils/log";
|
import { log } from "../../utils/log";
|
||||||
import bunextInit from "../../functions/bunext-init";
|
import bunextInit from "../../functions/bunext-init";
|
||||||
|
import rewritePagesModule from "../../utils/rewrite-pages-module";
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
return new Command("dev")
|
return new Command("dev")
|
||||||
@ -11,6 +12,7 @@ export default function () {
|
|||||||
|
|
||||||
log.info("Running development server ...");
|
log.info("Running development server ...");
|
||||||
|
|
||||||
|
await rewritePagesModule();
|
||||||
await bunextInit();
|
await bunextInit();
|
||||||
|
|
||||||
await startServer();
|
await startServer();
|
||||||
|
|||||||
@ -64,7 +64,10 @@ export default async function allPagesBundler(params?: Params) {
|
|||||||
return { contents: source, loader: "tsx" };
|
return { contents: source, loader: "tsx" };
|
||||||
}
|
}
|
||||||
|
|
||||||
const strippedCode = stripServerSideLogic({ txt_code: source });
|
const strippedCode = stripServerSideLogic({
|
||||||
|
txt_code: source,
|
||||||
|
file_path: args.path,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
contents: strippedCode,
|
contents: strippedCode,
|
||||||
|
|||||||
@ -1,78 +1,101 @@
|
|||||||
|
import path from "path";
|
||||||
import ts from "typescript";
|
import ts from "typescript";
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
txt_code: string;
|
txt_code: string;
|
||||||
|
file_path: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function stripServerSideLogic({ txt_code }: Params) {
|
export default function stripServerSideLogic({ txt_code, file_path }: Params) {
|
||||||
const sourceFile = ts.createSourceFile(
|
const sourceFile = ts.createSourceFile(
|
||||||
"temp.tsx",
|
"file.tsx",
|
||||||
txt_code,
|
txt_code,
|
||||||
ts.ScriptTarget.Latest,
|
ts.ScriptTarget.Latest,
|
||||||
true,
|
true,
|
||||||
ts.ScriptKind.TSX,
|
ts.ScriptKind.TSX,
|
||||||
);
|
);
|
||||||
|
const printer = ts.createPrinter();
|
||||||
|
const file_fir_name = path.dirname(file_path);
|
||||||
|
|
||||||
const transformer: ts.TransformerFactory<ts.SourceFile> = (context) => {
|
const transformer: ts.TransformerFactory<ts.SourceFile> =
|
||||||
return (rootNode) => {
|
(context) => (rootNode) => {
|
||||||
const visitor = (node: ts.Node): ts.Node | undefined => {
|
const visitor = (node: ts.Node): ts.Node | undefined => {
|
||||||
|
// 1. Strip the 'server' export
|
||||||
if (
|
if (
|
||||||
ts.isVariableStatement(node) &&
|
ts.isVariableStatement(node) &&
|
||||||
node.modifiers?.some(
|
node.modifiers?.some(
|
||||||
(m) => m.kind === ts.SyntaxKind.ExportKeyword,
|
(m) => m.kind === ts.SyntaxKind.ExportKeyword,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const isServerExport =
|
const isServer = node.declarationList.declarations.some(
|
||||||
node.declarationList.declarations.some(
|
|
||||||
(d) =>
|
(d) =>
|
||||||
ts.isIdentifier(d.name) &&
|
ts.isIdentifier(d.name) && d.name.text === "server",
|
||||||
d.name.text === "server",
|
|
||||||
);
|
);
|
||||||
if (isServerExport) return undefined; // Remove it
|
if (isServer) return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. Convert relative imports to absolute imports
|
||||||
|
if (ts.isImportDeclaration(node)) {
|
||||||
|
const moduleSpecifier = node.moduleSpecifier;
|
||||||
|
if (
|
||||||
|
ts.isStringLiteral(moduleSpecifier) &&
|
||||||
|
moduleSpecifier.text.startsWith(".")
|
||||||
|
) {
|
||||||
|
// Resolve the relative path to an absolute filesystem path
|
||||||
|
const absolutePath = path.resolve(
|
||||||
|
file_fir_name,
|
||||||
|
moduleSpecifier.text,
|
||||||
|
);
|
||||||
|
|
||||||
|
return ts.factory.updateImportDeclaration(
|
||||||
|
node,
|
||||||
|
node.modifiers,
|
||||||
|
node.importClause,
|
||||||
|
ts.factory.createStringLiteral(absolutePath),
|
||||||
|
node.attributes,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ts.visitEachChild(node, visitor, context);
|
return ts.visitEachChild(node, visitor, context);
|
||||||
};
|
};
|
||||||
return ts.visitNode(rootNode, visitor) as ts.SourceFile;
|
return ts.visitNode(rootNode, visitor) as ts.SourceFile;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const result = ts.transform(sourceFile, [transformer]);
|
const result = ts.transform(sourceFile, [transformer]);
|
||||||
const printer = ts.createPrinter();
|
const intermediate = printer.printFile(result.transformed[0]);
|
||||||
const strippedCode = printer.printFile(result.transformed[0]);
|
|
||||||
|
|
||||||
const cleanSourceFile = ts.createSourceFile(
|
// Pass 2: Cleanup unused imports (Same logic as before)
|
||||||
|
const cleanSource = ts.createSourceFile(
|
||||||
"clean.tsx",
|
"clean.tsx",
|
||||||
strippedCode,
|
intermediate,
|
||||||
ts.ScriptTarget.Latest,
|
ts.ScriptTarget.Latest,
|
||||||
true,
|
true,
|
||||||
ts.ScriptKind.TSX,
|
ts.ScriptKind.TSX,
|
||||||
);
|
);
|
||||||
|
const cleanup: ts.TransformerFactory<ts.SourceFile> =
|
||||||
// Simple reference check: if a named import isn't found in the text, drop it
|
(context) => (rootNode) => {
|
||||||
const cleanupTransformer: ts.TransformerFactory<ts.SourceFile> = (
|
|
||||||
context,
|
|
||||||
) => {
|
|
||||||
return (rootNode) => {
|
|
||||||
const visitor = (node: ts.Node): ts.Node | undefined => {
|
const visitor = (node: ts.Node): ts.Node | undefined => {
|
||||||
if (ts.isImportDeclaration(node)) {
|
if (ts.isImportDeclaration(node)) {
|
||||||
const clause = node.importClause;
|
const clause = node.importClause;
|
||||||
if (!clause) return node;
|
if (!clause) return node;
|
||||||
|
|
||||||
// Handle named imports like { BunextPageProps, BunextPageServerFn }
|
|
||||||
if (
|
if (
|
||||||
clause.namedBindings &&
|
clause.namedBindings &&
|
||||||
ts.isNamedImports(clause.namedBindings)
|
ts.isNamedImports(clause.namedBindings)
|
||||||
) {
|
) {
|
||||||
const activeElements =
|
const used = clause.namedBindings.elements.filter(
|
||||||
clause.namedBindings.elements.filter((el) => {
|
(el) => {
|
||||||
const name = el.name.text;
|
const regex = new RegExp(
|
||||||
// Check if the name appears anywhere else in the file
|
`\\b${el.name.text}\\b`,
|
||||||
const regex = new RegExp(`\\b${name}\\b`, "g");
|
"g",
|
||||||
const matches = strippedCode.match(regex);
|
);
|
||||||
return matches && matches.length > 1; // 1 for the import itself, >1 for usage
|
return (
|
||||||
});
|
(intermediate.match(regex) || []).length > 1
|
||||||
|
);
|
||||||
if (activeElements.length === 0) return undefined;
|
},
|
||||||
|
);
|
||||||
|
if (used.length === 0) return undefined;
|
||||||
return ts.factory.updateImportDeclaration(
|
return ts.factory.updateImportDeclaration(
|
||||||
node,
|
node,
|
||||||
node.modifiers,
|
node.modifiers,
|
||||||
@ -80,27 +103,27 @@ export default function stripServerSideLogic({ txt_code }: Params) {
|
|||||||
clause,
|
clause,
|
||||||
clause.isTypeOnly,
|
clause.isTypeOnly,
|
||||||
clause.name,
|
clause.name,
|
||||||
ts.factory.createNamedImports(activeElements),
|
ts.factory.createNamedImports(used),
|
||||||
),
|
),
|
||||||
node.moduleSpecifier,
|
node.moduleSpecifier,
|
||||||
node.attributes,
|
node.attributes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle default imports like 'import BunSQLite'
|
|
||||||
if (clause.name) {
|
if (clause.name) {
|
||||||
const name = clause.name.text;
|
const regex = new RegExp(
|
||||||
const regex = new RegExp(`\\b${name}\\b`, "g");
|
`\\b${clause.name.text}\\b`,
|
||||||
const matches = strippedCode.match(regex);
|
"g",
|
||||||
if (!matches || matches.length <= 1) return undefined;
|
);
|
||||||
|
if ((intermediate.match(regex) || []).length <= 1)
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ts.visitEachChild(node, visitor, context);
|
return ts.visitEachChild(node, visitor, context);
|
||||||
};
|
};
|
||||||
return ts.visitNode(rootNode, visitor) as ts.SourceFile;
|
return ts.visitNode(rootNode, visitor) as ts.SourceFile;
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const finalResult = ts.transform(cleanSourceFile, [cleanupTransformer]);
|
const final = ts.transform(cleanSource, [cleanup]);
|
||||||
return printer.printFile(finalResult.transformed[0]);
|
return printer.printFile(final.transformed[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ export default async function rewritePagesModule(params?: Params) {
|
|||||||
const origin_page_content = await Bun.file(page_path).text();
|
const origin_page_content = await Bun.file(page_path).text();
|
||||||
const dst_page_content = stripServerSideLogic({
|
const dst_page_content = stripServerSideLogic({
|
||||||
txt_code: origin_page_content,
|
txt_code: origin_page_content,
|
||||||
|
file_path: page_path,
|
||||||
});
|
});
|
||||||
|
|
||||||
await Bun.write(dst_path, dst_page_content, {
|
await Bun.write(dst_path, dst_page_content, {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user