@tbox.cn/app-provider-mock 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tbox.cn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @tbox.cn/app-provider-mock
2
+
3
+ 商圈 Mock Provider 包(provider 拆包 F1b):全槽 local 供给(member×5 / parking×3 /
4
+ promotion×4 / shopping-guide×4 + mall.info,17 槽全 local:true——免传输/凭据/实例配置)。
5
+
6
+ - 实现自持(R3-1:dag 铁律禁 provider 依赖业务模块):mock 数据内聚于本包,member 卡面文案
7
+ 中立化("示例会员卡");shopping 域为静态 seed 派生(门店/类目/楼层目录)。
8
+ - 模板缺省绑定(F2):裸跑即完整 mock 演示——免业务凭据,不免模型密钥。
9
+ - 装配走 `tbox-app module add`(provider 即无卡模块)。
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Mock Provider 包入口(provider 拆包 F1b)。
3
+ * 服务端能力经 `./server` 子路径(与官方 provider 包同构)。
4
+ */
5
+ declare const providerId = "provider-mock";
6
+
7
+ export { providerId };
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // src/index.ts
2
+ var providerId = "provider-mock";
3
+ export {
4
+ providerId
5
+ };
@@ -0,0 +1,246 @@
1
+ import { ServiceAdapterFactory, ServerContext } from '@tbox.cn/app-sdk/server';
2
+ import { MemberAccountPort, MemberProfilePort, MemberCardPort, MemberBenefitsPort, MemberEnrollmentPort, MemberAccountSnapshot, MemberProfileSnapshot, MemberCardSnapshot, Points, MemberBenefitsSnapshot, PointUsageRecord, DiscountRule, MemberEnrollmentInput, MemberEnrollmentResult, MemberEnrollmentFormDefinition, ParkingQueryPort, ParkingPaymentPort, ParkingVehiclePort, ParkingQueryContext, QuoteSnapshot, ParkingVehicle, ParkingRecordPage, ParkingPaymentRecord, ParkingInfo, ParkingBenefit, ParkingLocation, PromotionOfferQueryPort, PromotionEntitlementPort, PromotionActivityPort, PromotionAcquisitionPort, PromotionQueryContext, PromotionSearchInput, PromotionOfferPage, PromotionOffer, PromotionEntitlementPage, PromotionEntitlement, PromotionActivityPage, PromotionActivityDetail, PromotionOperation, CatalogQueryPort, ShopDirectoryQueryPort, CommercialCategoryQueryPort, MallDirectoryQueryPort, ShopSearchCriteria, ShoppingPage, ShopRecord, ShoppingQueryContext, CategoryRecord, MallDirectoryRecord, ProductSearchCriteria, ProductRecord, ProductFacetsRecord } from '@tbox.cn/app-contracts-mall';
3
+ import { Router } from 'express';
4
+
5
+ /**
6
+ * Mock member 实现(provider-mock 自持——R3-1 裁决:provider 不得依赖业务模块,实现自持
7
+ * 而非包装 module-member InMemory)。演示面最小集:开户/卡面/积分/流水/入会闭环
8
+ * (demo ref 恒 `demo:` 前缀,厂商中立)。
9
+ */
10
+
11
+ type MockMemberService = MemberAccountPort & MemberProfilePort & MemberCardPort & MemberBenefitsPort & MemberEnrollmentPort;
12
+ /** mock 壳侧登录用户(换码器固定身份;mock 语义 = 单 demo 用户/部署) */
13
+ declare const MOCK_SHELL_USER_ID = "demo-user";
14
+ /** 入会落地(幂等):enroll 路由/enroll() 共用;余额缺省 300;登录成功即清除登出态 */
15
+ declare function enrollMockMember(userId: string): void;
16
+ declare function isMockMemberEnrolled(userId: string): boolean;
17
+ /** 登出标记(mock 档登出态模拟:仅对已入会用户有意义;重登录即清除) */
18
+ declare function logoutMockMember(userId: string): void;
19
+ declare function isMockMemberLoggedOut(userId: string): boolean;
20
+ /** 测试复位(沿 __resetAuthClientSingleton 先例——模块级共享状态可重置) */
21
+ declare function __resetMockMemberState(): void;
22
+ declare class MockMemberServiceImpl implements MockMemberService {
23
+ /**
24
+ * 开卡入会落地页深链(module-member MemberService.enrollUrl 接口面——CTA 卡深链为可选
25
+ * 透传素材,mock 出厂面恒配 demo 值)。demo 值厂商中立(appId=demo),点击在壳内
26
+ * navigateTo 失败即无害降级。
27
+ */
28
+ readonly enrollUrl = "alipays://platformapi/startapp?appId=demo&page=v/index/index";
29
+ /** 登录页深链(同上,可选透传素材;供未登录引导卡跳转)。 */
30
+ readonly loginUrl = "alipays://platformapi/startapp?appId=demo&page=v/login/index";
31
+ /** 默认访客(无种子):demo-user 初始 not_enrolled,经入会闭环翻为 active */
32
+ constructor(initial?: Record<string, number>);
33
+ getAccount(userId: string): Promise<MemberAccountSnapshot>;
34
+ getProfile(_userId: string): Promise<MemberProfileSnapshot>;
35
+ getCard(userId: string): Promise<MemberCardSnapshot | null>;
36
+ queryPoints(userId: string): Promise<Points>;
37
+ getBenefits(_userId: string): Promise<MemberBenefitsSnapshot>;
38
+ listPointUsage(_userId: string, page: number, pageSize: number): Promise<{
39
+ items: PointUsageRecord[];
40
+ total: number;
41
+ }>;
42
+ queryDiscount(): Promise<DiscountRule | undefined>;
43
+ deductPoints(userId: string, amount: number, _key: string): Promise<boolean>;
44
+ refundPoints(userId: string, amount: number, _key: string): Promise<boolean>;
45
+ awardPoints(userId: string, amount: number): Promise<boolean>;
46
+ enroll(input: MemberEnrollmentInput): Promise<MemberEnrollmentResult>;
47
+ getEnrollmentStatus(userId: string, _attemptRef: string): Promise<{
48
+ status: "active";
49
+ memberRef: string;
50
+ reason?: undefined;
51
+ } | {
52
+ status: "failed";
53
+ reason: string;
54
+ memberRef?: undefined;
55
+ }>;
56
+ /** 入会表单定义(模块 queryEnrollmentForm 工具消费;无参对齐 InMemory 先例) */
57
+ getEnrollmentFormDefinition(): Promise<MemberEnrollmentFormDefinition>;
58
+ }
59
+
60
+ /**
61
+ * Mock parking 实现(provider-mock 自持——R3-1 裁决)。演示面最小集:报价/车辆/记录/
62
+ * 综合信息/权益/寻车 + 三步支付链 mock 闭环(reconcile 恒 PAID 收口)。demo ref 恒
63
+ * `demo:` 前缀,厂商中立;车牌未提供时以演示车(demo-plate)兜底。
64
+ */
65
+
66
+ type MockParkingService = ParkingQueryPort & ParkingPaymentPort & ParkingVehiclePort;
67
+ declare class MockParkingServiceImpl implements MockParkingService {
68
+ private vehicles;
69
+ private records;
70
+ constructor(mallId?: string);
71
+ private mallId;
72
+ queryFee(q: ParkingQueryContext, input: {
73
+ plateNo?: string;
74
+ vehicleRef?: string;
75
+ }): Promise<readonly QuoteSnapshot[]>;
76
+ listVehicles(): Promise<{
77
+ bound: readonly ParkingVehicle[];
78
+ }>;
79
+ listPaymentRecords(_q: ParkingQueryContext, page: number, pageSize: number): Promise<ParkingRecordPage>;
80
+ getPaymentRecordDetail(_q: ParkingQueryContext, recordRef: string): Promise<ParkingPaymentRecord>;
81
+ getInvoiceSettings(): Promise<{
82
+ parkingInvoiceEnabled: boolean;
83
+ }>;
84
+ listInvoiceableOrders(_q: ParkingQueryContext, page: number, pageSize: number): Promise<ParkingRecordPage>;
85
+ queryParkingInfo(_q: ParkingQueryContext, kind: ParkingInfo['kind']): Promise<ParkingInfo>;
86
+ queryApplicableBenefits(_q: ParkingQueryContext, _plateNo: string): Promise<readonly ParkingBenefit[]>;
87
+ locateVehicle(_q: ParkingQueryContext, _plateNo: string): Promise<ParkingLocation | null>;
88
+ createOrder(_q: ParkingQueryContext, quoteRef: string): Promise<{
89
+ payOrderId?: string;
90
+ paymentRef: string;
91
+ }>;
92
+ getOrderInfo(_q: ParkingQueryContext, _paymentRef: string): Promise<{
93
+ orderInfo?: string;
94
+ channel: string;
95
+ payableFeeCents: number | undefined;
96
+ }>;
97
+ getPaymentSign(_q: ParkingQueryContext, _paymentRef: string): Promise<{
98
+ orderInfo: string;
99
+ }>;
100
+ uploadResult(): Promise<void>;
101
+ reconcile(_q: ParkingQueryContext, _paymentRef: string): Promise<'PAID' | 'PAYING' | 'CANCELLED' | 'UNKNOWN'>;
102
+ reprice(q: ParkingQueryContext, quoteRef: string, benefitRefs: readonly string[]): Promise<QuoteSnapshot>;
103
+ applyInvoice(_q: ParkingQueryContext, recordRef: string): Promise<void>;
104
+ bindVehicle(_q: ParkingQueryContext, plateNo: string): Promise<ParkingVehicle>;
105
+ unbindVehicle(_q: ParkingQueryContext, input: {
106
+ plateNo?: string;
107
+ vehicleRef?: string;
108
+ }): Promise<void>;
109
+ }
110
+
111
+ /**
112
+ * Mock promotion 实现(provider-mock 自持——R3-1 裁决)。演示面最小集:搜索/精查/推荐/
113
+ * 资产列表/活动列表/领取闭环(acquire 恒 SUCCEEDED)。demo ref 恒 `demo:` 前缀,厂商中立。
114
+ */
115
+
116
+ type MockPromotionService = PromotionOfferQueryPort & PromotionEntitlementPort & PromotionActivityPort & PromotionAcquisitionPort;
117
+ declare class MockPromotionServiceImpl implements MockPromotionService {
118
+ searchOffers(_q: PromotionQueryContext, input: PromotionSearchInput): Promise<PromotionOfferPage>;
119
+ getOfferDetail(_q: PromotionQueryContext, input: {
120
+ offerRef?: string;
121
+ entitlementRef?: string;
122
+ keyword?: string;
123
+ }): Promise<PromotionOffer | null>;
124
+ recommendOffers(): Promise<readonly PromotionOffer[]>;
125
+ listEntitlements(_q: PromotionQueryContext, _input: PromotionSearchInput): Promise<PromotionEntitlementPage>;
126
+ getEntitlementDetail(_q: PromotionQueryContext, entitlementRef: string): Promise<PromotionEntitlement | null>;
127
+ listActivities(): Promise<PromotionActivityPage>;
128
+ getActivityDetail(_q: PromotionQueryContext, activityRef: string): Promise<PromotionActivityDetail | null>;
129
+ listActivityCategories(): Promise<{
130
+ categoryId: string;
131
+ name: string;
132
+ }[]>;
133
+ acquire(_q: PromotionQueryContext, input: {
134
+ offerRef: string;
135
+ externalMemberRef: string;
136
+ idempotencyKey: string;
137
+ }): Promise<PromotionOperation>;
138
+ getOperation(_q: PromotionQueryContext, operationRef: string): Promise<PromotionOperation | null>;
139
+ }
140
+
141
+ /**
142
+ * Mock shopping 实现(provider-mock 自持——R3-1 裁决:provider 不得依赖业务模块)。
143
+ * 演示面:门店/类目/楼层目录(remote 检索域四键形状的 catalog/shop/category/directory)。
144
+ *
145
+ * 设计决策:
146
+ * - 单一真源:DEMO_BUILDINGS 楼栋→楼层→门店 seed;类目/楼层业态/计数派生聚合;
147
+ * floorCode/buildingCode 派生同值(code=name,消除 mall-context id ↔ search-shops
148
+ * 过滤键隐式映射)。
149
+ * - 纯 mock:静态数组 + 内存过滤,零 IO、零外部依赖(不依赖知识库/TBOX_API_KEY/datasetId)。
150
+ * - merchantId 连字符格式(demo-shop-NNNN):LLM 从卡片 value 提取友好;getShop 入参 trim。
151
+ * - catalog 空实现(对齐真实档 C 端):演示面不覆盖商品目录,门店链路为演示重点。
152
+ * - 构造器接受 seed(默认 DEMO_BUILDINGS):测试可注入定制数据。
153
+ */
154
+
155
+ interface ShopSeed {
156
+ merchantId: string;
157
+ name: string;
158
+ brand?: string;
159
+ businessCategories: string[];
160
+ unitName: string;
161
+ status: {
162
+ code: 'enabled' | 'disabled';
163
+ label: string;
164
+ };
165
+ }
166
+ interface DemoFloor {
167
+ floorName: string;
168
+ shops: ShopSeed[];
169
+ }
170
+ interface DemoBuilding {
171
+ buildingName: string;
172
+ floors: DemoFloor[];
173
+ }
174
+ declare class MockShoppingServiceImpl implements CatalogQueryPort, ShopDirectoryQueryPort, CommercialCategoryQueryPort, MallDirectoryQueryPort {
175
+ private readonly buildings;
176
+ private readonly shops;
177
+ private readonly categories;
178
+ constructor(seed?: readonly DemoBuilding[]);
179
+ searchShops(criteria: ShopSearchCriteria): Promise<ShoppingPage<ShopRecord>>;
180
+ getShop(shopId: string, _ctx: ShoppingQueryContext): Promise<ShopRecord | null>;
181
+ listCategories(_ctx: ShoppingQueryContext): Promise<readonly CategoryRecord[]>;
182
+ getDirectory(ctx: ShoppingQueryContext): Promise<MallDirectoryRecord | null>;
183
+ searchProducts(criteria: ProductSearchCriteria): Promise<ShoppingPage<ProductRecord>>;
184
+ getProduct(_productId: string, _ctx: ShoppingQueryContext): Promise<ProductRecord | null>;
185
+ getFacets(_criteria: ProductSearchCriteria): Promise<ProductFacetsRecord>;
186
+ }
187
+
188
+ declare const MOCK_MALL_INFO_PROVIDER = "mock";
189
+ declare const MOCK_MALL_INFO_IMPL = "mock-mall-info@1";
190
+ /** mock mall.info adapter 工厂(对齐真实厂商 adapter 工厂形态) */
191
+ declare const mockMallInfoFactory: ServiceAdapterFactory;
192
+
193
+ /**
194
+ * Mock 入会落地点路由(入会体验闭环 C5):POST /api/m/provider-mock/demo/member-enroll。
195
+ *
196
+ * 容器 mock-enrollment 页(dev 脚手架)与 curl 联调共用:
197
+ * - body `{userId?}`:缺省 MOCK_SHELL_USER_ID(mock 页无参——与真实 gate 无参协议面一致;
198
+ * curl 可定向翻 dev_h5 等浏览器 dev 用户造会员态调试)。
199
+ * - 幂等(Set.add / 余额保守写);NODE_ENV=production → 503(provider-mock 不进生产装配,双保险)。
200
+ * - 经全局 /api 鉴权(AUTH_MODE 缺省 required)——调用方须携 dev-login 令牌;
201
+ * 匿名写显式拒绝(不随 AUTH_MODE 放宽)。
202
+ * - doctor naked-write-route:/demo 前缀在白名单内(webhook/upload/demo/run)。
203
+ *
204
+ * 决策逻辑抽纯函数 resolveMockEnroll(单测直达,路由层只做 HTTP 形状映射)。
205
+ */
206
+
207
+ declare function createMockEnrollRouter(): Router;
208
+
209
+ /**
210
+ * Mock Provider 包服务端入口(provider 拆包 F1b)。
211
+ *
212
+ * 17 槽 local 供给(member×5 / parking×3 / promotion×4 / guide×4 + mall.info;manifest
213
+ * contributes.providers.slots,local:true):F2 模块 ports
214
+ * slot 一行化后经 createIntegrationsRegistry.resolveService 解析——local 短路免传输/
215
+ * 凭据/实例配置。实现自持(R3-1:provider 不得依赖业务模块——workspace-dag 铁律),
216
+ * demo ref 恒 `demo:` 前缀,厂商中立。
217
+ *
218
+ * F1b 阶段形态:adapter 工厂注册经 ctx.integrations(F2 模板装配 createIntegrationsRegistry
219
+ * 接线后生效);F1b 前模块仍走探测链,本包装配无行为影响。shopping-guide 槽四键形状
220
+ * (catalog 空 + shop/category/directory 纯 mock 数据);assistance/navigation 本地知识库域
221
+ * 归模块本地 adapter,不属 provider 供给面。
222
+ *
223
+ * 入会体验闭环(C5)追加两件:
224
+ * - scoped mock 换码器(ctx.authExchanges):固定 demo-user、GUEST/MEMBER 双形态对齐
225
+ * 真实厂商换码协议(潜客 token=''+openid ↔ 会员 token+memberId)——mock 档冷登走与
226
+ * 真实档同一条换码链,H5 侧代码零分叉。刻意不实现 devExternalCredentials:dev-login
227
+ * 走协议 fail-soft 无 claim 签发(login-routes 三层解析能力口缺席即跳过)。
228
+ * - mock 入会落地路由(ctx.routes):POST /demo/member-enroll(容器 mock-enrollment 页
229
+ * 回调 + curl 联调)。
230
+ */
231
+
232
+ declare const MOCK_PROVIDER = "mock";
233
+ declare const MOCK_MEMBER_IMPL = "mock-member@1";
234
+ declare const MOCK_PARKING_IMPL = "mock-parking@1";
235
+ declare const MOCK_PROMOTION_IMPL = "mock-promotion@1";
236
+ declare const MOCK_SHOPPING_IMPL = "mock-shopping@1";
237
+
238
+ declare const serverModule: {
239
+ declaration: {
240
+ moduleId: string;
241
+ };
242
+ cards: {};
243
+ register(ctx: ServerContext): void;
244
+ };
245
+
246
+ export { MOCK_MALL_INFO_IMPL, MOCK_MALL_INFO_PROVIDER, MOCK_MEMBER_IMPL, MOCK_PARKING_IMPL, MOCK_PROMOTION_IMPL, MOCK_PROVIDER, MOCK_SHELL_USER_ID, MOCK_SHOPPING_IMPL, MockMemberServiceImpl, MockParkingServiceImpl, MockPromotionServiceImpl, MockShoppingServiceImpl, __resetMockMemberState, createMockEnrollRouter, enrollMockMember, isMockMemberEnrolled, isMockMemberLoggedOut, logoutMockMember, mockMallInfoFactory, serverModule };