mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-21 00:44:41 +08:00
feat: add cf pages support
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -H 0.0.0.0",
|
||||
"build": "next build",
|
||||
"dev": "pnpm gen:runtime && next dev -H 0.0.0.0",
|
||||
"build": "pnpm gen:runtime && next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"lint:fix": "eslint src --fix && pnpm format",
|
||||
@@ -14,10 +14,13 @@
|
||||
"test": "jest",
|
||||
"format": "prettier -w .",
|
||||
"format:check": "prettier -c .",
|
||||
"gen:runtime": "node scripts/convert-config.js",
|
||||
"postbuild": "next-sitemap --config next-sitemap.config.js",
|
||||
"prepare": "husky install"
|
||||
"prepare": "husky install",
|
||||
"pages:build": "pnpm gen:runtime && next build && next-sitemap --config next-sitemap.config.js && npx @cloudflare/next-on-pages --experimental-minify"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cloudflare/next-on-pages": "^1.13.12",
|
||||
"@headlessui/react": "^2.2.4",
|
||||
"@heroicons/react": "^2.2.0",
|
||||
"@vidstack/react": "^1.12.13",
|
||||
|
||||
2488
pnpm-lock.yaml
generated
2488
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
61
scripts/convert-config.js
Normal file
61
scripts/convert-config.js
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env node
|
||||
/* eslint-disable */
|
||||
// AUTO-GENERATED SCRIPT: Converts config.json to TypeScript definition.
|
||||
// Usage: node scripts/convert-config.js
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Resolve project root (one level up from scripts folder)
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
|
||||
// Paths
|
||||
const configPath = path.join(projectRoot, 'config.json');
|
||||
const libDir = path.join(projectRoot, 'src', 'lib');
|
||||
const oldRuntimePath = path.join(libDir, 'runtime.ts');
|
||||
const newRuntimePath = path.join(libDir, 'runtime.ts');
|
||||
|
||||
// Delete the old runtime.ts file if it exists
|
||||
if (fs.existsSync(oldRuntimePath)) {
|
||||
fs.unlinkSync(oldRuntimePath);
|
||||
console.log('旧的 runtime.ts 已删除');
|
||||
}
|
||||
|
||||
// Read and parse config.json
|
||||
let rawConfig;
|
||||
try {
|
||||
rawConfig = fs.readFileSync(configPath, 'utf8');
|
||||
} catch (err) {
|
||||
console.error(`无法读取 ${configPath}:`, err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let config;
|
||||
try {
|
||||
config = JSON.parse(rawConfig);
|
||||
} catch (err) {
|
||||
console.error('config.json 不是有效的 JSON:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Prepare TypeScript file content
|
||||
const tsContent =
|
||||
`// 该文件由 scripts/convert-config.js 自动生成,请勿手动修改\n` +
|
||||
`/* eslint-disable */\n\n` +
|
||||
`export const config = ${JSON.stringify(config, null, 2)} as const;\n\n` +
|
||||
`export type RuntimeConfig = typeof config;\n\n` +
|
||||
`export default config;\n`;
|
||||
|
||||
// Ensure lib directory exists
|
||||
if (!fs.existsSync(libDir)) {
|
||||
fs.mkdirSync(libDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Write to runtime.ts
|
||||
try {
|
||||
fs.writeFileSync(newRuntimePath, tsContent, 'utf8');
|
||||
console.log('已生成 src/lib/runtime.ts');
|
||||
} catch (err) {
|
||||
console.error('写入 runtime.ts 失败:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -185,6 +185,8 @@ async function getVideoDetail(
|
||||
return getDetailFromApi(apiSite, id);
|
||||
}
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const id = searchParams.get('id');
|
||||
|
||||
@@ -54,6 +54,8 @@ async function fetchDoubanData(url: string): Promise<DoubanApiResponse> {
|
||||
}
|
||||
}
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const result = process.env.PASSWORD;
|
||||
|
||||
@@ -5,6 +5,8 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { PlayRecord } from '@/lib/db';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const records = await db.getAllPlayRecords();
|
||||
|
||||
@@ -3,6 +3,8 @@ import { NextResponse } from 'next/server';
|
||||
import { API_CONFIG, ApiSite, getApiSites, getCacheTime } from '@/lib/config';
|
||||
import { cleanHtmlTags } from '@/lib/utils';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
// 根据环境变量决定最大搜索页数,默认 5
|
||||
const MAX_SEARCH_PAGES: number =
|
||||
Number(process.env.NEXT_PUBLIC_SEARCH_MAX_PAGE) || 5;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import runtimeConfig from './runtime';
|
||||
|
||||
export interface ApiSite {
|
||||
key: string;
|
||||
@@ -47,11 +46,8 @@ export const API_CONFIG = {
|
||||
},
|
||||
};
|
||||
|
||||
// 在模块加载时立即读取配置文件并缓存到内存,后续调用直接返回缓存内容,避免重复文件 I/O
|
||||
const configPath = path.join(process.cwd(), 'config.json');
|
||||
const cachedConfig: Config = JSON.parse(
|
||||
fs.readFileSync(configPath, 'utf-8')
|
||||
) as Config;
|
||||
// 在模块加载时立即读取 runtime.ts 中的配置并缓存到内存,避免重复文件 I/O
|
||||
const cachedConfig: Config = runtimeConfig as unknown as Config;
|
||||
|
||||
export function getConfig(): Config {
|
||||
return cachedConfig;
|
||||
|
||||
92
src/lib/runtime.ts
Normal file
92
src/lib/runtime.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
// 该文件由 scripts/convert-config.js 自动生成,请勿手动修改
|
||||
/* eslint-disable */
|
||||
|
||||
export const config = {
|
||||
cache_time: 7200,
|
||||
api_site: {
|
||||
dyttzy: {
|
||||
api: 'http://caiji.dyttzyapi.com/api.php/provide/vod',
|
||||
name: '电影天堂资源',
|
||||
detail: 'http://caiji.dyttzyapi.com',
|
||||
},
|
||||
ruyi: {
|
||||
api: 'https://cj.rycjapi.com/api.php/provide/vod',
|
||||
name: '如意资源',
|
||||
},
|
||||
heimuer: {
|
||||
api: 'https://json.heimuer.xyz/api.php/provide/vod',
|
||||
name: '黑木耳',
|
||||
detail: 'https://heimuer.tv',
|
||||
},
|
||||
bfzy: {
|
||||
api: 'https://bfzyapi.com/api.php/provide/vod',
|
||||
name: '暴风资源',
|
||||
},
|
||||
tyyszy: {
|
||||
api: 'https://tyyszy.com/api.php/provide/vod',
|
||||
name: '天涯资源',
|
||||
},
|
||||
ffzy: {
|
||||
api: 'http://ffzy5.tv/api.php/provide/vod',
|
||||
name: '非凡影视',
|
||||
detail: 'http://ffzy5.tv',
|
||||
},
|
||||
zy360: {
|
||||
api: 'https://360zy.com/api.php/provide/vod',
|
||||
name: '360资源',
|
||||
},
|
||||
iqiyi: {
|
||||
api: 'https://www.iqiyizyapi.com/api.php/provide/vod',
|
||||
name: 'iqiyi资源',
|
||||
},
|
||||
wolong: {
|
||||
api: 'https://wolongzyw.com/api.php/provide/vod',
|
||||
name: '卧龙资源',
|
||||
},
|
||||
hwba: {
|
||||
api: 'https://cjhwba.com/api.php/provide/vod',
|
||||
name: '华为吧资源',
|
||||
},
|
||||
jisu: {
|
||||
api: 'https://jszyapi.com/api.php/provide/vod',
|
||||
name: '极速资源',
|
||||
detail: 'https://jszyapi.com',
|
||||
},
|
||||
dbzy: {
|
||||
api: 'https://dbzy.tv/api.php/provide/vod',
|
||||
name: '豆瓣资源',
|
||||
},
|
||||
mozhua: {
|
||||
api: 'https://mozhuazy.com/api.php/provide/vod',
|
||||
name: '魔爪资源',
|
||||
},
|
||||
mdzy: {
|
||||
api: 'https://www.mdzyapi.com/api.php/provide/vod',
|
||||
name: '魔都资源',
|
||||
},
|
||||
zuid: {
|
||||
api: 'https://api.zuidapi.com/api.php/provide/vod',
|
||||
name: '最大资源',
|
||||
},
|
||||
yinghua: {
|
||||
api: 'https://m3u8.apiyhzy.com/api.php/provide/vod',
|
||||
name: '樱花资源',
|
||||
},
|
||||
wujin: {
|
||||
api: 'https://api.wujinapi.me/api.php/provide/vod',
|
||||
name: '无尽资源',
|
||||
},
|
||||
wwzy: {
|
||||
api: 'https://wwzy.tv/api.php/provide/vod',
|
||||
name: '旺旺短剧',
|
||||
},
|
||||
ikun: {
|
||||
api: 'https://ikunzyapi.com/api.php/provide/vod',
|
||||
name: 'iKun资源',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export type RuntimeConfig = typeof config;
|
||||
|
||||
export default config;
|
||||
11
wrangler.toml
Normal file
11
wrangler.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
name = "moontv"
|
||||
compatibility_date = "2025-06-28"
|
||||
|
||||
# 指定 Pages 产物目录,供 `wrangler pages dev` 本地预览使用
|
||||
pages_build_output_dir = ".vercel/output/static"
|
||||
|
||||
# 开启 Node.js API 兼容层(next-on-pages 已自动注入所需 polyfill)
|
||||
compatibility_flags = ["nodejs_compat"]
|
||||
|
||||
[build]
|
||||
command = "pnpm install --frozen-lockfile && pnpm run pages:build"
|
||||
Reference in New Issue
Block a user