feat: migrate to bun runtime and update dependencies
This commit is contained in:
		@@ -14,6 +14,10 @@
 | 
			
		||||
    "typescript": "^4.0.0",
 | 
			
		||||
    "@types/react": "^18.0.0",
 | 
			
		||||
    "@types/react-dom": "^18.0.0",
 | 
			
		||||
    "bun-types": "^0.1.0"
 | 
			
		||||
  }
 | 
			
		||||
    "bun-types": "^0.1.0",
 | 
			
		||||
    "@types/bun": "latest"
 | 
			
		||||
  },
 | 
			
		||||
  "module": "src/index.tsx",
 | 
			
		||||
  "type": "module",
 | 
			
		||||
  "private": true
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								package.json
									
									
									
									
									
								
							@@ -5,11 +5,16 @@
 | 
			
		||||
    "start": "bun run server.ts"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "rss-parser": "^3.12.0",
 | 
			
		||||
    "openai": "^4.0.0",
 | 
			
		||||
    "@aws-sdk/client-polly": "^3.0.0",
 | 
			
		||||
    "better-sqlite3": "^8.0.0",
 | 
			
		||||
    "bun-router": "^0.1.0"
 | 
			
		||||
    "@aws-sdk/client-polly": "^3.823.0",
 | 
			
		||||
    "openai": "^4.104.0",
 | 
			
		||||
    "rss-parser": "^3.13.0"
 | 
			
		||||
  },
 | 
			
		||||
  "type": "module"
 | 
			
		||||
  "type": "module",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/bun": "latest"
 | 
			
		||||
  },
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "peerDependencies": {
 | 
			
		||||
    "typescript": "^5"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,7 @@ interface FeedItem {
 | 
			
		||||
 | 
			
		||||
async function main() {
 | 
			
		||||
  const parser = new Parser<FeedItem>();
 | 
			
		||||
  const feedUrls = [
 | 
			
		||||
    "https://example.com/feed1.rss",
 | 
			
		||||
  ];
 | 
			
		||||
  const feedUrls = ["https://example.com/feed1.rss"];
 | 
			
		||||
 | 
			
		||||
  for (const url of feedUrls) {
 | 
			
		||||
    const feed = await parser.parseURL(url);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import Database from "better-sqlite3";
 | 
			
		||||
import { Database } from "bun:sqlite";
 | 
			
		||||
import path from "path";
 | 
			
		||||
 | 
			
		||||
const dbPath = path.join(__dirname, "../data/podcast.db");
 | 
			
		||||
@@ -28,17 +28,26 @@ export interface Episode {
 | 
			
		||||
  sourceLink: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function markAsProcessed(feedUrl: string, itemId: string): Promise<boolean> {
 | 
			
		||||
  const stmt = db.prepare("SELECT 1 FROM processed_feed_items WHERE feed_url = ? AND item_id = ?");
 | 
			
		||||
export async function markAsProcessed(
 | 
			
		||||
  feedUrl: string,
 | 
			
		||||
  itemId: string,
 | 
			
		||||
): Promise<boolean> {
 | 
			
		||||
  const stmt = db.prepare(
 | 
			
		||||
    "SELECT 1 FROM processed_feed_items WHERE feed_url = ? AND item_id = ?",
 | 
			
		||||
  );
 | 
			
		||||
  const row = stmt.get(feedUrl, itemId);
 | 
			
		||||
  if (row) return true;
 | 
			
		||||
  const insert = db.prepare("INSERT INTO processed_feed_items (feed_url, item_id, processed_at) VALUES (?, ?, ?)");
 | 
			
		||||
  const insert = db.prepare(
 | 
			
		||||
    "INSERT INTO processed_feed_items (feed_url, item_id, processed_at) VALUES (?, ?, ?)",
 | 
			
		||||
  );
 | 
			
		||||
  insert.run(feedUrl, itemId, new Date().toISOString());
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function saveEpisode(ep: Episode): Promise<void> {
 | 
			
		||||
  const stmt = db.prepare("INSERT OR IGNORE INTO episodes (id, title, pubDate, audioPath, sourceLink) VALUES (?, ?, ?, ?, ?)");
 | 
			
		||||
  const stmt = db.prepare(
 | 
			
		||||
    "INSERT OR IGNORE INTO episodes (id, title, pubDate, audioPath, sourceLink) VALUES (?, ?, ?, ?, ?)",
 | 
			
		||||
  );
 | 
			
		||||
  stmt.run(ep.id, ep.title, ep.pubDate, ep.audioPath, ep.sourceLink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,13 +7,14 @@ export async function updatePodcastRSS() {
 | 
			
		||||
 | 
			
		||||
  const channelTitle = "自動生成ポッドキャスト";
 | 
			
		||||
  const channelLink = "https://your-domain.com/podcast";
 | 
			
		||||
  const channelDescription = "RSSフィードから自動生成されたポッドキャストです。";
 | 
			
		||||
  const channelDescription =
 | 
			
		||||
    "RSSフィードから自動生成されたポッドキャストです。";
 | 
			
		||||
  const lastBuildDate = new Date().toUTCString();
 | 
			
		||||
 | 
			
		||||
  let itemsXml = "";
 | 
			
		||||
  for (const ep of episodes) {
 | 
			
		||||
    const fileUrl = `https://your-domain.com/podcast_audio/${path.basename(
 | 
			
		||||
      ep.audioPath
 | 
			
		||||
      ep.audioPath,
 | 
			
		||||
    )}`;
 | 
			
		||||
    const pubDate = new Date(ep.pubDate).toUTCString();
 | 
			
		||||
    itemsXml += `
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,12 @@
 | 
			
		||||
import fs from "fs";
 | 
			
		||||
import path from "path";
 | 
			
		||||
import {
 | 
			
		||||
  PollyClient,
 | 
			
		||||
  SynthesizeSpeechCommand,
 | 
			
		||||
} from "@aws-sdk/client-polly";
 | 
			
		||||
import { PollyClient, SynthesizeSpeechCommand } from "@aws-sdk/client-polly";
 | 
			
		||||
 | 
			
		||||
const polly = new PollyClient({ region: "ap-northeast-1" });
 | 
			
		||||
 | 
			
		||||
export async function generateTTS(
 | 
			
		||||
  itemId: string,
 | 
			
		||||
  scriptText: string
 | 
			
		||||
  scriptText: string,
 | 
			
		||||
): Promise<string> {
 | 
			
		||||
  const params = {
 | 
			
		||||
    OutputFormat: "mp3",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,29 @@
 | 
			
		||||
{
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "target": "ES2020",
 | 
			
		||||
    "module": "ESNext",
 | 
			
		||||
    "moduleResolution": "Node",
 | 
			
		||||
    // Environment setup & latest features
 | 
			
		||||
    "lib": ["ESNext"],
 | 
			
		||||
    "target": "ESNext",
 | 
			
		||||
    "module": "Preserve",
 | 
			
		||||
    "moduleDetection": "force",
 | 
			
		||||
    "jsx": "react-jsx",
 | 
			
		||||
    "allowJs": true,
 | 
			
		||||
 | 
			
		||||
    // Bundler mode
 | 
			
		||||
    "moduleResolution": "bundler",
 | 
			
		||||
    "allowImportingTsExtensions": true,
 | 
			
		||||
    "verbatimModuleSyntax": true,
 | 
			
		||||
    "noEmit": true,
 | 
			
		||||
 | 
			
		||||
    // Best practices
 | 
			
		||||
    "strict": true,
 | 
			
		||||
    "esModuleInterop": true,
 | 
			
		||||
    "forceConsistentCasingInFileNames": true,
 | 
			
		||||
    "resolveJsonModule": true,
 | 
			
		||||
    "skipLibCheck": true,
 | 
			
		||||
    "outDir": "dist"
 | 
			
		||||
  },
 | 
			
		||||
  "include": ["scripts", "services", "server.ts"]
 | 
			
		||||
    "noFallthroughCasesInSwitch": true,
 | 
			
		||||
    "noUncheckedIndexedAccess": true,
 | 
			
		||||
    "noImplicitOverride": true,
 | 
			
		||||
 | 
			
		||||
    // Some stricter flags (disabled by default)
 | 
			
		||||
    "noUnusedLocals": false,
 | 
			
		||||
    "noUnusedParameters": false,
 | 
			
		||||
    "noPropertyAccessFromIndexSignature": false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user