Files
memind/server/portal-auth-services-bootstrap.mjs
T
john fde6503bdf
Memind CI / Test, build, and release guards (push) Has been cancelled
feat(mindspace): add SEO/GEO delivery, page template catalog, and admin hooks
Enable optional SEO/GEO injection and discovery routes for confirmed public pages while keeping private pages noindex. Add premium page template skills, portal catalog API, template shop UI, and Baidu push gated by memind_adm config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 08:06:12 +08:00

193 lines
5.7 KiB
JavaScript

import { createBillingAdminConfigService } from '../billing-admin-config.mjs';
import { createRechargeService } from '../billing-recharge.mjs';
import {
createPlanCatalogService,
createSubscriptionService,
ensurePlanCatalogSchema,
} from '../billing-subscription.mjs';
import { resolveNormalizedRouterDecisionMode } from '../chat-intent-router.mjs';
import {
createPageTemplateCatalogService,
ensureTemplateCatalogSchema,
} from '../page-template-catalog.mjs';
import {
createSessionAccess,
isSessionBrokerEnabled,
} from '../session-broker.mjs';
import { isSessionBrokerMetricsEnabled } from '../session-broker-metrics.mjs';
import { isSessionStreamReplayEnabled } from '../session-stream.mjs';
import { createUserAuth } from '../user-auth.mjs';
import { createUserDataSpaceService } from '../user-data-space-service.mjs';
import {
createWechatOAuthService,
loadWechatOAuthConfig,
} from '../wechat-oauth.mjs';
import {
createWechatPayClient,
loadWechatPayConfig,
} from '../wechat-pay.mjs';
function isEnabledFlag(value) {
return ['1', 'true', 'yes', 'on'].includes(
String(value ?? '').trim().toLowerCase(),
);
}
export async function bootstrapPortalAuthServices({
pool,
h5Root,
usersRoot,
mindSearchConfigService,
env = process.env,
logger = console,
ensurePlanCatalogSchemaFn = ensurePlanCatalogSchema,
ensureTemplateCatalogSchemaFn = ensureTemplateCatalogSchema,
createPlanCatalogServiceFn = createPlanCatalogService,
createPageTemplateCatalogServiceFn = createPageTemplateCatalogService,
createSubscriptionServiceFn = createSubscriptionService,
createUserAuthFn = createUserAuth,
createUserDataSpaceServiceFn = createUserDataSpaceService,
createSessionAccessFn = createSessionAccess,
isSessionBrokerEnabledFn = isSessionBrokerEnabled,
isSessionBrokerMetricsEnabledFn =
isSessionBrokerMetricsEnabled,
resolveNormalizedRouterDecisionModeFn =
resolveNormalizedRouterDecisionMode,
isSessionStreamReplayEnabledFn =
isSessionStreamReplayEnabled,
loadWechatPayConfigFn = loadWechatPayConfig,
createWechatPayClientFn = createWechatPayClient,
loadWechatOAuthConfigFn = loadWechatOAuthConfig,
createWechatOAuthServiceFn = createWechatOAuthService,
createRechargeServiceFn = createRechargeService,
createBillingAdminConfigServiceFn = createBillingAdminConfigService,
} = {}) {
if (
!pool ||
!h5Root ||
!usersRoot ||
typeof mindSearchConfigService?.getEffectiveConfig !==
'function'
) {
throw new Error(
'bootstrapPortalAuthServices requires pool, roots, and MindSearch config',
);
}
await ensurePlanCatalogSchemaFn(pool);
await ensureTemplateCatalogSchemaFn(pool);
const planCatalogService =
createPlanCatalogServiceFn(pool);
const subscriptionService =
createSubscriptionServiceFn(pool, {
getPlanAsync: (planType) =>
planCatalogService.getPlan(planType),
});
subscriptionService._planCatalogService =
planCatalogService;
const billingConfigService =
createBillingAdminConfigServiceFn(pool, { env });
await billingConfigService.ensureSchema();
const userAuth = createUserAuthFn(pool, {
usersRoot,
h5Root,
defaultSignupBalanceCents: Number(
env.H5_SIGNUP_BALANCE_CENTS ?? 500,
),
subscriptionService,
billingConfigService,
getMindSearchConfig: () =>
mindSearchConfigService.getEffectiveConfig(),
provisionUserDataSpace: async ({
userId,
workspaceRoot,
}) => {
const service = createUserDataSpaceServiceFn({
workspaceRoot,
userId,
query: pool,
});
return service.ensureReady();
},
});
const sessionAccess = createSessionAccessFn({
userAuth,
enabled: isSessionBrokerEnabledFn(),
});
if (sessionAccess.enabled) {
logger.log(
'[Portal] Session Broker enabled (MEMIND_SESSION_BROKER_ENABLED=1)',
);
}
const routerDecisionMode =
resolveNormalizedRouterDecisionModeFn(env);
const h5SessionFlags = [
sessionAccess.enabled &&
'MEMIND_SESSION_BROKER_ENABLED',
isSessionBrokerMetricsEnabledFn() &&
'MEMIND_SESSION_BROKER_METRICS',
routerDecisionMode !== 'off' &&
`MEMIND_ROUTER_NORMALIZED_DECISION=${routerDecisionMode}`,
isSessionStreamReplayEnabledFn() &&
'MEMIND_SESSION_STREAM_REPLAY',
isEnabledFlag(env.MEMIND_SSE_EVENT_TAXONOMY) &&
'MEMIND_SSE_EVENT_TAXONOMY',
isEnabledFlag(env.MEMIND_RUN_STREAM_REPLAY) &&
'MEMIND_RUN_STREAM_REPLAY',
isEnabledFlag(env.MEMIND_H5_HTML_FINISH_GUARD) &&
'MEMIND_H5_HTML_FINISH_GUARD',
].filter(Boolean);
if (h5SessionFlags.length) {
logger.log(
`[Portal] H5 session flags: ${h5SessionFlags.join(', ')}`,
);
}
const wechatPayClient = createWechatPayClientFn(
loadWechatPayConfigFn(),
);
const templateCatalogService = createPageTemplateCatalogServiceFn(pool, {
userAuth,
h5Root,
wechatPay: wechatPayClient,
});
await templateCatalogService.ensureReady();
const rechargeService = createRechargeServiceFn(pool, {
userAuth,
wechatPay: wechatPayClient,
templateCatalogService,
});
const wechatOAuthService =
createWechatOAuthServiceFn(
pool,
loadWechatOAuthConfigFn(),
{ userAuth },
);
if (wechatPayClient.enabled) {
logger.log(
`WeChat Pay recharge enabled (${wechatPayClient.apiVersion ?? 'unknown'})`,
);
}
if (wechatOAuthService.enabled) {
logger.log('WeChat OAuth login enabled');
}
return {
planCatalogService,
subscriptionService,
billingConfigService,
userAuth,
sessionAccess,
routerDecisionMode,
h5SessionFlags,
wechatPayClient,
wechatOAuthService,
rechargeService,
templateCatalogService,
};
}