Skip to content

Commit

Permalink
fix the heroku building issue DIYgod#15819
Browse files Browse the repository at this point in the history
  • Loading branch information
WindowsXp-Beta committed Oct 26, 2024
1 parent a71410f commit f61dfa0
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 69 deletions.
48 changes: 34 additions & 14 deletions lib/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { directoryImport } from 'directory-import';
import { Hono, type Handler } from 'hono';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import fs from 'node:fs';
import { serveStatic } from '@hono/node-server/serve-static';
import { config } from '@/config';

import index from '@/routes/index';
import healthz from '@/routes/healthz';
import robotstxt from '@/routes/robots.txt';
Expand All @@ -26,20 +26,35 @@ let namespaces: Record<
}
> = {};

switch (process.env.NODE_ENV) {
case 'test':
case 'production':
// @ts-expect-error
namespaces = await import('../assets/build/routes.json');
break;
default:
modules = directoryImport({
targetDirectoryPath: path.join(__dirname, './routes'),
importPattern: /\.ts$/,
}) as typeof modules;
async function loadNamespaces() {
switch (process.env.NODE_ENV) {
case 'test':
case 'production':
try {
const routesPath = path.join(process.cwd(), 'assets', 'build', 'routes.json');
if (fs.existsSync(routesPath)) {
const routesContent = await fs.promises.readFile(routesPath, 'utf-8');
namespaces = JSON.parse(routesContent);
} else {
console.warn('routes.json not found. Falling back to directory import.');
await loadModules();
}
} catch (error) {
console.error('Error loading routes.json:', error);
await loadModules();
}
break;
default:
await loadModules();
}
}

if (Object.keys(modules).length) {
async function loadModules() {
modules = directoryImport({
targetDirectoryPath: path.join(__dirname, './routes'),
importPattern: /\.ts$/,
}) as typeof modules;

for (const module in modules) {
const content = modules[module] as
| {
Expand Down Expand Up @@ -81,9 +96,12 @@ if (Object.keys(modules).length) {
}
}

await loadNamespaces();

export { namespaces };

const app = new Hono();

for (const namespace in namespaces) {
const subApp = app.basePath(`/${namespace}`);
for (const path in namespaces[namespace].routes) {
Expand All @@ -103,10 +121,12 @@ for (const namespace in namespaces) {
app.get('/', index);
app.get('/healthz', healthz);
app.get('/robots.txt', robotstxt);

if (config.debugInfo) {
// Only enable tracing in debug mode
app.get('/metrics', metrics);
}

app.use(
'/*',
serveStatic({
Expand All @@ -115,4 +135,4 @@ app.use(
})
);

export default app;
export default app;
142 changes: 87 additions & 55 deletions scripts/workflow/build-routes.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,105 @@
import { namespaces } from '../../lib/registry';
import { RadarItem } from '../../lib/types';
import { parse } from 'tldts';
import fs from 'node:fs';
import path from 'node:path';
import fs from 'fs/promises';
import path from 'path';
import toSource from 'tosource';

import { getCurrentPath } from '../../lib/utils/helpers';

const __dirname = getCurrentPath(import.meta.url);

const maintainers: Record<string, string[]> = {};
const radar: {
[domain: string]: {
_name: string;
[subdomain: string]: RadarItem[] | string;
};
} = {};
async function ensureDirectoryExists(dirPath: string) {
try {
await fs.mkdir(dirPath, { recursive: true });
} catch (error) {
console.error(`Error creating directory ${dirPath}:`, error);
}
}

for (const namespace in namespaces) {
let defaultCategory = namespaces[namespace].categories?.[0];
if (!defaultCategory) {
for (const path in namespaces[namespace].routes) {
if (namespaces[namespace].routes[path].categories) {
defaultCategory = namespaces[namespace].routes[path].categories[0];
break;
async function writeJsonFile(filePath: string, data: any) {
try {
await fs.writeFile(filePath, JSON.stringify(data, null, 2));
console.log(`Successfully wrote ${filePath}`);
} catch (error) {
console.error(`Error writing ${filePath}:`, error);
}
}

async function main() {
const maintainers: Record<string, string[]> = {};
const radar: {
[domain: string]: {
_name: string;
[subdomain: string]: RadarItem[] | string;
};
} = {};

for (const namespace in namespaces) {
let defaultCategory = namespaces[namespace].categories?.[0];
if (!defaultCategory) {
for (const path in namespaces[namespace].routes) {
if (namespaces[namespace].routes[path].categories) {
defaultCategory = namespaces[namespace].routes[path].categories[0];
break;
}
}
}
}
if (!defaultCategory) {
defaultCategory = 'other';
}
for (const path in namespaces[namespace].routes) {
const realPath = `/${namespace}${path}`;
const data = namespaces[namespace].routes[path];
const categories = data.categories || namespaces[namespace].categories || [defaultCategory];
// maintainers
if (data.maintainers) {
maintainers[realPath] = data.maintainers;
if (!defaultCategory) {
defaultCategory = 'other';
}
// radar
if (data.radar?.length) {
for (const radarItem of data.radar) {
const parsedDomain = parse(new URL('https://' + radarItem.source[0]).hostname);
const subdomain = parsedDomain.subdomain || '.';
const domain = parsedDomain.domain;
if (domain) {
if (!radar[domain]) {
radar[domain] = {
_name: namespaces[namespace].name,
};
}
if (!radar[domain][subdomain]) {
radar[domain][subdomain] = [];
for (const path in namespaces[namespace].routes) {
const realPath = `/${namespace}${path}`;
const data = namespaces[namespace].routes[path];
const categories = data.categories || namespaces[namespace].categories || [defaultCategory];
// maintainers
if (data.maintainers) {
maintainers[realPath] = data.maintainers;
}
// radar
if (data.radar?.length) {
for (const radarItem of data.radar) {
const parsedDomain = parse(new URL('https://' + radarItem.source[0]).hostname);
const subdomain = parsedDomain.subdomain || '.';
const domain = parsedDomain.domain;
if (domain) {
if (!radar[domain]) {
radar[domain] = {
_name: namespaces[namespace].name,
};
}
if (!radar[domain][subdomain]) {
radar[domain][subdomain] = [];
}
radar[domain][subdomain].push({
title: radarItem.title || data.name,
docs: `https://docs.rsshub.app/routes/${categories[0]}`,
source: radarItem.source.map((source) => {
const sourceURL = new URL('https://' + source);
return sourceURL.pathname + sourceURL.search + sourceURL.hash;
}),
target: radarItem.target ? `/${namespace}${radarItem.target}` : realPath,
});
}
radar[domain][subdomain].push({
title: radarItem.title || data.name,
docs: `https://docs.rsshub.app/routes/${categories[0]}`,
source: radarItem.source.map((source) => {
const sourceURL = new URL('https://' + source);
return sourceURL.pathname + sourceURL.search + sourceURL.hash;
}),
target: radarItem.target ? `/${namespace}${radarItem.target}` : realPath,
});
}
}
}
}

// Use process.cwd() to get the absolute path to the project root
const projectRoot = process.cwd();
const buildDir = path.join(projectRoot, 'assets', 'build');

// Ensure the build directory exists
await ensureDirectoryExists(buildDir);

// Write files using absolute paths
await writeJsonFile(path.join(buildDir, 'radar-rules.json'), radar);
await fs.writeFile(path.join(buildDir, 'radar-rules.js'), `(${toSource(radar)})`);
await writeJsonFile(path.join(buildDir, 'maintainers.json'), maintainers);
await writeJsonFile(path.join(buildDir, 'routes.json'), namespaces);
}

fs.writeFileSync(path.join(__dirname, '../../assets/build/radar-rules.json'), JSON.stringify(radar, null, 2));
fs.writeFileSync(path.join(__dirname, '../../assets/build/radar-rules.js'), `(${toSource(radar)})`);
fs.writeFileSync(path.join(__dirname, '../../assets/build/maintainers.json'), JSON.stringify(maintainers, null, 2));
fs.writeFileSync(path.join(__dirname, '../../assets/build/routes.json'), JSON.stringify(namespaces, null, 2));
main().catch(error => {
console.error('An error occurred during the build process:', error);
process.exit(1);
});

0 comments on commit f61dfa0

Please sign in to comment.