结构调整

This commit is contained in:
桃树夭 committed 2026-10-04 00:00:45 +08:00
1 parent 1c89f558d6
commit e2544f8feb
1109 files changed
+5522 -5959

No files matched your search

@@ -21,7 +21,7 @@ description: Daoyou NestJS API、认证、授权、Better Auth、ALTCHA、admin
## Configuration and Workspace Boundary
- API builds with `nest build` (Nest CLI 12 ESM Rspack); Web builds with Vite. API may import `@daoyou/shared/*`, never Web; shared cannot import either host. LLM generators and prompt rendering belong in `apps/api/src/lib/generation`.
- API builds with `nest build` (Nest CLI 12 default tsc, NodeNext ESM); shared builds first with tsc and exports dist JavaScript/declarations; Web builds with Vite. API lint uses Oxlint with type-aware Promise checks and import boundaries; Web/shared/tools retain ESLint. API may import `@daoyou/shared/*`, never Web; shared cannot import either host. LLM generators and prompt rendering belong in `apps/api/src/lib/generation`.
- Nest services inject `AppConfigService`; independent libraries read `getRuntimeEnvironment()`. The snapshot is validated once with Zod; dotenv discovery is disabled. Never log credential values on validation failure.
- `DatabaseModule` exports the existing Drizzle client, preserving one pool and transaction propagation. Runtime closes it after request/message drain.
@@ -36,7 +36,7 @@ description: Daoyou NestJS API、认证、授权、Better Auth、ALTCHA、admin
- `@Access('active')` resolves `user` / `activeCultivatorRef` through `SessionService`; it does not hydrate a full cultivator or inject a DB executor.
- `@Access('admin')` uses `adminAccess.ts` (`ADMIN_USER_IDS` or legacy `ADMIN_EMAILS`); `account-admin` requires configured user ID authorization.
- `JsonBody` reads raw bytes in its first Pipe after guards, then passes parsed JSON to validation pipes. Keep its parameter factory synchronous: Nest 12 does not await a factory's Promise before the first Pipe. The reader does not inflate content-encoding; the business ceiling is 128 MiB and the webhook's independent limit is 256 KiB. `FirstQuery` reads the original URL without a 1,000-key truncation: query objects keep the first decoded key, named reads prefer a literal key over encoded aliases, and malformed UTF-8 escapes remain intact. Express query parsing is disabled; use `FirstQuery` for business queries. Zod pipes retain the intended 400 versus legacy-unhandled 500 behavior.
- Inspect each admin controller's access metadata; do not assume a filename or frontend loader supplies authorization. Use explicit constructor `@Inject` because the Nest CLI Rspack build disables implicit design-type metadata.
- Inspect each admin controller's access metadata; do not assume a filename or frontend loader supplies authorization. Use explicit constructor `@Inject` because the API TypeScript configuration disables implicit design-type metadata. API/shared relative imports name emitted `.js` files; JSON imports use `with { type: 'json' }`. Nest CLI assets copy Markdown prompts; the registry reads them once at module initialization.
- Keep `NotFoundModule` last in `AppModule.imports`: its fallback controllers preserve authorization for unknown paths in previously protected namespaces, after every concrete feature route. Do not broaden these fallbacks to all API or admin paths.
- `/internal/cron/*` uses `Authorization: Bearer ${CRON_SECRET}`, not user sessions. In production, missing `CRON_SECRET` returns 500.
+3 -3
View File
@@ -8,8 +8,8 @@ AI agents should read this first. Keep changes small, project-specific, and back
- This repo is `NestJS + React SPA`, not Next.js or SSR.
- Runtime stack: Node.js 24, NestJS 12 (Express/native ws), pnpm + Turborepo tooling, React 19, React Router 8, Vite, Tailwind CSS 4, PostgreSQL, Drizzle ORM, Better Auth, Redis, NATS, AI SDK.
- Use the pinned `pnpm` version and `pnpm-lock.yaml` for development and deployment. Do not introduce Bun/npm/yarn lockfiles. Turborepo orchestrates package builds, typechecks and persistent development tasks.
- pnpm workspaces: `apps/api`, `apps/web`, `packages/shared`. Each owns its runtime dependencies; root owns lint/test/maintenance tooling. Shared must not import either app; API and Web may import shared. ESLint enforces these boundaries, repository direction, and combat core independence.
- Use the pinned `pnpm` version and `pnpm-lock.yaml` for development and deployment. Do not introduce Bun/npm/yarn lockfiles. Turborepo orchestrates package builds and typechecks; turbo watch rebuilds dependencies and restarts persistent development tasks.
- pnpm workspaces: `apps/api`, `apps/web`, `packages/shared`. Each owns its runtime dependencies; root owns lint/test/maintenance tooling. Shared must not import either app; API and Web may import shared. ESLint (Web/shared/tools) and Oxlint (API) enforce these boundaries, repository direction, and combat core independence.
- Path aliases are `@app` -> `apps/web/src`, `@server` -> `apps/api/src`, and `@daoyou/shared/*` resolves through the workspace package exports (no source alias bypass).
## Key Directories
@@ -38,7 +38,7 @@ pnpm run db:migrate
```
- `dev[:api|:web]` selects `env/local.env`; `prd[:api|:web]` selects `env/staging.env`. Node/Nest explicitly loads the selected file; maintenance scripts use `node --env-file=... --import tsx`.
- `pnpm run build` uses Turbo to build the independent API and Web packages; Nest CLI 12 builds `apps/api` with its ESM Rspack builder; Vite builds `apps/web`. The old V5 resolver Worker target was retired in Phase 10H. Preserve the remaining CI/CD entrypoints.
- `pnpm run build` uses Turbo to build the independent API and Web packages; Nest CLI 12 builds `apps/api` with its default tsc builder; shared is compiled first with tsc and exports JavaScript/declarations from dist; Vite builds `apps/web`. The old V5 resolver Worker target was retired in Phase 10H. Preserve the remaining CI/CD entrypoints.
- Vitest uses node environment and discovers tests only under `packages/shared/src`.
- Docker runtime contains Node, the pnpm-deployed API production dependencies, package metadata and `dist`; ALTCHA uses the server-side `ALTCHA_HMAC_SECRET` and does not require a frontend site key.
- GitHub Actions runs lint/typecheck/shared tests/build on PRs and master pushes; tag pushes build the API image and always publish latest.
+285
View File
@@ -0,0 +1,285 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"env": {
"node": true
},
"categories": {
"correctness": "off"
},
"rules": {
"constructor-super": "off",
"for-direction": "error",
"getter-return": "off",
"no-async-promise-executor": "error",
"no-case-declarations": "error",
"no-class-assign": "off",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-const-assign": "off",
"no-constant-binary-expression": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-class-members": "off",
"no-dupe-else-if": "error",
"no-dupe-keys": "off",
"no-duplicate-case": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-empty-pattern": "error",
"no-empty-static-block": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-fallthrough": "error",
"no-func-assign": "off",
"no-global-assign": "error",
"no-import-assign": "off",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-new-native-nonconstructor": "off",
"no-nonoctal-decimal-escape": "error",
"no-obj-calls": "off",
"no-prototype-builtins": "error",
"no-redeclare": "off",
"no-regex-spaces": "error",
"no-self-assign": "error",
"no-setter-return": "off",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-this-before-super": "off",
"no-unassigned-vars": "error",
"no-undef": "off",
"no-unexpected-multiline": "error",
"no-unreachable": "off",
"no-unsafe-finally": "error",
"no-unsafe-negation": "off",
"no-unsafe-optional-chaining": "error",
"no-unused-labels": "error",
"no-unused-private-class-members": "error",
"no-unused-vars": "error",
"no-useless-assignment": "error",
"no-useless-backreference": "error",
"no-useless-catch": "error",
"no-useless-escape": "error",
"no-with": "off",
"preserve-caught-error": "error",
"require-yield": "error",
"use-isnan": "error",
"valid-typeof": "error",
"no-var": "error",
"prefer-const": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"typescript/ban-ts-comment": "error",
"no-array-constructor": "error",
"typescript/no-duplicate-enum-values": "error",
"typescript/no-empty-object-type": "error",
"typescript/no-explicit-any": "error",
"typescript/no-extra-non-null-assertion": "error",
"typescript/no-misused-new": "error",
"typescript/no-namespace": "error",
"typescript/no-non-null-asserted-optional-chain": "error",
"typescript/no-require-imports": "error",
"typescript/no-this-alias": "error",
"typescript/no-unnecessary-type-constraint": "error",
"typescript/no-unsafe-declaration-merging": "error",
"typescript/no-unsafe-function-type": "error",
"no-unused-expressions": "error",
"typescript/no-wrapper-object-types": "error",
"typescript/prefer-as-const": "error",
"typescript/prefer-namespace-keyword": "error",
"typescript/triple-slash-reference": "error",
"typescript/no-floating-promises": "error"
},
"ignorePatterns": ["dist/**", "node_modules/**"],
"overrides": [
{
"files": [
"src/main.ts",
"src/http/**/*.ts",
"src/runtime/**/*.ts",
"src/realtime/**/*.ts"
],
"rules": {
"typescript/no-misused-promises": "error"
}
},
{
"files": ["src/**/*.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": ["@app/*", "@daoyou/web*", "**/apps/web/**"]
}
]
}
},
{
"files": ["src/lib/repositories/**/*.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["@app/*", "@daoyou/web*", "**/apps/web/**"]
},
{
"group": [
"@server/*/application/**",
"@server/sects/organization/**"
],
"message": "Repositories must not call application services."
}
]
}
]
}
},
{
"files": ["src/**/*.service.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": ["@app/*", "@daoyou/web*", "**/apps/web/**"],
"paths": [
{
"name": "@server/lib/drizzle/db.js",
"importNames": ["db", "getExecutor"],
"message": "Inject DRIZZLE_DATABASE in Nest services; pass it to repository calls."
}
]
}
]
},
"excludeFiles": [
"src/market/**/*.service.ts",
"src/inventory/**/*.service.ts"
]
},
{
"files": ["src/market/**/*.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["@app/*", "@daoyou/web*", "**/apps/web/**"]
},
{
"group": [
"@server/cultivator/application/**",
"@server/inventory/application/**"
],
"message": "Market uses public character queries and inventory operations/providers."
}
]
}
]
}
},
{
"files": ["src/inventory/**/*.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["@app/*", "@daoyou/web*", "**/apps/web/**"]
},
{
"group": ["@server/market/**", "**/market/application/**"],
"message": "Inventory owns recycling and must not depend on Market."
}
]
}
]
}
},
{
"files": ["src/market/**/*.service.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["@app/*", "@daoyou/web*", "**/apps/web/**"]
},
{
"group": [
"@server/cultivator/application/**",
"@server/inventory/application/**"
],
"message": "Market uses public character queries and inventory operations/providers."
}
],
"paths": [
{
"name": "@server/lib/drizzle/db.js",
"importNames": ["db", "getExecutor"],
"message": "Inject DRIZZLE_DATABASE in Nest services; pass it to repository calls."
}
]
}
]
}
},
{
"files": ["src/inventory/**/*.service.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["@app/*", "@daoyou/web*", "**/apps/web/**"]
},
{
"group": ["@server/market/**", "**/market/application/**"],
"message": "Inventory owns recycling and must not depend on Market."
}
],
"paths": [
{
"name": "@server/lib/drizzle/db.js",
"importNames": ["db", "getExecutor"],
"message": "Inject DRIZZLE_DATABASE in Nest services; pass it to repository calls."
}
]
}
]
}
},
{
"files": ["src/lib/mq/**/*.ts"],
"rules": {
"no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["@app/*", "@daoyou/web*", "**/apps/web/**"]
},
{
"group": [
"@server/*/application/**",
"@server/sects/organization/**",
"@server/runtime/**"
],
"message": "Business message registration belongs to Runtime; MQ libraries own transport."
}
]
}
]
}
}
]
}
+7 -7
View File
@@ -4,13 +4,13 @@
"sourceRoot": "src",
"entryFile": "main",
"compilerOptions": {
"builder": {
"type": "rspack",
"options": {
"configPath": "rspack.config.mjs"
}
},
"tsConfigPath": "tsconfig.build.json",
"deleteOutDir": true
"deleteOutDir": true,
"assets": [
{
"include": "prompts/*.md",
"watchAssets": true
}
]
}
}
+5 -7
View File
@@ -8,8 +8,9 @@
],
"scripts": {
"build": "nest build",
"dev": "APP_ENV=local NODE_ENV=development nest start --watch --no-shell --env-file ../../env/local.env",
"prd": "APP_ENV=staging NODE_ENV=development nest start --watch --no-shell --env-file ../../env/staging.env",
"dev": "APP_ENV=local NODE_ENV=development nest start --no-shell --env-file ../../env/local.env",
"lint": "oxlint --type-aware -c .oxlintrc.json src/ scripts/",
"prd": "APP_ENV=staging NODE_ENV=development nest start --no-shell --env-file ../../env/staging.env",
"start": "node dist/main.js",
"typecheck": "tsc --noEmit -p tsconfig.json"
},
@@ -46,15 +47,12 @@
},
"devDependencies": {
"@nestjs/cli": "^12.0.8",
"@rspack/core": "^1.5.8",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.6",
"@types/nodemailer": "^8.0.1",
"@types/pg": "^8.23.1",
"@types/ws": "^8.18.2",
"fork-ts-checker-webpack-plugin": "^9.1.0",
"tsconfig-paths-webpack-plugin": "^4.2.0",
"webpack": "^5.105.4",
"webpack-node-externals": "^3.0.0"
"oxlint": "^1.58.0",
"oxlint-tsgolint": "^7.0.2001"
}
}
-38
View File
@@ -1,38 +0,0 @@
import { readFileSync } from 'node:fs';
import { builtinModules } from 'node:module';
const { dependencies } = JSON.parse(
readFileSync(new URL('./package.json', import.meta.url), 'utf8'),
);
// Nest CLI 12's ESM builder bundles workspace sources and Markdown.
// Runtime npm dependencies stay external for Node and the production image.
export default (options) => {
options.module.rules[0].use[0].options.jsc.transform.decoratorMetadata = false;
return {
...options,
devtool: 'source-map',
externalsPresets: { node: false },
externals: [
({ request }, callback) => {
const packageName = request?.startsWith('@')
? request.split('/').slice(0, 2).join('/')
: request?.split('/')[0];
if (
request &&
!request.startsWith('@daoyou/shared/') &&
(request.startsWith('node:') ||
builtinModules.includes(request) ||
dependencies[packageName])
) {
return callback(null, `module ${request}`);
}
callback();
},
],
module: {
...options.module,
rules: [...options.module.rules, { test: /\.md$/, type: 'asset/source' }],
},
};
};
@@ -1,8 +1,8 @@
/** Maintenance command: default read-only inventory; --apply requires explicit record IDs. */
import { and, eq, inArray, sql } from 'drizzle-orm';
import { z } from 'zod';
import { db } from '../src/lib/drizzle/db';
import { sectTaskRecords } from '../src/lib/drizzle/schema';
import { db } from '../src/lib/drizzle/db.js';
import { sectTaskRecords } from '../src/lib/drizzle/schema.js';
const args = process.argv.slice(2);
const apply = args.includes('--apply');
@@ -2,18 +2,18 @@
import { and, asc, eq, sql } from 'drizzle-orm';
import { createHash } from 'node:crypto';
import { z } from 'zod';
import { db, type DbExecutor } from '../src/lib/drizzle/db';
import { inventoryItems } from '../src/lib/drizzle/schema';
import { redisLockKeys, withRedisLock } from '../src/lib/redis/lock';
import { lockCultivatorForStateMutation } from '../src/lib/repositories/playerStateRepository';
import { db, type DbExecutor } from '../src/lib/drizzle/db.js';
import { inventoryItems } from '../src/lib/drizzle/schema.js';
import { redisLockKeys, withRedisLock } from '../src/lib/redis/lock.js';
import { lockCultivatorForStateMutation } from '../src/lib/repositories/playerStateRepository.js';
import {
assertInventoryIdle,
inventoryItemOf,
saveInventoryPlan,
} from '../src/inventory/application/InventoryService';
import { inventoryStackKey } from '../src/inventory/application/inventoryStackKey';
import { ResourceEventCommitter } from '../src/player/application/state/ResourceEventCommitter';
import { compactStorage, type InventoryItem } from '../../../packages/shared/src/inventory';
} from '../src/inventory/application/InventoryService.js';
import { inventoryStackKey } from '../src/inventory/application/inventoryStackKey.js';
import { ResourceEventCommitter } from '../src/player/application/state/ResourceEventCommitter.js';
import { compactStorage, type InventoryItem } from '../../../packages/shared/src/inventory/index.js';
const args = process.argv.slice(2);
const all = args.includes('--all');
@@ -1,8 +1,8 @@
/** Offline maintenance only. No conversion of old requirements into new equipment rules. */
import { and, inArray, sql } from 'drizzle-orm';
import { z } from 'zod';
import { db } from '../src/lib/drizzle/db';
import { sectTaskRecords } from '../src/lib/drizzle/schema';
import { db } from '../src/lib/drizzle/db.js';
import { sectTaskRecords } from '../src/lib/drizzle/schema.js';
const args = process.argv.slice(2);
const apply = args.includes('--apply');
+3 -3
View File
@@ -6,9 +6,9 @@ import {
} from '@daoyou/shared/contracts/account';
import { fromNodeHeaders } from 'better-auth/node';
import type { Request } from 'express';
import { SessionService } from '../auth/session.service';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { SessionService } from '../auth/session.service.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
@Controller('api/account')
export class AccountController {
+2 -2
View File
@@ -1,6 +1,6 @@
import { Module } from '@nestjs/common';
import { AuthModule } from '../auth/auth.module';
import { AccountController } from './account.controller';
import { AuthModule } from '../auth/auth.module.js';
import { AccountController } from './account.controller.js';
@Module({ imports: [AuthModule], controllers: [AccountController] })
export class AccountModule {}
+7 -7
View File
@@ -9,7 +9,7 @@ import {
Res,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import type { AuthUser } from '@server/lib/auth/types.js';
import {
AdminAccountBanRequestSchema,
AdminAccountChangeEmailRequestSchema,
@@ -20,12 +20,12 @@ import {
} from '@daoyou/shared/contracts/adminAccounts';
import { fromNodeHeaders } from 'better-auth/node';
import type { Request, Response } from 'express';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { AccountsService } from './accounts.service';
import { AdminErrors } from './admin-errors';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { AccountsService } from './accounts.service.js';
import { AdminErrors } from './admin-errors.js';
function authHeaders(response: Response) {
return (headers: Headers) => {
+6 -6
View File
@@ -8,12 +8,12 @@ import {
type AdminAccountListQuery,
} from '@daoyou/shared/contracts/adminAccounts';
import { HttpException, Inject, Injectable } from '@nestjs/common';
import { DRIZZLE_DATABASE } from '@server/database/database.service';
import { auth } from '@server/lib/auth/auth';
import { authAccounts, authSessions } from '@server/lib/auth/schema';
import type { AuthUser } from '@server/lib/auth/types';
import { runDbTasks, type DbClient } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import { DRIZZLE_DATABASE } from '@server/database/database.service.js';
import { auth } from '@server/lib/auth/auth.js';
import { authAccounts, authSessions } from '@server/lib/auth/schema.js';
import type { AuthUser } from '@server/lib/auth/types.js';
import { runDbTasks, type DbClient } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import { APIError } from 'better-auth/api';
import { and, eq, inArray } from 'drizzle-orm';
type AuthHeaders = (headers: Headers) => void;
+2 -2
View File
@@ -1,5 +1,5 @@
import { redisLockErrorResponse } from '@server/lib/http/errors';
import { apiErrorFilter } from '../http/error-filter';
import { redisLockErrorResponse } from '@server/lib/http/errors.js';
import { apiErrorFilter } from '../http/error-filter.js';
export const AdminErrors = apiErrorFilter((error) => {
const lock = redisLockErrorResponse(error);
+8 -8
View File
@@ -6,14 +6,14 @@ import {
Patch,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { AdminErrors } from './admin-errors';
import { AdminFeedbackService } from './feedback.service';
import { MonitoringService } from './monitoring.service';
import { SettingsService } from './settings.service';
import type { AuthUser } from '@server/lib/auth/types.js';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { AdminErrors } from './admin-errors.js';
import { AdminFeedbackService } from './feedback.service.js';
import { MonitoringService } from './monitoring.service.js';
import { SettingsService } from './settings.service.js';
@Controller('api/admin')
@Access('admin')
+23 -23
View File
@@ -1,27 +1,27 @@
import { Module } from '@nestjs/common';
import { DatabaseModule } from '@server/database/database.module';
import { AccountsController } from './accounts.controller';
import { AccountsService } from './accounts.service';
import { AdminController } from './admin.controller';
import { AdminFeedbackService } from './feedback.service';
import { AdminItemLibraryController } from './item-library.controller';
import { AdminItemLibraryService } from './item-library.service';
import { MonitoringService } from './monitoring.service';
import { AdminRedeemCodesController } from './redeem-codes.controller';
import { AdminRedeemCodesService } from './redeem-codes.service';
import { AdminReputationShopController } from './reputation-shop.controller';
import { AdminReputationShopService } from './reputation-shop.service';
import { AdminRewardItemsController } from './reward-items.controller';
import { AdminRewardItemsService } from './reward-items.service';
import { AdminSectShopController } from './sect-shop.controller';
import { AdminSectShopService } from './sect-shop.service';
import { SettingsService } from './settings.service';
import { AdminSponsorshipController } from './sponsorship.controller';
import { AdminSponsorshipService } from './sponsorship.service';
import { AdminSystemMailsController } from './system-mails.controller';
import { AdminSystemMailsService } from './system-mails.service';
import { AdminTowerController } from './tower.controller';
import { AdminTowerService } from './tower.service';
import { DatabaseModule } from '@server/database/database.module.js';
import { AccountsController } from './accounts.controller.js';
import { AccountsService } from './accounts.service.js';
import { AdminController } from './admin.controller.js';
import { AdminFeedbackService } from './feedback.service.js';
import { AdminItemLibraryController } from './item-library.controller.js';
import { AdminItemLibraryService } from './item-library.service.js';
import { MonitoringService } from './monitoring.service.js';
import { AdminRedeemCodesController } from './redeem-codes.controller.js';
import { AdminRedeemCodesService } from './redeem-codes.service.js';
import { AdminReputationShopController } from './reputation-shop.controller.js';
import { AdminReputationShopService } from './reputation-shop.service.js';
import { AdminRewardItemsController } from './reward-items.controller.js';
import { AdminRewardItemsService } from './reward-items.service.js';
import { AdminSectShopController } from './sect-shop.controller.js';
import { AdminSectShopService } from './sect-shop.service.js';
import { SettingsService } from './settings.service.js';
import { AdminSponsorshipController } from './sponsorship.controller.js';
import { AdminSponsorshipService } from './sponsorship.service.js';
import { AdminSystemMailsController } from './system-mails.controller.js';
import { AdminSystemMailsService } from './system-mails.service.js';
import { AdminTowerController } from './tower.controller.js';
import { AdminTowerService } from './tower.service.js';
@Module({
imports: [DatabaseModule],
@@ -1,11 +1,11 @@
import { SpiritSeedGenerator } from '@server/lib/generation/SpiritSeedGenerator';
import { SpiritSeedGenerator } from '@server/lib/generation/SpiritSeedGenerator.js';
import {
getExecutor,
type DbExecutor,
type DbTransaction,
} from '@server/lib/drizzle/db';
import { itemLibrary } from '@server/lib/drizzle/schema';
import { MaterialGenerator } from '@server/lib/generation/MaterialGenerator';
} from '@server/lib/drizzle/db.js';
import { itemLibrary } from '@server/lib/drizzle/schema.js';
import { MaterialGenerator } from '@server/lib/generation/MaterialGenerator.js';
import type { MaterialSkeleton } from '@daoyou/shared/engine/material/creation/types';
import {
ItemLibraryEntrySchema,
@@ -21,7 +21,7 @@ import {
} from '@daoyou/shared/types/constants';
import type { Material } from '@daoyou/shared/types/cultivator';
import { and, asc, eq, gte, inArray, sql } from 'drizzle-orm';
import { computeItemLibrarySampleKey } from '@server/lib/utils/itemLibrarySampleKey';
import { computeItemLibrarySampleKey } from '@server/lib/utils/itemLibrarySampleKey.js';
type ItemLibraryRow = typeof itemLibrary.$inferSelect;
@@ -1,10 +1,10 @@
import { redeemCodeClaims, redeemCodes } from '@server/lib/drizzle/schema';
import { resolveRedeemCodeRewardAttachments } from '@server/lib/redeem/reward';
import { redeemCodeClaims, redeemCodes } from '@server/lib/drizzle/schema.js';
import { resolveRedeemCodeRewardAttachments } from '@server/lib/redeem/reward.js';
import { materializeRewardAttachments } from '@daoyou/shared/contracts/adminRewards';
import { and, eq, sql } from 'drizzle-orm';
import { randomUUID } from 'node:crypto';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors';
import { MailService } from '@server/mail/application/MailService';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors.js';
import { MailService } from '@server/mail/application/MailService.js';
export class RedeemClaimError extends Error {
constructor(
+6 -6
View File
@@ -1,16 +1,16 @@
import { HttpException, Inject, Injectable } from '@nestjs/common';
import { DRIZZLE_DATABASE } from '@server/database/database.service';
import type { DbClient } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import { DRIZZLE_DATABASE } from '@server/database/database.service.js';
import type { DbClient } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import {
findFeedbackById,
findFeedbacks,
updateFeedbackStatus,
type FeedbackStatus,
type FeedbackType,
} from '@server/lib/repositories/feedbackRepository';
import { MailService } from '@server/mail/application/MailService';
import { updateSpiritStones } from '@server/cultivator/application/readers/CultivatorStateRepository';
} from '@server/lib/repositories/feedbackRepository.js';
import { MailService } from '@server/mail/application/MailService.js';
import { updateSpiritStones } from '@server/cultivator/application/readers/CultivatorStateRepository.js';
import { and, eq, inArray } from 'drizzle-orm';
import { z } from 'zod';
@@ -8,12 +8,12 @@ import {
Put,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { AdminErrors } from './admin-errors';
import { AdminItemLibraryService } from './item-library.service';
import type { AuthUser } from '@server/lib/auth/types.js';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { AdminErrors } from './admin-errors.js';
import { AdminItemLibraryService } from './item-library.service.js';
@Controller('api/admin/item-library')
@Access('admin')
+3 -3
View File
@@ -2,7 +2,7 @@ import { HttpException, Injectable } from '@nestjs/common';
import {
getItemLibraryDailyMaterialGenerationSettings,
upsertItemLibraryDailyMaterialGenerationSettings,
} from '@server/lib/repositories/appSettingsRepository';
} from '@server/lib/repositories/appSettingsRepository.js';
import {
archiveItemLibraryEntry,
createItemLibraryEntry,
@@ -10,11 +10,11 @@ import {
listItemLibrary,
normalizeItemLibraryFilters,
updateItemLibraryEntry,
} from '@server/lib/repositories/itemLibraryRepository';
} from '@server/lib/repositories/itemLibraryRepository.js';
import {
generateMaterialLibraryEntries,
generateSpiritSeedLibraryEntries,
} from '@server/admin/application/MaterialLibraryService';
} from '@server/admin/application/MaterialLibraryService.js';
import { ItemLibraryDailyMaterialGenerationSettingsSchema } from '@daoyou/shared/lib/constants/appSettings';
import {
CreateItemLibraryEntrySchema,
+2 -2
View File
@@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import { getLlmMetricsSnapshot } from '@server/lib/llm/metricsStore';
import { getOnlineUsersSnapshot } from '@server/realtime/infrastructure/onlinePresenceService';
import { getLlmMetricsSnapshot } from '@server/lib/llm/metricsStore.js';
import { getOnlineUsersSnapshot } from '@server/realtime/infrastructure/onlinePresenceService.js';
@Injectable()
export class MonitoringService {
@@ -7,12 +7,12 @@ import {
Post,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { AdminErrors } from './admin-errors';
import { AdminRedeemCodesService } from './redeem-codes.service';
import type { AuthUser } from '@server/lib/auth/types.js';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { AdminErrors } from './admin-errors.js';
import { AdminRedeemCodesService } from './redeem-codes.service.js';
@Controller('api/admin/redeem-codes')
@Access('admin')
+5 -5
View File
@@ -4,15 +4,15 @@ import {
} from '@daoyou/shared/contracts/adminRewards';
import type { MailAttachment } from '@daoyou/shared/types/mail';
import { HttpException, Inject, Injectable } from '@nestjs/common';
import { DRIZZLE_DATABASE } from '@server/database/database.service';
import type { DbClient } from '@server/lib/drizzle/db';
import { redeemCodes } from '@server/lib/drizzle/schema';
import { DRIZZLE_DATABASE } from '@server/database/database.service.js';
import type { DbClient } from '@server/lib/drizzle/db.js';
import { redeemCodes } from '@server/lib/drizzle/schema.js';
import {
generateRedeemCode,
isValidRedeemCodeFormat,
normalizeRedeemCode,
} from '@server/lib/redeem/code';
import { describeRedeemCodeReward } from '@server/lib/redeem/reward';
} from '@server/lib/redeem/code.js';
import { describeRedeemCodeReward } from '@server/lib/redeem/reward.js';
import { and, desc, eq, type SQL } from 'drizzle-orm';
import { z } from 'zod';
@@ -8,12 +8,12 @@ import {
Put,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { AdminErrors } from './admin-errors';
import { AdminReputationShopService } from './reputation-shop.service';
import type { AuthUser } from '@server/lib/auth/types.js';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { AdminErrors } from './admin-errors.js';
import { AdminReputationShopService } from './reputation-shop.service.js';
@Controller('api/admin/reputation-shop')
@Access('admin')
@@ -5,7 +5,7 @@ import {
listReputationShopItems,
ReputationShopError,
updateReputationShopItem,
} from '@server/reputation-shop/application/ReputationShopService';
} from '@server/reputation-shop/application/ReputationShopService.js';
import {
ReputationShopItemMutationSchema,
ReputationShopListQuerySchema,
@@ -1,11 +1,11 @@
import { Controller, HttpCode, Inject, Post, UseFilters } from '@nestjs/common';
import { AdminItemGenerationSchema } from '@daoyou/shared/contracts/adminItemGeneration';
import type { z } from 'zod';
import { Access } from '../auth/access';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { AdminErrors } from './admin-errors';
import { AdminRewardItemsService } from './reward-items.service';
import { Access } from '../auth/access.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { AdminErrors } from './admin-errors.js';
import { AdminRewardItemsService } from './reward-items.service.js';
@Controller('api/admin/reward-items')
@Access('admin')
+1 -1
View File
@@ -1,5 +1,5 @@
import { HttpException, Injectable } from '@nestjs/common';
import { getQuotaCategoryForFamily } from '@server/alchemy/application/AlchemyRecipeRules';
import { getQuotaCategoryForFamily } from '@server/alchemy/application/AlchemyRecipeRules.js';
import { TALISMAN_SCENARIO_OPTIONS } from '@daoyou/shared/config/talismanScenarios';
import { AdminItemGenerationSchema } from '@daoyou/shared/contracts/adminItemGeneration';
import { RewardItemSchema } from '@daoyou/shared/contracts/adminRewards';
+6 -6
View File
@@ -8,12 +8,12 @@ import {
Put,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { AdminErrors } from './admin-errors';
import { AdminSectShopService } from './sect-shop.service';
import type { AuthUser } from '@server/lib/auth/types.js';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { AdminErrors } from './admin-errors.js';
import { AdminSectShopService } from './sect-shop.service.js';
@Controller('api/admin/sect-shop')
@Access('admin')
+1 -1
View File
@@ -5,7 +5,7 @@ import {
listSectShopItems,
SectShopError,
updateSectShopItem,
} from '@server/sects/application/SectShopService';
} from '@server/sects/application/SectShopService.js';
import {
SectShopItemMutationSchema,
SectShopListQuerySchema,
+1 -1
View File
@@ -4,7 +4,7 @@ import {
getAuthPageAnnouncement,
getResolvedCommunityQqGroupNumber,
upsertAppSetting,
} from '@server/lib/repositories/appSettingsRepository';
} from '@server/lib/repositories/appSettingsRepository.js';
import { APP_SETTING_KEYS } from '@daoyou/shared/lib/constants/appSettings';
import { z } from 'zod';
+6 -6
View File
@@ -8,12 +8,12 @@ import {
Put,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { AdminErrors } from './admin-errors';
import { AdminSponsorshipService } from './sponsorship.service';
import type { AuthUser } from '@server/lib/auth/types.js';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { AdminErrors } from './admin-errors.js';
import { AdminSponsorshipService } from './sponsorship.service.js';
@Controller('api/admin/sponsorship')
@Access('admin')
+3 -3
View File
@@ -1,5 +1,5 @@
import { HttpException, Injectable } from '@nestjs/common';
import { getAfdianSponsorshipConfig } from '@server/lib/repositories/appSettingsRepository';
import { getAfdianSponsorshipConfig } from '@server/lib/repositories/appSettingsRepository.js';
import {
getSponsorshipOrderForAdmin,
grantManualSponsorshipMerit,
@@ -10,8 +10,8 @@ import {
rotateSponsorshipClaimAsAdmin,
SponsorshipApplicationError,
updateSponsorshipConfigAsAdmin,
} from '@server/sponsorship/application/SponsorshipApplicationService';
import { requireSponsorshipProvider } from '@server/lib/sponsorship/providerRegistry';
} from '@server/sponsorship/application/SponsorshipApplicationService.js';
import { requireSponsorshipProvider } from '@server/lib/sponsorship/providerRegistry.js';
import {
AfdianSponsorshipConfigSchema,
SPONSORSHIP_TIER_IDS,
@@ -8,20 +8,20 @@ import {
Put,
UseFilters,
} from '@nestjs/common';
import type { AuthUser } from '@server/lib/auth/types';
import type { AuthUser } from '@server/lib/auth/types.js';
import type { z } from 'zod';
import { Access, CurrentUser } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { AdminErrors } from './admin-errors';
import { Access, CurrentUser } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { AdminErrors } from './admin-errors.js';
import {
CreateSchema,
ListSchema,
RevisionSchema,
UpdateSchema,
} from './system-mails-input';
import { AdminSystemMailsService } from './system-mails.service';
} from './system-mails-input.js';
import { AdminSystemMailsService } from './system-mails.service.js';
@Controller('api/admin/system-mails')
@Access('admin')
@UseFilters(AdminErrors)
+4 -4
View File
@@ -1,8 +1,8 @@
import { SystemMailInputSchema } from '@daoyou/shared/contracts/systemMail';
import { HttpException, Inject, Injectable } from '@nestjs/common';
import { DRIZZLE_DATABASE } from '@server/database/database.service';
import type { DbClient } from '@server/lib/drizzle/db';
import { mails, systemMailCampaigns } from '@server/lib/drizzle/schema';
import { DRIZZLE_DATABASE } from '@server/database/database.service.js';
import type { DbClient } from '@server/lib/drizzle/db.js';
import { mails, systemMailCampaigns } from '@server/lib/drizzle/schema.js';
import { and, desc, eq, ilike, sql } from 'drizzle-orm';
import { createHash } from 'node:crypto';
import { z } from 'zod';
@@ -11,7 +11,7 @@ import {
ListSchema,
RevisionSchema,
UpdateSchema,
} from './system-mails-input';
} from './system-mails-input.js';
const countDeliveries = sql<number>`(select count(*)::int from ${mails} delivered where delivered.system_mail_campaign_id = ${systemMailCampaigns}.id)`;
function values(input: z.infer<typeof SystemMailInputSchema>) {
return {
+7 -7
View File
@@ -9,13 +9,13 @@ import {
} from '@nestjs/common';
import type { Response } from 'express';
import type { z } from 'zod';
import { Access } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { AdminErrors } from './admin-errors';
import { TowerQuerySchema, TowerRegenerateSchema } from './tower-input';
import { AdminTowerService } from './tower.service';
import { Access } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { AdminErrors } from './admin-errors.js';
import { TowerQuerySchema, TowerRegenerateSchema } from './tower-input.js';
import { AdminTowerService } from './tower.service.js';
@Controller('api/admin/tower-enemy-sets')
@Access('admin')
+2 -2
View File
@@ -5,7 +5,7 @@ import {
readTowerWeekRecord,
regenerateTowerWeek,
towerWeekFingerprint,
} from '@server/lib/repositories/towerRepository';
} from '@server/lib/repositories/towerRepository.js';
import type { AdminTowerView } from '@daoyou/shared/contracts/adminTower';
import {
publishedTowerEncounter,
@@ -16,7 +16,7 @@ import {
getTowerSeasonMeta,
} from '@daoyou/shared/lib/tower/season';
import { z } from 'zod';
import { TowerQuerySchema, TowerRegenerateSchema } from './tower-input';
import { TowerQuerySchema, TowerRegenerateSchema } from './tower-input.js';
@Injectable()
export class AdminTowerService {
async read(query: z.infer<typeof TowerQuerySchema>) {
@@ -8,21 +8,21 @@ import {
Post,
UseFilters,
} from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError.js';
import { z } from 'zod';
import { Access, CurrentCultivator } from '../auth/access';
import { apiErrorFilter } from '../http/error-filter';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { AlchemyFormulasService } from './alchemy-formulas.service';
import { Access, CurrentCultivator } from '../auth/access.js';
import { apiErrorFilter } from '../http/error-filter.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { AlchemyFormulasService } from './alchemy-formulas.service.js';
import {
DiscoveryConfirmSchema,
FormulaAnalyzeSchema,
FormulaIdParamSchema,
FormulaListQuerySchema,
} from './alchemy-input';
} from './alchemy-input.js';
function formulaErrors(message: string, includeDetails = true) {
return apiErrorFilter((error) => {
@@ -2,19 +2,19 @@ import { Injectable } from '@nestjs/common';
import {
assertAlchemyMaterialVersions,
readAlchemyMaterials,
} from '@server/alchemy/application/inventory/AlchemyInventory';
} from '@server/alchemy/application/inventory/AlchemyInventory.js';
import {
analyzeFormulaMaterials,
confirmDiscoveryCandidate,
deleteCultivatorFormula,
listCultivatorFormulasPage,
} from '@server/alchemy/application/AlchemyFormulaService';
} from '@server/alchemy/application/AlchemyFormulaService.js';
import type { z } from 'zod';
import type {
DiscoveryConfirmSchema,
FormulaAnalyzeSchema,
FormulaListQuerySchema,
} from './alchemy-input';
} from './alchemy-input.js';
@Injectable()
export class AlchemyFormulasService {
+4 -4
View File
@@ -1,8 +1,8 @@
import { Module } from '@nestjs/common';
import { AlchemyFormulasController } from './alchemy-formulas.controller';
import { AlchemyFormulasService } from './alchemy-formulas.service';
import { CraftController } from './craft.controller';
import { CraftService } from './craft.service';
import { AlchemyFormulasController } from './alchemy-formulas.controller.js';
import { AlchemyFormulasService } from './alchemy-formulas.service.js';
import { CraftController } from './craft.controller.js';
import { CraftService } from './craft.service.js';
@Module({
controllers: [AlchemyFormulasController, CraftController],
@@ -1,6 +1,6 @@
import { renderPrompt } from '@server/lib/prompts';
import { generateAiObject } from '@server/utils/aiClient';
import { stableCompactStringify, truncateText } from '@server/utils/llmPayload';
import { renderPrompt } from '@server/lib/prompts/index.js';
import { generateAiObject } from '@server/utils/aiClient.js';
import { stableCompactStringify, truncateText } from '@server/utils/llmPayload.js';
import {
GENERATABLE_ALCHEMY_PROPERTY_KEY_VALUES,
getAlchemyPropertyLabel,
@@ -18,7 +18,7 @@ import {
FORMULA_MATERIAL_VERDICT_VALUES,
} from '@daoyou/shared/types/consumable';
import { z } from 'zod';
import type { PreparedAlchemyMaterial } from '@server/alchemy/application/AlchemyRecipeRules';
import type { PreparedAlchemyMaterial } from '@server/alchemy/application/AlchemyRecipeRules.js';
const weightedAlchemyPropertySchema = z.object({
key: z.enum(GENERATABLE_ALCHEMY_PROPERTY_KEY_VALUES),
@@ -2,18 +2,18 @@ import {
getExecutor,
type DbExecutor,
type DbTransaction,
} from '@server/lib/drizzle/db';
import { alchemyFormulas, cultivators } from '@server/lib/drizzle/schema';
import { redis } from '@server/lib/redis';
import { parseRedisJson } from '@server/lib/redis/json';
} from '@server/lib/drizzle/db.js';
import { alchemyFormulas, cultivators } from '@server/lib/drizzle/schema.js';
import { redis } from '@server/lib/redis/index.js';
import { parseRedisJson } from '@server/lib/redis/json.js';
import {
aggregateAlchemyProperties,
buildAlchemyBatchProfile,
buildAlchemyPropertyTags,
getQuotaCategoryForFamily,
type PreparedAlchemyMaterial,
} from '@server/alchemy/application/AlchemyRecipeRules';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository';
} from '@server/alchemy/application/AlchemyRecipeRules.js';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository.js';
import { ALCHEMY_MAX_DOSE } from '@daoyou/shared/config/alchemyInput';
import type { ResourceOperationSettlement } from '@daoyou/shared/engine/resource/types';
import type { AlchemyBagMaterial } from '@daoyou/shared/inventory/alchemy';
@@ -77,14 +77,14 @@ import {
consumeAlchemyMaterials,
grantAlchemyOutput,
loadAlchemyMaterials,
} from '@server/alchemy/application/inventory/AlchemyInventory';
} from '@server/alchemy/application/inventory/AlchemyInventory.js';
import {
assembleAlchemyOutputConsumables,
type AlchemyOutputDraft,
} from '@server/alchemy/application/inventory/AlchemyOutputAssembler';
import { alchemyFormulaAnalyzer } from '@server/alchemy/application/AlchemyFormulaAnalyzer';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError';
import { sectOrganizationFacade } from '@server/sects/organization';
} from '@server/alchemy/application/inventory/AlchemyOutputAssembler.js';
import { alchemyFormulaAnalyzer } from '@server/alchemy/application/AlchemyFormulaAnalyzer.js';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError.js';
import { sectOrganizationFacade } from '@server/sects/organization/index.js';
const DISCOVERY_TTL_SECONDS = 600;
const FORMULA_ANALYSIS_TTL_SECONDS = 600;
@@ -1,6 +1,6 @@
import { getRuntimeEnvironment } from '@server/lib/config/environment';
import { renderPrompt } from '@server/lib/prompts';
import { generateAiObject } from '@server/utils/aiClient';
import { getRuntimeEnvironment } from '@server/lib/config/environment.js';
import { renderPrompt } from '@server/lib/prompts/index.js';
import { generateAiObject } from '@server/utils/aiClient.js';
import { formatAlchemyPropertyVector } from '@daoyou/shared/lib/alchemyProperties';
import type { ElementType, Quality } from '@daoyou/shared/types/constants';
import type {
@@ -1,6 +1,6 @@
import { renderPrompt } from '@server/lib/prompts';
import { generateAiObject } from '@server/utils/aiClient';
import { stableCompactStringify, truncateText } from '@server/utils/llmPayload';
import { renderPrompt } from '@server/lib/prompts/index.js';
import { generateAiObject } from '@server/utils/aiClient.js';
import { stableCompactStringify, truncateText } from '@server/utils/llmPayload.js';
import {
GENERATABLE_ALCHEMY_PROPERTY_KEY_VALUES,
getAlchemyPropertyLabel,
@@ -13,7 +13,7 @@ import {
type AlchemyRecipePlan,
} from '@daoyou/shared/types/consumable';
import { z } from 'zod';
import type { PreparedAlchemyMaterial } from '@server/alchemy/application/AlchemyRecipeRules';
import type { PreparedAlchemyMaterial } from '@server/alchemy/application/AlchemyRecipeRules.js';
const weightedAlchemyPropertySchema = z.object({
key: z.enum(GENERATABLE_ALCHEMY_PROPERTY_KEY_VALUES),
@@ -32,7 +32,7 @@ import type {
PillQuotaCategory,
WeightedAlchemyProperty,
} from '@daoyou/shared/types/consumable';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError.js';
export interface PreparedAlchemyMaterial {
id: string;
@@ -1,13 +1,13 @@
import { getExecutor, type DbTransaction } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import { getExecutor, type DbTransaction } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import {
buildAlchemyPropertyTags,
describeAlchemyPropertyVector,
getQuotaCategoryForFamily,
synthesizeAlchemyFromPlan,
type PreparedAlchemyMaterial,
} from '@server/alchemy/application/AlchemyRecipeRules';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository';
} from '@server/alchemy/application/AlchemyRecipeRules.js';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository.js';
import { ELEMENT_PREFIX_MAP } from '@daoyou/shared/config/alchemyConfig';
import { ALCHEMY_MAX_DOSE } from '@daoyou/shared/config/alchemyInput';
import type { ResourceOperationSettlement } from '@daoyou/shared/engine/resource/types';
@@ -45,22 +45,22 @@ import {
consumeAlchemyMaterials,
grantAlchemyOutput,
loadAlchemyMaterials,
} from '@server/alchemy/application/inventory/AlchemyInventory';
} from '@server/alchemy/application/inventory/AlchemyInventory.js';
import {
assembleAlchemyOutputConsumables,
type AlchemyOutputDraft,
} from '@server/alchemy/application/inventory/AlchemyOutputAssembler';
import { buildDiscoveryCandidate } from '@server/alchemy/application/AlchemyFormulaService';
import { AlchemyNarrativeEnricher } from '@server/alchemy/application/AlchemyNarrativeEnricher';
} from '@server/alchemy/application/inventory/AlchemyOutputAssembler.js';
import { buildDiscoveryCandidate } from '@server/alchemy/application/AlchemyFormulaService.js';
import { AlchemyNarrativeEnricher } from '@server/alchemy/application/AlchemyNarrativeEnricher.js';
import {
alchemyRecipePlanner,
type AlchemyRecipePlanner,
} from '@server/alchemy/application/AlchemyRecipePlanner';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError';
import { sectOrganizationFacade } from '@server/sects/organization';
} from '@server/alchemy/application/AlchemyRecipePlanner.js';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError.js';
import { sectOrganizationFacade } from '@server/sects/organization/index.js';
export { synthesizeAlchemyFromPlan as synthesizeAlchemy } from '@server/alchemy/application/AlchemyRecipeRules';
export { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError';
export { synthesizeAlchemyFromPlan as synthesizeAlchemy } from '@server/alchemy/application/AlchemyRecipeRules.js';
export { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError.js';
type MaterialRow = AlchemyBagMaterial;
@@ -2,8 +2,8 @@ import {
getExecutor,
type DbExecutor,
type DbTransaction,
} from '@server/lib/drizzle/db';
import { inventoryItems } from '@server/lib/drizzle/schema';
} from '@server/lib/drizzle/db.js';
import { inventoryItems } from '@server/lib/drizzle/schema.js';
import {
groupAlchemyBagMaterials,
groupAlchemyStorageMaterials,
@@ -13,12 +13,12 @@ import { inventoryStackIdentity } from '@daoyou/shared/inventory/stack-key';
import { consumableFactsOf } from '@daoyou/shared/items/definitions/consumables';
import type { Consumable } from '@daoyou/shared/types/cultivator';
import { and, eq, inArray } from 'drizzle-orm';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError.js';
import {
grantInventory,
inventoryItemOf,
saveInventoryPlan,
} from '@server/inventory/operations';
} from '@server/inventory/operations.js';
export async function readAlchemyMaterials(
owner: string,
@@ -1,4 +1,4 @@
import { calculateSingleElixirScore } from '@server/utils/rankingUtils';
import { calculateSingleElixirScore } from '@server/utils/rankingUtils.js';
import { resolveAlchemyEffects } from '@daoyou/shared/lib/alchemyEffectResolver';
import type {
AlchemyEffectRoute,
+12 -12
View File
@@ -8,19 +8,19 @@ import {
Post,
UseFilters,
} from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { redisLockErrorResponse } from '@server/lib/http/errors';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError';
import { PlayerCommandIdempotencyError } from '@server/player/application/state/CommandExecutors';
import { CraftCommandError } from '@server/forging/application/CraftApplicationService';
import { QiServiceError } from '@server/cultivator/application/QiService';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { redisLockErrorResponse } from '@server/lib/http/errors.js';
import { AlchemyServiceError } from '@server/alchemy/application/AlchemyServiceError.js';
import { PlayerCommandIdempotencyError } from '@server/player/application/state/CommandExecutors.js';
import { CraftCommandError } from '@server/forging/application/CraftApplicationService.js';
import { QiServiceError } from '@server/cultivator/application/QiService.js';
import { z } from 'zod';
import { Access, CurrentCultivator } from '../auth/access';
import { apiErrorFilter } from '../http/error-filter';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { CraftCommandSchema, CraftSchema } from './alchemy-input';
import { CraftService } from './craft.service';
import { Access, CurrentCultivator } from '../auth/access.js';
import { apiErrorFilter } from '../http/error-filter.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { CraftCommandSchema, CraftSchema } from './alchemy-input.js';
import { CraftService } from './craft.service.js';
const retired = new Set(['refine', 'create_skill', 'create_gongfa']);
const retiredMessage = '旧功法、神通及装备生产已停用,历史物品保留在洞府宝库';
+9 -9
View File
@@ -1,14 +1,14 @@
import { HttpException, Injectable } from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { assertAlchemyMaterialVersions } from '@server/alchemy/application/inventory/AlchemyInventory';
import { previewFormulaCraft } from '@server/alchemy/application/AlchemyFormulaService';
import { previewAlchemySelection } from '@server/alchemy/application/alchemyServiceV2';
import { executeCraftCommand } from '@server/forging/application/CraftApplicationService';
import { readCraftReadinessFacts } from '@server/cultivator/facts';
import { getPlayerPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository';
import { toPlayerStateMutationResponse } from '@server/player/application/state/ResourceMutationResponse';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { assertAlchemyMaterialVersions } from '@server/alchemy/application/inventory/AlchemyInventory.js';
import { previewFormulaCraft } from '@server/alchemy/application/AlchemyFormulaService.js';
import { previewAlchemySelection } from '@server/alchemy/application/alchemyServiceV2.js';
import { executeCraftCommand } from '@server/forging/application/CraftApplicationService.js';
import { readCraftReadinessFacts } from '@server/cultivator/facts.js';
import { getPlayerPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository.js';
import { toPlayerStateMutationResponse } from '@server/player/application/state/ResourceMutationResponse.js';
import type { z } from 'zod';
import type { CraftCommandSchema, CraftSchema } from './alchemy-input';
import type { CraftCommandSchema, CraftSchema } from './alchemy-input.js';
@Injectable()
export class CraftService {
+45 -45
View File
@@ -1,51 +1,51 @@
import { getRuntimeEnvironment } from '@server/lib/config/environment';
import { ConfigurationModule } from './config/configuration.module';
import { getRuntimeEnvironment } from '@server/lib/config/environment.js';
import { ConfigurationModule } from './config/configuration.module.js';
import { Module } from '@nestjs/common';
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
import { allowsLocalDevTools } from '@daoyou/shared/config/deployment';
import { AccountModule } from './account/account.module';
import { AdminModule } from './admin/admin.module';
import { AlchemyModule } from './alchemy/alchemy.module';
import { ArenaModule } from './arena/arena.module';
import { AuctionModule } from './auction/auction.module';
import { AuthModule } from './auth/auth.module';
import { BeastsModule } from './beasts/beasts.module';
import { BlackMarketModule } from './black-market/black-market.module';
import { CombatModule } from './combat/combat.module';
import { CommunityModule } from './community/community.module';
import { CultivatorModule } from './cultivator/cultivator.module';
import { DevToolsModule } from './dev-tools/dev-tools.module';
import { DivinationModule } from './divination/divination.module';
import { DungeonModule } from './dungeon/dungeon.module';
import { EnemiesModule } from './enemies/enemies.module';
import { EnlightenmentModule } from './enlightenment/enlightenment.module';
import { FeedbackModule } from './feedback/feedback.module';
import { ForgingModule } from './forging/forging.module';
import { GenesisModule } from './genesis/genesis.module';
import { HealthModule } from './health/health.module';
import { ApiExceptionFilter } from './http/api-exception.filter';
import { NotFoundModule } from './http/not-found.module';
import { RequestContextInterceptor } from './http/request-context.interceptor';
import { HuntsModule } from './hunts/hunts.module';
import { InscriptionsModule } from './inscriptions/inscriptions.module';
import { InventoryModule } from './inventory/inventory.module';
import { LegacyItemsModule } from './legacy-items/legacy-items.module';
import { MailModule } from './mail/mail.module';
import { ManualsModule } from './manuals/manuals.module';
import { MarketModule } from './market/market.module';
import { PlayerModule } from './player/player.module';
import { RankingsModule } from './rankings/rankings.module';
import { RealtimeModule } from './realtime/realtime.module';
import { ReputationShopModule } from './reputation-shop/reputation-shop.module';
import { ReshapeModule } from './reshape/reshape.module';
import { RuntimeModule } from './runtime/runtime.module';
import { SectsModule } from './sects/sects.module';
import { SocialModule } from './social/social.module';
import { SpiritFieldModule } from './spirit-field/spirit-field.module';
import { SponsorshipModule } from './sponsorship/sponsorship.module';
import { StoryModule } from './story/story.module';
import { TasksModule } from './tasks/tasks.module';
import { TowerModule } from './tower/tower.module';
import { AccountModule } from './account/account.module.js';
import { AdminModule } from './admin/admin.module.js';
import { AlchemyModule } from './alchemy/alchemy.module.js';
import { ArenaModule } from './arena/arena.module.js';
import { AuctionModule } from './auction/auction.module.js';
import { AuthModule } from './auth/auth.module.js';
import { BeastsModule } from './beasts/beasts.module.js';
import { BlackMarketModule } from './black-market/black-market.module.js';
import { CombatModule } from './combat/combat.module.js';
import { CommunityModule } from './community/community.module.js';
import { CultivatorModule } from './cultivator/cultivator.module.js';
import { DevToolsModule } from './dev-tools/dev-tools.module.js';
import { DivinationModule } from './divination/divination.module.js';
import { DungeonModule } from './dungeon/dungeon.module.js';
import { EnemiesModule } from './enemies/enemies.module.js';
import { EnlightenmentModule } from './enlightenment/enlightenment.module.js';
import { FeedbackModule } from './feedback/feedback.module.js';
import { ForgingModule } from './forging/forging.module.js';
import { GenesisModule } from './genesis/genesis.module.js';
import { HealthModule } from './health/health.module.js';
import { ApiExceptionFilter } from './http/api-exception.filter.js';
import { NotFoundModule } from './http/not-found.module.js';
import { RequestContextInterceptor } from './http/request-context.interceptor.js';
import { HuntsModule } from './hunts/hunts.module.js';
import { InscriptionsModule } from './inscriptions/inscriptions.module.js';
import { InventoryModule } from './inventory/inventory.module.js';
import { LegacyItemsModule } from './legacy-items/legacy-items.module.js';
import { MailModule } from './mail/mail.module.js';
import { ManualsModule } from './manuals/manuals.module.js';
import { MarketModule } from './market/market.module.js';
import { PlayerModule } from './player/player.module.js';
import { RankingsModule } from './rankings/rankings.module.js';
import { RealtimeModule } from './realtime/realtime.module.js';
import { ReputationShopModule } from './reputation-shop/reputation-shop.module.js';
import { ReshapeModule } from './reshape/reshape.module.js';
import { RuntimeModule } from './runtime/runtime.module.js';
import { SectsModule } from './sects/sects.module.js';
import { SocialModule } from './social/social.module.js';
import { SpiritFieldModule } from './spirit-field/spirit-field.module.js';
import { SponsorshipModule } from './sponsorship/sponsorship.module.js';
import { StoryModule } from './story/story.module.js';
import { TasksModule } from './tasks/tasks.module.js';
import { TowerModule } from './tower/tower.module.js';
@Module({
imports: [
@@ -1,8 +1,8 @@
import { isRedisLockContention, withRedisLock } from '@server/lib/redis/lock';
import { isRedisLockContention, withRedisLock } from '@server/lib/redis/lock.js';
import type { ArenaRoomV1 } from '@daoyou/shared/contracts/arena';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService';
import { createArenaV6 } from '@server/combat/application/CombatV6ArenaService';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService.js';
import { createArenaV6 } from '@server/combat/application/CombatV6ArenaService.js';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore.js';
export interface ArenaBattleStartResult {
readonly room: ArenaRoomV1;
@@ -1,4 +1,4 @@
import { redis } from '@server/lib/redis';
import { redis } from '@server/lib/redis/index.js';
import {
allArenaSeatsReady,
ARENA_ROOM_INVITE_CODE_LENGTH,
@@ -10,21 +10,21 @@ import {
Req,
UseFilters,
} from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { isAllowedRealtimeOrigin } from '@server/lib/http/realtimeOrigin';
import { ArenaV6Error } from '@server/combat/application/CombatV6ArenaService';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { isAllowedRealtimeOrigin } from '@server/lib/http/realtimeOrigin.js';
import { ArenaV6Error } from '@server/combat/application/CombatV6ArenaService.js';
import {
ArenaV6SubmitSchema,
type ArenaV6Submit,
} from '@daoyou/shared/contracts/combatV6Arena';
import type { Request } from 'express';
import { z } from 'zod';
import { Access, CurrentCultivator } from '../auth/access';
import { apiErrorFilter } from '../http/error-filter';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { ArenaBattlesService } from './arena-battles.service';
import { Access, CurrentCultivator } from '../auth/access.js';
import { apiErrorFilter } from '../http/error-filter.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { ArenaBattlesService } from './arena-battles.service.js';
const ArenaErrors = apiErrorFilter((error) => {
if (error instanceof ArenaV6Error)
+2 -2
View File
@@ -1,11 +1,11 @@
import { Injectable } from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import {
arenaReplayV6,
ownedArenaV6,
submitArenaV6,
watchedArenaV6,
} from '@server/combat/application/CombatV6ArenaService';
} from '@server/combat/application/CombatV6ArenaService.js';
import { arenaView } from '@daoyou/shared/combat-v6/arena';
import type { ArenaV6Submit } from '@daoyou/shared/contracts/combatV6Arena';
+8 -8
View File
@@ -1,24 +1,24 @@
import { Inject, Injectable, type OnModuleDestroy } from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { isAllowedRealtimeOrigin } from '@server/lib/http/realtimeOrigin';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { isAllowedRealtimeOrigin } from '@server/lib/http/realtimeOrigin.js';
import {
arenaSocketState,
subscribeArenaSpectators,
subscribeArenaV6,
} from '@server/combat/application/CombatV6ArenaBroadcast';
} from '@server/combat/application/CombatV6ArenaBroadcast.js';
import {
ArenaV6Error,
ownedArenaV6,
watchedArenaV6,
} from '@server/combat/application/CombatV6ArenaService';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore';
} from '@server/combat/application/CombatV6ArenaService.js';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore.js';
import { fromNodeHeaders } from 'better-auth/node';
import type { IncomingMessage } from 'node:http';
import { WebSocket } from 'ws';
import { z } from 'zod';
import { SessionService } from '../auth/session.service';
import type { HandshakeError } from '../http/websocket-request';
import { arenaSocketRoute } from './arena-socket';
import { SessionService } from '../auth/session.service.js';
import type { HandshakeError } from '../http/websocket-request.js';
import { arenaSocketRoute } from './arena-socket.js';
type ArenaConnection = {
actor: ActiveCultivatorRef;
+5 -5
View File
@@ -7,7 +7,7 @@ import {
Post,
Res,
} from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import {
ArenaCreateRoomSchema,
ArenaJoinRoomSchema,
@@ -16,10 +16,10 @@ import {
} from '@daoyou/shared/contracts/arena';
import type { Response } from 'express';
import { z } from 'zod';
import { Access, CurrentCultivator } from '../auth/access';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { ArenaRoomsService } from './arena-rooms.service';
import { Access, CurrentCultivator } from '../auth/access.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { ArenaRoomsService } from './arena-rooms.service.js';
const RoomIdSchema = z
.string()
+8 -8
View File
@@ -4,14 +4,14 @@ import {
REALM_VALUES,
} from '@daoyou/shared/types/constants';
import { HttpException, Inject, Injectable } from '@nestjs/common';
import { DRIZZLE_DATABASE } from '@server/database/database.service';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import type { DbClient } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import { ArenaBattleStartOrchestrator } from '@server/arena/application/ArenaBattleStartOrchestrator';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService';
import { publishArenaRoomChanges } from '@server/realtime/infrastructure/arenaRoomBroadcaster';
import { CombatV6BuildError } from '@server/combat/application/CombatV6BuildService';
import { DRIZZLE_DATABASE } from '@server/database/database.service.js';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import type { DbClient } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import { ArenaBattleStartOrchestrator } from '@server/arena/application/ArenaBattleStartOrchestrator.js';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService.js';
import { publishArenaRoomChanges } from '@server/realtime/infrastructure/arenaRoomBroadcaster.js';
import { CombatV6BuildError } from '@server/combat/application/CombatV6BuildService.js';
import { and, eq } from 'drizzle-orm';
import { z } from 'zod';
+2 -2
View File
@@ -2,8 +2,8 @@ import { Inject } from '@nestjs/common';
import { WebSocketGateway, type OnGatewayConnection } from '@nestjs/websockets';
import type { IncomingMessage } from 'node:http';
import type { WebSocket } from 'ws';
import { ArenaRealtimeService } from './arena-realtime.service';
import { ARENA_SOCKET_PATH } from './arena-socket';
import { ArenaRealtimeService } from './arena-realtime.service.js';
import { ARENA_SOCKET_PATH } from './arena-socket.js';
@WebSocketGateway({ path: ARENA_SOCKET_PATH, maxPayload: 2048 })
export class ArenaGateway implements OnGatewayConnection {
+11 -11
View File
@@ -1,15 +1,15 @@
import { Module } from '@nestjs/common';
import { DatabaseModule } from '@server/database/database.module';
import { ArenaBattleStartOrchestrator } from '@server/arena/application/ArenaBattleStartOrchestrator';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore';
import { AuthModule } from '../auth/auth.module';
import { ArenaBattlesController } from './arena-battles.controller';
import { ArenaBattlesService } from './arena-battles.service';
import { ArenaRealtimeService } from './arena-realtime.service';
import { ArenaRoomsController } from './arena-rooms.controller';
import { ArenaRoomsService } from './arena-rooms.service';
import { ArenaGateway } from './arena.gateway';
import { DatabaseModule } from '@server/database/database.module.js';
import { ArenaBattleStartOrchestrator } from '@server/arena/application/ArenaBattleStartOrchestrator.js';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService.js';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore.js';
import { AuthModule } from '../auth/auth.module.js';
import { ArenaBattlesController } from './arena-battles.controller.js';
import { ArenaBattlesService } from './arena-battles.service.js';
import { ArenaRealtimeService } from './arena-realtime.service.js';
import { ArenaRoomsController } from './arena-rooms.controller.js';
import { ArenaRoomsService } from './arena-rooms.service.js';
import { ArenaGateway } from './arena.gateway.js';
@Module({
imports: [DatabaseModule, AuthModule],
@@ -1,6 +1,6 @@
import type { DbTransaction } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock';
import type { DbTransaction } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock.js';
import type {
AuctionBeastListRequest,
AuctionListRequest,
@@ -13,9 +13,9 @@ import {
clearAuctionListingsCache,
listBeast,
listItem,
} from '@server/auction/application/AuctionService';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors';
import { readCultivatorName } from '@server/cultivator/facts';
} from '@server/auction/application/AuctionService.js';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors.js';
import { readCultivatorName } from '@server/cultivator/facts.js';
export async function executeAuctionBuyCommand(args: {
listingId: string;
@@ -1,5 +1,5 @@
import { redis } from '@server/lib/redis';
import * as auctionRepository from '@server/lib/repositories/auctionRepository';
import { redis } from '@server/lib/redis/index.js';
import * as auctionRepository from '@server/lib/repositories/auctionRepository.js';
import {
AUCTION_MAX_TRANSACTION_TOTAL,
calculateAuctionSettlement,
@@ -22,31 +22,31 @@ import {
import { itemDefinition, ItemGrantSchema } from '@daoyou/shared/inventory';
import type { MailAttachment } from '@daoyou/shared/types/mail';
import { and, eq, sql } from 'drizzle-orm';
import { getExecutor, type DbTransaction } from '@server/lib/drizzle/db';
import * as schema from '@server/lib/drizzle/schema';
import { getExecutor, type DbTransaction } from '@server/lib/drizzle/db.js';
import * as schema from '@server/lib/drizzle/schema.js';
import {
beastFromRow,
beastIndividualData,
readBeastRoster,
} from '@server/lib/repositories/combatV6BeastRepository';
import { assertBeastIdle, BeastError } from '@server/combat/application/BeastMutationGuard';
} from '@server/lib/repositories/combatV6BeastRepository.js';
import { assertBeastIdle, BeastError } from '@server/combat/application/BeastMutationGuard.js';
import {
assertFriend,
FriendServiceError,
getInviteTarget,
} from '@server/social/application/FriendService';
} from '@server/social/application/FriendService.js';
import {
assertInventoryIdle,
InventoryError,
inventoryItemOf,
saveInventoryPlan,
} from '@server/inventory/operations';
import { publicMailAttachment } from '@server/mail/application/MailInventory';
import { MailService } from '@server/mail/application/MailService';
} from '@server/inventory/operations.js';
import { publicMailAttachment } from '@server/mail/application/MailInventory.js';
import { MailService } from '@server/mail/application/MailService.js';
import {
consumeFirstTalismanByScenario,
TalismanScenarioError,
} from '@server/inscriptions/application/TalismanScenarioService';
} from '@server/inscriptions/application/TalismanScenarioService.js';
export class AuctionServiceError extends Error {
constructor(
+6 -6
View File
@@ -1,10 +1,10 @@
import { redisLockErrorResponse } from '@server/lib/http/errors';
import { AuctionServiceError } from '@server/auction/application/AuctionService';
import { BeastError } from '@server/combat/application/BeastMutationGuard';
import { PlayerCommandIdempotencyError } from '@server/player/application/state/CommandExecutors';
import { InventoryError } from '@server/inventory/operations';
import { redisLockErrorResponse } from '@server/lib/http/errors.js';
import { AuctionServiceError } from '@server/auction/application/AuctionService.js';
import { BeastError } from '@server/combat/application/BeastMutationGuard.js';
import { PlayerCommandIdempotencyError } from '@server/player/application/state/CommandExecutors.js';
import { InventoryError } from '@server/inventory/operations.js';
import { z } from 'zod';
import { apiErrorFilter } from '../http/error-filter';
import { apiErrorFilter } from '../http/error-filter.js';
const statusMap: Record<string, number> = {
INSUFFICIENT_FUNDS: 400,
+8 -8
View File
@@ -9,20 +9,20 @@ import {
Post,
UseFilters,
} from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import {
AuctionBeastListSchema,
AuctionBuySchema,
AuctionListSchema,
} from '@daoyou/shared/contracts/auction';
import { z } from 'zod';
import { Access, CurrentCultivator } from '../auth/access';
import { FirstQuery } from '../http/first-query';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { AuctionListingsErrors, auctionMutationErrors } from './auction-errors';
import { ListingsSchema } from './auction-input';
import { AuctionService } from './auction.service';
import { Access, CurrentCultivator } from '../auth/access.js';
import { FirstQuery } from '../http/first-query.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { AuctionListingsErrors, auctionMutationErrors } from './auction-errors.js';
import { ListingsSchema } from './auction-input.js';
import { AuctionService } from './auction.service.js';
@Controller('api/auction')
@Access('active')
+2 -2
View File
@@ -1,6 +1,6 @@
import { Module } from '@nestjs/common';
import { AuctionController } from './auction.controller';
import { AuctionService } from './auction.service';
import { AuctionController } from './auction.controller.js';
import { AuctionService } from './auction.service.js';
@Module({ controllers: [AuctionController], providers: [AuctionService] })
export class AuctionModule {}
+6 -6
View File
@@ -1,21 +1,21 @@
import { Injectable } from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import * as auctionRepository from '@server/lib/repositories/auctionRepository';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import * as auctionRepository from '@server/lib/repositories/auctionRepository.js';
import {
buyAuctionListing,
cancelAuctionListing,
listAuctionBeast,
listAuctionItem,
} from '@server/auction/application/AuctionApplicationService';
import { publicAuctionListing } from '@server/auction/application/AuctionService';
import { toPlayerStateMutationResponse } from '@server/player/application/state/ResourceMutationResponse';
} from '@server/auction/application/AuctionApplicationService.js';
import { publicAuctionListing } from '@server/auction/application/AuctionService.js';
import { toPlayerStateMutationResponse } from '@server/player/application/state/ResourceMutationResponse.js';
import type {
AuctionBeastListRequest,
AuctionBuySchema,
AuctionListRequest,
} from '@daoyou/shared/contracts/auction';
import type { z } from 'zod';
import type { ListingsSchema } from './auction-input';
import type { ListingsSchema } from './auction-input.js';
@Injectable()
export class AuctionService {
+4 -4
View File
@@ -6,12 +6,12 @@ import {
type ExecutionContext,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { isAdminIdentity, isAdminUserId } from '@server/lib/auth/adminAccess';
import { isAdminIdentity, isAdminUserId } from '@server/lib/auth/adminAccess.js';
import { fromNodeHeaders } from 'better-auth/node';
import type { Response } from 'express';
import type { GameRequest } from '../http/request';
import { ACCESS_POLICY, type AccessPolicy } from './access';
import { SessionService } from './session.service';
import type { GameRequest } from '../http/request.js';
import { ACCESS_POLICY, type AccessPolicy } from './access.js';
import { SessionService } from './session.service.js';
@Injectable()
export class AccessGuard implements CanActivate {
+1 -1
View File
@@ -3,7 +3,7 @@ import {
SetMetadata,
type ExecutionContext,
} from '@nestjs/common';
import type { GameRequest } from '../http/request';
import type { GameRequest } from '../http/request.js';
export type AccessPolicy =
'public' | 'user' | 'active' | 'admin' | 'account-admin';
+4 -4
View File
@@ -1,9 +1,9 @@
import { Module } from '@nestjs/common';
import { APP_GUARD } from '@nestjs/core';
import { AccessGuard } from './access.guard';
import { CaptchaController } from './captcha.controller';
import { CaptchaService } from './captcha.service';
import { SessionService } from './session.service';
import { AccessGuard } from './access.guard.js';
import { CaptchaController } from './captcha.controller.js';
import { CaptchaService } from './captcha.service.js';
import { SessionService } from './session.service.js';
@Module({
controllers: [CaptchaController],
+3 -3
View File
@@ -1,7 +1,7 @@
import { Controller, Get, Header, Inject } from '@nestjs/common';
import { FirstQuery } from '../http/first-query';
import { Access } from './access';
import { CaptchaService } from './captcha.service';
import { FirstQuery } from '../http/first-query.js';
import { Access } from './access.js';
import { CaptchaService } from './captcha.service.js';
@Controller('api/captcha')
@Access('public')
+1 -1
View File
@@ -3,7 +3,7 @@ import {
createAltchaChallenge,
isAltchaAction,
isAltchaServerEnabled,
} from '@server/lib/auth/altcha';
} from '@server/lib/auth/altcha.js';
@Injectable()
export class CaptchaService {
+3 -3
View File
@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common';
import { resolveActiveCultivatorRef } from '@server/lib/auth/activeCultivator';
import { auth } from '@server/lib/auth/auth';
import type { AuthUser } from '@server/lib/auth/types';
import { resolveActiveCultivatorRef } from '@server/lib/auth/activeCultivator.js';
import { auth } from '@server/lib/auth/auth.js';
import type { AuthUser } from '@server/lib/auth/types.js';
@Injectable()
export class SessionService {
+8 -8
View File
@@ -9,8 +9,8 @@ import {
Put,
UseFilters,
} from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { BeastError } from '@server/combat/application/CombatV6BeastService';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { BeastError } from '@server/combat/application/CombatV6BeastService.js';
import {
BeastAllocateSchema,
BeastClaimSchema,
@@ -20,12 +20,12 @@ import {
BeastRestSchema,
} from '@daoyou/shared/contracts/combatV6Beasts';
import { z } from 'zod';
import { Access, CurrentCultivator } from '../auth/access';
import { CombatErrors, combatErrorResponse } from '../combat/combat-errors';
import { apiErrorFilter } from '../http/error-filter';
import { JsonBody } from '../http/json-body';
import { ZodPipe } from '../http/zod.pipe';
import { BeastsService } from './beasts.service';
import { Access, CurrentCultivator } from '../auth/access.js';
import { CombatErrors, combatErrorResponse } from '../combat/combat-errors.js';
import { apiErrorFilter } from '../http/error-filter.js';
import { JsonBody } from '../http/json-body.js';
import { ZodPipe } from '../http/zod.pipe.js';
import { BeastsService } from './beasts.service.js';
const FusionErrors = apiErrorFilter((error) => {
if (error instanceof BeastError)
+3 -3
View File
@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common';
import { DatabaseModule } from '@server/database/database.module';
import { BeastsController } from './beasts.controller';
import { BeastsService } from './beasts.service';
import { DatabaseModule } from '@server/database/database.module.js';
import { BeastsController } from './beasts.controller.js';
import { BeastsService } from './beasts.service.js';
@Module({
imports: [DatabaseModule],
+4 -4
View File
@@ -6,9 +6,9 @@ import type {
BeastRestSchema,
} from '@daoyou/shared/contracts/combatV6Beasts';
import { Inject, Injectable } from '@nestjs/common';
import { DRIZZLE_DATABASE } from '@server/database/database.service';
import type { DbClient } from '@server/lib/drizzle/db';
import { readBeastRoster } from '@server/lib/repositories/combatV6BeastRepository';
import { DRIZZLE_DATABASE } from '@server/database/database.service.js';
import type { DbClient } from '@server/lib/drizzle/db.js';
import { readBeastRoster } from '@server/lib/repositories/combatV6BeastRepository.js';
import {
allocateBeastPoints,
claimStarterBeast,
@@ -18,7 +18,7 @@ import {
renameBeast,
restBeast,
updateBeastLineup,
} from '@server/combat/application/CombatV6BeastService';
} from '@server/combat/application/CombatV6BeastService.js';
import type { z } from 'zod';
@Injectable()
@@ -1,9 +1,9 @@
import { renderPrompt } from '@server/lib/prompts';
import { generateAiObject, streamAiText } from '@server/utils/aiClient';
import { truncateText } from '@server/utils/llmPayload';
import { renderPrompt } from '@server/lib/prompts/index.js';
import { generateAiObject, streamAiText } from '@server/utils/aiClient.js';
import { truncateText } from '@server/utils/llmPayload.js';
import type { BlackMarketNegotiationOutcome } from '@daoyou/shared/lib/blackMarketNegotiation';
import { z } from 'zod';
import type { BlackMarketTurnContext, BlackMarketTurnProposal } from '@server/black-market/application/types';
import type { BlackMarketTurnContext, BlackMarketTurnProposal } from '@server/black-market/application/types.js';
const turnProposalSchema = z.object({
intent: z.enum([
@@ -1,8 +1,8 @@
import type { DbTransaction } from '@server/lib/drizzle/db';
import { listPlayerMutationRequestsByPrefix } from '@server/lib/repositories/playerStateRepository';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors';
import { qiCurrencyChange } from '@server/cultivator/application/QiResourceChanges';
import { QiService } from '@server/cultivator/application/QiService';
import type { DbTransaction } from '@server/lib/drizzle/db.js';
import { listPlayerMutationRequestsByPrefix } from '@server/lib/repositories/playerStateRepository.js';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors.js';
import { qiCurrencyChange } from '@server/cultivator/application/QiResourceChanges.js';
import { QiService } from '@server/cultivator/application/QiService.js';
import {
blackMarketEntryCost,
blackMarketEntryId,
@@ -1,13 +1,13 @@
import { renderPrompt } from '@server/lib/prompts';
import { redis } from '@server/lib/redis';
import { parseRedisJson } from '@server/lib/redis/json';
import { generateAiObject } from '@server/utils/aiClient';
import { stableCompactStringify, truncateText } from '@server/utils/llmPayload';
import { renderPrompt } from '@server/lib/prompts/index.js';
import { redis } from '@server/lib/redis/index.js';
import { parseRedisJson } from '@server/lib/redis/json.js';
import { generateAiObject } from '@server/utils/aiClient.js';
import { stableCompactStringify, truncateText } from '@server/utils/llmPayload.js';
import { sanitizeBlackMarketObservationText } from '@daoyou/shared/lib/blackMarketObservations';
import type { Material } from '@daoyou/shared/types/cultivator';
import { createHash } from 'node:crypto';
import { z } from 'zod';
import type { BlackMarketInternalObservation } from '@server/black-market/application/types';
import type { BlackMarketInternalObservation } from '@server/black-market/application/types.js';
const CACHE_TTL_SECONDS = 24 * 60 * 60;
@@ -1,13 +1,13 @@
import { renderPrompt } from '@server/lib/prompts';
import { generateAiObject } from '@server/utils/aiClient';
import { truncateText } from '@server/utils/llmPayload';
import { renderPrompt } from '@server/lib/prompts/index.js';
import { generateAiObject } from '@server/utils/aiClient.js';
import { truncateText } from '@server/utils/llmPayload.js';
import type { BlackMarketPricingState } from '@daoyou/shared/lib/blackMarketPricing';
import { z } from 'zod';
import type { BlackMarketNpcConfig } from '@server/black-market/application/BlackMarketNpcConfig';
import type { BlackMarketNpcConfig } from '@server/black-market/application/BlackMarketNpcConfig.js';
import type {
BlackMarketInternalObservation,
BlackMarketNpcBeliefState,
} from '@server/black-market/application/types';
} from '@server/black-market/application/types.js';
const beliefSchema = z.object({
suspectedTypes: z.array(z.string().trim().min(1).max(24)).min(1).max(3),
@@ -1,15 +1,15 @@
import { getRuntimeEnvironment } from '@server/lib/config/environment';
import { deliverMarketMaterial } from '@server/market/application/MarketInventoryDelivery';
import type { DbTransaction } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock';
import { findPlayerMutationRequest } from '@server/lib/repositories/playerStateRepository';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors';
import { getRuntimeEnvironment } from '@server/lib/config/environment.js';
import { deliverMarketMaterial } from '@server/market/application/MarketInventoryDelivery.js';
import type { DbTransaction } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock.js';
import { findPlayerMutationRequest } from '@server/lib/repositories/playerStateRepository.js';
import { playerCommandExecutor } from '@server/player/application/state/CommandExecutors.js';
import {
materialLibraryEntryToMaterial,
sampleMaterialLibraryEntryByPreferences,
} from '@server/admin/application/MaterialLibraryService';
import { readCultivatorRealm } from '@server/cultivator/facts';
} from '@server/admin/application/MaterialLibraryService.js';
import { readCultivatorRealm } from '@server/cultivator/facts.js';
import type { ResourceChangeDescriptor } from '@daoyou/shared/contracts/resources';
import { MaterialFactsSchema } from '@daoyou/shared/items/definitions/materials';
import {
@@ -61,22 +61,22 @@ import { createHmac, randomUUID } from 'node:crypto';
import {
blackMarketConversationService,
fallbackTurnReply,
} from '@server/black-market/application/BlackMarketConversationService';
} from '@server/black-market/application/BlackMarketConversationService.js';
import {
grantBlackMarketEntry,
listBlackMarketEntryGrants,
} from '@server/black-market/application/BlackMarketEntryService';
import { buildBlackMarketMask } from '@server/black-market/application/BlackMarketMaskService';
import { BLACK_MARKET_NPCS, getBlackMarketNpc } from '@server/black-market/application/BlackMarketNpcConfig';
import { blackMarketObservationService } from '@server/black-market/application/BlackMarketObservationService';
import { blackMarketPerceptionService } from '@server/black-market/application/BlackMarketPerceptionService';
import { blackMarketSessionRepository } from '@server/black-market/application/BlackMarketSessionRepository';
} from '@server/black-market/application/BlackMarketEntryService.js';
import { buildBlackMarketMask } from '@server/black-market/application/BlackMarketMaskService.js';
import { BLACK_MARKET_NPCS, getBlackMarketNpc } from '@server/black-market/application/BlackMarketNpcConfig.js';
import { blackMarketObservationService } from '@server/black-market/application/BlackMarketObservationService.js';
import { blackMarketPerceptionService } from '@server/black-market/application/BlackMarketPerceptionService.js';
import { blackMarketSessionRepository } from '@server/black-market/application/BlackMarketSessionRepository.js';
import type {
BlackMarketInternalSession,
BlackMarketPreparedTurn,
BlackMarketTurnContext,
BlackMarketTurnProposal,
} from '@server/black-market/application/types';
} from '@server/black-market/application/types.js';
const PURCHASE_SOURCE = 'black_market_purchase';
const SESSION_MESSAGE_LIMIT = 24;
@@ -1,6 +1,6 @@
import { redis } from '@server/lib/redis';
import { parseRedisJson } from '@server/lib/redis/json';
import type { BlackMarketInternalSession } from '@server/black-market/application/types';
import { redis } from '@server/lib/redis/index.js';
import { parseRedisJson } from '@server/lib/redis/json.js';
import type { BlackMarketInternalSession } from '@server/black-market/application/types.js';
const SESSION_PREFIX = 'black-market:v9:session';
@@ -8,28 +8,28 @@ import {
Res,
UseFilters,
} from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { redisLockErrorResponse } from '@server/lib/http/errors';
import { BlackMarketServiceError } from '@server/black-market/application/BlackMarketService';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { redisLockErrorResponse } from '@server/lib/http/errors.js';
import { BlackMarketServiceError } from '@server/black-market/application/BlackMarketService.js';
import {
QiInsufficientError,
QiServiceError,
} from '@server/cultivator/application/QiService';
} from '@server/cultivator/application/QiService.js';
import type { Response as ExpressResponse } from 'express';
import { z } from 'zod';
import { Access, CurrentCultivator } from '../auth/access';
import { apiErrorFilter } from '../http/error-filter';
import { JsonBody } from '../http/json-body';
import { withRequestAbort } from '../http/request-abort';
import { streamSseEvents } from '../http/sse';
import { ZodPipe } from '../http/zod.pipe';
import { Access, CurrentCultivator } from '../auth/access.js';
import { apiErrorFilter } from '../http/error-filter.js';
import { JsonBody } from '../http/json-body.js';
import { withRequestAbort } from '../http/request-abort.js';
import { streamSseEvents } from '../http/sse.js';
import { ZodPipe } from '../http/zod.pipe.js';
import {
CommitSchema,
InteractSchema,
LeaveSchema,
OpenSessionSchema,
} from './black-market-input';
import { BlackMarketService } from './black-market.service';
} from './black-market-input.js';
import { BlackMarketService } from './black-market.service.js';
const BlackMarketErrors = apiErrorFilter((error) => {
const lock = redisLockErrorResponse(error);
@@ -2,9 +2,9 @@ import { Module } from '@nestjs/common';
import {
BlackMarketConversationService,
blackMarketConversationService,
} from '@server/black-market/application/BlackMarketConversationService';
import { BlackMarketController } from './black-market.controller';
import { BlackMarketService } from './black-market.service';
} from '@server/black-market/application/BlackMarketConversationService.js';
import { BlackMarketController } from './black-market.controller.js';
import { BlackMarketService } from './black-market.service.js';
@Module({
controllers: [BlackMarketController],
@@ -1,6 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
import type { ActiveCultivatorRef } from '@server/lib/auth/types';
import { BlackMarketConversationService } from '@server/black-market/application/BlackMarketConversationService';
import type { ActiveCultivatorRef } from '@server/lib/auth/types.js';
import { BlackMarketConversationService } from '@server/black-market/application/BlackMarketConversationService.js';
import {
commitBlackMarketPurchase,
completeBlackMarketReply,
@@ -8,8 +8,8 @@ import {
leaveBlackMarketSession,
openBlackMarketSession,
prepareBlackMarketInteraction,
} from '@server/black-market/application/BlackMarketService';
import { toPlayerStateMutationResponse } from '@server/player/application/state/ResourceMutationResponse';
} from '@server/black-market/application/BlackMarketService.js';
import { toPlayerStateMutationResponse } from '@server/player/application/state/ResourceMutationResponse.js';
import type { BlackMarketInteractStreamEvent } from '@daoyou/shared/types/blackMarket';
import type { z } from 'zod';
import type {
@@ -17,7 +17,7 @@ import type {
InteractSchema,
LeaveSchema,
OpenSessionSchema,
} from './black-market-input';
} from './black-market-input.js';
@Injectable()
export class BlackMarketService {
@@ -1,4 +1,4 @@
import { hasActiveCombat } from '@server/combat/application/CombatOccupancy';
import { hasActiveCombat } from '@server/combat/application/CombatOccupancy.js';
export class BeastError extends Error {
readonly status = 409;
@@ -1,14 +1,14 @@
import { db } from '@server/lib/drizzle/db';
import { dungeonRuns } from '@server/lib/drizzle/schema';
import { redis } from '@server/lib/redis';
import { parseRedisJson } from '@server/lib/redis/json';
import { activeBreakthroughBattle } from '@server/combat/application/CombatV6BreakthroughOccupancy';
import { arenaOccupancyKey, CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore';
import { activeSectTaskBattle } from '@server/combat/application/CombatV6SectTaskOccupancy';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore';
import { pendingRanking } from '@server/combat/application/CombatV6RankingService';
import { towerRunKey } from '@server/tower/occupancy';
import { db } from '@server/lib/drizzle/db.js';
import { dungeonRuns } from '@server/lib/drizzle/schema.js';
import { redis } from '@server/lib/redis/index.js';
import { parseRedisJson } from '@server/lib/redis/json.js';
import { activeBreakthroughBattle } from '@server/combat/application/CombatV6BreakthroughOccupancy.js';
import { arenaOccupancyKey, CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore.js';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore.js';
import { activeSectTaskBattle } from '@server/combat/application/CombatV6SectTaskOccupancy.js';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore.js';
import { pendingRanking } from '@server/combat/application/CombatV6RankingService.js';
import { towerRunKey } from '@server/tower/occupancy.js';
import type { CombatActivityNotice } from '@daoyou/shared/contracts/combatActivity';
import { shouldExpireTowerRun } from '@daoyou/shared/lib/tower/lifecycle';
import { and, eq, inArray, isNotNull, ne, or } from 'drizzle-orm';
@@ -1,13 +1,13 @@
import { hasDungeonBattle } from '@server/dungeon/occupancy';
import { db, type DbExecutor } from '@server/lib/drizzle/db';
import { redis } from '@server/lib/redis';
import { hasActiveRanking } from '@server/lib/redis/rankingChallenge';
import { hasTowerBattle } from '@server/tower/occupancy';
import { arenaOccupancyKey } from '@server/combat/application/CombatV6ArenaStore';
import { hasActiveBreakthroughBattle } from '@server/combat/application/CombatV6BreakthroughOccupancy';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore';
import { hasActiveSectTaskBattle } from '@server/combat/application/CombatV6SectTaskOccupancy';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore';
import { hasDungeonBattle } from '@server/dungeon/occupancy.js';
import { db, type DbExecutor } from '@server/lib/drizzle/db.js';
import { redis } from '@server/lib/redis/index.js';
import { hasActiveRanking } from '@server/lib/redis/rankingChallenge.js';
import { hasTowerBattle } from '@server/tower/occupancy.js';
import { arenaOccupancyKey } from '@server/combat/application/CombatV6ArenaStore.js';
import { hasActiveBreakthroughBattle } from '@server/combat/application/CombatV6BreakthroughOccupancy.js';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore.js';
import { hasActiveSectTaskBattle } from '@server/combat/application/CombatV6SectTaskOccupancy.js';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore.js';
/**
* 角色同时只能有一场战斗。层间蜃楼、秘境探索和待迎战只保留进度,不占用。
@@ -4,13 +4,13 @@ import type {
ArenaSocketMessage,
} from '@daoyou/shared/contracts/combatV6Arena';
import { ARENA_PUBLIC_VIEW } from '@daoyou/shared/contracts/combatV6Arena';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService.js';
import {
publishNatsCoreMessage,
subscribeNatsCoreSubject,
waitForNatsCoreSubjectReady,
} from '@server/realtime/infrastructure/natsCorePubSub';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore';
} from '@server/realtime/infrastructure/natsCorePubSub.js';
import { CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore.js';
const subject = (id: string) => `daoyou.realtime.combat-v6.arena.${id}`;
export async function subscribeArenaV6(
@@ -1,8 +1,8 @@
import { ConditionService } from '@server/cultivator/application/ConditionService';
import { ConditionService } from '@server/cultivator/application/ConditionService.js';
import { evaluateFateContext } from '@daoyou/shared/lib/fates';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository.js';
import type { HuntTeam } from '@daoyou/shared/contracts/hunts';
import { prepareHuntReward } from '@server/hunts/application/HuntRewardService';
import { prepareHuntReward } from '@server/hunts/application/HuntRewardService.js';
import { HUNT_BOSSES, huntIsOpen } from '@daoyou/shared/hunts/config';
import { huntRealmAllowed } from '@daoyou/shared/hunts/rules';
import type { RealmType } from '@daoyou/shared/types/constants';
@@ -14,17 +14,17 @@ import {
} from '@daoyou/shared/engine/combat-v6/hunts/content';
import { playerAppearances } from '@daoyou/shared/combat-v6/unit-appearance';
import type { CombatV6UnitAppearance } from '@daoyou/shared/contracts/combatV6';
import { db } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import { getJetStreamClient } from '@server/lib/nats';
import { redis } from '@server/lib/redis';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock';
import { db } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import { getJetStreamClient } from '@server/lib/nats/index.js';
import { redis } from '@server/lib/redis/index.js';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock.js';
import {
archiveCombatV6Replay,
findOwnedCombatV6Replay,
} from '@server/lib/repositories/combatV6ReplayRepository';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository';
import { hasActiveCombat } from '@server/combat/application/CombatOccupancy';
} from '@server/lib/repositories/combatV6ReplayRepository.js';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository.js';
import { hasActiveCombat } from '@server/combat/application/CombatOccupancy.js';
import {
arenaBattle,
arenaDefaultCommand,
@@ -61,11 +61,11 @@ import { projectCharacterToCombatV6 } from '@daoyou/shared/engine/combat-v6/proj
import { characterBattleSkills } from '@daoyou/shared/engine/combat-v6/projection/character-battle-skills';
import { and, eq } from 'drizzle-orm';
import { JSONCodec } from 'nats';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService';
import { publishArenaRoomChanges } from '@server/realtime/infrastructure/arenaRoomBroadcaster';
import { broadcastArenaV6 } from '@server/combat/application/CombatV6ArenaBroadcast';
import { arenaDueKey, CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore';
import { assembleCombatV6TrainingPlayer } from '@server/combat/application/CombatV6BuildService';
import { ArenaRoomService } from '@server/arena/application/ArenaRoomService.js';
import { publishArenaRoomChanges } from '@server/realtime/infrastructure/arenaRoomBroadcaster.js';
import { broadcastArenaV6 } from '@server/combat/application/CombatV6ArenaBroadcast.js';
import { arenaDueKey, CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore.js';
import { assembleCombatV6TrainingPlayer } from '@server/combat/application/CombatV6BuildService.js';
export class ArenaV6Error extends Error {
constructor(
@@ -1,4 +1,4 @@
import { redis } from '@server/lib/redis';
import { redis } from '@server/lib/redis/index.js';
import {
ARENA_V6_PROTOCOL,
type ArenaRuntime,
@@ -1,9 +1,9 @@
import { db } from '@server/lib/drizzle/db';
import { db } from '@server/lib/drizzle/db.js';
import {
readCustomAutoStrategy,
removeCustomAutoStrategy,
saveCustomAutoStrategy,
} from '@server/lib/repositories/combatV6AutoStrategyRepository';
} from '@server/lib/repositories/combatV6AutoStrategyRepository.js';
import { autoStatusChoices } from '@daoyou/shared/combat-v6/auto-status-options';
import {
defaultAutoStrategy,
@@ -11,7 +11,7 @@ import {
} from '@daoyou/shared/combat-v6/auto-strategy';
import { COMBAT_V6_SECT_DEFINITIONS } from '@daoyou/shared/engine/combat-v6/content';
import { projectCharacterToCombatV6 } from '@daoyou/shared/engine/combat-v6/projection';
import { assembleCombatV6TrainingPlayer } from '@server/combat/application/CombatV6BuildService';
import { assembleCombatV6TrainingPlayer } from '@server/combat/application/CombatV6BuildService.js';
export class AutoStrategyError extends Error {}
@@ -2,20 +2,20 @@ import {
db,
type DbExecutor,
type DbTransaction,
} from '@server/lib/drizzle/db';
} from '@server/lib/drizzle/db.js';
import {
cultivatorBeastFusions,
cultivatorBeastLineups,
cultivatorBeasts,
} from '@server/lib/drizzle/schema';
import { createDomainEvent } from '@server/lib/mq/domainEventWriter';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock';
} from '@server/lib/drizzle/schema.js';
import { createDomainEvent } from '@server/lib/mq/domainEventWriter.js';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock.js';
import {
beastIndividualData,
readBeastOwner,
readBeastRoster,
} from '@server/lib/repositories/combatV6BeastRepository';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository';
} from '@server/lib/repositories/combatV6BeastRepository.js';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository.js';
import { beastTradePreview } from '@daoyou/shared/contracts/beastTrade';
import {
BeastNameSchema,
@@ -42,13 +42,13 @@ import {
import { and, eq, inArray } from 'drizzle-orm';
import { createHash, randomInt, randomUUID } from 'node:crypto';
import type { z } from 'zod';
import { readCultivatorPublicIdentity } from '@server/cultivator/facts';
import { updateSpiritStones } from '@server/cultivator/application/readers/CultivatorStateRepository';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter';
import { textFilter } from '@server/social/application/textFilter';
import { readCultivatorPublicIdentity } from '@server/cultivator/facts.js';
import { updateSpiritStones } from '@server/cultivator/application/readers/CultivatorStateRepository.js';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter.js';
import { textFilter } from '@server/social/application/textFilter.js';
import { assertBeastIdle, BeastError } from '@server/combat/application/BeastMutationGuard';
export { BeastError } from '@server/combat/application/BeastMutationGuard';
import { assertBeastIdle, BeastError } from '@server/combat/application/BeastMutationGuard.js';
export { BeastError } from '@server/combat/application/BeastMutationGuard.js';
async function fusionRecord(
cultivatorId: string,
@@ -1,5 +1,5 @@
import { db, type DbExecutor } from '@server/lib/drizzle/db';
import { cultivatorTasks } from '@server/lib/drizzle/schema';
import { db, type DbExecutor } from '@server/lib/drizzle/db.js';
import { cultivatorTasks } from '@server/lib/drizzle/schema.js';
import { and, eq, sql } from 'drizzle-orm';
export async function activeBreakthroughBattle(
@@ -1,16 +1,16 @@
import { publicUnitAppearances } from '@daoyou/shared/combat-v6/unit-appearance';
import { db, type DbTransaction } from '@server/lib/drizzle/db';
import { cultivators, cultivatorTasks } from '@server/lib/drizzle/schema';
import { dungeonPlayer } from '@server/dungeon/combat-player';
import { redis } from '@server/lib/redis';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock';
import { settleBeastDeaths } from '@server/lib/repositories/combatV6BeastRepository';
import { archiveCombatV6Replay } from '@server/lib/repositories/combatV6ReplayRepository';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository';
import { db, type DbTransaction } from '@server/lib/drizzle/db.js';
import { cultivators, cultivatorTasks } from '@server/lib/drizzle/schema.js';
import { dungeonPlayer } from '@server/dungeon/combat-player.js';
import { redis } from '@server/lib/redis/index.js';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock.js';
import { settleBeastDeaths } from '@server/lib/repositories/combatV6BeastRepository.js';
import { archiveCombatV6Replay } from '@server/lib/repositories/combatV6ReplayRepository.js';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository.js';
import {
findCultivatorTaskById,
updateCultivatorTask,
} from '@server/lib/repositories/taskRepository';
} from '@server/lib/repositories/taskRepository.js';
import { automaticCommands } from '@daoyou/shared/combat-v6/auto';
import {
combatV6Display,
@@ -38,10 +38,10 @@ import type { CultivatorCondition } from '@daoyou/shared/types/condition';
import type { TaskInstanceMetadata } from '@daoyou/shared/types/task';
import { eq } from 'drizzle-orm';
import { randomInt, randomUUID } from 'node:crypto';
import { ConditionService } from '@server/cultivator/application/ConditionService';
import { assertInventoryIdle } from '@server/inventory/operations';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter';
import { TaskService } from '@server/tasks/application/TaskService';
import { ConditionService } from '@server/cultivator/application/ConditionService.js';
import { assertInventoryIdle } from '@server/inventory/operations.js';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter.js';
import { TaskService } from '@server/tasks/application/TaskService.js';
type Actor = { userId: string; cultivatorId: string };
const key = (id: string) => `combat:v6:breakthrough:${id}`;
@@ -1,12 +1,12 @@
import { readCharacterEquipment, readCharacterManuals } from '@server/lib/repositories/characterLoadoutRepository';
import { db, runDbTasks, type DbExecutor } from '@server/lib/drizzle/db';
import { readCharacterEquipment, readCharacterManuals } from '@server/lib/repositories/characterLoadoutRepository.js';
import { db, runDbTasks, type DbExecutor } from '@server/lib/drizzle/db.js';
import {
sectCombatStates,
sectMeridianLoadouts,
sectMethodProgress,
} from '@server/lib/drizzle/schema';
import { readBeastRoster } from '@server/lib/repositories/combatV6BeastRepository';
import { readCustomAutoStrategy } from '@server/lib/repositories/combatV6AutoStrategyRepository';
} from '@server/lib/drizzle/schema.js';
import { readBeastRoster } from '@server/lib/repositories/combatV6BeastRepository.js';
import { readCustomAutoStrategy } from '@server/lib/repositories/combatV6AutoStrategyRepository.js';
import { defaultAutoStrategy } from '@daoyou/shared/combat-v6/auto-strategy';
import {
characterIdentityRow,
@@ -15,9 +15,9 @@ import {
readSectMethodLevels,
readActiveSectCombatProgress,
lockActiveMembership,
} from '@server/lib/repositories/sectCombatRepository';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter';
} from '@server/lib/repositories/sectCombatRepository.js';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository.js';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter.js';
import type {
SectPathSelectionRequest,
SectCombatView,
@@ -36,7 +36,7 @@ import { projectCharacterToCombatV6 } from '@daoyou/shared/engine/combat-v6/proj
import type { CultivatorCondition } from '@daoyou/shared/types/condition';
import type { RealmStage, RealmType } from '@daoyou/shared/types/constants';
import { and, eq, isNull, sql } from 'drizzle-orm';
import { assertCombatV6MutationAllowed } from '@server/combat/application/CombatV6MutationGuard';
import { assertCombatV6MutationAllowed } from '@server/combat/application/CombatV6MutationGuard.js';
export class CombatV6BuildError extends Error {
constructor(
@@ -1,11 +1,11 @@
import type { DbTransaction } from '@server/lib/drizzle/db';
import { cultivators } from '@server/lib/drizzle/schema';
import type { DbTransaction } from '@server/lib/drizzle/db.js';
import { cultivators } from '@server/lib/drizzle/schema.js';
import { rebaseCharacterResources } from '@daoyou/shared/lib/cultivatorDisplay';
import { evaluateFateContext } from '@daoyou/shared/lib/fates';
import type { CultivatorCondition } from '@daoyou/shared/types/condition';
import { eq } from 'drizzle-orm';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository';
import { readCombatV6ConditionAuthority } from '@server/combat/application/CombatV6ConditionAuthority';
import { getCultivatorPreHeavenFates } from '@server/cultivator/application/readers/CultivatorProfileRepository.js';
import { readCombatV6ConditionAuthority } from '@server/combat/application/CombatV6ConditionAuthority.js';
/** Runs in the build/profile mutation transaction, before its condition invalidation is published. */
export async function refreshCombatV6CharacterResources(id: string, tx: DbTransaction) {
@@ -1,18 +1,18 @@
import { redis } from '@server/lib/redis';
import { arenaOccupancyKey, CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore';
import { hasTowerBattle } from '@server/tower/occupancy';
import { readCharacterCombatBuild } from '@server/lib/repositories/characterLoadoutRepository';
import type { DbExecutor } from '@server/lib/drizzle/db';
import { hasActiveDungeon } from '@server/dungeon/occupancy';
import { redis } from '@server/lib/redis/index.js';
import { arenaOccupancyKey, CombatV6ArenaStore } from '@server/combat/application/CombatV6ArenaStore.js';
import { hasTowerBattle } from '@server/tower/occupancy.js';
import { readCharacterCombatBuild } from '@server/lib/repositories/characterLoadoutRepository.js';
import type { DbExecutor } from '@server/lib/drizzle/db.js';
import { hasActiveDungeon } from '@server/dungeon/occupancy.js';
import {
characterIdentityRow,
} from '@server/lib/repositories/sectCombatRepository';
} from '@server/lib/repositories/sectCombatRepository.js';
import { projectCharacterDisplaySnapshot } from '@daoyou/shared/lib/cultivatorDisplay';
import type { CultivatorCondition } from '@daoyou/shared/types/condition';
import type { RealmStage, RealmType } from '@daoyou/shared/types/constants';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore';
import { activeSectTaskBattle } from '@server/combat/application/CombatV6SectTaskOccupancy';
import { activeBreakthroughBattle } from '@server/combat/application/CombatV6BreakthroughOccupancy';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore.js';
import { activeSectTaskBattle } from '@server/combat/application/CombatV6SectTaskOccupancy.js';
import { activeBreakthroughBattle } from '@server/combat/application/CombatV6BreakthroughOccupancy.js';
import { SectTaskRecordPayloadSchema } from '@daoyou/shared/engine/sect';
import { SectV6TargetSchema } from '@daoyou/shared/contracts/combatV6SectTask';
@@ -1,30 +1,30 @@
import { runJournalSettlement, describeJournal } from '@server/player/application/JournalSettlement';
import { db } from '@server/lib/drizzle/db';
import { cultivators, messageConsumptions } from '@server/lib/drizzle/schema';
import { createDomainEvent } from '@server/lib/mq/domainEventWriter';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock';
import { runJournalSettlement, describeJournal } from '@server/player/application/JournalSettlement.js';
import { db } from '@server/lib/drizzle/db.js';
import { cultivators, messageConsumptions } from '@server/lib/drizzle/schema.js';
import { createDomainEvent } from '@server/lib/mq/domainEventWriter.js';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock.js';
import {
settleBeastDeaths,
settleBeastProgress,
} from '@server/lib/repositories/combatV6BeastRepository';
} from '@server/lib/repositories/combatV6BeastRepository.js';
import {
claimMessageForConsumer,
COMBAT_V6_CONDITION_CONSUMER,
} from '@server/lib/repositories/messageConsumptionRepository';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository';
} from '@server/lib/repositories/messageConsumptionRepository.js';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository.js';
import { beastTradePreview } from '@daoyou/shared/contracts/beastTrade';
import { settleWildResources } from '@daoyou/shared/engine/combat-v6/wild/rules';
import { storyMarkForSignal } from '@daoyou/shared/story/signals';
import type { CultivatorCondition } from '@daoyou/shared/types/condition';
import { and, eq } from 'drizzle-orm';
import { ConditionService } from '@server/cultivator/application/ConditionService';
import { grantInventory } from '@server/inventory/operations';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter';
import { StoryService } from '@server/story/application/StoryService';
import { readCultivatorPublicIdentity } from '@server/cultivator/facts';
import { publishResourceEvents } from '@server/realtime/infrastructure/playerStateBroadcaster';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore';
import { ConditionService } from '@server/cultivator/application/ConditionService.js';
import { grantInventory } from '@server/inventory/operations.js';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter.js';
import { StoryService } from '@server/story/application/StoryService.js';
import { readCultivatorPublicIdentity } from '@server/cultivator/facts.js';
import { publishResourceEvents } from '@server/realtime/infrastructure/playerStateBroadcaster.js';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore.js';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore.js';
const store = new CombatV6WildStore();
const common = new CombatV6RuntimeStore();
@@ -1,16 +1,16 @@
import { readCharacterManuals } from '@server/lib/repositories/characterLoadoutRepository';
import { db, type DbExecutor } from '@server/lib/drizzle/db';
import { readCharacterManuals } from '@server/lib/repositories/characterLoadoutRepository.js';
import { db, type DbExecutor } from '@server/lib/drizzle/db.js';
import {
cultivatorManualSlots,
cultivatorManualStates,
cultivators,
inventoryItems,
} from '@server/lib/drizzle/schema';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock';
} from '@server/lib/drizzle/schema.js';
import { redisLockKeys, withRedisLock } from '@server/lib/redis/lock.js';
import {
characterIdentityRow,
} from '@server/lib/repositories/sectCombatRepository';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository';
} from '@server/lib/repositories/sectCombatRepository.js';
import { lockCultivatorForStateMutation } from '@server/lib/repositories/playerStateRepository.js';
import {
getOrInitCultivationProgress,
stripExpCapForStorage,
@@ -29,9 +29,9 @@ import {
InventoryError,
inventoryItemOf,
saveInventoryPlan,
} from '@server/inventory/operations';
import { publishResourceEvents } from '@server/realtime/infrastructure/playerStateBroadcaster';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter';
} from '@server/inventory/operations.js';
import { publishResourceEvents } from '@server/realtime/infrastructure/playerStateBroadcaster.js';
import { ResourceEventCommitter } from '@server/player/application/state/ResourceEventCommitter.js';
async function readManualFacts(owner: string, q: DbExecutor) {
const character = await characterIdentityRow(owner, q);
@@ -1,7 +1,7 @@
import { projectCombatV6Condition } from '@server/combat/application/CombatV6ConditionProjector';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore';
import { wildTerminal } from '@server/combat/application/CombatV6WildSessionService';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore';
import { projectCombatV6Condition } from '@server/combat/application/CombatV6ConditionProjector.js';
import { CombatV6RuntimeStore } from '@server/combat/application/CombatV6RuntimeStore.js';
import { wildTerminal } from '@server/combat/application/CombatV6WildSessionService.js';
import { CombatV6WildStore } from '@server/combat/application/CombatV6WildStore.js';
/** Transfer continues only after the old battle's resource transaction committed. */
export async function settleWildBeforeMembershipChange(cultivatorId: string) {
Loaded 100 of 1109 files, more files were not shown because too many files have changed in this diff. Show more