327 lines
10 KiB
JavaScript
327 lines
10 KiB
JavaScript
import { ensureMindSpaceConfig, loadMindSpaceConfig } from '../mindspace-config.mjs';
|
|
import { createMindSearchConfigService } from '../mindsearch-config.mjs';
|
|
import { createMindSpaceService } from '../mindspace.mjs';
|
|
import {
|
|
assertMindSpaceServerAdapterContract,
|
|
createMindSpaceServerAdapter,
|
|
} from '../mindspace-server-adapter.mjs';
|
|
import {
|
|
resolveMindSpaceRuntimeConfig,
|
|
} from '../mindspace-runtime-config.mjs';
|
|
import { createWorkspacePageDeliverService } from '../mindspace-workspace-page-deliver.mjs';
|
|
import { ensurePageDataHtmlPagesBound } from '../page-data-workspace-ensure.mjs';
|
|
import { createPageDataPublicService } from '../page-data-public-service.mjs';
|
|
import { createPageDataService } from '../page-data-service.mjs';
|
|
import {
|
|
ensureAlgorithmConfig,
|
|
loadAlgorithmConfig,
|
|
recalculateHotScores,
|
|
} from '../plaza-algorithm.mjs';
|
|
import { createPlazaEventService } from '../plaza-events.mjs';
|
|
import { createPlazaInteractionService } from '../plaza-interactions.mjs';
|
|
import { createPlazaOpsService } from '../plaza-ops.mjs';
|
|
import { createPlazaPostService, formatPostRow } from '../plaza-posts.mjs';
|
|
import { createPlazaRecommendService } from '../plaza-recommend.mjs';
|
|
import { createPlazaRedis } from '../plaza-redis.mjs';
|
|
import { createPlazaSeoService } from '../plaza-seo.mjs';
|
|
import {
|
|
startPlazaTasks,
|
|
writebackPublications,
|
|
} from '../plaza-tasks.mjs';
|
|
import { createScheduleService } from '../schedule-service.mjs';
|
|
import { createFeedbackService } from '../user-feedback.mjs';
|
|
import { PUBLISH_KEY_UUID } from '../user-publish.mjs';
|
|
import { initSchema } from '../db.mjs';
|
|
|
|
export async function bootstrapPortalDomainServices({
|
|
pool,
|
|
h5Root,
|
|
env = process.env,
|
|
runtime,
|
|
analyticsConfig = {},
|
|
getUserAuth = () => null,
|
|
getSessionSnapshotService = () => null,
|
|
onMindSearchSchemaReady = () => {},
|
|
registerPublicHtmlArtifactsForConversation,
|
|
workspaceMaintenanceEnabled = true,
|
|
logger = console,
|
|
initSchemaFn = initSchema,
|
|
createMindSearchConfigServiceFn =
|
|
createMindSearchConfigService,
|
|
ensureMindSpaceConfigFn = ensureMindSpaceConfig,
|
|
loadMindSpaceConfigFn = loadMindSpaceConfig,
|
|
createScheduleServiceFn = createScheduleService,
|
|
createPageDataServiceFn = createPageDataService,
|
|
createPageDataPublicServiceFn =
|
|
createPageDataPublicService,
|
|
createFeedbackServiceFn = createFeedbackService,
|
|
createMindSpaceServiceFn = createMindSpaceService,
|
|
createMindSpaceServerAdapterFn =
|
|
createMindSpaceServerAdapter,
|
|
assertMindSpaceServerAdapterContractFn =
|
|
assertMindSpaceServerAdapterContract,
|
|
createWorkspacePageDeliverServiceFn =
|
|
createWorkspacePageDeliverService,
|
|
ensurePageDataHtmlPagesBoundFn =
|
|
ensurePageDataHtmlPagesBound,
|
|
resolveMindSpaceRuntimeConfigFn =
|
|
resolveMindSpaceRuntimeConfig,
|
|
ensureAlgorithmConfigFn = ensureAlgorithmConfig,
|
|
loadAlgorithmConfigFn = loadAlgorithmConfig,
|
|
createPlazaRedisFn = createPlazaRedis,
|
|
createPlazaSeoServiceFn = createPlazaSeoService,
|
|
createPlazaInteractionServiceFn =
|
|
createPlazaInteractionService,
|
|
createPlazaEventServiceFn = createPlazaEventService,
|
|
createPlazaRecommendServiceFn =
|
|
createPlazaRecommendService,
|
|
createPlazaPostServiceFn = createPlazaPostService,
|
|
createPlazaOpsServiceFn = createPlazaOpsService,
|
|
startPlazaTasksFn = startPlazaTasks,
|
|
recalculateHotScoresFn = recalculateHotScores,
|
|
writebackPublicationsFn = writebackPublications,
|
|
formatPostRowFn = formatPostRow,
|
|
publishKeyUuid = PUBLISH_KEY_UUID,
|
|
} = {}) {
|
|
if (!pool || !runtime) {
|
|
throw new Error(
|
|
'bootstrapPortalDomainServices requires pool and runtime',
|
|
);
|
|
}
|
|
if (
|
|
typeof registerPublicHtmlArtifactsForConversation !==
|
|
'function'
|
|
) {
|
|
throw new Error(
|
|
'bootstrapPortalDomainServices requires artifact registration',
|
|
);
|
|
}
|
|
|
|
const mindSearchConfigService =
|
|
createMindSearchConfigServiceFn(pool);
|
|
await mindSearchConfigService.ensureSchema();
|
|
await onMindSearchSchemaReady({
|
|
pool,
|
|
mindSearchConfigService,
|
|
});
|
|
await initSchemaFn(pool);
|
|
await ensureMindSpaceConfigFn(pool, { env });
|
|
const storedMindSpaceConfig =
|
|
await loadMindSpaceConfigFn(pool, {
|
|
env,
|
|
includeAnalyticsSecret: true,
|
|
});
|
|
let resolvedAnalyticsConfig = analyticsConfig;
|
|
if (storedMindSpaceConfig?.analytics) {
|
|
resolvedAnalyticsConfig = {
|
|
...analyticsConfig,
|
|
...storedMindSpaceConfig.analytics,
|
|
enabled: Boolean(
|
|
storedMindSpaceConfig.analytics.enabled &&
|
|
storedMindSpaceConfig.analytics.websiteId &&
|
|
storedMindSpaceConfig.analytics.idSecret,
|
|
),
|
|
hostPath: '/analytics',
|
|
scriptPath: '/analytics/script.js',
|
|
};
|
|
}
|
|
|
|
const scheduleService = createScheduleServiceFn(pool, {
|
|
defaultTimezone:
|
|
env.H5_DEFAULT_TIMEZONE || 'Asia/Shanghai',
|
|
});
|
|
const pageDataService = createPageDataServiceFn({
|
|
getUserAuth,
|
|
getPool: () => pool,
|
|
resolveWorkspaceRoot: async (user) => {
|
|
if (user?.workspaceRoot) return user.workspaceRoot;
|
|
const userAuth = getUserAuth();
|
|
if (!userAuth || !user?.id) return null;
|
|
return userAuth.resolveWorkingDir(user.id);
|
|
},
|
|
});
|
|
const pageDataPublicService =
|
|
createPageDataPublicServiceFn({
|
|
getPool: () => pool,
|
|
resolveH5Root: () => h5Root,
|
|
});
|
|
const feedbackService = createFeedbackServiceFn(pool);
|
|
const mindSpace = createMindSpaceServiceFn(pool, {
|
|
maxFileBytes: runtime.maxFileBytes,
|
|
aiDailyLimit: runtime.aiDailyLimit,
|
|
publicPageLimit: runtime.publicPageLimit,
|
|
monthlyViewLimit: runtime.monthlyViewLimit,
|
|
scheduleService,
|
|
});
|
|
|
|
const resolveUserIdForAgentSession = async (sessionId) => {
|
|
const [rows] = await pool.query(
|
|
`SELECT user_id FROM h5_user_sessions WHERE agent_session_id = ? LIMIT 1`,
|
|
[sessionId],
|
|
);
|
|
return rows[0]?.user_id ?? null;
|
|
};
|
|
const mindSpaceRuntimeAdapter =
|
|
assertMindSpaceServerAdapterContractFn(
|
|
createMindSpaceServerAdapterFn({
|
|
pool,
|
|
h5Root,
|
|
env,
|
|
maxFileBytes: runtime.maxFileBytes,
|
|
publicPageLimit: runtime.publicPageLimit,
|
|
resolveUserIdForAgentSession,
|
|
resolveWorkspaceRoot: (userId) =>
|
|
getUserAuth().resolveWorkingDir(userId),
|
|
resolveSessionSnapshot: (sessionId) =>
|
|
getSessionSnapshotService()?.get?.(sessionId),
|
|
registerPublicHtmlArtifactsForConversation,
|
|
syncWorkspaceAssetsEnabled:
|
|
workspaceMaintenanceEnabled,
|
|
remote: runtime.remote,
|
|
logger,
|
|
}),
|
|
);
|
|
mindSpaceRuntimeAdapter.assertReady?.();
|
|
|
|
const mindSpaceServiceFacade =
|
|
mindSpaceRuntimeAdapter.serviceFacade;
|
|
const mindSpaceConversationPackageRegistry =
|
|
mindSpaceRuntimeAdapter.conversationPackageRegistry;
|
|
const mindSpaceAssets =
|
|
mindSpaceRuntimeAdapter.assetService;
|
|
const mindSpacePages = mindSpaceRuntimeAdapter.pageService;
|
|
const mindSpacePageSync =
|
|
mindSpaceRuntimeAdapter.pageSyncService;
|
|
const mindSpacePageLiveEdit =
|
|
mindSpaceRuntimeAdapter.pageLiveEditService;
|
|
const mindSpaceAssetAgent =
|
|
mindSpaceRuntimeAdapter.assetAgentService;
|
|
const mindSpacePublications =
|
|
mindSpaceRuntimeAdapter.publicationService;
|
|
const workspacePageDeliver =
|
|
createWorkspacePageDeliverServiceFn({
|
|
pool,
|
|
pageService: mindSpacePages,
|
|
publicationService: mindSpacePublications,
|
|
pageSyncService: mindSpacePageSync,
|
|
pageDataEnsure: {
|
|
ensurePageDataHtmlPagesBound:
|
|
ensurePageDataHtmlPagesBoundFn,
|
|
},
|
|
h5Root,
|
|
storageRoot:
|
|
resolveMindSpaceRuntimeConfigFn(h5Root, env)
|
|
.storageRoot,
|
|
findPageByRelativePath:
|
|
mindSpacePages.findPageByRelativePath.bind(
|
|
mindSpacePages,
|
|
),
|
|
logger,
|
|
});
|
|
|
|
const resolveUserIdByDirKey = async (dirKey) => {
|
|
let userId = dirKey;
|
|
if (!publishKeyUuid.test(dirKey)) {
|
|
const [rows] = await pool.query(
|
|
`SELECT id FROM h5_users WHERE username = ? LIMIT 1`,
|
|
[dirKey],
|
|
);
|
|
userId = rows[0]?.id;
|
|
}
|
|
return userId ?? null;
|
|
};
|
|
|
|
await ensureAlgorithmConfigFn(pool);
|
|
const plazaAlgorithmConfig =
|
|
await loadAlgorithmConfigFn(pool);
|
|
const plazaRedis = await createPlazaRedisFn(
|
|
env.PLAZA_REDIS_URL,
|
|
pool,
|
|
);
|
|
if (plazaRedis.enabled) {
|
|
logger.log('Plaza Redis enabled');
|
|
}
|
|
const plazaSeo = createPlazaSeoServiceFn(pool);
|
|
const plazaInteractions =
|
|
createPlazaInteractionServiceFn(pool, {
|
|
formatPostRow: formatPostRowFn,
|
|
plazaRedis,
|
|
});
|
|
const plazaEvents = createPlazaEventServiceFn(pool);
|
|
const plazaRecommend = createPlazaRecommendServiceFn(pool, {
|
|
eventService: plazaEvents,
|
|
formatPostRow: formatPostRowFn,
|
|
loadViewerReactions: (viewerId, postIds) =>
|
|
plazaInteractions.loadViewerReactions(
|
|
viewerId,
|
|
postIds,
|
|
),
|
|
algorithmConfig: plazaAlgorithmConfig,
|
|
});
|
|
let plazaOps = null;
|
|
const plazaPosts = createPlazaPostServiceFn(pool, {
|
|
loadViewerReactions: (viewerId, postIds) =>
|
|
plazaInteractions.loadViewerReactions(
|
|
viewerId,
|
|
postIds,
|
|
),
|
|
plazaRedis,
|
|
algorithmConfig: plazaAlgorithmConfig,
|
|
recommendService: plazaRecommend,
|
|
onPostPublished: (postId) =>
|
|
plazaSeo?.notifyPostPublished(postId),
|
|
loadFeaturedPosts: async (viewerId) => {
|
|
if (!plazaOps) {
|
|
return {
|
|
homepage_banner: [],
|
|
trending: [],
|
|
category_top: {},
|
|
};
|
|
}
|
|
return plazaOps.loadActiveFeaturedPosts(viewerId);
|
|
},
|
|
});
|
|
plazaOps = createPlazaOpsServiceFn(pool, {
|
|
formatPostRow: formatPostRowFn,
|
|
reviewPost: (...args) => plazaPosts.reviewPost(...args),
|
|
invalidateFeedCaches: () =>
|
|
plazaRedis?.invalidateFeedCaches?.(),
|
|
});
|
|
startPlazaTasksFn({
|
|
pool,
|
|
plazaRedis,
|
|
recalculateHotScores: recalculateHotScoresFn,
|
|
writebackPublications: writebackPublicationsFn,
|
|
});
|
|
|
|
return {
|
|
mindSearchConfigService,
|
|
mindSpaceAnalyticsConfig: resolvedAnalyticsConfig,
|
|
scheduleService,
|
|
pageDataService,
|
|
pageDataPublicService,
|
|
feedbackService,
|
|
mindSpace,
|
|
mindSpaceRuntimeAdapter,
|
|
mindSpaceServiceFacade,
|
|
mindSpaceConversationPackageRegistry,
|
|
mindSpaceAssets,
|
|
mindSpacePages,
|
|
mindSpacePageSync,
|
|
mindSpacePageLiveEdit,
|
|
mindSpaceAssetAgent,
|
|
mindSpacePublications,
|
|
workspacePageDeliver,
|
|
resolveUserIdByDirKey,
|
|
plazaRedis,
|
|
plazaSeo,
|
|
plazaInteractions,
|
|
plazaEvents,
|
|
plazaRecommend,
|
|
plazaPosts,
|
|
plazaOps,
|
|
mindSpaceCleanup:
|
|
mindSpaceRuntimeAdapter.cleanupService,
|
|
};
|
|
}
|