[598-32][@ant] feat: backend+SDK подписочный канал marketplace (Фаза 2A) — realtime-события пайщика вместо поллинга

Поднят первый GraphQL-subscription поверх graphql-ws на том же /v1/graphql:
- PubSubModule (@Global, in-memory) — единый брокер событий приложения.
- Подписка marketplaceEvents: union MarketplaceEvent (OrderReadyToReceive |
  ReceptionPendingSign) — «сигнал, а не данные»; детали клиент дочитывает
  авторизованным query.
- Мост MarketplaceRealtimeBridge: доменные события EventEmitter2 (эмит после
  commit в PG, INV-12) → публикация в ПЕРСОНАЛЬНЫЙ топик адресата
  (marketplace:events:<coop>:<account>). Чужому пайщику событие физически не
  попадает — топик строится из аккаунта, не из аргументов клиента.
- Аутентификация ws — в graphql-ws onConnect: верификация access-JWT из
  connectionParams, sub кладётся в контекст; единый context прокидывает юзера
  в req.user, чтобы @CurrentUser работал и на ws. HTTP-путь не тронут.
- DRY: резолв юзера по sub вынесен в resolveUserBySub (стратегия + резолвер).
- SDK: новая категория Subscriptions.Marketplace.Events (строгая типизация
  IInput/IOutput, селектор union через ...on), геттер Client.Subscription
  прокидывает Authorization в connectionParams. ZEUS-клиент пересобран.

