| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- import express from 'express';
- import { readFileSync } from 'node:fs';
- // @ts-ignore
- import { XMLHttpRequest } from 'xmlhttprequest';
- // @ts-ignore
- globalThis.XMLHttpRequest = XMLHttpRequest;
- // Polyfill localStorage for Parse SDK
- const memoryStorage = {
- _data: new Map<string, string>(),
- getItem(key: string) {
- return this._data.get(key) || null;
- },
- setItem(key: string, value: string) {
- this._data.set(key, String(value));
- },
- removeItem(key: string) {
- this._data.delete(key);
- },
- clear() {
- this._data.clear();
- },
- key(index: number) {
- return Array.from(this._data.keys())[index] || null;
- },
- get length() {
- return this._data.size;
- }
- };
- // @ts-ignore
- globalThis.localStorage = memoryStorage;
- /**
- * 注意:生产/客户实例正式入口是 fmode-server 加载 api/routes.ts。
- * 本 server.ts 仅作本地开发壳,不挂载直连上游的 Sorftime/TikHub token。
- */
- function getConfig() {
- try {
- const configPath = process.env.NODE_ENV === 'test' ? './config.test.json' : './config.json';
- const configContent = readFileSync(configPath, 'utf-8');
- return JSON.parse(configContent);
- } catch (error: unknown) {
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
- console.warn('Config file not found, using defaults:', errorMessage);
- return {
- parse: {
- port: 3000,
- appId: 'TARGET_PARSE_APP_ID',
- serverURL: 'http://localhost:3000/parse'
- }
- };
- }
- }
- const app = express();
- app.use(express.json());
- app.use(express.urlencoded({ extended: true }));
- async function startServer() {
- const config = getConfig();
- const PORT = process.env.PORT || config.parse?.port || 3000;
- const Parse = require('parse');
- Parse.initialize(config.parse.appId);
- Parse.serverURL = `http://localhost:${PORT}/parse`;
- Parse.masterKey = config.parse.masterKey;
- // @ts-ignore
- globalThis.Parse = Parse;
- app.use((req: any, res: any, next: () => void) => {
- console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
- next();
- });
- app.get('/health', (req: any, res: any) => {
- res.json({
- status: 'healthy',
- instance: 'TARGET-voc-instance',
- timestamp: new Date().toISOString(),
- uptime: process.uptime()
- });
- });
- app.get('/', (req: any, res: any) => {
- res.json({
- message: 'TARGET VOC Instance - dev shell',
- version: '1.0.0-customer-relay',
- note: 'Production uses fmode-server + api/routes.ts',
- endpoints: ['/api', '/health', '/parse']
- });
- });
- // 开发壳可选挂载 api/routes(正式环境由 fmode-server 自动扫描)
- try {
- const apiRouter = (await import('./api/routes.ts')).default;
- app.use('/api', apiRouter);
- console.log('[DevShell] /api mounted from api/routes.ts');
- } catch (e: any) {
- console.warn('[DevShell] api/routes.ts not mounted in this runtime:', e?.message || e);
- }
- app.use((req: any, res: any) => {
- res.status(404).json({
- message: 'Not Found',
- path: req.path,
- method: req.method
- });
- });
- app.use((err: any, req: any, res: any, next: any) => {
- console.error('Error:', err?.message || err);
- res.status(500).json({
- message: 'Internal Server Error',
- error: err?.message
- });
- });
- app.listen(PORT, () => {
- console.log(`[TARGET-voc-instance] listening on :${PORT}`);
- });
- }
- startServer().catch((err) => {
- console.error('Failed to start server:', err);
- process.exit(1);
- });
|