上传文件至「/」

This commit is contained in:
2026-10-12 02:10:43 +00:00
commit 54b4d8f8c5
5 changed files with 1173 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
feat(ewallet): 支持会员 card_num 场景 (Task 15171) 并新增 msgw contentSend 路由
- member.profile 与 createMockContext 增加 card_num 字段及 MOCK_TASK_15171_ENABLED 开关
- 新增 memberProfileCardNum 路由与对应测试
- 新增 ewl/msgw/contentSend 路由并在 registerRoutes 注册
- 包管理从 npm 迁移到 yarn
+481
View File
@@ -0,0 +1,481 @@
# Mock Gateway
本项目是 **独立 Git 仓库** 的本地 Mock 网关,用于模拟 eWallet 后端依赖的 Bally/EDIP 接口,避免在 `Backend` 主代码中持续保留绕过逻辑。
## 已内置的 Mock 接口
- `POST /edip/v1/token/get`
- `POST /edip/v1/token/refresh`
- `POST /ewl/bal/v1/cardpin/validate`
- `POST /ewl/promotion/v1/promotion/all`
- `POST /ewl/bal/v1/promotion/all` (兼容旧地址)
- `POST /ewl/promotion/v1/promotion/backdate/all`
- `POST /ewl/bal/v1/promotion/backdate/all` (兼容旧地址)
- `POST /ewl/mkt-rm/v1/team/hierarchy`
- `POST /ewl/bal/v1/prize/redeem`
- `POST /ewl/bal/v1/point/void`
- `POST /ewl/promotion/v1/redeemedpromotion/detail`
- `POST /ewl/bal/v1/redeemedpromotion/detail` (兼容旧地址)
- `POST /ewl/promotion/v1/playerpromotion/redeem`
- `POST /ewl/bal/v1/playerpromotion/redeem` (兼容旧地址)
- `POST /ewl/promotion/v1/redeemedpromotion/void`
- `POST /ewl/bal/v1/redeemedpromotion/void` (兼容旧地址)
- `POST /ewl/edip/v1/member/profile`
- `POST /ewl/bal/v1/player/image`
- `POST /ewl/bal/v1/player/earn`
- `POST /api/v1/prize-redemptions/sync`
- `GET /healthz`
## 已内置的 LDAP Mock(新增)
- 协议:LDAPv3
- 默认监听:`ldap://0.0.0.0:1389`
- 支持能力:`Simple Bind` + `Search`
固定行为(与对接约定一致):
1. manager bind DN:`cn=s-cicd-app,OU=ServiceAccount,dc=macausjm-glp,dc=com`
2. 用户搜索:base `dc=macausjm-glp,dc=com` + filter `(sAMAccountName={username})`
3. 组搜索:base `OU=SecurityGroups,OU=GLPUsers,dc=macausjm-glp,dc=com` + filter `(member={userDn})`
4. 用户条目属性:`sAMAccountName` / `cn` / `mail` / `memberOf`
5. 组条目属性:`cn` / `member`
并且支持用户 DN + 密码直接 bind 成功(基于内置默认用户或 `MOCK_LDAP_USERS_JSON` 配置用户)。
另外默认开启“任意用户名/密码放行”联调模式(`MOCK_LDAP_ALLOW_ANY_USER_MODE=true`):
- 前端输入任意账号密码都可通过后端 LDAP 认证
- `(sAMAccountName={username})` 会按 `{username}` 动态返回用户条目
- `(member={userDn})` 会返回组条目(默认 `SG-APP-EWALLET-SUPER-ADMIN`)
推荐做法:通过 `MOCK_LDAP_USERS_JSON` / `MOCK_LDAP_GROUPS_JSON` 在 `Mock_Gateway` 侧配置用户与用户组,不要再在 `Backend` 代码里硬编码开发账号或组别。
## 本地启动
```bash
cd Mock_Gateway
npm install
cp .env.example .env
npm run start
```
开发联调建议使用自动重启模式(监听 `src/` 与 `.env` 变更):
```bash
npm run dev
```
默认监听:`http://127.0.0.1:19090`
LDAP 默认监听:`ldap://0.0.0.0:1389`
## Promotion 完整链路 mock
默认的 `playerpromotion/redeem` 仍然只是静态回包。
如果你要在本地继续联调 promotion 首打、redeemed history、reprint 这一整条链路,可以开启下面这组桥接配置,让 `Mock_Gateway` 在 promotion redeem 成功后继续:
1. 登录本地 `Backend`
2. 调用真实 `POST /api/v1/prize-redemptions`
3. 把同一笔 `redemptionId` 记录进 mock 的 `redeemedpromotion/detail`
建议同时满足以下前提:
- 本地 `Backend` 已启动
- 本地 `Backend` 已接到当前 `Mock_Gateway` 的 LDAP mock
- 测试会员在本地 wallet 里对 `MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET` 有足够余额
推荐配置:
```bash
MOCK_PROMOTION_REDEMPTION_BRIDGE_ENABLED=true
MOCK_PROMOTION_REDEMPTION_BRIDGE_BASE_URL=http://127.0.0.1:8080
MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_PASSWORD=mock-password
MOCK_PROMOTION_REDEMPTION_BRIDGE_TIMEOUT_MS=30000
MOCK_PROMOTION_REDEMPTION_INITIATE_SOURCE=PROMOTION_MODULE
MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET=m-comp
```
说明:
- `MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_USERNAME` 留空时,默认复用本次 redeem 请求里的 `loginId`
- `MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET` 默认用 `m-comp` 作为 source wallet bucket
- 桥接成功后,`/ewl/bal/v1/redeemedpromotion/detail` 会优先返回本次实际生成的 mock redeemed record
### Promotion issue-to-wallet 控制
当前 `Mock_Gateway` 已支持两层控制 promotion redeem -> 本地 `prize-redemptions` 的 `issueTargetToWallet`:
1. 显式覆盖,优先级最高
2. 现有推断,作为兜底
显式覆盖支持两种写法:
- 请求级:
- `data.issueTargetToWallet: [true, false, ...]`,按 `outcomeId` 顺序逐项覆盖;同一个 `outcomeId` 重复出现且每次选择不同 `Open Item / Auto Settle` 时,必须走这个数组
- `data.issueTargetToWalletByOutcomeId: { "11330011": true, "11330012": false }`,按 outcomeId 精确覆盖
- fixture 级:
- `outcomeList[].mockIssueTargetToWallet`
- `outcomeList[].prize.mockIssueTargetToWallet`
当以上显式覆盖都没有提供时,才回退到现有推断规则:
- `gisPrizeIdentifier[index]` 非空 -> `issueTargetToWallet=false`
- 否则 `deliveryMode=EXTERNAL_ONLY` -> `false`
- 其他情况 -> `true`
这意味着:
- 对 `USER_CHOICE` prize,如需稳定复现同一个 outcome 在 openitem / autosettle 之间切换,推荐直接在 mock 请求或 fixture 中提供显式覆盖,不要只依赖 `deliveryMode`
- 如果一个请求里允许同一个 `outcomeId` 重复出现且每次选择不同,优先使用 `issueTargetToWallet` 数组;`issueTargetToWalletByOutcomeId` 只适合一个 outcomeId 对应一个固定值的场景
- 如果调用方需要,也可以通过 body 的 `issueTargetToWalletByOutcomeId` / `issueTargetToWallet`,或自定义 header `X-Ewallet-Mock-Issue-Target-To-Wallet-By-Outcome-Id` 给 mock 传入显式覆盖;未提供时仍按当前默认推断执行
- 旧链路不受影响;未提供覆盖时仍保持当前默认行为
### UI 点测同一个 outcome 的本地预设
如果不改 Backend,但希望在 UI 上对同一个 outcome 反复点测 `Open Item / Auto Settle`,可以先写入 mock runtime override:
```bash
curl -s -X POST http://127.0.0.1:19090/mock-api/promotion-redeem/fulfillment-overrides \
-H 'Content-Type: application/json' \
-d '{
"accountNum": "80010991",
"promotionId": 11330,
"promotionRuleId": 1133001,
"outcomeId": 11330011,
"issueTargetToWallet": false
}'
```
说明:
- `issueTargetToWallet=true` 表示本次同一个 outcome 走 `Open Item`
- `issueTargetToWallet=false` 表示本次同一个 outcome 走 `Auto Settle`
- 写入后,直接在 UI 点同一个 outcome 即可;mock 会优先使用这份 runtime override
- override 默认会持久化到 `./runtime/promotion-redeem-fulfillment-overrides.json`,重启 `Mock_Gateway` 后仍会保留
- 可通过 `GET /mock-api/promotion-redeem/fulfillment-overrides` 查看当前预设
- 可通过 `DELETE /mock-api/promotion-redeem/fulfillment-overrides?accountNum=80010991&promotionId=11330&promotionRuleId=1133001&outcomeId=11330011` 清除单条预设
## 与 Backend 集成
在 Backend 启动环境中设置:
```bash
MOCK_GATEWAY_BASE_URL=http://127.0.0.1:19090
BALLY_BASE_URL=${MOCK_GATEWAY_BASE_URL}
EDIP_BASE_URL=${MOCK_GATEWAY_BASE_URL}
BALLY_REDEEM_BASE_URL=${MOCK_GATEWAY_BASE_URL}
BALLY_PROMOTION_BASE_URL=${MOCK_GATEWAY_BASE_URL}
# 建议关闭旧的本地 member 直返 mock,改走网关
BALLY_MEMBER_QUERY_LOCAL_MOCK_ENABLED=false
```
## Task12085 本地故障注入
当前 `Mock_Gateway` 已支持直接注入 Member Profile 两类关键故障:
1. `503` / 服务不可用
```bash
MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE=503
MOCK_MEMBER_PROFILE_FORCE_ERROR_CODE=MOCK_503
MOCK_MEMBER_PROFILE_FORCE_ERROR_MSG='Mock member profile unavailable'
```
2. 响应超时
```bash
MOCK_MEMBER_PROFILE_DELAY_MS=15000
```
建议:
- `MOCK_MEMBER_PROFILE_DELAY_MS` 需要大于 Backend 当前 member profile 调用的阻塞超时,才能稳定触发超时
- 如果你只想打 member profile 故障,保持 `MOCK_EDIP_FORCE_ERROR_CODE` 为空,让 token 继续正常返回
- 测完后把这些变量清空并重启 `Mock_Gateway`
## 快速验证
```bash
curl -s http://127.0.0.1:19090/healthz
curl -s -X POST http://127.0.0.1:19090/edip/v1/token/get \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"account":"a","password":"b","key":"k","secret":"s"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/cardpin/validate \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"810006843","pin":"1234"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/promotion/v1/promotion/all \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/promotion/all \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/mkt-rm/v1/team/hierarchy \
-H 'Content-Type: application/json' \
-d '{"schema":{"terminalCode":"MOCK-PC"},"data":{"userName":"mock.user","staffId":"M000001"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/prize/redeem \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718","prizeCode":"MOCK"}}'
curl -s -X POST http://127.0.0.1:19090/api/v1/prize-redemptions/sync \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"correlationId":"mock-correlation-id"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/point/void \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"transId":"mock-redeem-id"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/redeemedpromotion/detail \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718"}}'
curl -s -X POST http://127.0.0.1:19090/ewl/promotion/v1/playerpromotion/redeem \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718","promotionId":100002}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/playerpromotion/redeem \
-H 'Content-Type: application/json' \
-d '{
"schema": {},
"data": {
"accountNum": "80010991",
"promotionId": 11330,
"promotionRuleId": 1133001,
"outcomeId": [11330011, 11330012, 11330013],
"issueTargetToWalletByOutcomeId": {
"11330011": true,
"11330012": false,
"11330013": false
}
}
}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/playerpromotion/redeem \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"accountNum":"800048718","promotionId":100002}}'
curl -s -X POST http://127.0.0.1:19090/ewl/promotion/v1/redeemedpromotion/void \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"redeemedId":<上一步 detail 响应里的 redemptionId>}}'
curl -s -X POST http://127.0.0.1:19090/ewl/bal/v1/redeemedpromotion/void \
-H 'Content-Type: application/json' \
-d '{"schema":{},"data":{"redeemedId":<上一步 detail 响应里的 redemptionId>}}'
# LDAP manager bind(默认 manager 密码可留空,便于 Backend 只改 LDAP_URL)
ldapsearch -x -H ldap://127.0.0.1:1389 \
-D "cn=s-cicd-app,OU=ServiceAccount,dc=macausjm-glp,dc=com" \
-w "any-password" \
-b "dc=macausjm-glp,dc=com" \
"(sAMAccountName=mock.user)" sAMAccountName cn mail memberOf
# LDAP user bind(DN + 密码)
ldapsearch -x -H ldap://127.0.0.1:1389 \
-D "cn=mock.user,OU=GLPUsers,dc=macausjm-glp,dc=com" \
-w "mock-user-password" \
-b "OU=SecurityGroups,OU=GLPUsers,dc=macausjm-glp,dc=com" \
"(member=cn=mock.user,OU=GLPUsers,dc=macausjm-glp,dc=com)" cn member
# 建议把默认组名设置成 Backend 角色表已有 code(如 `SG-APP-EWALLET-SUPER-ADMIN`),更容易看到非空 permissions
```
## 页面数据模板(JSON)
- `fixtures/token.get.json`:`/edip/v1/token/get` 成功响应模板
- `fixtures/member.profile.json`:`/ewl/edip/v1/member/profile` 成功响应模板
- `fixtures/promotions.capture.800048718.json`:`/ewl/promotion/v1/promotion/all` 抓包模板
- `fixtures/promotions.capture.<account>.json`:按会员号隔离的 promotion fixture;存在同名文件时,mock 会优先对该会员返回该文件内容
- promotion fixture 可额外带 `outcomeList[].mockIssueTargetToWallet` 或 `outcomeList[].prize.mockIssueTargetToWallet`,用于稳定指定某个 outcome 走 openitem / autosettle
当前已补一条专用于完整链路测试的会员:
- `80010991`
- promotionId:`10991`
- promotion:`LP-MOCK-REPRINT-CHAIN`
- ruleId:`1099101`
- outcomeId:`10991011`
- targetPrizeCode:`lp-ee-nsuwr-5pts-20-fb`
- 另有 3-outcome 的 `USER_CHOICE` 测试 promotion:
- promotionId:`11330`
- promotion:`LP-MOCK-USER-CHOICE-3-OUTCOMES`
- ruleId:`1133001`
- outcomeId:`11330011` -> `it-test-fb-$1`
- outcomeId:`11330012` -> `it-test-nnpc-$1`
- outcomeId:`11330013` -> `it-test-ebo-$1`
- 这 3 个 outcome 都可在 UI 上分别切 `Open Item / Auto Settle`,用于本地验证 promotion redeem -> prize-redemptions -> redeemed detail 整条链路
说明:
- 以上模板用于维护响应“静态骨架”
- 动态字段仍由网关运行时覆盖(如 `accessToken`、`refreshToken`、`accountNum`、`playerId`、以及 LDAP 用户相关字段)
## 代码结构(已拆分)
- `src/server.js`:仅保留启动、路由装配、404 与 LDAP 启动
- `src/ldap/createMockLdapService.js`:LDAP 相关逻辑独立维护
- `src/context/createMockContext.js`:共享配置、fixture 加载、通用工具函数
- `src/routes/**`:每个接口路径一个独立文件(便于新增与变更)
## 常用环境变量
- `MOCK_PROMOTION_CAPTURE_FILE`:promotion 抓包文件路径(默认读取仓库内 `./fixtures/promotions.capture.800048718.json`)
- `MOCK_PROMOTION_MAX_ITEMS`:promotion 返回上限(eligible/entitled 各自限制,默认 `30`)
- `MOCK_TASK_10766_ENABLED`:开启 Task 10766 复现场景(默认 `false`)
- `MOCK_TASK_10766_ACCOUNT_NUM`:Task 10766 固定 mock 会员号(默认 `80010766`)
- `MOCK_TASK_10766_PROMOTION_CAPTURE_FILE`:Task 10766 promotion fixture(默认 `./fixtures/promotions.capture.10766.json`)
- `MOCK_TASK_10766_MEMBER_EBONUS`:Task 10766 会员资料接口返回的 eBonus 数值(默认 `8888`)
- `MOCK_TASK_10766_REDEEM_ERROR_CODE` / `MOCK_TASK_10766_REDEEM_ERROR_MSG` / `MOCK_TASK_10766_REDEEM_RESULT`:Task 10766 的 `playerpromotion/redeem` 定向失败控制
- `MOCK_TASK_10852_ENABLED`:开启 Task 10852 多 outcome promotion 复现场景(默认 `false`)
- `MOCK_TASK_10852_ACCOUNT_NUM`:Task 10852 固定 mock 会员号(默认 `80010852`)
- `MOCK_TASK_10852_PROMOTION_CAPTURE_FILE`:Task 10852 promotion fixture,默认使用隔离的 entitled 双 outcome 抓包 `./fixtures/promotions.capture.10852.json`
- `MOCK_TASK_10852_MEMBER_EBONUS`:Task 10852 会员资料接口返回的 eBonus 数值(默认 `188`)
- `MOCK_TOKEN_GET_FIXTURE_FILE`:`/edip/v1/token/get` JSON 模板文件路径(默认 `./fixtures/token.get.json`)
- `MOCK_MEMBER_PROFILE_FIXTURE_FILE`:`/ewl/edip/v1/member/profile` JSON 模板文件路径(默认 `./fixtures/member.profile.json`)
- `MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE`:`/ewl/edip/v1/member/profile` 强制返回指定 HTTP 状态码,例如 `503`
- `MOCK_MEMBER_PROFILE_FORCE_ERROR_CODE`:配合 `MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE` 返回错误码
- `MOCK_MEMBER_PROFILE_FORCE_ERROR_MSG`:配合 `MOCK_MEMBER_PROFILE_FORCE_STATUS_CODE` 返回错误信息
- `MOCK_MEMBER_PROFILE_DELAY_MS`:`/ewl/edip/v1/member/profile` 延迟响应毫秒数,可用于本地模拟超时
- `MOCK_TEAM_HIERARCHY_STATUS`:`team/hierarchy` 的 `status`(默认 `true`)
- `MOCK_TEAM_HIERARCHY_ERROR_CODE` / `MOCK_TEAM_HIERARCHY_MESSAGE`:`team/hierarchy` 错误模拟
- `MOCK_TEAM_HIERARCHY_ROLE` / `MOCK_TEAM_HIERARCHY_DEPARTMENT` / `MOCK_TEAM_HIERARCHY_TAGS`:`team/hierarchy` 返回字段
- `MOCK_PRIZE_REDEEM_ERROR_CODE` / `MOCK_PRIZE_REDEEM_ERROR_MSG` / `MOCK_PRIZE_REDEEM_VALUE`:`prize/redeem` 返回控制(`MOCK_PRIZE_REDEEM_VALUE` 留空时自动生成交易号)
- `MOCK_POINT_VOID_ERROR_CODE` / `MOCK_POINT_VOID_ERROR_MSG` / `MOCK_POINT_VOID_RESULT`:`point/void` 返回控制
- `MOCK_REDEEMED_PROMOTION_DETAIL_ERROR_CODE` / `MOCK_REDEEMED_PROMOTION_DETAIL_ERROR_MSG`:`redeemedpromotion/detail` 返回控制
- `MOCK_REDEEMED_PROMOTION_DETAIL_INCLUDE_DEFAULT_RECORD`:是否返回默认一条 `outcomeList`(默认 `true`)
- `MOCK_REDEEMED_PROMOTION_DETAIL_VOIDED`:默认记录是否标记已作废(默认 `false`)
- `MOCK_PLAYERPROMOTION_REDEEM_ERROR_CODE` / `MOCK_PLAYERPROMOTION_REDEEM_ERROR_MSG` / `MOCK_PLAYERPROMOTION_REDEEM_RESULT`:`playerpromotion/redeem` 返回控制
- `MOCK_PROMOTION_REDEMPTION_BRIDGE_ENABLED`:开启 promotion redeem -> 本地 `prize-redemptions` 桥接(默认 `false`)
- `MOCK_PROMOTION_REDEMPTION_BRIDGE_BASE_URL`:本地 Backend 基地址(默认 `http://127.0.0.1:8080`)
- `MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_USERNAME` / `MOCK_PROMOTION_REDEMPTION_BRIDGE_LOGIN_PASSWORD`:桥接调用 Backend 登录用账号;用户名留空时默认复用本次 redeem 的 `loginId`
- `MOCK_PROMOTION_REDEMPTION_BRIDGE_TIMEOUT_MS`:桥接调用超时毫秒数(默认 `30000`);本地完整链路联调建议至少保留 `30000`
- `MOCK_PROMOTION_REDEMPTION_INITIATE_SOURCE`:桥接到 `prize-redemptions` 时写入的 `initiateSource`(默认 `PROMOTION_MODULE`)
- `MOCK_PROMOTION_REDEMPTION_SOURCE_BUCKET`:桥接到 `prize-redemptions` 时使用的 source wallet bucket(默认 `m-comp`)
- `MOCK_PROMOTION_REDEMPTION_ID_START`:mock redeemed history 的起始 `redemptionId`;留空时默认用进程启动时的 Unix 秒级时间戳作为 seed,且会限制在 Backend `int` 可解析范围内,避免 Mock_Gateway 重启后重复复用旧 `redemptionId`
- `MOCK_REDEEMEDPROMOTION_VOID_ERROR_CODE` / `MOCK_REDEEMEDPROMOTION_VOID_ERROR_MSG` / `MOCK_REDEEMEDPROMOTION_VOID_RESULT`:`redeemedpromotion/void` 返回控制
- `MOCK_PRIZE_REDEMPTIONS_SYNC_SUCCESS` / `MOCK_PRIZE_REDEMPTIONS_SYNC_MESSAGE`:`/api/v1/prize-redemptions/sync` 返回控制
- `MOCK_LDAP_ENABLED`:是否启用 LDAP mock(默认 `true`)
- `MOCK_LDAP_HOST`:LDAP 监听地址(默认 `0.0.0.0`)
- `MOCK_LDAP_PORT`:LDAP 监听端口(默认 `1389`)
- `MOCK_LDAP_BASE_DN`:LDAP 基础 DN(默认 `dc=macausjm-glp,dc=com`)
- `MOCK_LDAP_MANAGER_DN`:manager bind DN(默认 `cn=s-cicd-app,OU=ServiceAccount,dc=macausjm-glp,dc=com`)
- `MOCK_LDAP_GROUP_BASE_DN`:组搜索 base(默认 `OU=SecurityGroups,OU=GLPUsers,dc=macausjm-glp,dc=com`)
- `MOCK_LDAP_ALLOW_ANY_USER_MODE`:任意用户名/密码放行模式(默认 `true`)
- `MOCK_LDAP_ALLOW_ANY_USER_OU`:动态用户 DN 的 OU 段(默认 `OU=GLPUsers`)
- `MOCK_LDAP_ALLOW_ANY_USER_GROUP_CN`:动态用户默认组名(默认 `SG-APP-EWALLET-SUPER-ADMIN`)
- `MOCK_LDAP_ALLOW_ANY_USER_MAIL_DOMAIN`:动态用户邮箱域名(默认 `macausjm-glp.com`)
- `MOCK_LDAP_MANAGER_PASSWORD`:manager bind 密码;留空时允许任意密码(便于仅改 `LDAP_URL` 联调)
- `MOCK_LDAP_DEFAULT_USER_*`:默认单用户 mock 配置
- `MOCK_LDAP_USERS_JSON`:JSON 数组,多用户覆盖配置
## Task 10766 复现场景
打开 `.env`,加入或覆盖以下配置:
```bash
MOCK_TASK_10766_ENABLED=true
MOCK_TASK_10766_ACCOUNT_NUM=80010766
MOCK_TASK_10766_PROMOTION_CAPTURE_FILE=./fixtures/promotions.capture.10766.json
MOCK_TASK_10766_MEMBER_EBONUS=8888
MOCK_TASK_10766_REDEEM_ERROR_CODE=EWALLET_HTTP_ERROR
MOCK_TASK_10766_REDEEM_ERROR_MSG=ewallet connection failed: 404 NOT_FOUND, {"success":false,"message":"Prize definition not found"}
MOCK_TASK_10766_REDEEM_RESULT=false
```
复现方式:
1. 启动 `Mock_Gateway`
2. 前后端联调继续指向本地 mock 网关
3. 在 `Wallet` 页面搜索会员 `80010766`
4. 切到 `Promotion`
5. 搜索 `cny`
6. 选择 `CNY Gift Set Earn & Get-2026 / GS-8pts-LCH Gift Set Abalone + Scallop`
7. 点击 `Redeem` 并完成确认
预期:
- 会员资料接口返回 `eBonus=8888`
- promotion 列表固定返回 Task 10766 专用 fixture
- `POST /ewl/promotion/v1/playerpromotion/redeem` 固定返回 `Prize definition not found` 场景
- 可稳定复现 10766 对应的 promotion redeem 失败明细展示问题
## Task 10852 复现场景
打开 `.env`,加入或覆盖以下配置:
```bash
MOCK_TASK_10852_ENABLED=true
MOCK_TASK_10852_ACCOUNT_NUM=80010852
MOCK_TASK_10852_PROMOTION_CAPTURE_FILE=./fixtures/promotions.capture.10852.json
MOCK_TASK_10852_MEMBER_EBONUS=188
```
复现方式:
1. 启动 `Mock_Gateway`
2. 前后端联调继续指向本地 mock 网关
3. 在 `Wallet` 页面搜索会员 `80010852`
4. 切到 `Promotion`
5. 搜索 `cny`
6. 选择 `CNY Gift Set Earn & Get-2026`
7. 勾选两个 outcome 后继续兑换流程
预期:
- 会员资料接口返回 `eBonus=188`
- `POST /ewl/promotion/v1/promotion/all` 固定返回可点击的 entitled 双 outcome promotion
- 前端会稳定走到 `targetPrizes` 多项场景,便于验证 10852 的最小修复
## 按会员号自动注入 Promotion Fixture
除了现有的 Task 10766 / 10852 专用开关外,`Mock_Gateway` 现在还支持按会员号自动加载 fixture:
- 文件命名:`fixtures/promotions.capture.<customerId>.json`
- 命中规则:当 `/ewl/promotion/v1/promotion/all` 的 `accountNum` 与文件名中的会员号一致时,自动返回该 fixture
- backdate 文件命名:`fixtures/promotions.backdate.<customerId>.json`
- backdate 命中规则:当 `/ewl/promotion/v1/promotion/backdate/all` 的 `accountNum` 与文件名中的会员号一致时,自动返回该 fixture
- 优先级:Task 10766 / 10852 专用场景优先,其次才是按会员号自动加载的 fixture
示例:
- `fixtures/promotions.capture.800038008.json`
- `fixtures/promotions.capture.80010852.json`
- `fixtures/promotions.backdate.800038008.json`
适用场景:
- 需要保留某个会员的真实采样 promotion 规则
- 想快速补充新的 `minOutcome / maxOutcome / outcomeList / prize` 组合
- 不希望影响默认共享 mock 数据
## 使用本地测试开发网关的时候可以使用以下会员号
按 `Mock_Gateway` 当前代码中的“定向逻辑 / 定向 fixture / 固定路由”统计,特别会员号共有 `5` 个(不含默认模板/示例号):
1. `800038008` - backdate 固定会员号。
`/ewl/promotion/v1/promotion/entitledBackDate` 和 `/ewl/promotion/v1/promotion/entitledBackDate/all` 会固定返回这个会员号的 backdate promotion;仓库里也有它的普通 promotion fixture 和 backdate fixture。
2. `80010766` - Task 10766 专用复现号。
开启 `MOCK_TASK_10766_ENABLED=true` 后,会员资料固定返回 `eBonus=8888`,promotion 列表走专用 fixture,`playerpromotion/redeem` 固定复现 `Prize definition not found` 失败场景。
3. `80010852` - Task 10852 专用复现号。
开启 `MOCK_TASK_10852_ENABLED=true` 后,会员资料固定返回 `eBonus=188`,promotion 列表走专用 fixture,并强制提供可点击的 entitled 双 outcome 场景,用于验证多 outcome redeem。
4. `80010991` - 完整链路 / 同 outcome 切换场景号。
命中专用 `promotions.capture.80010991.json`,内含单 outcome reprint chain 和 3-outcome `USER_CHOICE` promotion;也用于 runtime fulfillment override,方便在 UI 上反复验证同一个 outcome 的 `Open Item / Auto Settle` 切换。
5. `100000059` - redeemed promotion detail 专用号。
命中 `award.promotions.100000059.json`,用于 `redeemedpromotion/detail` 返回账户级已兑 promotion 明细。
以下号码也出现在 `Mock_Gateway` 中,但更适合视为默认模板 / 示例数据,不计入上面的“特别会员号”:
1. `800048718` - 默认 promotion 抓包模板来源。
没有专属定向逻辑,未命中其他专用场景时,普通账号会回落到这份默认 promotion fixture。
2. `800049052` - 默认 redeemed promotions 示例号。
只在 `redeemedpromotion/detail` 没传账号且没有账户级记录时,作为默认示例数据中的 `customerId` 出现。
800048718 老会员----换新账号----910700001
BIN
View File
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
{
"name": "ewallet-mock-gateway",
"version": "0.1.0",
"private": true,
"description": "Local mock gateway for eWallet external Bally/EDIP APIs",
"main": "src/server.js",
"engines": {
"node": ">=18"
},
"scripts": {
"start": "node src/server.js",
"dev": "node --watch --watch-preserve-output --watch-path=src --watch-path=.env src/server.js",
"test": "node --test tests/*.test.js"
},
"dependencies": {
"dotenv": "^16.4.7",
"express": "^4.21.2",
"ldapjs": "^3.0.7"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
+665
View File
@@ -0,0 +1,665 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@ldapjs/asn1@^1.2.0":
"integrity" "sha512-KX/qQJ2xxzvO2/WOvr1UdQ+8P5dVvuOLk/C9b1bIkXxZss8BaR28njXdPgFCpj5aHaf1t8PmuVnea+N9YG9YMw=="
"resolved" "https://registry.npmmirror.com/@ldapjs/asn1/-/asn1-1.2.0.tgz"
"version" "1.2.0"
"@ldapjs/asn1@^2.0.0", "@ldapjs/asn1@2.0.0":
"integrity" "sha512-G9+DkEOirNgdPmD0I8nu57ygQJKOOgFEMKknEuQvIHbGLwP3ny1mY+OTUYLCbCaGJP4sox5eYgBJRuSUpnAddA=="
"resolved" "https://registry.npmmirror.com/@ldapjs/asn1/-/asn1-2.0.0.tgz"
"version" "2.0.0"
"@ldapjs/attribute@^1.0.0", "@ldapjs/attribute@1.0.0":
"integrity" "sha512-ptMl2d/5xJ0q+RgmnqOi3Zgwk/TMJYG7dYMC0Keko+yZU6n+oFM59MjQOUht5pxJeS4FWrImhu/LebX24vJNRQ=="
"resolved" "https://registry.npmmirror.com/@ldapjs/attribute/-/attribute-1.0.0.tgz"
"version" "1.0.0"
dependencies:
"@ldapjs/asn1" "2.0.0"
"@ldapjs/protocol" "^1.2.1"
"process-warning" "^2.1.0"
"@ldapjs/change@^1.0.0":
"integrity" "sha512-EOQNFH1RIku3M1s0OAJOzGfAohuFYXFY4s73wOhRm4KFGhmQQ7MChOh2YtYu9Kwgvuq1B0xKciXVzHCGkB5V+Q=="
"resolved" "https://registry.npmmirror.com/@ldapjs/change/-/change-1.0.0.tgz"
"version" "1.0.0"
dependencies:
"@ldapjs/asn1" "2.0.0"
"@ldapjs/attribute" "1.0.0"
"@ldapjs/controls@^2.1.0":
"integrity" "sha512-2pFdD1yRC9V9hXfAWvCCO2RRWK9OdIEcJIos/9cCVP9O4k72BY1bLDQQ4KpUoJnl4y/JoD4iFgM+YWT3IfITWw=="
"resolved" "https://registry.npmmirror.com/@ldapjs/controls/-/controls-2.1.0.tgz"
"version" "2.1.0"
dependencies:
"@ldapjs/asn1" "^1.2.0"
"@ldapjs/protocol" "^1.2.1"
"@ldapjs/dn@^1.1.0":
"integrity" "sha512-R72zH5ZeBj/Fujf/yBu78YzpJjJXG46YHFo5E4W1EqfNpo1UsVPqdLrRMXeKIsJT3x9dJVIfR6OpzgINlKpi0A=="
"resolved" "https://registry.npmmirror.com/@ldapjs/dn/-/dn-1.1.0.tgz"
"version" "1.1.0"
dependencies:
"@ldapjs/asn1" "2.0.0"
"process-warning" "^2.1.0"
"@ldapjs/filter@^2.1.1":
"integrity" "sha512-TwPK5eEgNdUO1ABPBUQabcZ+h9heDORE4V9WNZqCtYLKc06+6+UAJ3IAbr0L0bYTnkkWC/JEQD2F+zAFsuikNw=="
"resolved" "https://registry.npmmirror.com/@ldapjs/filter/-/filter-2.1.1.tgz"
"version" "2.1.1"
dependencies:
"@ldapjs/asn1" "2.0.0"
"@ldapjs/protocol" "^1.2.1"
"process-warning" "^2.1.0"
"@ldapjs/messages@^1.3.0":
"integrity" "sha512-K7xZpXJ21bj92jS35wtRbdcNrwmxAtPwy4myeh9duy/eR3xQKvikVycbdWVzkYEAVE5Ce520VXNOwCHjomjCZw=="
"resolved" "https://registry.npmmirror.com/@ldapjs/messages/-/messages-1.3.0.tgz"
"version" "1.3.0"
dependencies:
"@ldapjs/asn1" "^2.0.0"
"@ldapjs/attribute" "^1.0.0"
"@ldapjs/change" "^1.0.0"
"@ldapjs/controls" "^2.1.0"
"@ldapjs/dn" "^1.1.0"
"@ldapjs/filter" "^2.1.1"
"@ldapjs/protocol" "^1.2.1"
"process-warning" "^2.2.0"
"@ldapjs/protocol@^1.2.1":
"integrity" "sha512-O89xFDLW2gBoZWNXuXpBSM32/KealKCTb3JGtJdtUQc7RjAk8XzrRgyz02cPAwGKwKPxy0ivuC7UP9bmN87egQ=="
"resolved" "https://registry.npmmirror.com/@ldapjs/protocol/-/protocol-1.2.1.tgz"
"version" "1.2.1"
"abstract-logging@^2.0.1":
"integrity" "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA=="
"resolved" "https://registry.npmmirror.com/abstract-logging/-/abstract-logging-2.0.1.tgz"
"version" "2.0.1"
"accepts@~1.3.8":
"integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="
"resolved" "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz"
"version" "1.3.8"
dependencies:
"mime-types" "~2.1.34"
"negotiator" "0.6.3"
"array-flatten@1.1.1":
"integrity" "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
"resolved" "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz"
"version" "1.1.1"
"assert-plus@^1.0.0":
"integrity" "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="
"resolved" "https://registry.npmmirror.com/assert-plus/-/assert-plus-1.0.0.tgz"
"version" "1.0.0"
"backoff@^2.5.0":
"integrity" "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA=="
"resolved" "https://registry.npmmirror.com/backoff/-/backoff-2.5.0.tgz"
"version" "2.5.0"
dependencies:
"precond" "0.2"
"body-parser@~1.20.3":
"integrity" "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="
"resolved" "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.4.tgz"
"version" "1.20.4"
dependencies:
"bytes" "~3.1.2"
"content-type" "~1.0.5"
"debug" "2.6.9"
"depd" "2.0.0"
"destroy" "~1.2.0"
"http-errors" "~2.0.1"
"iconv-lite" "~0.4.24"
"on-finished" "~2.4.1"
"qs" "~6.14.0"
"raw-body" "~2.5.3"
"type-is" "~1.6.18"
"unpipe" "~1.0.0"
"bytes@~3.1.2":
"integrity" "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
"resolved" "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz"
"version" "3.1.2"
"call-bind-apply-helpers@^1.0.1", "call-bind-apply-helpers@^1.0.2":
"integrity" "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="
"resolved" "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz"
"version" "1.0.2"
dependencies:
"es-errors" "^1.3.0"
"function-bind" "^1.1.2"
"call-bound@^1.0.2":
"integrity" "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="
"resolved" "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz"
"version" "1.0.4"
dependencies:
"call-bind-apply-helpers" "^1.0.2"
"get-intrinsic" "^1.3.0"
"content-disposition@~0.5.4":
"integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="
"resolved" "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz"
"version" "0.5.4"
dependencies:
"safe-buffer" "5.2.1"
"content-type@~1.0.4", "content-type@~1.0.5":
"integrity" "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
"resolved" "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz"
"version" "1.0.5"
"cookie-signature@~1.0.6":
"integrity" "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="
"resolved" "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.7.tgz"
"version" "1.0.7"
"cookie@~0.7.1":
"integrity" "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="
"resolved" "https://registry.npmmirror.com/cookie/-/cookie-0.7.2.tgz"
"version" "0.7.2"
"core-util-is@1.0.2":
"integrity" "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
"resolved" "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.2.tgz"
"version" "1.0.2"
"debug@2.6.9":
"integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="
"resolved" "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz"
"version" "2.6.9"
dependencies:
"ms" "2.0.0"
"depd@~2.0.0", "depd@2.0.0":
"integrity" "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
"resolved" "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz"
"version" "2.0.0"
"destroy@~1.2.0", "destroy@1.2.0":
"integrity" "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
"resolved" "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz"
"version" "1.2.0"
"dotenv@^16.4.7":
"integrity" "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="
"resolved" "https://registry.npmmirror.com/dotenv/-/dotenv-16.6.1.tgz"
"version" "16.6.1"
"dunder-proto@^1.0.1":
"integrity" "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="
"resolved" "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz"
"version" "1.0.1"
dependencies:
"call-bind-apply-helpers" "^1.0.1"
"es-errors" "^1.3.0"
"gopd" "^1.2.0"
"ee-first@1.1.1":
"integrity" "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
"resolved" "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz"
"version" "1.1.1"
"encodeurl@~2.0.0":
"integrity" "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="
"resolved" "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz"
"version" "2.0.0"
"es-define-property@^1.0.1":
"integrity" "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
"resolved" "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz"
"version" "1.0.1"
"es-errors@^1.3.0":
"integrity" "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
"resolved" "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz"
"version" "1.3.0"
"es-object-atoms@^1.0.0", "es-object-atoms@^1.1.1":
"integrity" "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="
"resolved" "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz"
"version" "1.1.1"
dependencies:
"es-errors" "^1.3.0"
"escape-html@~1.0.3":
"integrity" "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
"resolved" "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz"
"version" "1.0.3"
"etag@~1.8.1":
"integrity" "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
"resolved" "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz"
"version" "1.8.1"
"express@^4.21.2":
"integrity" "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="
"resolved" "https://registry.npmmirror.com/express/-/express-4.22.1.tgz"
"version" "4.22.1"
dependencies:
"accepts" "~1.3.8"
"array-flatten" "1.1.1"
"body-parser" "~1.20.3"
"content-disposition" "~0.5.4"
"content-type" "~1.0.4"
"cookie" "~0.7.1"
"cookie-signature" "~1.0.6"
"debug" "2.6.9"
"depd" "2.0.0"
"encodeurl" "~2.0.0"
"escape-html" "~1.0.3"
"etag" "~1.8.1"
"finalhandler" "~1.3.1"
"fresh" "~0.5.2"
"http-errors" "~2.0.0"
"merge-descriptors" "1.0.3"
"methods" "~1.1.2"
"on-finished" "~2.4.1"
"parseurl" "~1.3.3"
"path-to-regexp" "~0.1.12"
"proxy-addr" "~2.0.7"
"qs" "~6.14.0"
"range-parser" "~1.2.1"
"safe-buffer" "5.2.1"
"send" "~0.19.0"
"serve-static" "~1.16.2"
"setprototypeof" "1.2.0"
"statuses" "~2.0.1"
"type-is" "~1.6.18"
"utils-merge" "1.0.1"
"vary" "~1.1.2"
"extsprintf@^1.2.0":
"integrity" "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA=="
"resolved" "https://registry.npmmirror.com/extsprintf/-/extsprintf-1.4.1.tgz"
"version" "1.4.1"
"finalhandler@~1.3.1":
"integrity" "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="
"resolved" "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.3.2.tgz"
"version" "1.3.2"
dependencies:
"debug" "2.6.9"
"encodeurl" "~2.0.0"
"escape-html" "~1.0.3"
"on-finished" "~2.4.1"
"parseurl" "~1.3.3"
"statuses" "~2.0.2"
"unpipe" "~1.0.0"
"forwarded@0.2.0":
"integrity" "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
"resolved" "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz"
"version" "0.2.0"
"fresh@~0.5.2":
"integrity" "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
"resolved" "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz"
"version" "0.5.2"
"function-bind@^1.1.2":
"integrity" "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
"resolved" "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz"
"version" "1.1.2"
"get-intrinsic@^1.2.5", "get-intrinsic@^1.3.0":
"integrity" "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="
"resolved" "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz"
"version" "1.3.0"
dependencies:
"call-bind-apply-helpers" "^1.0.2"
"es-define-property" "^1.0.1"
"es-errors" "^1.3.0"
"es-object-atoms" "^1.1.1"
"function-bind" "^1.1.2"
"get-proto" "^1.0.1"
"gopd" "^1.2.0"
"has-symbols" "^1.1.0"
"hasown" "^2.0.2"
"math-intrinsics" "^1.1.0"
"get-proto@^1.0.1":
"integrity" "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="
"resolved" "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz"
"version" "1.0.1"
dependencies:
"dunder-proto" "^1.0.1"
"es-object-atoms" "^1.0.0"
"gopd@^1.2.0":
"integrity" "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="
"resolved" "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz"
"version" "1.2.0"
"has-symbols@^1.1.0":
"integrity" "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
"resolved" "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz"
"version" "1.1.0"
"hasown@^2.0.2":
"integrity" "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="
"resolved" "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz"
"version" "2.0.2"
dependencies:
"function-bind" "^1.1.2"
"http-errors@~2.0.0", "http-errors@~2.0.1":
"integrity" "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="
"resolved" "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.1.tgz"
"version" "2.0.1"
dependencies:
"depd" "~2.0.0"
"inherits" "~2.0.4"
"setprototypeof" "~1.2.0"
"statuses" "~2.0.2"
"toidentifier" "~1.0.1"
"iconv-lite@~0.4.24":
"integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="
"resolved" "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz"
"version" "0.4.24"
dependencies:
"safer-buffer" ">= 2.1.2 < 3"
"inherits@~2.0.4":
"integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
"resolved" "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz"
"version" "2.0.4"
"ipaddr.js@1.9.1":
"integrity" "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
"resolved" "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz"
"version" "1.9.1"
"ldapjs@^3.0.7":
"integrity" "sha512-1ky+WrN+4CFMuoekUOv7Y1037XWdjKpu0xAPwSP+9KdvmV9PG+qOKlssDV6a+U32apwxdD3is/BZcWOYzN30cg=="
"resolved" "https://registry.npmmirror.com/ldapjs/-/ldapjs-3.0.7.tgz"
"version" "3.0.7"
dependencies:
"@ldapjs/asn1" "^2.0.0"
"@ldapjs/attribute" "^1.0.0"
"@ldapjs/change" "^1.0.0"
"@ldapjs/controls" "^2.1.0"
"@ldapjs/dn" "^1.1.0"
"@ldapjs/filter" "^2.1.1"
"@ldapjs/messages" "^1.3.0"
"@ldapjs/protocol" "^1.2.1"
"abstract-logging" "^2.0.1"
"assert-plus" "^1.0.0"
"backoff" "^2.5.0"
"once" "^1.4.0"
"vasync" "^2.2.1"
"verror" "^1.10.1"
"math-intrinsics@^1.1.0":
"integrity" "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
"resolved" "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz"
"version" "1.1.0"
"media-typer@0.3.0":
"integrity" "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
"resolved" "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz"
"version" "0.3.0"
"merge-descriptors@1.0.3":
"integrity" "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="
"resolved" "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz"
"version" "1.0.3"
"methods@~1.1.2":
"integrity" "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
"resolved" "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz"
"version" "1.1.2"
"mime-db@1.52.0":
"integrity" "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
"resolved" "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz"
"version" "1.52.0"
"mime-types@~2.1.24", "mime-types@~2.1.34":
"integrity" "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="
"resolved" "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz"
"version" "2.1.35"
dependencies:
"mime-db" "1.52.0"
"mime@1.6.0":
"integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
"resolved" "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz"
"version" "1.6.0"
"ms@2.0.0":
"integrity" "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
"resolved" "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz"
"version" "2.0.0"
"ms@2.1.3":
"integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
"resolved" "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz"
"version" "2.1.3"
"negotiator@0.6.3":
"integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
"resolved" "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz"
"version" "0.6.3"
"object-inspect@^1.13.3":
"integrity" "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="
"resolved" "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz"
"version" "1.13.4"
"on-finished@~2.4.1":
"integrity" "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="
"resolved" "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz"
"version" "2.4.1"
dependencies:
"ee-first" "1.1.1"
"once@^1.4.0":
"integrity" "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="
"resolved" "https://registry.npmmirror.com/once/-/once-1.4.0.tgz"
"version" "1.4.0"
dependencies:
"wrappy" "1"
"parseurl@~1.3.3":
"integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
"resolved" "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz"
"version" "1.3.3"
"path-to-regexp@~0.1.12":
"integrity" "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
"resolved" "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz"
"version" "0.1.12"
"precond@0.2":
"integrity" "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ=="
"resolved" "https://registry.npmmirror.com/precond/-/precond-0.2.3.tgz"
"version" "0.2.3"
"process-warning@^2.1.0", "process-warning@^2.2.0":
"integrity" "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA=="
"resolved" "https://registry.npmmirror.com/process-warning/-/process-warning-2.3.2.tgz"
"version" "2.3.2"
"proxy-addr@~2.0.7":
"integrity" "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="
"resolved" "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz"
"version" "2.0.7"
dependencies:
"forwarded" "0.2.0"
"ipaddr.js" "1.9.1"
"qs@~6.14.0":
"integrity" "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ=="
"resolved" "https://registry.npmmirror.com/qs/-/qs-6.14.1.tgz"
"version" "6.14.1"
dependencies:
"side-channel" "^1.1.0"
"range-parser@~1.2.1":
"integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
"resolved" "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz"
"version" "1.2.1"
"raw-body@~2.5.3":
"integrity" "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="
"resolved" "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.3.tgz"
"version" "2.5.3"
dependencies:
"bytes" "~3.1.2"
"http-errors" "~2.0.1"
"iconv-lite" "~0.4.24"
"unpipe" "~1.0.0"
"safe-buffer@5.2.1":
"integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
"resolved" "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz"
"version" "5.2.1"
"safer-buffer@>= 2.1.2 < 3":
"integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
"resolved" "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz"
"version" "2.1.2"
"send@~0.19.0", "send@~0.19.1":
"integrity" "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="
"resolved" "https://registry.npmmirror.com/send/-/send-0.19.2.tgz"
"version" "0.19.2"
dependencies:
"debug" "2.6.9"
"depd" "2.0.0"
"destroy" "1.2.0"
"encodeurl" "~2.0.0"
"escape-html" "~1.0.3"
"etag" "~1.8.1"
"fresh" "~0.5.2"
"http-errors" "~2.0.1"
"mime" "1.6.0"
"ms" "2.1.3"
"on-finished" "~2.4.1"
"range-parser" "~1.2.1"
"statuses" "~2.0.2"
"serve-static@~1.16.2":
"integrity" "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="
"resolved" "https://registry.npmmirror.com/serve-static/-/serve-static-1.16.3.tgz"
"version" "1.16.3"
dependencies:
"encodeurl" "~2.0.0"
"escape-html" "~1.0.3"
"parseurl" "~1.3.3"
"send" "~0.19.1"
"setprototypeof@~1.2.0", "setprototypeof@1.2.0":
"integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
"resolved" "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz"
"version" "1.2.0"
"side-channel-list@^1.0.0":
"integrity" "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="
"resolved" "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz"
"version" "1.0.0"
dependencies:
"es-errors" "^1.3.0"
"object-inspect" "^1.13.3"
"side-channel-map@^1.0.1":
"integrity" "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="
"resolved" "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz"
"version" "1.0.1"
dependencies:
"call-bound" "^1.0.2"
"es-errors" "^1.3.0"
"get-intrinsic" "^1.2.5"
"object-inspect" "^1.13.3"
"side-channel-weakmap@^1.0.2":
"integrity" "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="
"resolved" "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz"
"version" "1.0.2"
dependencies:
"call-bound" "^1.0.2"
"es-errors" "^1.3.0"
"get-intrinsic" "^1.2.5"
"object-inspect" "^1.13.3"
"side-channel-map" "^1.0.1"
"side-channel@^1.1.0":
"integrity" "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="
"resolved" "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz"
"version" "1.1.0"
dependencies:
"es-errors" "^1.3.0"
"object-inspect" "^1.13.3"
"side-channel-list" "^1.0.0"
"side-channel-map" "^1.0.1"
"side-channel-weakmap" "^1.0.2"
"statuses@~2.0.1", "statuses@~2.0.2":
"integrity" "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="
"resolved" "https://registry.npmmirror.com/statuses/-/statuses-2.0.2.tgz"
"version" "2.0.2"
"toidentifier@~1.0.1":
"integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
"resolved" "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz"
"version" "1.0.1"
"type-is@~1.6.18":
"integrity" "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="
"resolved" "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz"
"version" "1.6.18"
dependencies:
"media-typer" "0.3.0"
"mime-types" "~2.1.24"
"unpipe@~1.0.0":
"integrity" "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
"resolved" "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz"
"version" "1.0.0"
"utils-merge@1.0.1":
"integrity" "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
"resolved" "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz"
"version" "1.0.1"
"vary@~1.1.2":
"integrity" "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
"resolved" "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz"
"version" "1.1.2"
"vasync@^2.2.1":
"integrity" "sha512-Hq72JaTpcTFdWiNA4Y22Amej2GH3BFmBaKPPlDZ4/oC8HNn2ISHLkFrJU4Ds8R3jcUi7oo5Y9jcMHKjES+N9wQ=="
"resolved" "https://registry.npmmirror.com/vasync/-/vasync-2.2.1.tgz"
"version" "2.2.1"
dependencies:
"verror" "1.10.0"
"verror@^1.10.1":
"integrity" "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg=="
"resolved" "https://registry.npmmirror.com/verror/-/verror-1.10.1.tgz"
"version" "1.10.1"
dependencies:
"assert-plus" "^1.0.0"
"core-util-is" "1.0.2"
"extsprintf" "^1.2.0"
"verror@1.10.0":
"integrity" "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw=="
"resolved" "https://registry.npmmirror.com/verror/-/verror-1.10.0.tgz"
"version" "1.10.0"
dependencies:
"assert-plus" "^1.0.0"
"core-util-is" "1.0.2"
"extsprintf" "^1.2.0"
"wrappy@1":
"integrity" "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
"resolved" "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz"
"version" "1.0.2"