|
@@ -0,0 +1,59 @@
|
|
|
|
|
+// The multi-app worker provides a deliberately small REST facade, not the Parse SDK.
|
|
|
|
|
+// Adapt only Xiaoshu gateway-local bindings inside its own isolated worker.
|
|
|
|
|
+export async function resolveXiaoshuRuntime(nativeParse, nativePsql, request, loadEnvironment) {
|
|
|
|
|
+ if (typeof nativeParse.User === 'function' && typeof nativePsql.tx === 'function') {
|
|
|
|
|
+ return { Parse: nativeParse, Psql: nativePsql };
|
|
|
|
|
+ }
|
|
|
|
|
+ const load = loadEnvironment || (async () => {
|
|
|
|
|
+ const { workerData } = await import('node:worker_threads');
|
|
|
|
|
+ const { createRequire } = await import('node:module');
|
|
|
|
|
+ const require = createRequire('/opt/future-server/package.json');
|
|
|
|
|
+ const SDK = require('parse/node');
|
|
|
|
|
+ const coreModule = require('parse/lib/node/CoreManager.js');
|
|
|
|
|
+ return { SDK, CoreManager: coreModule.default || coreModule, workerData };
|
|
|
|
|
+ });
|
|
|
|
|
+ const { SDK, CoreManager, workerData } = await load();
|
|
|
|
|
+ const db = nativePsql.db;
|
|
|
|
|
+ if (workerData?.companyId !== '7pIbDBJmKx' || workerData.config?.appId !== '7pIbDBJmKx_main'
|
|
|
|
|
+ || nativeParse.applicationId !== workerData.config.appId
|
|
|
|
|
+ || !nativeParse.masterKey || nativeParse.masterKey !== workerData.config.masterKey
|
|
|
|
|
+ || typeof workerData.token !== 'string' || !workerData.token
|
|
|
|
|
+ || !/^http:\/\/127\.0\.0\.1:\d+\/data\/?$/.test(nativeParse.serverURL)
|
|
|
|
|
+ || typeof db?.tx !== 'function') {
|
|
|
|
|
+ throw new Error('Unsupported Xiaoshu isolated runtime');
|
|
|
|
|
+ }
|
|
|
|
|
+ // One tenant per worker thread; these SDK settings never cross tenant workers.
|
|
|
|
|
+ SDK.initialize(nativeParse.applicationId, undefined, nativeParse.masterKey);
|
|
|
|
|
+ SDK.serverURL = nativeParse.serverURL;
|
|
|
|
|
+ CoreManager.set('REQUEST_HEADERS', { 'x-fmode-worker-token': workerData.token });
|
|
|
|
|
+ CoreManager.set('REQUEST_ATTEMPT_LIMIT', 1);
|
|
|
|
|
+ for (const [field, className] of [['user', '_User'], ['company', 'Company'], ['account', 'Account']]) {
|
|
|
|
|
+ const value = request[field];
|
|
|
|
|
+ if (!value) continue;
|
|
|
|
|
+ const json = typeof value.toJSON === 'function' ? value.toJSON() : value;
|
|
|
|
|
+ if (!json.objectId) throw new Error('Invalid Xiaoshu runtime identity');
|
|
|
|
|
+ request[field] = SDK.Object.fromJSON({ ...json, className });
|
|
|
|
|
+ }
|
|
|
|
|
+ return { Parse: SDK, Psql: db };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function withXiaoshuRuntime(code) {
|
|
|
|
|
+ const marker = '// XIAOSHU_ISOLATED_RUNTIME_COMPAT_V1';
|
|
|
|
|
+ if (code.includes(marker)) return code;
|
|
|
|
|
+ const pattern = /async function handler\s*\(/g;
|
|
|
|
|
+ if ([...code.matchAll(pattern)].length !== 1) throw new Error('Expected exactly one async handler');
|
|
|
|
|
+ return code.replace(pattern, 'async function xiaoshuBusinessHandler(') + '\n' + marker + '\n'
|
|
|
|
|
+ + resolveXiaoshuRuntime.toString() + `
|
|
|
|
|
+async function handler(request, response) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const runtime = await resolveXiaoshuRuntime(Parse, Psql, request);
|
|
|
|
|
+ Parse = runtime.Parse;
|
|
|
|
|
+ Psql = runtime.Psql;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('[XiaoshuRuntime] ' + String(error?.message || error));
|
|
|
|
|
+ return response.status(503).json({ success: false, error: 'runtime_compatibility_error', message: '小树服务暂时不可用,请稍后重试', retcode: -1, retmsg: '小树服务暂时不可用,请稍后重试', result: null });
|
|
|
|
|
+ }
|
|
|
|
|
+ return xiaoshuBusinessHandler(request, response);
|
|
|
|
|
+}
|
|
|
|
|
+`;
|
|
|
|
|
+}
|