Зачем: убрать 10-сек поллинг гейта подписи на месте — позиции пункта должны
прилетать в реальном времени и приватно, а не по капле общими опросами.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ant
2026-06-09 08:05:14 +00:00
parent 89ba2f61c4
commit 8c9dc31b58
20 changed files with 710 additions and 47 deletions
+2
View File
@@ -130,6 +130,7 @@
"graphql": "^16.9.0",
"graphql-request": "^7.1.2",
"graphql-scalars": "^1.24.0",
"graphql-subscriptions": "^2.0.0",
"graphql-tools": "^9.0.2",
"graphql-type-json": "^0.3.2",
"graphql-ws": "^5.16.0",
@@ -166,6 +167,7 @@
"rxjs": "^7.8.2",
"socket.io-client": "^4.7.5",
"spectaql": "^3.0.5",
"subscriptions-transport-ws": "^0.11.0",
"swagger-jsdoc": "^6.0.8",
"swagger-ui-express": "^4.1.6",
"threads": "^1.7.0",
@@ -6,6 +6,7 @@ import config from '~/config/config';
import { tokenTypes } from '~/types/token.types';
import { USER_REPOSITORY, UserRepository } from '~/domain/user/repositories/user.repository';
import { UserDomainService, USER_DOMAIN_SERVICE } from '~/domain/user/services/user-domain.service';
import { resolveUserBySub } from '~/application/auth/utils/resolve-user-by-sub';
@Injectable()
export class JwtAuthStrategy extends PassportStrategy(JwtStrategy) {
@@ -24,27 +25,7 @@ export class JwtAuthStrategy extends PassportStrategy(JwtStrategy) {
throw new Error('Invalid token type');
}
const userId = payload.sub;
// Определяем тип ID заранее для оптимизации запросов
let user;
if (this.isLegacyMongoId(userId)) {
// Это legacy MongoDB ObjectId
try {
user = await this.userDomainService.getUserByLegacyMongoId(userId);
} catch (error) {
throw new Error('Пользователь с указанным JWT не найден');
}
} else if (this.isValidUuid(userId)) {
// Это новый UUID
user = await this.userRepository.findById(userId);
if (!user) {
throw new Error('Пользователь с указанным JWT не найден');
}
} else {
// Неизвестный формат ID
throw new Error('Неверный формат ID пользователя в JWT токене');
}
const user = await resolveUserBySub(payload.sub, this.userRepository, this.userDomainService);
// Возвращаем объект в формате, совместимом с MonoAccountDomainInterface
return {
@@ -64,23 +45,4 @@ export class JwtAuthStrategy extends PassportStrategy(JwtStrategy) {
subscriber_hash: user.subscriber_hash,
};
}
/**
* Проверяет, является ли строка legacy MongoDB ObjectId (24 hex символа)
*/
private isLegacyMongoId(id: string): boolean {
return /^[a-f\d]{24}$/i.test(id);
}
/**
* Проверяет, является ли строка валидным UUID (с дефисами или без)
*/
private isValidUuid(id: string): boolean {
// UUID с дефисами: 8-4-4-4-12
const uuidWithDashes = /^[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}$/i;
// UUID без дефисов: 32 символа
const uuidWithoutDashes = /^[a-f\d]{32}$/i;
return uuidWithDashes.test(id) || uuidWithoutDashes.test(id);
}
}
@@ -0,0 +1,35 @@
import { UserRepository } from '~/domain/user/repositories/user.repository';
import { UserDomainService } from '~/domain/user/services/user-domain.service';
/**
* Резолвит пользователя по `sub` из JWT — единый источник для passport-стратегии
* (HTTP) и резолвера подписки (WebSocket). `sub` может быть legacy Mongo ObjectId
* (24 hex) либо UUID; формат определяет, в какой источник идти.
*/
export async function resolveUserBySub(
sub: string,
userRepository: UserRepository,
userDomainService: UserDomainService
) {
if (isLegacyMongoId(sub)) {
return userDomainService.getUserByLegacyMongoId(sub);
}
if (isValidUuid(sub)) {
const user = await userRepository.findById(sub);
if (!user) {
throw new Error('Пользователь с указанным JWT не найден');
}
return user;
}
throw new Error('Неверный формат ID пользователя в JWT токене');
}
function isLegacyMongoId(id: string): boolean {
return /^[a-f\d]{24}$/i.test(id);
}
function isValidUuid(id: string): boolean {
const uuidWithDashes = /^[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}$/i;
const uuidWithoutDashes = /^[a-f\d]{32}$/i;
return uuidWithDashes.test(id) || uuidWithoutDashes.test(id);
}
@@ -0,0 +1,70 @@
import { createUnionType, Field, ObjectType } from '@nestjs/graphql';
/**
* Дискриминатор полезной нагрузки realtime-события marketplace.
*
* Поле служебное — НЕ публикуется как @Field; используется только в
* resolveType union'а, чтобы выбрать конкретный тип на проводе. Издатель
* (bridge) проставляет его в публикуемый объект.
*/
export enum MarketplaceEventType {
ORDER_READY_TO_RECEIVE = 'ORDER_READY_TO_RECEIVE',
RECEPTION_PENDING_SIGN = 'RECEPTION_PENDING_SIGN',
}
@ObjectType('MarketplaceOrderReadyToReceiveEvent', {
description: 'Заказ пайщика собран на пункте и ожидает его подписи получения.',
})
export class MarketplaceOrderReadyToReceiveEventDTO {
eventType!: MarketplaceEventType.ORDER_READY_TO_RECEIVE;
@Field(() => String, { description: 'Идентификатор заказа.' })
order_id!: string;
@Field(() => String, { description: 'Контрольная сумма заказа.' })
order_hash!: string;
@Field(() => String, { description: 'Пункт выдачи, где заказ готов к получению.' })
braname!: string;
}
@ObjectType('MarketplaceReceptionPendingSignEvent', {
description: 'Поставка ожидает подписи поставщика на пункте приёмки.',
})
export class MarketplaceReceptionPendingSignEventDTO {
eventType!: MarketplaceEventType.RECEPTION_PENDING_SIGN;
@Field(() => String, { description: 'Идентификатор приёмки.' })
reception_id!: string;
@Field(() => String, { description: 'Наименование кооперативного участка приёмки.' })
ku_name!: string;
}
/**
* Объединение всех типов realtime-событий персонального канала пайщика.
*
* Принцип «сигнал, а не данные»: payload несёт только идентификаторы +
* минимальный контекст, чтобы клиент понял «что обновить». Полные данные
* (состав, цены, персональное) клиент дочитывает авторизованным query.
* Поэтому даже при ошибке маршрутизации приватного в канал не утекает.
*/
export const MarketplaceEventUnion = createUnionType({
name: 'MarketplaceEvent',
types: () =>
[MarketplaceOrderReadyToReceiveEventDTO, MarketplaceReceptionPendingSignEventDTO] as const,
resolveType(value: { eventType?: MarketplaceEventType }) {
switch (value.eventType) {
case MarketplaceEventType.ORDER_READY_TO_RECEIVE:
return MarketplaceOrderReadyToReceiveEventDTO;
case MarketplaceEventType.RECEPTION_PENDING_SIGN:
return MarketplaceReceptionPendingSignEventDTO;
default:
return null;
}
},
});
export type MarketplaceEventPayload =
| MarketplaceOrderReadyToReceiveEventDTO
| MarketplaceReceptionPendingSignEventDTO;
@@ -0,0 +1,14 @@
import { Field, InputType } from '@nestjs/graphql';
/**
* Параметры подписки на персональный канал событий пайщика.
*
* `coopname` принимается для симметрии с query/mutation и сверяется сервером
* с собственным кооперативом. Адресация канала строится из имени аккаунта
* JWT, НЕ из этого поля — подменить чужой поток через аргумент нельзя.
*/
@InputType('MarketplaceEventsInput')
export class MarketplaceEventsInputDTO {
@Field(() => String, { description: 'Кооперативное имя.' })
coopname!: string;
}
@@ -136,6 +136,10 @@ import {
MarketplaceCheckoutService,
MARKETPLACE_CHECKOUT_SERVICE,
} from './services/marketplace-checkout.service';
// Фаза 2: realtime-подписка marketplace (GraphQL subscription поверх graphql-ws).
import { PubSubModule } from '~/infrastructure/pubsub/pubsub.module';
import { MarketplaceEventsResolver } from './resolvers/marketplace-events.resolver';
import { MarketplaceRealtimeBridge } from './realtime/marketplace-realtime.bridge';
/**
* Модуль приложения marketplace
@@ -176,6 +180,8 @@ import {
]),
// Эпик 8: writeoff cron сканер должен видеть marketplace_inventory
TypeOrmModule.forFeature([MarketplaceInventoryEntity], 'marketplace'),
// Фаза 2: общий PubSub (@Global) для realtime-канала событий пайщика.
PubSubModule,
// ExtensionDomainService инжектится @Optional() в MarketplaceWriteoffCronService —
// импортировать ExtensionDomainModule сюда нельзя (цикл AppModule → ExtensionDomainModule →
// ExtensionsModule → MarketplacePluginModule → MarketplaceExtensionApplicationModule).
@@ -207,6 +213,10 @@ import {
MarketplaceReturnClaimResolver,
// Эпик 16 — корзина заказчика
MarketplaceCartResolver,
// Фаза 2 — realtime-подписка персонального канала пайщика + мост из
// доменных событий (EventEmitter2) в PubSub.
MarketplaceEventsResolver,
MarketplaceRealtimeBridge,
// Guards (Story 1.3 / Story 1.6)
MarketplaceMembershipGuard,
@@ -0,0 +1,57 @@
import { Inject, Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { PubSub } from 'graphql-subscriptions';
import { PUB_SUB } from '~/infrastructure/pubsub/pubsub.module';
import {
MARKETPLACE_APL_SUPPLIER_SIGN_REQUEST_EVENT,
MARKETPLACE_ORDER_READY_TO_RECEIVE_EVENT,
MarketplaceAplSupplierSignRequestEvent,
MarketplaceOrderReadyToReceiveEvent,
} from '../events/marketplace-notification.events';
import {
MarketplaceEventType,
MarketplaceOrderReadyToReceiveEventDTO,
MarketplaceReceptionPendingSignEventDTO,
} from '../dto/marketplace-event.dto';
import { marketplaceMemberTopic } from './marketplace-realtime.topics';
/**
* Мост: внутренние доменные события marketplace (EventEmitter2, эмитятся ПОСЛЕ
* commit'а в PG — INV-12) → персональный realtime-канал адресата через PubSub.
*
* Маршрутизация по получателю — гарантия приватности: публикуем в топик
* конкретного аккаунта-адресата (orderer/supplier), а не в общий канал.
* Payload — только сигнал (идентификаторы + контекст), детали клиент
* дочитывает авторизованным query.
*/
@Injectable()
export class MarketplaceRealtimeBridge {
constructor(@Inject(PUB_SUB) private readonly pubSub: PubSub) {}
@OnEvent(MARKETPLACE_ORDER_READY_TO_RECEIVE_EVENT)
async onOrderReadyToReceive(event: MarketplaceOrderReadyToReceiveEvent): Promise<void> {
const payload: MarketplaceOrderReadyToReceiveEventDTO = {
eventType: MarketplaceEventType.ORDER_READY_TO_RECEIVE,
order_id: event.order_id,
order_hash: event.order_hash,
braname: event.braname,
};
await this.pubSub.publish(
marketplaceMemberTopic(event.coopname, event.orderer_account),
payload
);
}
@OnEvent(MARKETPLACE_APL_SUPPLIER_SIGN_REQUEST_EVENT)
async onSupplierSignRequest(event: MarketplaceAplSupplierSignRequestEvent): Promise<void> {
const payload: MarketplaceReceptionPendingSignEventDTO = {
eventType: MarketplaceEventType.RECEPTION_PENDING_SIGN,
reception_id: event.apl_reception_id,
ku_name: event.ku_name,
};
await this.pubSub.publish(
marketplaceMemberTopic(event.coopname, event.supplier_account),
payload
);
}
}
@@ -0,0 +1,12 @@
/**
* Имя PubSub-топика персонального канала событий пайщика.
*
* Инвариант приватности: события публикуются и читаются ТОЛЬКО по топику
* конкретного получателя. Подписчик строит топик из имени аккаунта своего
* JWT (не из аргументов запроса), издатель (bridge) — из аккаунта-адресата
* доменного события. Поэтому событие физически не попадает в канал чужого
* пайщика. См. OQ-T15 (per-cooperative scope) — здесь усилено до per-member.
*/
export function marketplaceMemberTopic(coopname: string, username: string): string {
return `marketplace:events:${coopname}:${username}`;
}
@@ -0,0 +1,59 @@
import { ForbiddenException, Inject, Injectable } from '@nestjs/common';
import { Args, Resolver, Subscription } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';
import config from '~/config/config';
import { CurrentUser } from '~/application/auth/decorators/current-user.decorator';
import { USER_REPOSITORY, UserRepository } from '~/domain/user/repositories/user.repository';
import { UserDomainService, USER_DOMAIN_SERVICE } from '~/domain/user/services/user-domain.service';
import { resolveUserBySub } from '~/application/auth/utils/resolve-user-by-sub';
import { PUB_SUB } from '~/infrastructure/pubsub/pubsub.module';
import {
MarketplaceEventPayload,
MarketplaceEventUnion,
} from '../dto/marketplace-event.dto';
import { MarketplaceEventsInputDTO } from '../dto/marketplace-events-input.dto';
import { marketplaceMemberTopic } from '../realtime/marketplace-realtime.topics';
/**
* Единственная подписка приложения marketplace: персональный поток событий
* пайщика. Аутентификация соединения — в graphql-ws `onConnect` (см.
* graphql.module.ts), который кладёт `sub` JWT в контекст; здесь по `sub`
* резолвится имя аккаунта и строится приватный топик. Клиент НЕ может задать
* чужой топик — он выводится из токена, аргумент `input.coopname` лишь
* сверяется с кооперативом инстанса.
*/
@Resolver()
@Injectable()
export class MarketplaceEventsResolver {
constructor(
@Inject(PUB_SUB) private readonly pubSub: PubSub,
@Inject(USER_REPOSITORY) private readonly userRepository: UserRepository,
@Inject(USER_DOMAIN_SERVICE) private readonly userDomainService: UserDomainService
) {}
@Subscription(() => MarketplaceEventUnion, {
name: 'marketplaceEvents',
description: 'Персональный поток событий пайщика в Столе заказов.',
resolve: (payload: MarketplaceEventPayload) => payload,
})
async marketplaceEvents(
@CurrentUser() user: { sub?: string; username?: string },
@Args('input') input: MarketplaceEventsInputDTO
): Promise<AsyncIterator<MarketplaceEventPayload>> {
if (input.coopname !== config.coopname) {
throw new ForbiddenException('Подписка доступна только в рамках своего кооператива.');
}
const username = user.username ?? (await this.resolveUsername(user.sub));
const topic = marketplaceMemberTopic(config.coopname, username);
return this.pubSub.asyncIterator<MarketplaceEventPayload>(topic);
}
private async resolveUsername(sub: string | undefined): Promise<string> {
if (!sub) {
throw new ForbiddenException('Не удалось определить пайщика из токена подписки.');
}
const account = await resolveUserBySub(sub, this.userRepository, this.userDomainService);
return account.username;
}
}
@@ -7,6 +7,18 @@ import { docDirectiveTransformer } from './directives/doc.directive';
import { GraphQLError, GraphQLFormattedError } from 'graphql';
import { fieldAuthDirectiveTransformer } from './directives/fieldAuth.directive';
import logger from '~/config/logger';
import * as jwt from 'jsonwebtoken';
import { tokenTypes } from '~/types/token.types';
/**
* Bearer-токен из connectionParams ws-соединения. Принимаем и сам токен, и
* форму `Bearer <token>` — клиенты Zeus шлют по-разному.
*/
function extractBearerToken(raw: unknown): string | null {
if (typeof raw !== 'string' || !raw) return null;
const match = raw.match(/^Bearer\s+(.+)$/i);
return match ? match[1] : raw;
}
@Global()
@Module({
@@ -20,6 +32,39 @@ import logger from '~/config/logger';
// context: ({ req }) => req,
playground: { endpoint: '/v1/graphql', settings: { 'request.credentials': 'same-origin' } },
path: '/v1/graphql', // здесь можно задать другой путь, когда потребуется,
// Realtime-подписки поверх graphql-ws на том же пути. Аутентификация
// соединения — однократно в onConnect: верифицируем access-JWT из
// connectionParams и кладём `sub` в `extra`, чтобы операции читали юзера
// из контекста. Невалидный/отсутствующий токен → соединение отклоняется.
subscriptions: {
'graphql-ws': {
path: '/v1/graphql',
onConnect: (context: any) => {
const params = context?.connectionParams ?? {};
const token = extractBearerToken(params.authorization ?? params.Authorization);
if (!token) return false;
try {
const payload: any = jwt.verify(token, config.jwt.secret);
if (payload?.type !== tokenTypes.ACCESS) return false;
context.extra = context.extra ?? {};
context.extra.user = { sub: payload.sub };
return true;
} catch {
return false;
}
},
},
},
// Единый context для HTTP и WS. Для ws (graphql-ws Context содержит
// `extra`) прокидываем аутентифицированного юзера в req.user, чтобы
// существующие @CurrentUser/декораторы работали без изменений. Для HTTP
// возвращаем { req, res } как есть.
context: (ctx: any) => {
if (ctx && typeof ctx === 'object' && 'extra' in ctx) {
return { req: { user: ctx.extra?.user ?? null, headers: {} } };
}
return ctx;
},
transformSchema: (schema) => {
schema = docDirectiveTransformer(schema, 'auth');
schema = fieldAuthDirectiveTransformer(schema, 'auth');
@@ -0,0 +1,26 @@
import { Global, Module } from '@nestjs/common';
import { PubSub } from 'graphql-subscriptions';
/**
* DI-токен единственного in-memory PubSub приложения.
*
* Why in-memory (не graphql-redis-subscriptions): один controller обслуживает
* один кооператив (config.coopname) одним процессом — горизонтального шардинга
* подписчиков по нескольким инстансам в MVP нет, поэтому межпроцессный брокер
* избыточен. При переходе на multi-instance замена — только эта фабрика
* (RedisPubSub с тем же интерфейсом asyncIterator/publish), потребители не
* меняются.
*/
export const PUB_SUB = Symbol('PUB_SUB');
@Global()
@Module({
providers: [
{
provide: PUB_SUB,
useFactory: () => new PubSub(),
},
],
exports: [PUB_SUB],
})
export class PubSubModule {}
+26 -1
View File
@@ -718,6 +718,9 @@ export const AllTypesProps: Record<string,any> = {
},
MarketplaceDetailKUInput:{
workingHours:"WorkingHoursInput"
},
MarketplaceEventsInput:{
},
MarketplaceFinalizeIssuanceInput:{
signed_document:"MarketplaceIssueActSignedDocumentInput"
@@ -2352,6 +2355,11 @@ export const AllTypesProps: Record<string,any> = {
SubmitVoteInput:{
votes:"VoteDistributionInput"
},
Subscription:{
marketplaceEvents:{
input:"MarketplaceEventsInput"
}
},
SystemStatus: "enum" as const,
TranscriptionStatus: "enum" as const,
TriggerNotificationWorkflowInput:{
@@ -4166,6 +4174,10 @@ export const ReturnTypes: Record<string,any> = {
picture:"String",
value:"String"
},
MarketplaceEvent:{
"...on MarketplaceOrderReadyToReceiveEvent":"MarketplaceOrderReadyToReceiveEvent",
"...on MarketplaceReceptionPendingSignEvent":"MarketplaceReceptionPendingSignEvent"
},
MarketplaceExpressPickupCandidate:{
braname:"String",
offerer_account:"String",
@@ -4356,6 +4368,11 @@ export const ReturnTypes: Record<string,any> = {
totalCount:"Int",
totalPages:"Int"
},
MarketplaceOrderReadyToReceiveEvent:{
braname:"String",
order_hash:"String",
order_id:"String"
},
MarketplaceOutgoingPaymentRequest:{
amount:"String",
apl_reception_id:"ID",
@@ -4382,6 +4399,10 @@ export const ReturnTypes: Record<string,any> = {
typeId:"Int",
typeName:"String"
},
MarketplaceReceptionPendingSignEvent:{
ku_name:"String",
reception_id:"String"
},
MarketplaceRegistrationOfferStatus:{
agreement_id:"String",
agreement_type:"String",
@@ -5792,6 +5813,9 @@ export const ReturnTypes: Record<string,any> = {
action:"ExtendedBlockchainAction",
documentAggregate:"DocumentAggregate"
},
Subscription:{
marketplaceEvents:"MarketplaceEvent"
},
SubscriptionStatsDto:{
active:"Int",
inactive:"Int",
@@ -5963,5 +5987,6 @@ export const ReturnTypes: Record<string,any> = {
export const Ops = {
query: "Query" as const,
mutation: "Mutation" as const
mutation: "Mutation" as const,
subscription: "Subscription" as const
}
+129 -2
View File
@@ -1104,7 +1104,7 @@ export type ScalarCoders = {
JSONObject?: ScalarResolver;
ID?: ScalarResolver;
}
type ZEUS_UNIONS = GraphQLTypes["PaymentMethodData"] | GraphQLTypes["PrivateAccountSearchData"] | GraphQLTypes["UserCertificateUnion"]
type ZEUS_UNIONS = GraphQLTypes["MarketplaceEvent"] | GraphQLTypes["PaymentMethodData"] | GraphQLTypes["PrivateAccountSearchData"] | GraphQLTypes["UserCertificateUnion"]
export type ValueTypes = {
["Account"]: AliasType<{
@@ -6750,6 +6750,14 @@ export type ValueTypes = {
__typename?: boolean | `@${string}`,
['...on MarketplaceDictionaryValue']?: Omit<ValueTypes["MarketplaceDictionaryValue"], "...on MarketplaceDictionaryValue">
}>;
["MarketplaceEvent"]: AliasType<{ ["...on MarketplaceOrderReadyToReceiveEvent"]?: ValueTypes["MarketplaceOrderReadyToReceiveEvent"],
["...on MarketplaceReceptionPendingSignEvent"]?: ValueTypes["MarketplaceReceptionPendingSignEvent"]
__typename?: boolean | `@${string}`
}>;
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string | Variable<any, string>
};
["MarketplaceExpressPickupCandidate"]: AliasType<{
/** КУ-получатель. */
braname?:boolean | `@${string}`,
@@ -7337,6 +7345,17 @@ export type ValueTypes = {
totalPages?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceOrderPaginationResult']?: Omit<ValueTypes["MarketplaceOrderPaginationResult"], "...on MarketplaceOrderPaginationResult">
}>;
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: AliasType<{
/** Пункт выдачи, где заказ готов к получению. */
braname?:boolean | `@${string}`,
/** Контрольная сумма заказа. */
order_hash?:boolean | `@${string}`,
/** Идентификатор заказа. */
order_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceOrderReadyToReceiveEvent']?: Omit<ValueTypes["MarketplaceOrderReadyToReceiveEvent"], "...on MarketplaceOrderReadyToReceiveEvent">
}>;
/** Этап жизненного цикла заказа. */
["MarketplaceOrderStatus"]:MarketplaceOrderStatus;
@@ -7387,6 +7406,15 @@ export type ValueTypes = {
typeName?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceProductType']?: Omit<ValueTypes["MarketplaceProductType"], "...on MarketplaceProductType">
}>;
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: AliasType<{
/** Наименование кооперативного участка приёмки. */
ku_name?:boolean | `@${string}`,
/** Идентификатор приёмки. */
reception_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceReceptionPendingSignEvent']?: Omit<ValueTypes["MarketplaceReceptionPendingSignEvent"], "...on MarketplaceReceptionPendingSignEvent">
}>;
["MarketplaceRegistrationOfferStatus"]: AliasType<{
/** AGREEMENT_ID (например `marketplace_offer`) */
@@ -10921,6 +10949,11 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
/** Распределение голосов */
votes: Array<ValueTypes["VoteDistributionInput"]> | Variable<any, string>
};
["Subscription"]: AliasType<{
marketplaceEvents?: [{ input: ValueTypes["MarketplaceEventsInput"] | Variable<any, string>},ValueTypes["MarketplaceEvent"]],
__typename?: boolean | `@${string}`,
['...on Subscription']?: Omit<ValueTypes["Subscription"], "...on Subscription">
}>;
["SubscriptionStatsDto"]: AliasType<{
/** Количество активных подписок */
active?:boolean | `@${string}`,
@@ -17014,6 +17047,15 @@ export type ResolverInputTypes = {
value?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
["MarketplaceEvent"]: AliasType<{
MarketplaceOrderReadyToReceiveEvent?:ResolverInputTypes["MarketplaceOrderReadyToReceiveEvent"],
MarketplaceReceptionPendingSignEvent?:ResolverInputTypes["MarketplaceReceptionPendingSignEvent"],
__typename?: boolean | `@${string}`
}>;
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string
};
["MarketplaceExpressPickupCandidate"]: AliasType<{
/** КУ-получатель. */
braname?:boolean | `@${string}`,
@@ -17585,6 +17627,16 @@ export type ResolverInputTypes = {
/** Общее количество страниц */
totalPages?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: AliasType<{
/** Пункт выдачи, где заказ готов к получению. */
braname?:boolean | `@${string}`,
/** Контрольная сумма заказа. */
order_hash?:boolean | `@${string}`,
/** Идентификатор заказа. */
order_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
/** Этап жизненного цикла заказа. */
["MarketplaceOrderStatus"]:MarketplaceOrderStatus;
@@ -17633,6 +17685,14 @@ export type ResolverInputTypes = {
/** Название типа товара */
typeName?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: AliasType<{
/** Наименование кооперативного участка приёмки. */
ku_name?:boolean | `@${string}`,
/** Идентификатор приёмки. */
reception_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
["MarketplaceRegistrationOfferStatus"]: AliasType<{
/** AGREEMENT_ID (например `marketplace_offer`) */
@@ -21051,6 +21111,10 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
/** Распределение голосов */
votes: Array<ResolverInputTypes["VoteDistributionInput"]>
};
["Subscription"]: AliasType<{
marketplaceEvents?: [{ input: ResolverInputTypes["MarketplaceEventsInput"]},ResolverInputTypes["MarketplaceEvent"]],
__typename?: boolean | `@${string}`
}>;
["SubscriptionStatsDto"]: AliasType<{
/** Количество активных подписок */
active?:boolean | `@${string}`,
@@ -21638,6 +21702,7 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
["schema"]: AliasType<{
query?:ResolverInputTypes["Query"],
mutation?:ResolverInputTypes["Mutation"],
subscription?:ResolverInputTypes["Subscription"],
__typename?: boolean | `@${string}`
}>;
["ID"]:unknown
@@ -26947,6 +27012,11 @@ export type ModelTypes = {
picture?: string | undefined | null,
/** Значение */
value: string
};
["MarketplaceEvent"]:ModelTypes["MarketplaceOrderReadyToReceiveEvent"] | ModelTypes["MarketplaceReceptionPendingSignEvent"];
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string
};
["MarketplaceExpressPickupCandidate"]: {
/** КУ-получатель. */
@@ -27498,6 +27568,15 @@ export type ModelTypes = {
totalCount: number,
/** Общее количество страниц */
totalPages: number
};
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: {
/** Пункт выдачи, где заказ готов к получению. */
braname: string,
/** Контрольная сумма заказа. */
order_hash: string,
/** Идентификатор заказа. */
order_id: string
};
["MarketplaceOrderStatus"]:MarketplaceOrderStatus;
["MarketplaceOutgoingPaymentRequest"]: {
@@ -27542,6 +27621,13 @@ export type ModelTypes = {
typeId: number,
/** Название типа товара */
typeName: string
};
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: {
/** Наименование кооперативного участка приёмки. */
ku_name: string,
/** Идентификатор приёмки. */
reception_id: string
};
["MarketplaceRegistrationOfferStatus"]: {
/** AGREEMENT_ID (например `marketplace_offer`) */
@@ -31599,6 +31685,10 @@ export type ModelTypes = {
project_hash: string,
/** Распределение голосов */
votes: Array<ModelTypes["VoteDistributionInput"]>
};
["Subscription"]: {
/** Персональный поток событий пайщика в Столе заказов. */
marketplaceEvents: ModelTypes["MarketplaceEvent"]
};
["SubscriptionStatsDto"]: {
/** Количество активных подписок */
@@ -32158,7 +32248,8 @@ export type ModelTypes = {
["ZeroReportSignerType"]:ZeroReportSignerType;
["schema"]: {
query?: ModelTypes["Query"] | undefined | null,
mutation?: ModelTypes["Mutation"] | undefined | null
mutation?: ModelTypes["Mutation"] | undefined | null,
subscription?: ModelTypes["Subscription"] | undefined | null
};
["ID"]:any
}
@@ -37809,6 +37900,15 @@ export type GraphQLTypes = {
/** Значение */
value: string,
['...on MarketplaceDictionaryValue']: Omit<GraphQLTypes["MarketplaceDictionaryValue"], "...on MarketplaceDictionaryValue">
};
["MarketplaceEvent"]:{
__typename:"MarketplaceOrderReadyToReceiveEvent" | "MarketplaceReceptionPendingSignEvent"
['...on MarketplaceOrderReadyToReceiveEvent']: '__union' & GraphQLTypes["MarketplaceOrderReadyToReceiveEvent"];
['...on MarketplaceReceptionPendingSignEvent']: '__union' & GraphQLTypes["MarketplaceReceptionPendingSignEvent"];
};
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string
};
["MarketplaceExpressPickupCandidate"]: {
__typename: "MarketplaceExpressPickupCandidate",
@@ -38397,6 +38497,17 @@ export type GraphQLTypes = {
/** Общее количество страниц */
totalPages: number,
['...on MarketplaceOrderPaginationResult']: Omit<GraphQLTypes["MarketplaceOrderPaginationResult"], "...on MarketplaceOrderPaginationResult">
};
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: {
__typename: "MarketplaceOrderReadyToReceiveEvent",
/** Пункт выдачи, где заказ готов к получению. */
braname: string,
/** Контрольная сумма заказа. */
order_hash: string,
/** Идентификатор заказа. */
order_id: string,
['...on MarketplaceOrderReadyToReceiveEvent']: Omit<GraphQLTypes["MarketplaceOrderReadyToReceiveEvent"], "...on MarketplaceOrderReadyToReceiveEvent">
};
/** Этап жизненного цикла заказа. */
["MarketplaceOrderStatus"]: MarketplaceOrderStatus;
@@ -38447,6 +38558,15 @@ export type GraphQLTypes = {
/** Название типа товара */
typeName: string,
['...on MarketplaceProductType']: Omit<GraphQLTypes["MarketplaceProductType"], "...on MarketplaceProductType">
};
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: {
__typename: "MarketplaceReceptionPendingSignEvent",
/** Наименование кооперативного участка приёмки. */
ku_name: string,
/** Идентификатор приёмки. */
reception_id: string,
['...on MarketplaceReceptionPendingSignEvent']: Omit<GraphQLTypes["MarketplaceReceptionPendingSignEvent"], "...on MarketplaceReceptionPendingSignEvent">
};
["MarketplaceRegistrationOfferStatus"]: {
__typename: "MarketplaceRegistrationOfferStatus",
@@ -42774,6 +42894,12 @@ export type GraphQLTypes = {
project_hash: string,
/** Распределение голосов */
votes: Array<GraphQLTypes["VoteDistributionInput"]>
};
["Subscription"]: {
__typename: "Subscription",
/** Персональный поток событий пайщика в Столе заказов. */
marketplaceEvents: GraphQLTypes["MarketplaceEvent"],
['...on Subscription']: Omit<GraphQLTypes["Subscription"], "...on Subscription">
};
["SubscriptionStatsDto"]: {
__typename: "SubscriptionStatsDto",
@@ -44208,6 +44334,7 @@ type ZEUS_VARIABLES = {
["MarketplaceCreateWriteoffDraftInput"]: ValueTypes["MarketplaceCreateWriteoffDraftInput"];
["MarketplaceDeclineOrdersBatchInput"]: ValueTypes["MarketplaceDeclineOrdersBatchInput"];
["MarketplaceDetailKUInput"]: ValueTypes["MarketplaceDetailKUInput"];
["MarketplaceEventsInput"]: ValueTypes["MarketplaceEventsInput"];
["MarketplaceFinalizeIssuanceInput"]: ValueTypes["MarketplaceFinalizeIssuanceInput"];
["MarketplaceGenerateInventoryLabelInput"]: ValueTypes["MarketplaceGenerateInventoryLabelInput"];
["MarketplaceGeocodeStatus"]: ValueTypes["MarketplaceGeocodeStatus"];
+7 -1
View File
@@ -11,6 +11,7 @@ import { ZeusScalars } from './zeus/index'
export * as Classes from './classes'
export * as Mutations from './mutations'
export * as Queries from './queries'
export * as Subscriptions from './subscriptions'
export * as Selectors from './selectors'
export * as Types from './types'
@@ -183,7 +184,12 @@ export class Client {
* Подписка на GraphQL-события.
*/
public get Subscription() {
return ZeusSubscription(this.options.api_url.replace(/^http/, 'ws'))
// Прокидываем заголовки (в т.ч. Authorization) — Zeus кладёт их в
// connectionParams ws-соединения, по которым сервер аутентифицирует
// подписку в onConnect. Без этого канал был бы анонимным и отклонялся.
return ZeusSubscription(this.options.api_url.replace(/^http/, 'ws'), {
headers: this.currentHeaders,
})
}
/**
@@ -0,0 +1 @@
export * as Marketplace from './marketplace'
@@ -0,0 +1,2 @@
/** Персональный realtime-канал событий пайщика в Столе заказов */
export * as Events from './marketplaceEvents'
@@ -0,0 +1,42 @@
import { $, type GraphQLTypes, type InputType, type ModelTypes, Selector } from '../../zeus/index'
/**
* Персональный realtime-канал событий пайщика в Столе заказов.
*
* Подписка несёт «сигнал» (идентификаторы + минимальный контекст), а не данные:
* получив событие, клиент дочитывает детали авторизованным query. Сервер
* адресует события по аккаунту из JWT соединения — чужое в канал не попадает.
*
* Union `MarketplaceEvent` дискриминируется по `__typename`; выбирай поля
* нужного типа через `... on`.
*/
export const name = 'marketplaceEvents'
export const subscription = Selector('Subscription')({
[name]: [
{ input: $('input', 'MarketplaceEventsInput!') },
{
__typename: true,
'...on MarketplaceOrderReadyToReceiveEvent': {
order_id: true,
order_hash: true,
braname: true,
},
'...on MarketplaceReceptionPendingSignEvent': {
reception_id: true,
ku_name: true,
},
},
],
})
export interface IInput {
/**
* @private
*/
[key: string]: unknown
input: ModelTypes['MarketplaceEventsInput']
}
export type IOutput = InputType<GraphQLTypes['Subscription'], typeof subscription>
+26 -1
View File
@@ -718,6 +718,9 @@ export const AllTypesProps: Record<string,any> = {
},
MarketplaceDetailKUInput:{
workingHours:"WorkingHoursInput"
},
MarketplaceEventsInput:{
},
MarketplaceFinalizeIssuanceInput:{
signed_document:"MarketplaceIssueActSignedDocumentInput"
@@ -2352,6 +2355,11 @@ export const AllTypesProps: Record<string,any> = {
SubmitVoteInput:{
votes:"VoteDistributionInput"
},
Subscription:{
marketplaceEvents:{
input:"MarketplaceEventsInput"
}
},
SystemStatus: "enum" as const,
TranscriptionStatus: "enum" as const,
TriggerNotificationWorkflowInput:{
@@ -4166,6 +4174,10 @@ export const ReturnTypes: Record<string,any> = {
picture:"String",
value:"String"
},
MarketplaceEvent:{
"...on MarketplaceOrderReadyToReceiveEvent":"MarketplaceOrderReadyToReceiveEvent",
"...on MarketplaceReceptionPendingSignEvent":"MarketplaceReceptionPendingSignEvent"
},
MarketplaceExpressPickupCandidate:{
braname:"String",
offerer_account:"String",
@@ -4356,6 +4368,11 @@ export const ReturnTypes: Record<string,any> = {
totalCount:"Int",
totalPages:"Int"
},
MarketplaceOrderReadyToReceiveEvent:{
braname:"String",
order_hash:"String",
order_id:"String"
},
MarketplaceOutgoingPaymentRequest:{
amount:"String",
apl_reception_id:"ID",
@@ -4382,6 +4399,10 @@ export const ReturnTypes: Record<string,any> = {
typeId:"Int",
typeName:"String"
},
MarketplaceReceptionPendingSignEvent:{
ku_name:"String",
reception_id:"String"
},
MarketplaceRegistrationOfferStatus:{
agreement_id:"String",
agreement_type:"String",
@@ -5792,6 +5813,9 @@ export const ReturnTypes: Record<string,any> = {
action:"ExtendedBlockchainAction",
documentAggregate:"DocumentAggregate"
},
Subscription:{
marketplaceEvents:"MarketplaceEvent"
},
SubscriptionStatsDto:{
active:"Int",
inactive:"Int",
@@ -5963,5 +5987,6 @@ export const ReturnTypes: Record<string,any> = {
export const Ops = {
query: "Query" as const,
mutation: "Mutation" as const
mutation: "Mutation" as const,
subscription: "Subscription" as const
}
+129 -2
View File
@@ -1104,7 +1104,7 @@ export type ScalarCoders = {
JSONObject?: ScalarResolver;
ID?: ScalarResolver;
}
type ZEUS_UNIONS = GraphQLTypes["PaymentMethodData"] | GraphQLTypes["PrivateAccountSearchData"] | GraphQLTypes["UserCertificateUnion"]
type ZEUS_UNIONS = GraphQLTypes["MarketplaceEvent"] | GraphQLTypes["PaymentMethodData"] | GraphQLTypes["PrivateAccountSearchData"] | GraphQLTypes["UserCertificateUnion"]
export type ValueTypes = {
["Account"]: AliasType<{
@@ -6750,6 +6750,14 @@ export type ValueTypes = {
__typename?: boolean | `@${string}`,
['...on MarketplaceDictionaryValue']?: Omit<ValueTypes["MarketplaceDictionaryValue"], "...on MarketplaceDictionaryValue">
}>;
["MarketplaceEvent"]: AliasType<{ ["...on MarketplaceOrderReadyToReceiveEvent"]?: ValueTypes["MarketplaceOrderReadyToReceiveEvent"],
["...on MarketplaceReceptionPendingSignEvent"]?: ValueTypes["MarketplaceReceptionPendingSignEvent"]
__typename?: boolean | `@${string}`
}>;
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string | Variable<any, string>
};
["MarketplaceExpressPickupCandidate"]: AliasType<{
/** КУ-получатель. */
braname?:boolean | `@${string}`,
@@ -7337,6 +7345,17 @@ export type ValueTypes = {
totalPages?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceOrderPaginationResult']?: Omit<ValueTypes["MarketplaceOrderPaginationResult"], "...on MarketplaceOrderPaginationResult">
}>;
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: AliasType<{
/** Пункт выдачи, где заказ готов к получению. */
braname?:boolean | `@${string}`,
/** Контрольная сумма заказа. */
order_hash?:boolean | `@${string}`,
/** Идентификатор заказа. */
order_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceOrderReadyToReceiveEvent']?: Omit<ValueTypes["MarketplaceOrderReadyToReceiveEvent"], "...on MarketplaceOrderReadyToReceiveEvent">
}>;
/** Этап жизненного цикла заказа. */
["MarketplaceOrderStatus"]:MarketplaceOrderStatus;
@@ -7387,6 +7406,15 @@ export type ValueTypes = {
typeName?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceProductType']?: Omit<ValueTypes["MarketplaceProductType"], "...on MarketplaceProductType">
}>;
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: AliasType<{
/** Наименование кооперативного участка приёмки. */
ku_name?:boolean | `@${string}`,
/** Идентификатор приёмки. */
reception_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`,
['...on MarketplaceReceptionPendingSignEvent']?: Omit<ValueTypes["MarketplaceReceptionPendingSignEvent"], "...on MarketplaceReceptionPendingSignEvent">
}>;
["MarketplaceRegistrationOfferStatus"]: AliasType<{
/** AGREEMENT_ID (например `marketplace_offer`) */
@@ -10921,6 +10949,11 @@ validateReportEdits?: [{ editsJson: string | Variable<any, string>, reportType:
/** Распределение голосов */
votes: Array<ValueTypes["VoteDistributionInput"]> | Variable<any, string>
};
["Subscription"]: AliasType<{
marketplaceEvents?: [{ input: ValueTypes["MarketplaceEventsInput"] | Variable<any, string>},ValueTypes["MarketplaceEvent"]],
__typename?: boolean | `@${string}`,
['...on Subscription']?: Omit<ValueTypes["Subscription"], "...on Subscription">
}>;
["SubscriptionStatsDto"]: AliasType<{
/** Количество активных подписок */
active?:boolean | `@${string}`,
@@ -17014,6 +17047,15 @@ export type ResolverInputTypes = {
value?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
["MarketplaceEvent"]: AliasType<{
MarketplaceOrderReadyToReceiveEvent?:ResolverInputTypes["MarketplaceOrderReadyToReceiveEvent"],
MarketplaceReceptionPendingSignEvent?:ResolverInputTypes["MarketplaceReceptionPendingSignEvent"],
__typename?: boolean | `@${string}`
}>;
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string
};
["MarketplaceExpressPickupCandidate"]: AliasType<{
/** КУ-получатель. */
braname?:boolean | `@${string}`,
@@ -17585,6 +17627,16 @@ export type ResolverInputTypes = {
/** Общее количество страниц */
totalPages?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: AliasType<{
/** Пункт выдачи, где заказ готов к получению. */
braname?:boolean | `@${string}`,
/** Контрольная сумма заказа. */
order_hash?:boolean | `@${string}`,
/** Идентификатор заказа. */
order_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
/** Этап жизненного цикла заказа. */
["MarketplaceOrderStatus"]:MarketplaceOrderStatus;
@@ -17633,6 +17685,14 @@ export type ResolverInputTypes = {
/** Название типа товара */
typeName?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: AliasType<{
/** Наименование кооперативного участка приёмки. */
ku_name?:boolean | `@${string}`,
/** Идентификатор приёмки. */
reception_id?:boolean | `@${string}`,
__typename?: boolean | `@${string}`
}>;
["MarketplaceRegistrationOfferStatus"]: AliasType<{
/** AGREEMENT_ID (например `marketplace_offer`) */
@@ -21051,6 +21111,10 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
/** Распределение голосов */
votes: Array<ResolverInputTypes["VoteDistributionInput"]>
};
["Subscription"]: AliasType<{
marketplaceEvents?: [{ input: ResolverInputTypes["MarketplaceEventsInput"]},ResolverInputTypes["MarketplaceEvent"]],
__typename?: boolean | `@${string}`
}>;
["SubscriptionStatsDto"]: AliasType<{
/** Количество активных подписок */
active?:boolean | `@${string}`,
@@ -21638,6 +21702,7 @@ validateReportEdits?: [{ editsJson: string, reportType: ResolverInputTypes["Repo
["schema"]: AliasType<{
query?:ResolverInputTypes["Query"],
mutation?:ResolverInputTypes["Mutation"],
subscription?:ResolverInputTypes["Subscription"],
__typename?: boolean | `@${string}`
}>;
["ID"]:unknown
@@ -26947,6 +27012,11 @@ export type ModelTypes = {
picture?: string | undefined | null,
/** Значение */
value: string
};
["MarketplaceEvent"]:ModelTypes["MarketplaceOrderReadyToReceiveEvent"] | ModelTypes["MarketplaceReceptionPendingSignEvent"];
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string
};
["MarketplaceExpressPickupCandidate"]: {
/** КУ-получатель. */
@@ -27498,6 +27568,15 @@ export type ModelTypes = {
totalCount: number,
/** Общее количество страниц */
totalPages: number
};
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: {
/** Пункт выдачи, где заказ готов к получению. */
braname: string,
/** Контрольная сумма заказа. */
order_hash: string,
/** Идентификатор заказа. */
order_id: string
};
["MarketplaceOrderStatus"]:MarketplaceOrderStatus;
["MarketplaceOutgoingPaymentRequest"]: {
@@ -27542,6 +27621,13 @@ export type ModelTypes = {
typeId: number,
/** Название типа товара */
typeName: string
};
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: {
/** Наименование кооперативного участка приёмки. */
ku_name: string,
/** Идентификатор приёмки. */
reception_id: string
};
["MarketplaceRegistrationOfferStatus"]: {
/** AGREEMENT_ID (например `marketplace_offer`) */
@@ -31599,6 +31685,10 @@ export type ModelTypes = {
project_hash: string,
/** Распределение голосов */
votes: Array<ModelTypes["VoteDistributionInput"]>
};
["Subscription"]: {
/** Персональный поток событий пайщика в Столе заказов. */
marketplaceEvents: ModelTypes["MarketplaceEvent"]
};
["SubscriptionStatsDto"]: {
/** Количество активных подписок */
@@ -32158,7 +32248,8 @@ export type ModelTypes = {
["ZeroReportSignerType"]:ZeroReportSignerType;
["schema"]: {
query?: ModelTypes["Query"] | undefined | null,
mutation?: ModelTypes["Mutation"] | undefined | null
mutation?: ModelTypes["Mutation"] | undefined | null,
subscription?: ModelTypes["Subscription"] | undefined | null
};
["ID"]:any
}
@@ -37809,6 +37900,15 @@ export type GraphQLTypes = {
/** Значение */
value: string,
['...on MarketplaceDictionaryValue']: Omit<GraphQLTypes["MarketplaceDictionaryValue"], "...on MarketplaceDictionaryValue">
};
["MarketplaceEvent"]:{
__typename:"MarketplaceOrderReadyToReceiveEvent" | "MarketplaceReceptionPendingSignEvent"
['...on MarketplaceOrderReadyToReceiveEvent']: '__union' & GraphQLTypes["MarketplaceOrderReadyToReceiveEvent"];
['...on MarketplaceReceptionPendingSignEvent']: '__union' & GraphQLTypes["MarketplaceReceptionPendingSignEvent"];
};
["MarketplaceEventsInput"]: {
/** Кооперативное имя. */
coopname: string
};
["MarketplaceExpressPickupCandidate"]: {
__typename: "MarketplaceExpressPickupCandidate",
@@ -38397,6 +38497,17 @@ export type GraphQLTypes = {
/** Общее количество страниц */
totalPages: number,
['...on MarketplaceOrderPaginationResult']: Omit<GraphQLTypes["MarketplaceOrderPaginationResult"], "...on MarketplaceOrderPaginationResult">
};
/** Заказ пайщика собран на пункте и ожидает его подписи получения. */
["MarketplaceOrderReadyToReceiveEvent"]: {
__typename: "MarketplaceOrderReadyToReceiveEvent",
/** Пункт выдачи, где заказ готов к получению. */
braname: string,
/** Контрольная сумма заказа. */
order_hash: string,
/** Идентификатор заказа. */
order_id: string,
['...on MarketplaceOrderReadyToReceiveEvent']: Omit<GraphQLTypes["MarketplaceOrderReadyToReceiveEvent"], "...on MarketplaceOrderReadyToReceiveEvent">
};
/** Этап жизненного цикла заказа. */
["MarketplaceOrderStatus"]: MarketplaceOrderStatus;
@@ -38447,6 +38558,15 @@ export type GraphQLTypes = {
/** Название типа товара */
typeName: string,
['...on MarketplaceProductType']: Omit<GraphQLTypes["MarketplaceProductType"], "...on MarketplaceProductType">
};
/** Поставка ожидает подписи поставщика на пункте приёмки. */
["MarketplaceReceptionPendingSignEvent"]: {
__typename: "MarketplaceReceptionPendingSignEvent",
/** Наименование кооперативного участка приёмки. */
ku_name: string,
/** Идентификатор приёмки. */
reception_id: string,
['...on MarketplaceReceptionPendingSignEvent']: Omit<GraphQLTypes["MarketplaceReceptionPendingSignEvent"], "...on MarketplaceReceptionPendingSignEvent">
};
["MarketplaceRegistrationOfferStatus"]: {
__typename: "MarketplaceRegistrationOfferStatus",
@@ -42774,6 +42894,12 @@ export type GraphQLTypes = {
project_hash: string,
/** Распределение голосов */
votes: Array<GraphQLTypes["VoteDistributionInput"]>
};
["Subscription"]: {
__typename: "Subscription",
/** Персональный поток событий пайщика в Столе заказов. */
marketplaceEvents: GraphQLTypes["MarketplaceEvent"],
['...on Subscription']: Omit<GraphQLTypes["Subscription"], "...on Subscription">
};
["SubscriptionStatsDto"]: {
__typename: "SubscriptionStatsDto",
@@ -44208,6 +44334,7 @@ type ZEUS_VARIABLES = {
["MarketplaceCreateWriteoffDraftInput"]: ValueTypes["MarketplaceCreateWriteoffDraftInput"];
["MarketplaceDeclineOrdersBatchInput"]: ValueTypes["MarketplaceDeclineOrdersBatchInput"];
["MarketplaceDetailKUInput"]: ValueTypes["MarketplaceDetailKUInput"];
["MarketplaceEventsInput"]: ValueTypes["MarketplaceEventsInput"];
["MarketplaceFinalizeIssuanceInput"]: ValueTypes["MarketplaceFinalizeIssuanceInput"];
["MarketplaceGenerateInventoryLabelInput"]: ValueTypes["MarketplaceGenerateInventoryLabelInput"];
["MarketplaceGeocodeStatus"]: ValueTypes["MarketplaceGeocodeStatus"];
+16
View File
@@ -433,6 +433,9 @@ importers:
graphql-scalars:
specifier: ^1.24.0
version: 1.25.0(graphql@16.13.2)
graphql-subscriptions:
specifier: ^2.0.0
version: 2.0.0(graphql@16.13.2)
graphql-tools:
specifier: ^9.0.2
version: 9.0.26(graphql-ws@5.16.2(graphql@16.13.2))(graphql@16.13.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rxjs@7.8.2)(subscriptions-transport-ws@0.11.0(graphql@16.13.2))
@@ -541,6 +544,9 @@ importers:
spectaql:
specifier: ^3.0.5
version: 3.0.9
subscriptions-transport-ws:
specifier: ^0.11.0
version: 0.11.0(graphql@16.13.2)
swagger-jsdoc:
specifier: ^6.0.8
version: 6.2.8(openapi-types@12.1.3)
@@ -11936,6 +11942,11 @@ packages:
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
graphql-subscriptions@2.0.0:
resolution: {integrity: sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA==}
peerDependencies:
graphql: ^15.7.2 || ^16.0.0
graphql-tag@2.12.6:
resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==}
engines: {node: '>=10'}
@@ -33003,6 +33014,11 @@ snapshots:
graphql: 16.13.2
tslib: 2.8.1
graphql-subscriptions@2.0.0(graphql@16.13.2):
dependencies:
graphql: 16.13.2
iterall: 1.3.0
graphql-tag@2.12.6(graphql@16.13.2):
dependencies:
graphql: 16.13.2