This commit is contained in:
18631081161 2026-02-28 17:35:49 +08:00
commit 7e08a12d29
13239 changed files with 1379101 additions and 0 deletions

View File

@ -0,0 +1 @@
{"generationMode": "requirements-first"}

View File

@ -0,0 +1,668 @@
# 设计文档:黄岩停车积分兑换
## 概述
本系统是一个基于微信小程序的停车积分兑换平台,包含三个主要部分:
1. **微信小程序前端**:基于 uni-app (Vue 3) 开发,包含用户端和商户端
2. **后台API服务**:基于 .NET 10 (ASP.NET Core Web API) 开发提供RESTful API
3. **管理后台**:基于 Vue 3 + Element Plus 开发的Web管理系统
核心业务流程:用户通过特来电充电桩充电 → 系统接收充电订单推送 → 按规则计算积分 → 用户用积分兑换洗车优惠券 → 在门店使用优惠券(平台券扫码核销/驿公里券跳转使用)。
## 架构
### 整体架构
```mermaid
graph TB
subgraph 客户端
MP[微信小程序<br/>uni-app Vue3]
ADMIN[管理后台<br/>Vue3 + Element Plus]
end
subgraph 后台服务
API[API服务<br/>.NET 10 ASP.NET Core]
DB[(MySQL数据库)]
REDIS[(Redis缓存)]
end
subgraph 第三方服务
TLD[特来电API]
YGL[驿公里API]
WX[微信开放平台]
end
MP -->|HTTP/HTTPS| API
ADMIN -->|HTTP/HTTPS| API
API --> DB
API --> REDIS
API -->|AES-128-CBC + HMAC-MD5| TLD
API -->|DES + RSA| YGL
API -->|微信登录/手机号| WX
TLD -->|充电订单推送| API
YGL -->|核销/退回回调| API
```
### 小程序页面架构
```mermaid
graph LR
subgraph TabBar
HOME[首页]
POINTS[积分页]
MINE[我的页]
end
HOME --> STORE_COUPONS[门店可用优惠券页]
STORE_COUPONS --> QR_POPUP[二维码弹窗]
POINTS --> POINTS_DETAIL[积分明细页]
POINTS --> EXCHANGE[兑换流程]
MINE --> LOGIN[登录页]
MINE --> PROFILE[个人资料页]
MINE --> MY_COUPONS[我的优惠券页]
MINE --> VERIFY_RECORDS[核销记录页]
MINE --> AGREEMENT[用户协议/隐私政策页]
LOGIN --> ROLE_SELECT[身份选择页]
ROLE_SELECT --> STORE_PAGE[门店管理页-商户端]
STORE_PAGE --> SCAN[扫码核销]
STORE_PAGE --> CODE_VERIFY[券码核销]
STORE_PAGE --> STORE_RECORDS[商户核销记录页]
```
## 组件与接口
### 小程序前端组件
#### 页面组件
| 页面 | 路径 | 说明 |
|------|------|------|
| 首页 | pages/home/index | Banner、门店列表、弹窗入口 |
| 积分页 | pages/points/index | 积分余额、可兑换券列表 |
| 积分明细页 | pages/points/detail | 积分收支明细 |
| 我的页 | pages/mine/index | 个人信息、功能入口 |
| 登录页 | pages/login/index | 微信手机号登录 |
| 身份选择页 | pages/login/role-select | 商户/用户身份选择 |
| 个人资料页 | pages/mine/profile | 头像、昵称编辑 |
| 我的优惠券页 | pages/coupon/my-coupons | 券列表、筛选 |
| 门店可用优惠券页 | pages/coupon/store-coupons | 门店可用券 |
| 核销记录页 | pages/mine/verify-records | 用户核销记录 |
| 用户协议页 | pages/mine/agreement | 协议/隐私政策内容 |
| 门店管理页 | pages/merchant/index | 商户扫码/券码核销 |
| 商户核销记录页 | pages/merchant/records | 商户核销记录 |
#### 公共组件
| 组件 | 说明 |
|------|------|
| CouponCard | 优惠券卡片,支持平台券和驿公里券两种样式 |
| QrcodePopup | 优惠券二维码弹窗 |
| ConfirmDialog | 通用二次确认弹窗 |
| StoreCard | 门店信息卡片 |
| FilterBar | 筛选栏(门店/类型/状态) |
| PointsBadge | 积分余额展示组件 |
| RichContentPopup | 富文本内容弹窗(核销流程/积分说明) |
#### 工具模块
| 模块 | 路径 | 说明 |
|------|------|------|
| request | utils/request.js | 封装uni.request统一处理token、错误 |
| auth | utils/auth.js | 登录状态管理、token存储 |
### 后台API接口设计.NET 8 ASP.NET Core Web API
#### 认证相关
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/auth/login | 微信手机号登录 |
| POST | /api/auth/logout | 退出登录 |
| GET | /api/auth/check-merchant | 检查是否为商户员工 |
#### 用户相关
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/user/profile | 获取用户信息 |
| PUT | /api/user/profile | 更新用户信息(头像、昵称) |
#### 积分相关
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/points/balance | 获取积分余额 |
| GET | /api/points/records | 获取积分明细支持type/storeId筛选 |
#### 优惠券相关
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/coupons/available | 获取可兑换优惠券列表 |
| POST | /api/coupons/exchange | 兑换优惠券 |
| GET | /api/coupons/my | 获取我的优惠券支持status/storeId/type筛选 |
| GET | /api/coupons/store/:storeId | 获取门店可用优惠券 |
#### 核销相关
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/verify/scan | 扫码核销 |
| POST | /api/verify/code | 券码核销 |
| GET | /api/verify/records | 获取核销记录(用户端) |
| GET | /api/verify/merchant-records | 获取核销记录(商户端) |
#### 门店相关
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/stores | 获取门店列表 |
| GET | /api/stores/:id | 获取门店详情 |
#### 配置相关
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/config/banners | 获取Banner列表 |
| GET | /api/config/popups/:type | 获取弹窗内容verify-flow/points-desc |
| GET | /api/config/agreement/:type | 获取协议内容user-agreement/privacy-policy |
#### 第三方回调
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/callback/tld/charge-order | 特来电充电订单推送回调 |
| POST | /api/callback/ygl/verify | 驿公里优惠券核销回调 |
| POST | /api/callback/ygl/refund | 驿公里优惠券退回回调 |
#### 管理后台API
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/admin/login | 管理员登录 |
| GET/POST/PUT/DELETE | /api/admin/banners | Banner CRUD |
| GET/PUT | /api/admin/popups/:type | 弹窗内容管理 |
| GET/POST/PUT/DELETE | /api/admin/stores | 门店 CRUD |
| GET/POST/DELETE | /api/admin/merchants | 商户员工管理 |
| GET/POST/PUT/DELETE | /api/admin/coupon-templates | 优惠券模板 CRUD |
| GET | /api/admin/coupons | 优惠券发放记录 |
| GET | /api/admin/verify-records | 核销记录 |
| GET | /api/admin/users | 用户列表 |
| GET/PUT | /api/admin/points-rule | 积分规则配置 |
| GET/PUT | /api/admin/agreements/:type | 协议内容管理 |
| GET | /api/admin/dashboard | 数据统计概览 |
### 第三方API对接模块
#### 特来电对接模块 (Services/TldService.cs)
```csharp
/// <summary>
/// 特来电API对接服务
/// </summary>
public class TldService : ITldService
{
/// <summary>平台认证获取Token</summary>
Task<TokenResult> QueryTokenAsync(string operatorId, string operatorSecret);
/// <summary>处理充电订单推送</summary>
Task<ChargeOrderResult> HandleChargeOrderAsync(EncryptedRequest request);
/// <summary>AES-128-CBC 加密</summary>
string Encrypt(string data, string dataSecret, string dataSecretIV);
/// <summary>AES-128-CBC 解密</summary>
string Decrypt(string encryptedData, string dataSecret, string dataSecretIV);
/// <summary>HMAC-MD5 签名</summary>
string Sign(string operatorId, string data, string timestamp, string seq, string sigSecret);
/// <summary>HMAC-MD5 验签</summary>
bool Verify(string operatorId, string data, string timestamp, string seq, string sig, string sigSecret);
}
```
#### 驿公里对接模块 (Services/YglService.cs)
```csharp
/// <summary>
/// 驿公里API对接服务
/// </summary>
public class YglService : IYglService
{
/// <summary>查询优惠券包信息</summary>
Task<TicketPackageInfo> GetTicketPackageInfoAsync(string ticketPackageCode, string mobile);
/// <summary>发放优惠券</summary>
Task<GenerateTicketResult> GenerateTicketAsync(string ticketPackageCode, string mobile, string orderId, AmountInfo amount);
/// <summary>取消优惠券</summary>
Task<CancelTicketResult> CancelTicketAsync(string ticketPackageCode, string orderId, string refundReason, List<string> ticketIds);
/// <summary>处理核销回调</summary>
Task HandleVerifyCallbackAsync(YglVerifyCallback data);
/// <summary>处理退回回调</summary>
Task HandleRefundCallbackAsync(YglRefundCallback data);
/// <summary>DES 加密</summary>
string EncryptDes(string data, string desKey);
/// <summary>DES 解密</summary>
string DecryptDes(string encryptedData, string desKey);
/// <summary>RSA 签名</summary>
string SignRsa(string data, string privateKey);
/// <summary>RSA 验签</summary>
bool VerifyRsa(string data, string publicKey, string sign);
/// <summary>封装请求数据(加密+签名)</summary>
DataBean BuildRequest(object bodyJson, string desKey, string privateKey, string devId);
/// <summary>解析响应数据(解密+验签)</summary>
string ParseResponse(string responseData, string desKey, string publicKey);
}
```
## 数据模型
### 数据库表设计
```mermaid
erDiagram
users {
int id PK
varchar uid "6位随机数字不以0开头"
varchar phone "手机号,唯一"
varchar nickname "昵称"
varchar avatar "头像URL"
varchar openid "微信openid"
int points "当前积分余额"
boolean is_merchant "是否为商户员工"
int store_id FK "关联门店(商户员工)"
datetime created_at
datetime updated_at
}
stores {
int id PK
varchar name "门店名称"
varchar photo "门店照片URL"
varchar address "门店地址"
varchar phone "联系方式"
decimal latitude "纬度"
decimal longitude "经度"
enum type "human/unmanned 人工/无人"
boolean is_active "是否启用"
datetime created_at
datetime updated_at
}
coupon_templates {
int id PK
varchar name "优惠券名称"
enum coupon_type "free/discount 免费券/抵扣券"
decimal discount_amount "抵扣金额(抵扣券)"
int store_id FK "适用门店"
datetime valid_start "有效期开始"
datetime valid_end "有效期结束"
int total_count "总数量"
int remaining_count "剩余数量"
int points_cost "所需积分"
enum source "platform/ygl 平台券/驿公里券"
varchar ygl_ticket_package_code "驿公里券包码"
boolean is_active "是否启用"
datetime created_at
datetime updated_at
}
coupons {
int id PK
varchar code "券码9位随机字母+数字"
int template_id FK "优惠券模板"
int user_id FK "持有用户"
int store_id FK "适用门店"
enum status "unused/used/expired"
enum source "platform/ygl"
varchar ygl_ticket_id "驿公里优惠券ID"
varchar ygl_order_id "驿公里订单ID"
datetime exchanged_at "兑换时间"
datetime used_at "使用时间"
datetime expired_at "过期时间"
datetime created_at
}
points_records {
int id PK
int user_id FK
int amount "积分变化量(正为收入,负为支出)"
enum type "income/expense"
varchar reason "变化原因"
int coupon_id FK "关联优惠券(兑换时)"
int store_id FK "关联门店"
varchar tld_order_id "特来电订单号(充电收入时)"
datetime created_at
}
verify_records {
int id PK
int coupon_id FK
int user_id FK "用户"
int merchant_id FK "核销商户员工"
int store_id FK "核销门店"
enum verify_type "scan/code 扫码/券码"
datetime verified_at "核销时间"
}
banners {
int id PK
varchar image_url "图片URL"
int sort_order "排序"
boolean is_active "是否启用"
datetime created_at
datetime updated_at
}
popup_contents {
int id PK
enum type "verify-flow/points-desc"
text content "富文本内容"
datetime updated_at
}
agreements {
int id PK
enum type "user-agreement/privacy-policy"
text content "协议内容"
datetime updated_at
}
points_rules {
int id PK
decimal charge_amount "充电金额(元)"
int points_value "对应积分"
boolean is_active "是否启用"
datetime updated_at
}
admins {
int id PK
varchar username "管理员账号"
varchar password_hash "密码哈希"
datetime created_at
}
users ||--o{ coupons : "持有"
users ||--o{ points_records : "积分记录"
users ||--o{ verify_records : "核销记录(用户)"
stores ||--o{ coupon_templates : "适用门店"
stores ||--o{ coupons : "适用门店"
coupon_templates ||--o{ coupons : "模板生成"
coupons ||--o| verify_records : "核销"
```
### 券码生成算法
```csharp
/// <summary>
/// 生成9位随机券码
/// 规则:字母(a-z,A-Z)+数字(0-9)组成不以0开头
/// </summary>
public static string GenerateCouponCode()
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// 首位不能为0从非0字符中选取
const string firstChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789";
var random = Random.Shared;
var code = new char[9];
code[0] = firstChars[random.Next(firstChars.Length)];
for (int i = 1; i < 9; i++)
{
code[i] = chars[random.Next(chars.Length)];
}
return new string(code);
}
```
### UID生成算法
```csharp
/// <summary>
/// 生成6位随机UID
/// 规则纯数字不以0开头
/// </summary>
public static string GenerateUID()
{
var random = Random.Shared;
var uid = new char[6];
uid[0] = (char)('1' + random.Next(9)); // 1-9
for (int i = 1; i < 6; i++)
{
uid[i] = (char)('0' + random.Next(10)); // 0-9
}
return new string(uid);
}
```
## 正确性属性
*正确性属性是一种在系统所有有效执行中都应成立的特征或行为——本质上是关于系统应该做什么的形式化陈述。属性是人类可读规范与机器可验证正确性保证之间的桥梁。*
### Property 1券码格式正确性
*对于任意*生成的券码该券码长度应为9位由字母(a-z,A-Z)和数字(0-9)组成,且首字符不为数字'0'。
**Validates: Requirements 16.1, 16.2**
### Property 2券码唯一性
*对于任意*批量生成的N个券码所有券码应互不相同。
**Validates: Requirements 16.3**
### Property 3UID格式正确性
*对于任意*生成的UID该UID长度应为6位由纯数字组成且首位不为0。
**Validates: Requirements 1.3**
### Property 4特来电数据加解密 Round-Trip
*对于任意*有效的JSON数据使用AES-128-CBC加密后再解密应得到与原始数据等价的结果。
**Validates: Requirements 14.2, 14.4**
### Property 5特来电签名验签一致性
*对于任意*有效的消息数据使用HMAC-MD5签名后验签应通过对于任意被篡改的数据验签应失败。
**Validates: Requirements 14.5**
### Property 6驿公里数据加解密 Round-Trip
*对于任意*有效的JSON数据使用DES加密后再解密应得到与原始数据等价的结果使用RSA私钥签名后用公钥验签应通过。
**Validates: Requirements 15.4**
### Property 7积分计算正确性
*对于任意*充电金额和积分规则配置,按规则计算出的积分值应等于 floor(充电金额 / 规则金额) * 规则积分值。
**Validates: Requirements 14.3**
### Property 8积分兑换校验正确性
*对于任意*用户积分余额和优惠券所需积分,当余额 >= 所需积分时兑换应成功且余额减少对应值,当余额 < 所需积分时兑换应被拒绝且余额不变
**Validates: Requirements 6.2, 6.3, 6.4**
### Property 9优惠券兑换不变量
*对于任意*成功的优惠券兑换操作兑换后优惠券模板的剩余数量应减少1用户持有的该模板优惠券数量应增加1。
**Validates: Requirements 6.4**
### Property 10券码验证正确性
*对于任意*券码,如果该券码存在于系统中且对应优惠券状态为未使用且属于当前核销门店,则验证应通过;否则验证应失败并返回对应错误原因。
**Validates: Requirements 11.3, 11.5, 12.2**
### Property 11核销操作正确性
*对于任意*有效的核销操作,核销后该优惠券状态应变为已使用,且用户端查询该优惠券应反映已使用状态。
**Validates: Requirements 11.4, 11.6**
### Property 12优惠券按来源显示不同操作
*对于任意*优惠券,如果来源为平台券则应显示二维码按钮,如果来源为驿公里券则应显示使用方式说明和跳转按钮。
**Validates: Requirements 4.3, 7.4, 7.5**
### Property 13积分明细筛选正确性
*对于任意*积分记录集合和筛选条件(类型和门店),筛选后返回的每条记录应全部匹配所选类型和所选门店。
**Validates: Requirements 5.4, 5.6**
### Property 14优惠券列表筛选正确性
*对于任意*优惠券集合和筛选条件(状态、门店、类型),筛选后返回的每张优惠券应全部匹配所有筛选条件。
**Validates: Requirements 7.2, 7.3**
### Property 15门店可用优惠券筛选正确性
*对于任意*用户和门店,返回的可用优惠券应全部满足:属于该用户、属于该门店、状态为未使用。
**Validates: Requirements 4.2**
### Property 16商户身份识别正确性
*对于任意*手机号,如果该手机号在商户员工表中存在则应识别为商户员工,否则应识别为普通用户。
**Validates: Requirements 10.1**
### Property 17驿公里券兑换后状态
*对于任意*驿公里券兑换操作,兑换成功后该优惠券状态应直接标记为已使用。
**Validates: Requirements 6.6**
### Property 18驿公里回调处理正确性
*对于任意*驿公里核销回调,处理后本地优惠券状态应更新为已使用;*对于任意*驿公里退回回调,处理后应退还用户积分并更新券状态。
**Validates: Requirements 15.5, 15.6**
### Property 19用户信息更新 Round-Trip
*对于任意*有效的用户昵称和头像,更新后再查询应得到与更新值一致的结果。
**Validates: Requirements 2.3, 17.2**
### Property 20管理后台CRUD Round-Trip
*对于任意*管理后台资源Banner、门店、优惠券模板、商户员工、积分规则、弹窗内容、协议内容创建/更新后查询应得到与输入一致的结果。
**Validates: Requirements 18.2, 18.3, 18.4, 18.5, 18.6, 18.10, 18.11**
### Property 21API认证保护
*对于任意*需要认证的API请求如果缺少有效令牌或令牌已过期应返回401未授权错误。
**Validates: Requirements 17.14**
### Property 22门店列表信息完整性
*对于任意*门店数据,渲染后应包含门店照片、名称、位置、联系方式、可用优惠券数量和门店类型。
**Validates: Requirements 3.4**
### Property 23未登录路由守卫
*对于任意*需要登录的页面路径,未登录状态下访问应重定向到登录页。
**Validates: Requirements 1.1**
## 错误处理
### 网络错误
- 所有API请求统一封装在 `utils/request.js`设置请求超时时间默认10秒
- 网络异常时显示统一的错误提示("网络异常,请稍后重试"
- 关键操作(兑换、核销)失败时提供重试机制
### 认证错误
- Token过期时自动跳转登录页清除本地存储的过期Token
- 后台API使用ASP.NET Core中间件统一校验JWT Token
### 业务错误
- 积分不足兑换:返回明确的错误提示"积分不足"
- 优惠券已使用/已过期:核销时返回具体的失败原因
- 券码不存在:核销时返回"券码无效"
- 优惠券不属于当前门店:核销时返回"该优惠券不适用于本门店"
- 优惠券剩余数量为0兑换时返回"优惠券已兑完"
### 第三方API错误
- 特来电API验签失败返回签名错误响应码(4001)Token过期自动重新获取
- 驿公里API请求失败记录日志回调失败驿公里会在1小时内重试3次
- 驿公里券发放失败:回滚用户积分扣减,提示用户兑换失败
### 数据校验
- 所有API入参使用 FluentValidation 进行参数校验
- 券码格式校验9位字母+数字不以0开头
- 手机号格式校验11位数字
- 金额和积分值校验:非负整数
## 测试策略
### 测试框架选择
- **后台单元测试和属性测试**xUnit + FsCheck.NET属性测试库
- **后台API集成测试**xUnit + WebApplicationFactory
- **小程序端测试**Jest + fast-check逻辑层
### 属性测试Property-Based Testing
后台使用 `FsCheck.Xunit` 库进行属性测试,小程序端使用 `fast-check` 库。每个属性测试至少运行100次迭代。
每个属性测试必须用注释标注对应的设计文档属性编号:
```csharp
// Feature: huangyan-parking-points, Property 1: 券码格式正确性
[Property(MaxTest = 100)]
public Property CouponCode_ShouldHaveValidFormat() { ... }
```
重点属性测试覆盖:
- 券码和UID生成Property 1-3
- 加解密 Round-TripProperty 4-6
- 积分计算和兑换逻辑Property 7-9
- 核销验证逻辑Property 10-11
- 筛选逻辑Property 13-15
- CRUD Round-TripProperty 19-20
### 单元测试
单元测试聚焦于:
- 具体的示例和边界情况
- 第三方API请求构建和响应解析
- 错误处理路径
- UI组件的特定交互场景
### 集成测试
- API端到端流程测试登录→兑换→核销完整流程
- 第三方回调处理测试
- 数据库事务一致性测试

View File

@ -0,0 +1,257 @@
# 需求文档
## 简介
黄岩停车积分兑换微信小程序,用户通过特来电充电桩充电获取积分,积分可兑换洗车优惠券。优惠券分为平台自有券(扫码核销)和驿公里第三方券(跳转驿公里小程序使用)。商户端支持扫码核销和券码核销。项目基于 uni-app (Vue 3) 框架开发,目标平台为微信小程序。
## 术语表
- **小程序**:基于 uni-app (Vue 3) 开发的微信小程序客户端
- **用户**:使用小程序兑换优惠券和查看积分的普通用户
- **商户**:洗车门店的工作人员,负责核销优惠券
- **积分**:用户通过特来电充电桩充电获得的虚拟积分,可用于兑换优惠券
- **优惠券**:可用于洗车店支付抵扣的电子券,分为免费券和抵扣券
- **免费券**:使用后本次洗车免费的优惠券
- **抵扣券**:使用后可抵扣券值金额的优惠券,剩余金额用户线下支付
- **平台券**:由平台自有管理的优惠券,通过扫码或券码方式在门店核销
- **驿公里券**通过驿公里第三方API发放的优惠券需跳转驿公里小程序使用
- **券码**每张优惠券的唯一标识码9位随机字母+数字组成不以0开头
- **核销**:商户确认用户使用优惠券的操作,使优惠券状态变为已使用
- **特来电API**:特来电充电平台提供的接口,用于平台认证和充电订单推送
- **驿公里API**:驿公里洗车平台提供的接口,用于优惠券查询、发放、取消及回调
- **门店**:洗车服务门店,分为人工洗车店和无人洗车店两类
- **Banner**:首页顶部的轮播图,后台可配置内容
- **UID**用户唯一标识随机6位数字不以0开头
## 需求
### 需求 1用户认证与登录
**用户故事:** 作为用户,我希望通过微信手机号快速登录小程序,以便使用积分兑换和优惠券功能。
#### 验收标准
1. WHEN 未登录用户点击小程序中任意需要登录的功能按钮THE 小程序 SHALL 跳转至登录页面
2. WHEN 用户在登录页点击获取手机号按钮并授权THE 小程序 SHALL 通过微信手机号完成登录并跳转回原页面
3. WHEN 用户登录成功THE 小程序 SHALL 生成一个随机6位数字的UID不以0开头并关联到该用户账号
4. WHEN 用户点击退出登录按钮THE 小程序 SHALL 弹出二次确认弹窗,用户确认后清除登录状态并返回未登录界面
5. WHEN 用户取消退出登录确认弹窗THE 小程序 SHALL 关闭弹窗并保持当前登录状态
### 需求 2个人资料管理
**用户故事:** 作为用户,我希望查看和编辑个人资料,以便管理我的账户信息。
#### 验收标准
1. WHEN 用户进入个人资料页THE 小程序 SHALL 展示用户头像、昵称和UID
2. WHEN 用户点击更换头像THE 小程序 SHALL 支持获取微信头像或从相册选择头像
3. WHEN 用户修改昵称并保存THE 小程序 SHALL 更新昵称并持久化存储
4. THE 小程序 SHALL 将UID显示为不可编辑状态
### 需求 3首页展示
**用户故事:** 作为用户我希望在首页看到Banner、洗车店列表和相关说明入口以便快速了解和使用服务。
#### 验收标准
1. THE 小程序 SHALL 在首页顶部展示后台可配置的Banner轮播图
2. WHEN 用户点击核销流程按钮THE 小程序 SHALL 弹出核销流程说明弹窗(内容后台可配置)
3. WHEN 用户点击积分说明按钮THE 小程序 SHALL 弹出积分说明弹窗(内容后台可配置)
4. THE 小程序 SHALL 在首页展示洗车店列表,每个门店显示门店照片、门店名称、位置、联系方式、可用优惠券数量和门店类型(人工洗车店/无人洗车店)
5. WHEN 用户点击门店的查看优惠券按钮THE 小程序 SHALL 跳转至该门店的可用优惠券页面
6. WHEN 用户点击门店的导航按钮THE 小程序 SHALL 调用微信内置导航功能引导用户前往门店位置
### 需求 4门店可用优惠券页面
**用户故事:** 作为用户,我希望查看某个门店可用的优惠券详情,以便选择使用。
#### 验收标准
1. THE 小程序 SHALL 在门店可用优惠券页面顶部显示门店名称
2. THE 小程序 SHALL 展示用户已兑换且未使用的该门店优惠券列表,每张券显示优惠券名称、适用门店、券码、有效期和使用方式
3. WHEN 该优惠券为平台券时THE 小程序 SHALL 显示二维码按钮
4. WHEN 用户点击平台券的二维码按钮THE 小程序 SHALL 弹出包含券码二维码的弹窗
5. WHEN 商户扫码核销成功THE 小程序 SHALL 关闭二维码弹窗并弹出核销成功提示
6. IF 商户扫码核销失败THEN THE 小程序 SHALL 关闭二维码弹窗并弹出核销失败提示及失败原因
7. WHEN 用户点击核销成功弹窗的确定按钮THE 小程序 SHALL 关闭弹窗并刷新当前页面
### 需求 5积分展示与管理
**用户故事:** 作为用户,我希望查看积分余额和积分明细,以便了解积分的收支情况。
#### 验收标准
1. THE 小程序 SHALL 在积分页展示用户当前剩余积分
2. WHEN 用户点击积分说明按钮THE 小程序 SHALL 弹出积分说明弹窗(内容后台可配置)
3. WHEN 用户点击积分明细按钮THE 小程序 SHALL 跳转至积分明细页
4. THE 小程序 SHALL 在积分明细页提供全部、收入、支出三个筛选标签
5. THE 小程序 SHALL 在积分明细页每条记录显示积分变化原因、时间、兑换的优惠券名称和兑换门店
6. THE 小程序 SHALL 在积分明细页提供按门店筛选的下拉列表,默认显示全部门店
### 需求 6优惠券兑换
**用户故事:** 作为用户,我希望用积分兑换洗车优惠券,以便在洗车时享受优惠。
#### 验收标准
1. THE 小程序 SHALL 在积分页展示可兑换的优惠券列表,每张券显示优惠券名称、适用门店、有效期、剩余数量、使用方式和所需积分
2. WHEN 用户点击兑换按钮且积分不足THE 小程序 SHALL 弹出系统提示"积分不足"
3. WHEN 用户点击兑换按钮且积分充足THE 小程序 SHALL 弹出兑换二次确认弹窗
4. WHEN 用户在兑换确认弹窗点击确定THE 小程序 SHALL 执行兑换操作,扣减积分,更新优惠券剩余数量,并弹出"兑换成功"提示
5. WHEN 用户在兑换确认弹窗点击取消THE 小程序 SHALL 关闭弹窗且不执行兑换操作
6. WHEN 兑换的优惠券为驿公里券THE 小程序 SHALL 调用驿公里API发放优惠券并将该券直接标记为"已使用"状态
7. WHEN 兑换驿公里券前THE 小程序 SHALL 提示用户该券需在驿公里APP中使用
### 需求 7我的优惠券管理
**用户故事:** 作为用户,我希望查看和管理已兑换的优惠券,以便了解券的使用状态。
#### 验收标准
1. THE 小程序 SHALL 在我的优惠券页提供未使用、已使用、已过期三个标签页
2. THE 小程序 SHALL 提供按适用门店筛选功能,默认显示全部门店
3. THE 小程序 SHALL 提供按类型筛选功能(免费券/抵扣券),默认显示全部类型
4. WHEN 优惠券为平台券THE 小程序 SHALL 显示二维码按钮
5. WHEN 优惠券为驿公里券THE 小程序 SHALL 显示使用方式说明和点击跳转按钮
6. WHEN 用户点击驿公里券的跳转按钮THE 小程序 SHALL 跳转至驿公里洗车小程序
7. WHEN 优惠券被核销使用THE 小程序 SHALL 强制刷新我的优惠券页面
### 需求 8我的页面
**用户故事:** 作为用户,我希望在"我的"页面集中管理个人信息和常用功能入口。
#### 验收标准
1. WHEN 用户已登录THE 小程序 SHALL 在我的页面展示用户头像、昵称和UID
2. THE 小程序 SHALL 在我的页面展示剩余积分和剩余优惠券数量
3. WHEN 用户点击积分区域THE 小程序 SHALL 跳转至积分页
4. WHEN 用户点击优惠券区域THE 小程序 SHALL 跳转至我的优惠券页
5. WHEN 用户点击头像/昵称区域THE 小程序 SHALL 跳转至个人资料页
6. WHEN 用户点击核销记录按钮THE 小程序 SHALL 跳转至核销记录页
7. WHEN 用户点击联系我们按钮THE 小程序 SHALL 跳转至微信小程序自带客服页
8. WHEN 用户点击用户协议或隐私政策按钮THE 小程序 SHALL 跳转至对应的协议内容页面
### 需求 9核销记录
**用户故事:** 作为用户,我希望查看优惠券的核销记录,以便了解使用历史。
#### 验收标准
1. THE 小程序 SHALL 在核销记录页展示已核销优惠券列表,每条记录显示优惠券名称、使用时间和使用门店
### 需求 10商户身份识别与登录
**用户故事:** 作为商户员工,我希望通过手机号识别身份并选择以商户身份登录,以便进行优惠券核销操作。
#### 验收标准
1. WHEN 系统检测到登录手机号为已绑定的商户员工手机号THE 小程序 SHALL 跳转至身份选择页面
2. WHEN 商户员工点击"我是用户"按钮THE 小程序 SHALL 以普通用户身份登录小程序
3. WHEN 商户员工点击"我是商户"按钮THE 小程序 SHALL 跳转至门店管理页面
### 需求 11商户扫码核销
**用户故事:** 作为商户,我希望通过扫描用户优惠券二维码进行核销,以便快速完成服务确认。
#### 验收标准
1. WHEN 商户点击扫码核销按钮THE 小程序 SHALL 向用户申请相机权限
2. WHEN 相机权限获取成功THE 小程序 SHALL 打开相机扫码界面(仅支持拍照,不支持相册)
3. WHEN 扫码识别到有效的优惠券二维码THE 小程序 SHALL 弹出核销确认弹窗
4. WHEN 商户在核销确认弹窗点击确定THE 小程序 SHALL 执行核销操作并弹出核销成功提示
5. IF 扫码识别到无效二维码或核销操作失败THEN THE 小程序 SHALL 弹出核销失败弹窗并展示失败原因
6. WHEN 核销成功THE 小程序 SHALL 同步更新用户端的优惠券状态
### 需求 12商户券码核销
**用户故事:** 作为商户,我希望通过输入券码进行核销,以便在无法扫码时完成服务确认。
#### 验收标准
1. WHEN 商户点击券码核销按钮THE 小程序 SHALL 弹出券码输入弹窗
2. WHEN 商户输入券码并点击确定THE 小程序 SHALL 验证券码有效性
3. WHEN 券码验证通过THE 小程序 SHALL 弹出核销确认弹窗
4. IF 券码验证失败THEN THE 小程序 SHALL 弹出核销失败弹窗并展示失败原因
### 需求 13商户核销记录
**用户故事:** 作为商户,我希望查看门店的核销记录,以便追踪核销历史。
#### 验收标准
1. THE 小程序 SHALL 在商户核销记录页展示核销列表,每条记录显示优惠券名称、核销时间、核销类型(扫码/券码)、券码、优惠券类型(免费券/抵扣券)和用户手机号
### 需求 14特来电API对接积分同步
**用户故事:** 作为系统我需要对接特来电API同步充电订单数据以便根据充电金额为用户发放积分。
#### 验收标准
1. THE 系统 SHALL 通过特来电平台认证接口(/query_token获取访问令牌使用AES-128-CBC加密和HMAC-MD5签名
2. WHEN 特来电推送充电订单信息(/notification_charge_order_infoTHE 系统 SHALL 解密并验证订单数据
3. WHEN 收到有效的充电订单THE 系统 SHALL 根据充电金额按照配置的积分规则计算积分并发放给对应手机号的用户
4. THE 系统 SHALL 对特来电推送的订单数据进行AES-128-CBC解密和HMAC-MD5验签
5. IF 订单数据验签失败THEN THE 系统 SHALL 拒绝该订单并返回签名错误响应
### 需求 15驿公里API对接优惠券管理
**用户故事:** 作为系统我需要对接驿公里API管理第三方优惠券的发放和状态同步。
#### 验收标准
1. WHEN 用户兑换驿公里券THE 系统 SHALL 调用驿公里优惠券查询接口(/open/yglOpenPlatform/getTicketPackageInfo验证券包可用性
2. WHEN 券包验证通过THE 系统 SHALL 调用驿公里优惠券发放接口(/open/yglOpenPlatform/generateTicket发放优惠券
3. WHEN 需要取消已发放的驿公里券THE 系统 SHALL 调用驿公里优惠券取消接口(/open/yglOpenPlatform/cancelTicket
4. THE 系统 SHALL 使用DES加密和RSA签名处理驿公里API的请求和响应数据
5. WHEN 驿公里回调优惠券核销信息THE 系统 SHALL 更新本地优惠券状态为已使用
6. WHEN 驿公里回调优惠券退回信息THE 系统 SHALL 更新本地优惠券状态并退还用户积分
### 需求 16券码生成
**用户故事:** 作为系统,我需要为每张优惠券生成唯一的券码,以便用于核销识别。
#### 验收标准
1. THE 系统 SHALL 为每张优惠券生成9位随机字母+数字组成的唯一券码
2. THE 系统 SHALL 确保生成的券码不以数字0开头
3. THE 系统 SHALL 确保每个券码在系统内唯一,不与已有券码重复
### 需求 17后台API服务
**用户故事:** 作为系统我需要提供完整的后台API服务以便小程序前端和管理后台调用。
#### 验收标准
1. THE 后台API SHALL 提供用户认证接口,支持微信手机号登录并返回用户信息和访问令牌
2. THE 后台API SHALL 提供用户信息接口,支持查询和更新用户头像、昵称等个人资料
3. THE 后台API SHALL 提供积分查询接口,返回用户当前积分余额
4. THE 后台API SHALL 提供积分明细接口,支持按类型(全部/收入/支出)和门店筛选
5. THE 后台API SHALL 提供可兑换优惠券列表接口,返回优惠券名称、适用门店、有效期、剩余数量、使用方式和所需积分
6. THE 后台API SHALL 提供优惠券兑换接口,校验积分余额后执行兑换并返回结果
7. THE 后台API SHALL 提供用户优惠券列表接口,支持按状态(未使用/已使用/已过期)、门店和类型筛选
8. THE 后台API SHALL 提供核销接口,支持扫码核销和券码核销两种方式
9. THE 后台API SHALL 提供核销记录查询接口,支持用户端和商户端分别查询
10. THE 后台API SHALL 提供门店列表接口,返回门店照片、名称、位置、联系方式、门店类型和可用优惠券数量
11. THE 后台API SHALL 提供商户身份验证接口,根据手机号判断是否为商户员工
12. THE 后台API SHALL 提供Banner配置查询接口返回当前有效的Banner列表
13. THE 后台API SHALL 提供弹窗内容查询接口,返回核销流程说明和积分说明的配置内容
14. IF 请求缺少有效的访问令牌或令牌已过期THEN THE 后台API SHALL 返回401未授权错误
### 需求 18管理后台
**用户故事:** 作为管理员,我希望通过管理后台配置和管理小程序的各项业务数据。
#### 验收标准
1. THE 管理后台 SHALL 提供管理员登录功能,支持账号密码登录
2. THE 管理后台 SHALL 提供Banner管理功能支持新增、编辑、删除和排序Banner图片
3. THE 管理后台 SHALL 提供弹窗内容管理功能,支持编辑核销流程说明和积分说明的富文本内容
4. THE 管理后台 SHALL 提供门店管理功能,支持新增、编辑和删除门店信息(门店照片、名称、位置、联系方式、门店类型)
5. THE 管理后台 SHALL 提供商户员工管理功能,支持绑定和解绑门店员工手机号
6. THE 管理后台 SHALL 提供优惠券模板管理功能,支持配置优惠券名称、适用门店、有效期、总数量、使用方式(免费券/抵扣券)、券值金额、所需积分和券来源(平台券/驿公里券)
7. THE 管理后台 SHALL 提供优惠券发放记录查看功能,支持按用户、门店和状态筛选
8. THE 管理后台 SHALL 提供核销记录查看功能,支持按门店、时间范围和核销类型筛选
9. THE 管理后台 SHALL 提供用户管理功能,支持查看用户列表、积分余额和优惠券持有情况
10. THE 管理后台 SHALL 提供积分规则配置功能,支持设置充电金额与积分的兑换比例
11. THE 管理后台 SHALL 提供用户协议和隐私政策内容编辑功能
12. THE 管理后台 SHALL 提供数据统计概览,展示用户总数、优惠券发放总量、核销总量和积分发放总量

View File

@ -0,0 +1,250 @@
# 实现计划:黄岩停车积分兑换
## 概述
基于需求文档和设计文档将实现分为三大部分后台API服务.NET 10、微信小程序前端uni-app Vue 3、管理后台Vue 3 + Element Plus。任务按增量方式组织每个任务在前一个任务基础上构建。
## 任务
- [x] 1. 后台项目初始化与基础设施
- [x] 1.1 创建 .NET 10 ASP.NET Core Web API 项目结构
- 在 `server/` 目录下创建解决方案,包含 API 主项目、Domain 领域层、Infrastructure 基础设施层、Tests 测试项目
- 配置 MySQL 数据库连接Entity Framework Core + Pomelo.EntityFrameworkCore.MySql
- 配置 Redis 缓存连接StackExchange.Redis
- 配置 JWT 认证中间件
- 配置 FluentValidation 参数校验
- 配置 Serilog 日志
- _Requirements: 17.14_
- [x] 1.2 创建数据库实体模型和 DbContext
- 创建所有实体类User、Store、CouponTemplate、Coupon、PointsRecord、VerifyRecord、Banner、PopupContent、Agreement、PointsRule、Admin
- 配置 Entity Framework Core DbContext 和实体映射关系
- 创建数据库迁移脚本
- _Requirements: 17.1-17.13, 18.1-18.12_
- [x] 1.3 编写券码和UID生成的属性测试
- **Property 1: 券码格式正确性** — 对于任意生成的券码长度为9位由字母+数字组成,首字符不为'0'
- **Property 2: 券码唯一性** — 对于任意批量生成的N个券码所有券码互不相同
- **Property 3: UID格式正确性** — 对于任意生成的UID长度为6位纯数字首位不为0
- **Validates: Requirements 16.1, 16.2, 16.3, 1.3**
- [x] 1.4 实现券码生成工具类和UID生成工具类
- 实现 `CouponCodeGenerator.Generate()` 方法9位随机字母+数字不以0开头
- 实现 `UidGenerator.Generate()` 方法6位随机数字不以0开头
- 实现唯一性校验逻辑(数据库查重)
- _Requirements: 16.1, 16.2, 16.3, 1.3_
- [x] 2. 检查点 - 确保所有测试通过
- 确保所有测试通过,如有问题请向用户确认。
- [x] 3. 用户认证与第三方加解密模块
- [x] 3.1 实现微信登录服务
- 实现 `WechatService`:调用微信 code2Session 和手机号获取接口
- 实现 `AuthController`POST /api/auth/login微信手机号登录、POST /api/auth/logout、GET /api/auth/check-merchant
- 实现 JWT Token 生成和校验逻辑
- _Requirements: 1.1, 1.2, 1.3, 1.4, 10.1_
- [x] 3.2 编写特来电加解密属性测试
- **Property 4: 特来电数据加解密 Round-Trip** — 对于任意有效JSON数据AES-128-CBC加密后解密应得到原始数据
- **Property 5: 特来电签名验签一致性** — 对于任意消息数据HMAC-MD5签名后验签应通过篡改数据后验签应失败
- **Validates: Requirements 14.2, 14.4, 14.5**
- [x] 3.3 实现特来电对接服务
- 实现 `TldService`AES-128-CBC 加解密、HMAC-MD5 签名验签
- 实现 `TldCallbackController`POST /api/callback/tld/charge-order充电订单推送回调
- 实现平台认证 Token 获取和缓存逻辑
- _Requirements: 14.1, 14.2, 14.3, 14.4, 14.5_
- [x] 3.4 编写驿公里加解密属性测试
- **Property 6: 驿公里数据加解密 Round-Trip** — 对于任意有效JSON数据DES加密后解密应得到原始数据RSA签名后验签应通过
- **Validates: Requirements 15.4**
- [x] 3.5 实现驿公里对接服务
- 实现 `YglService`DES 加解密、RSA 签名验签、请求封装和响应解析
- 实现优惠券查询、发放、取消接口调用
- 实现 `YglCallbackController`POST /api/callback/ygl/verify核销回调、POST /api/callback/ygl/refund退回回调
- _Requirements: 15.1, 15.2, 15.3, 15.4, 15.5, 15.6_
- [x] 4. 检查点 - 确保所有测试通过
- 确保所有测试通过,如有问题请向用户确认。
- [x] 5. 积分与优惠券核心业务
- [x] 5.1 编写积分计算和兑换属性测试
- **Property 7: 积分计算正确性** — 对于任意充电金额和积分规则,计算结果应等于 floor(充电金额/规则金额)*规则积分值
- **Property 8: 积分兑换校验正确性** — 余额>=所需积分时兑换成功且余额减少,余额<所需积分时拒绝且余额不变
- **Property 9: 优惠券兑换不变量** — 兑换后模板剩余数量减1用户持有数量加1
- **Validates: Requirements 14.3, 6.2, 6.3, 6.4**
- [x] 5.2 实现积分服务
- 实现 `PointsService`:积分余额查询、积分明细查询(支持类型和门店筛选)、积分发放(充电订单触发)、积分扣减(兑换触发)
- 实现 `PointsController`GET /api/points/balance、GET /api/points/records
- 实现积分计算规则引擎
- _Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 14.3_
- [x] 5.3 编写核销验证属性测试
- **Property 10: 券码验证正确性** — 券码存在且未使用且属于当前门店则通过,否则失败并返回错误原因
- **Property 11: 核销操作正确性** — 核销后券状态变为已使用,用户端查询反映已使用状态
- **Validates: Requirements 11.3, 11.5, 12.2, 11.4, 11.6**
- [x] 5.4 实现优惠券服务
- 实现 `CouponService`:可兑换列表查询、兑换操作(积分校验+扣减+券码生成+驿公里API调用、用户优惠券查询支持状态/门店/类型筛选)、门店可用优惠券查询
- 实现 `CouponController`GET /api/coupons/available、POST /api/coupons/exchange、GET /api/coupons/my、GET /api/coupons/store/:storeId
- 驿公里券兑换后直接标记为已使用状态
- _Requirements: 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 7.1, 7.2, 7.3, 4.2_
- [x] 5.5 实现核销服务
- 实现 `VerifyService`:扫码核销、券码核销、核销记录查询(用户端和商户端)
- 实现 `VerifyController`POST /api/verify/scan、POST /api/verify/code、GET /api/verify/records、GET /api/verify/merchant-records
- _Requirements: 11.1-11.6, 12.1-12.4, 9.1, 13.1_
- [x] 6. 门店与配置API
- [x] 6.1 实现门店服务和用户信息服务
- 实现 `StoreService`:门店列表查询、门店详情查询
- 实现 `StoreController`GET /api/stores、GET /api/stores/:id
- 实现 `UserService`:用户信息查询和更新
- 实现 `UserController`GET /api/user/profile、PUT /api/user/profile
- _Requirements: 3.4, 2.1, 2.2, 2.3, 2.4_
- [x] 6.2 实现配置服务
- 实现 `ConfigService`Banner列表查询、弹窗内容查询、协议内容查询
- 实现 `ConfigController`GET /api/config/banners、GET /api/config/popups/:type、GET /api/config/agreement/:type
- _Requirements: 3.1, 3.2, 3.3, 8.8_
- [x] 6.3 编写筛选逻辑和API认证属性测试
- **Property 13: 积分明细筛选正确性** — 筛选后每条记录匹配所选类型和门店
- **Property 14: 优惠券列表筛选正确性** — 筛选后每张券匹配所有筛选条件
- **Property 15: 门店可用优惠券筛选正确性** — 返回的券全部属于该用户、该门店、状态为未使用
- **Property 16: 商户身份识别正确性** — 手机号在商户员工表中存在则识别为商户
- **Property 21: API认证保护** — 无效令牌请求返回401
- **Validates: Requirements 5.4, 5.6, 7.2, 7.3, 4.2, 10.1, 17.14**
- [x] 7. 检查点 - 确保所有后台测试通过
- 确保所有测试通过,如有问题请向用户确认。
- [x] 8. 管理后台API
- [x] 8.1 实现管理员认证
- 实现 `AdminAuthService`管理员登录、JWT Token 生成
- 实现 `AdminAuthController`POST /api/admin/login
- _Requirements: 18.1_
- [x] 8.2 实现管理后台CRUD接口
- 实现 Banner 管理GET/POST/PUT/DELETE /api/admin/banners
- 实现弹窗内容管理GET/PUT /api/admin/popups/:type
- 实现门店管理GET/POST/PUT/DELETE /api/admin/stores
- 实现商户员工管理GET/POST/DELETE /api/admin/merchants
- 实现优惠券模板管理GET/POST/PUT/DELETE /api/admin/coupon-templates
- 实现协议内容管理GET/PUT /api/admin/agreements/:type
- 实现积分规则配置GET/PUT /api/admin/points-rule
- _Requirements: 18.2, 18.3, 18.4, 18.5, 18.6, 18.10, 18.11_
- [x] 8.3 编写管理后台CRUD属性测试
- **Property 20: 管理后台CRUD Round-Trip** — 创建/更新后查询应得到与输入一致的结果
- **Validates: Requirements 18.2, 18.3, 18.4, 18.5, 18.6, 18.10, 18.11**
- [x] 8.4 实现管理后台查询和统计接口
- 实现优惠券发放记录查询GET /api/admin/coupons
- 实现核销记录查询GET /api/admin/verify-records
- 实现用户列表查询GET /api/admin/users
- 实现数据统计概览GET /api/admin/dashboard
- _Requirements: 18.7, 18.8, 18.9, 18.12_
- [x] 9. 检查点 - 确保所有后台API测试通过
- 确保所有测试通过,如有问题请向用户确认。
- [x] 10. 小程序基础框架搭建
- [x] 10.1 配置小程序项目结构和路由
- 更新 `pages.json` 配置所有页面路由和 TabBar首页/积分页/我的页)
- 创建所有页面目录和空白页面文件
- 配置全局样式 `uni.scss`
- 配置 `manifest.json` 微信小程序 appid 和权限
- _Requirements: 3.1-3.6, 5.1-5.6, 8.1-8.8_
- [x] 10.2 实现公共工具模块
- 实现 `utils/request.js`:封装 uni.request统一处理 Token 注入、错误提示、401 自动跳转登录
- 实现 `utils/auth.js`登录状态管理、Token 本地存储、登录态检查
- 实现 API 接口定义文件 `api/*.js`:按模块封装所有后台 API 调用
- _Requirements: 1.1, 17.14_
- [x] 10.3 实现公共组件
- 实现 `CouponCard` 组件:支持平台券(显示二维码按钮)和驿公里券(显示跳转按钮)两种样式
- 实现 `QrcodePopup` 组件:优惠券二维码弹窗,支持核销成功/失败回调
- 实现 `ConfirmDialog` 组件:通用二次确认弹窗
- 实现 `StoreCard` 组件:门店信息卡片(照片/名称/位置/联系方式/可用券数/类型)
- 实现 `FilterBar` 组件:筛选栏(门店/类型/状态下拉选择)
- 实现 `RichContentPopup` 组件:富文本内容弹窗
- _Requirements: 4.3, 7.4, 7.5, 3.4_
- [x] 11. 小程序用户端页面实现
- [x] 11.1 实现登录页和身份选择页
- 实现 `pages/login/index`:微信手机号授权登录按钮
- 实现 `pages/login/role-select`:商户员工身份选择(我是用户/我是商户)
- 实现路由守卫:未登录访问需登录页面时自动跳转登录页
- _Requirements: 1.1, 1.2, 10.1, 10.2, 10.3_
- [x] 11.2 实现首页
- 实现 `pages/home/index`Banner 轮播图、核销流程弹窗入口、积分说明弹窗入口、洗车店列表、导航按钮
- 调用门店列表 API 和 Banner API 加载数据
- _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6_
- [x] 11.3 实现门店可用优惠券页
- 实现 `pages/coupon/store-coupons`:门店名称、优惠券列表、二维码弹窗、核销成功/失败提示
- _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7_
- [x] 11.4 实现积分页
- 实现 `pages/points/index`:积分余额展示、积分说明弹窗、积分明细入口、可兑换优惠券列表、兑换流程(积分校验+二次确认+驿公里券提示)
- 实现 `pages/points/detail`:积分明细列表、全部/收入/支出标签、门店筛选下拉
- _Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7_
- [x] 11.5 实现我的页及子页面
- 实现 `pages/mine/index`:用户信息展示、积分/优惠券数量、功能入口列表、退出登录
- 实现 `pages/mine/profile`:头像/昵称编辑、UID只读展示
- 实现 `pages/mine/verify-records`:核销记录列表
- 实现 `pages/mine/agreement`:用户协议/隐私政策内容展示
- _Requirements: 8.1-8.8, 2.1-2.4, 9.1, 1.4, 1.5_
- [x] 11.6 实现我的优惠券页
- 实现 `pages/coupon/my-coupons`:未使用/已使用/已过期标签页、门店和类型筛选、平台券二维码按钮、驿公里券跳转按钮、核销后强制刷新
- _Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7_
- [x] 12. 小程序商户端页面实现
- [x] 12.1 实现门店管理页(商户端)
- 实现 `pages/merchant/index`:门店名称展示、扫码核销按钮(相机权限申请+扫码+核销确认)、券码核销按钮(输入弹窗+验证+核销确认)、核销记录入口
- _Requirements: 11.1-11.6, 12.1-12.4_
- [x] 12.2 实现商户核销记录页
- 实现 `pages/merchant/records`:核销记录列表(优惠券名称/核销时间/核销类型/券码/优惠券类型/手机号)
- _Requirements: 13.1_
- [x] 13. 检查点 - 确保小程序所有页面功能正常
- 确保所有测试通过,如有问题请向用户确认。
- [x] 14. 管理后台前端实现
- [x] 14.1 创建管理后台项目结构
- 在 `admin/` 目录下创建 Vue 3 + Vite + Element Plus 项目
- 配置路由Vue Router、状态管理Pinia、HTTP 请求封装Axios
- 实现管理员登录页和布局框架(侧边栏导航+顶部栏+内容区)
- _Requirements: 18.1_
- [x] 14.2 实现管理后台业务页面
- 实现数据统计概览页Dashboard用户总数、优惠券发放总量、核销总量、积分发放总量
- 实现 Banner 管理页:列表、新增/编辑弹窗、删除确认、排序拖拽
- 实现弹窗内容管理页:核销流程说明和积分说明的富文本编辑器
- 实现门店管理页:列表、新增/编辑表单(照片上传/名称/地址/联系方式/类型)、删除确认
- 实现商户员工管理页:列表、绑定/解绑手机号
- 实现优惠券模板管理页:列表、新增/编辑表单(名称/适用门店/有效期/数量/类型/积分/来源/驿公里券包码)
- 实现优惠券发放记录页:列表、按用户/门店/状态筛选
- 实现核销记录页:列表、按门店/时间/类型筛选
- 实现用户管理页:列表、查看积分和优惠券详情
- 实现积分规则配置页:充电金额与积分兑换比例设置
- 实现协议内容管理页:用户协议和隐私政策富文本编辑
- _Requirements: 18.2-18.12_
- [x] 15. 最终检查点 - 全部功能集成验证
- 确保所有测试通过,如有问题请向用户确认。
## 备注
- 每个任务引用了具体的需求编号以便追溯
- 检查点确保增量验证
- 属性测试验证通用正确性属性
- 单元测试验证具体示例和边界情况

View File

@ -0,0 +1,9 @@
---
inclusion: always
---
# 语言规则
- 始终使用中文回复用户的问题和对话。
- 代码注释使用中文。
- Git commit message 使用中文。

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"git.ignoreLimitWarning": true
}

View File

@ -0,0 +1 @@
import{_ as O,i as p,j as P,o as i,k as _,w as e,r as o,u as j,a as t,b as d,c as m,f as s,t as f,l as I,m as M}from"./index-DZCMG0nr.js";const q={class:"logo"},z={key:0},G={key:1},H={class:"header-left"},J={class:"page-title"},K={class:"header-right"},Q={class:"username"},W={__name:"AdminLayout",setup(X){const x=j(),u=p(!1),v=p(P()),g=()=>{I.confirm("确定要退出登录吗?","提示",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(()=>{M(),x.push("/login")}).catch(()=>{})};return(r,n)=>{const k=o("DataAnalysis"),l=o("el-icon"),a=o("el-menu-item"),y=o("Picture"),C=o("ChatDotRound"),B=o("OfficeBuilding"),b=o("User"),w=o("Ticket"),D=o("List"),T=o("CircleCheck"),L=o("UserFilled"),U=o("Setting"),A=o("Document"),E=o("el-menu"),F=o("el-aside"),N=o("Fold"),R=o("Expand"),S=o("el-button"),V=o("el-header"),$=o("router-view"),h=o("el-main"),c=o("el-container");return i(),_(c,{class:"layout-container"},{default:e(()=>[t(F,{width:u.value?"64px":"220px",class:"layout-aside"},{default:e(()=>[d("div",q,[u.value?(i(),m("span",G,"积分")):(i(),m("span",z,"黄岩停车积分"))]),t(E,{"default-active":r.$route.path,router:"",collapse:u.value,"background-color":"#304156","text-color":"#bfcbd9","active-text-color":"#409eff"},{default:e(()=>[t(a,{index:"/dashboard"},{title:e(()=>[...n[1]||(n[1]=[s("数据概览",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(k)]),_:1})]),_:1}),t(a,{index:"/banners"},{title:e(()=>[...n[2]||(n[2]=[s("Banner管理",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(y)]),_:1})]),_:1}),t(a,{index:"/popups"},{title:e(()=>[...n[3]||(n[3]=[s("弹窗内容管理",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(C)]),_:1})]),_:1}),t(a,{index:"/stores"},{title:e(()=>[...n[4]||(n[4]=[s("门店管理",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(B)]),_:1})]),_:1}),t(a,{index:"/merchants"},{title:e(()=>[...n[5]||(n[5]=[s("商户员工管理",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(b)]),_:1})]),_:1}),t(a,{index:"/coupon-templates"},{title:e(()=>[...n[6]||(n[6]=[s("优惠券模板管理",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(w)]),_:1})]),_:1}),t(a,{index:"/coupons"},{title:e(()=>[...n[7]||(n[7]=[s("优惠券发放记录",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(D)]),_:1})]),_:1}),t(a,{index:"/verify-records"},{title:e(()=>[...n[8]||(n[8]=[s("核销记录",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(T)]),_:1})]),_:1}),t(a,{index:"/users"},{title:e(()=>[...n[9]||(n[9]=[s("用户管理",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(L)]),_:1})]),_:1}),t(a,{index:"/points-rule"},{title:e(()=>[...n[10]||(n[10]=[s("积分规则配置",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(U)]),_:1})]),_:1}),t(a,{index:"/agreements"},{title:e(()=>[...n[11]||(n[11]=[s("协议内容管理",-1)])]),default:e(()=>[t(l,null,{default:e(()=>[t(A)]),_:1})]),_:1})]),_:1},8,["default-active","collapse"])]),_:1},8,["width"]),t(c,null,{default:e(()=>[t(V,{class:"layout-header"},{default:e(()=>[d("div",H,[t(l,{class:"collapse-btn",onClick:n[0]||(n[0]=Y=>u.value=!u.value)},{default:e(()=>[u.value?(i(),_(R,{key:1})):(i(),_(N,{key:0}))]),_:1}),d("span",J,f(r.$route.meta.title),1)]),d("div",K,[d("span",Q,f(v.value),1),t(S,{type:"danger",text:"",onClick:g},{default:e(()=>[...n[12]||(n[12]=[s("退出登录",-1)])]),_:1})])]),_:1}),t(h,{class:"layout-main"},{default:e(()=>[t($)]),_:1})]),_:1})]),_:1})}}},ee=O(W,[["__scopeId","data-v-94aa5d27"]]);export{ee as default};

View File

@ -0,0 +1 @@
.layout-container[data-v-94aa5d27]{height:100vh}.layout-aside[data-v-94aa5d27]{background-color:#304156;transition:width .3s;overflow:hidden}.logo[data-v-94aa5d27]{height:60px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:18px;font-weight:700;background-color:#263445}.layout-header[data-v-94aa5d27]{background:#fff;border-bottom:1px solid #e6e6e6;display:flex;align-items:center;justify-content:space-between;padding:0 20px}.header-left[data-v-94aa5d27]{display:flex;align-items:center;gap:12px}.collapse-btn[data-v-94aa5d27]{font-size:20px;cursor:pointer}.page-title[data-v-94aa5d27]{font-size:16px;font-weight:500}.header-right[data-v-94aa5d27]{display:flex;align-items:center;gap:12px}.username[data-v-94aa5d27]{color:#606266}.layout-main[data-v-94aa5d27]{background:#f0f2f5}

View File

@ -0,0 +1 @@
import{y as V,z as x}from"./index-BIlGw-iH.js";import{n as w,o as h,c as C,a,w as o,r as l,i as s,p as T,q as k,b as A,f as p,E as B}from"./index-DZCMG0nr.js";const D={style:{"margin-top":"16px","text-align":"right"}},U={__name:"Agreements",setup(E){const n=s("user-agreement"),t=s(""),r=s(!1),u=s(!1),i=async()=>{r.value=!0;try{const d=await V(n.value);t.value=d.data.content}catch{t.value=""}finally{r.value=!1}},v=async()=>{u.value=!0;try{await x(n.value,{content:t.value}),B.success("保存成功")}catch{}finally{u.value=!1}};return w(i),(d,e)=>{const m=l("el-tab-pane"),_=l("el-tabs"),g=l("el-input"),f=l("el-button"),y=l("el-card"),b=T("loading");return h(),C("div",null,[a(y,null,{header:o(()=>[...e[2]||(e[2]=[p("协议内容管理",-1)])]),default:o(()=>[a(_,{modelValue:n.value,"onUpdate:modelValue":e[0]||(e[0]=c=>n.value=c),onTabChange:i},{default:o(()=>[a(m,{label:"用户协议",name:"user-agreement"}),a(m,{label:"隐私政策",name:"privacy-policy"})]),_:1},8,["modelValue"]),k(a(g,{modelValue:t.value,"onUpdate:modelValue":e[1]||(e[1]=c=>t.value=c),type:"textarea",rows:18,placeholder:"请输入协议内容支持HTML富文本"},null,8,["modelValue"]),[[b,r.value]]),A("div",D,[a(f,{type:"primary",loading:u.value,onClick:v},{default:o(()=>[...e[3]||(e[3]=[p("保存",-1)])]),_:1},8,["loading"])])]),_:1})])}}};export{U as default};

1
admin/dist/assets/Banners-D7UhdNY-.js vendored Normal file
View File

@ -0,0 +1 @@
import{b as L,d as R,u as S,c as h}from"./index-BIlGw-iH.js";import{n as j,o as B,c as q,a as l,w as t,r as n,i,p as T,q as F,k as G,f as u,t as H,b as w,l as J,E as b}from"./index-DZCMG0nr.js";const K={style:{display:"flex","justify-content":"space-between","align-items":"center"}},X={__name:"Banners",setup(P){const y=i([]),v=i(!1),r=i(!1),p=i(!1),c=i(!1),f=i(null),o=i({imageUrl:"",sortOrder:0,isActive:!0}),_=async()=>{v.value=!0;try{const s=await L();y.value=s.data}catch{}finally{v.value=!1}},V=s=>{s?(c.value=!0,f.value=s.id,o.value={imageUrl:s.imageUrl,sortOrder:s.sortOrder,isActive:s.isActive}):(c.value=!1,f.value=null,o.value={imageUrl:"",sortOrder:0,isActive:!0}),r.value=!0},U=async()=>{p.value=!0;try{c.value?(await S(f.value,o.value),b.success("更新成功")):(await h(o.value),b.success("创建成功")),r.value=!1,_()}catch{}finally{p.value=!1}},x=s=>{J.confirm("确定要删除该Banner吗","提示",{type:"warning"}).then(async()=>{await R(s),b.success("删除成功"),_()}).catch(()=>{})};return j(_),(s,e)=>{const d=n("el-button"),m=n("el-table-column"),k=n("el-image"),C=n("el-tag"),A=n("el-table"),D=n("el-card"),O=n("el-input"),g=n("el-form-item"),E=n("el-input-number"),$=n("el-switch"),M=n("el-form"),N=n("el-dialog"),z=T("loading");return B(),q("div",null,[l(D,null,{header:t(()=>[w("div",K,[e[7]||(e[7]=w("span",null,"Banner管理",-1)),l(d,{type:"primary",onClick:e[0]||(e[0]=a=>V())},{default:t(()=>[...e[6]||(e[6]=[u("新增Banner",-1)])]),_:1})])]),default:t(()=>[F((B(),G(A,{data:y.value},{default:t(()=>[l(m,{prop:"id",label:"ID",width:"80"}),l(m,{label:"图片",width:"200"},{default:t(({row:a})=>[l(k,{src:a.imageUrl,style:{width:"160px",height:"80px"},fit:"cover"},null,8,["src"])]),_:1}),l(m,{prop:"sortOrder",label:"排序",width:"100"}),l(m,{label:"状态",width:"100"},{default:t(({row:a})=>[l(C,{type:a.isActive?"success":"info"},{default:t(()=>[u(H(a.isActive?"启用":"禁用"),1)]),_:2},1032,["type"])]),_:1}),l(m,{label:"操作",width:"180"},{default:t(({row:a})=>[l(d,{size:"small",onClick:I=>V(a)},{default:t(()=>[...e[8]||(e[8]=[u("编辑",-1)])]),_:1},8,["onClick"]),l(d,{size:"small",type:"danger",onClick:I=>x(a.id)},{default:t(()=>[...e[9]||(e[9]=[u("删除",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[z,v.value]])]),_:1}),l(N,{modelValue:r.value,"onUpdate:modelValue":e[5]||(e[5]=a=>r.value=a),title:c.value?"编辑Banner":"新增Banner",width:"500px"},{footer:t(()=>[l(d,{onClick:e[4]||(e[4]=a=>r.value=!1)},{default:t(()=>[...e[10]||(e[10]=[u("取消",-1)])]),_:1}),l(d,{type:"primary",loading:p.value,onClick:U},{default:t(()=>[...e[11]||(e[11]=[u("确定",-1)])]),_:1},8,["loading"])]),default:t(()=>[l(M,{model:o.value,"label-width":"80px"},{default:t(()=>[l(g,{label:"图片URL"},{default:t(()=>[l(O,{modelValue:o.value.imageUrl,"onUpdate:modelValue":e[1]||(e[1]=a=>o.value.imageUrl=a),placeholder:"请输入图片URL"},null,8,["modelValue"])]),_:1}),l(g,{label:"排序"},{default:t(()=>[l(E,{modelValue:o.value.sortOrder,"onUpdate:modelValue":e[2]||(e[2]=a=>o.value.sortOrder=a),min:0},null,8,["modelValue"])]),_:1}),l(g,{label:"状态"},{default:t(()=>[l($,{modelValue:o.value.isActive,"onUpdate:modelValue":e[3]||(e[3]=a=>o.value.isActive=a),"active-text":"启用","inactive-text":"禁用"},null,8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue","title"])])}}};export{X as default};

File diff suppressed because one or more lines are too long

1
admin/dist/assets/Coupons-Ml69bG6P.js vendored Normal file
View File

@ -0,0 +1 @@
import{h as N,s as B}from"./index-BIlGw-iH.js";import{n as S,o as p,c as g,a as e,w as l,i as _,r as n,h as U,p as z,F,v as L,k as y,f as d,q,t as f}from"./index-DZCMG0nr.js";const T={__name:"Coupons",setup(A){const b=_([]),v=_([]),m=_(!1),a=U({userPhone:"",storeId:null,status:""}),V=s=>s?new Date(s).toLocaleString("zh-CN"):"-",r=async()=>{m.value=!0;try{const s={};a.userPhone&&(s.userPhone=a.userPhone),a.storeId&&(s.storeId=a.storeId),a.status&&(s.status=a.status);const o=await B(s);b.value=o.data}catch{}finally{m.value=!1}};return S(async()=>{try{const s=await N();v.value=s.data}catch{}r()}),(s,o)=>{const w=n("el-input"),c=n("el-form-item"),i=n("el-option"),h=n("el-select"),C=n("el-button"),x=n("el-form"),u=n("el-table-column"),D=n("el-tag"),I=n("el-table"),P=n("el-card"),k=z("loading");return p(),g("div",null,[e(P,null,{header:l(()=>[...o[3]||(o[3]=[d("优惠券发放记录",-1)])]),default:l(()=>[e(x,{inline:!0,model:a,style:{"margin-bottom":"16px"}},{default:l(()=>[e(c,{label:"用户手机号"},{default:l(()=>[e(w,{modelValue:a.userPhone,"onUpdate:modelValue":o[0]||(o[0]=t=>a.userPhone=t),placeholder:"手机号",clearable:"",onClear:r},null,8,["modelValue"])]),_:1}),e(c,{label:"门店"},{default:l(()=>[e(h,{modelValue:a.storeId,"onUpdate:modelValue":o[1]||(o[1]=t=>a.storeId=t),placeholder:"全部门店",clearable:"",onChange:r},{default:l(()=>[(p(!0),g(F,null,L(v.value,t=>(p(),y(i,{key:t.id,label:t.name,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(c,{label:"状态"},{default:l(()=>[e(h,{modelValue:a.status,"onUpdate:modelValue":o[2]||(o[2]=t=>a.status=t),placeholder:"全部状态",clearable:"",onChange:r},{default:l(()=>[e(i,{label:"未使用",value:"unused"}),e(i,{label:"已使用",value:"used"}),e(i,{label:"已过期",value:"expired"})]),_:1},8,["modelValue"])]),_:1}),e(c,null,{default:l(()=>[e(C,{type:"primary",onClick:r},{default:l(()=>[...o[4]||(o[4]=[d("查询",-1)])]),_:1})]),_:1})]),_:1},8,["model"]),q((p(),y(I,{data:b.value},{default:l(()=>[e(u,{prop:"id",label:"ID",width:"60"}),e(u,{prop:"code",label:"券码",width:"120"}),e(u,{prop:"templateName",label:"优惠券名称"}),e(u,{prop:"userPhone",label:"用户手机号",width:"130"}),e(u,{prop:"storeName",label:"门店"}),e(u,{label:"状态",width:"90"},{default:l(({row:t})=>[e(D,{type:t.status==="unused"?"success":t.status==="used"?"info":"danger",size:"small"},{default:l(()=>[d(f({unused:"未使用",used:"已使用",expired:"已过期"}[t.status]||t.status),1)]),_:2},1032,["type"])]),_:1}),e(u,{label:"来源",width:"90"},{default:l(({row:t})=>[d(f(t.source==="platform"?"平台券":"驿公里券"),1)]),_:1}),e(u,{label:"兑换时间",width:"170"},{default:l(({row:t})=>[d(f(V(t.exchangedAt)),1)]),_:1})]),_:1},8,["data"])),[[k,m.value]])]),_:1})])}}};export{T as default};

View File

@ -0,0 +1 @@
import{g as h}from"./index-BIlGw-iH.js";import{_ as m,n as b,o as k,c as C,a as s,w as a,i as w,r as e,b as t,t as i}from"./index-DZCMG0nr.js";const g={class:"dashboard"},y={class:"stat-icon",style:{background:"#409eff"}},I={class:"stat-info"},x={class:"stat-value"},z={class:"stat-icon",style:{background:"#67c23a"}},D={class:"stat-info"},U={class:"stat-value"},V={class:"stat-icon",style:{background:"#e6a23c"}},B={class:"stat-info"},F={class:"stat-value"},N={class:"stat-icon",style:{background:"#f56c6c"}},P={class:"stat-info"},T={class:"stat-value"},E={__name:"Dashboard",setup(M){const l=w({totalUsers:0,totalCouponsIssued:0,totalVerified:0,totalPointsIssued:0});return b(async()=>{try{const _=await h();l.value=_.data}catch{}}),(_,o)=>{const r=e("UserFilled"),c=e("el-icon"),d=e("el-card"),n=e("el-col"),u=e("Ticket"),v=e("CircleCheck"),f=e("Coin"),p=e("el-row");return k(),C("div",g,[s(p,{gutter:20},{default:a(()=>[s(n,{span:6},{default:a(()=>[s(d,{shadow:"hover",class:"stat-card"},{default:a(()=>[t("div",y,[s(c,{size:28},{default:a(()=>[s(r)]),_:1})]),t("div",I,[t("div",x,i(l.value.totalUsers),1),o[0]||(o[0]=t("div",{class:"stat-label"},"用户总数",-1))])]),_:1})]),_:1}),s(n,{span:6},{default:a(()=>[s(d,{shadow:"hover",class:"stat-card"},{default:a(()=>[t("div",z,[s(c,{size:28},{default:a(()=>[s(u)]),_:1})]),t("div",D,[t("div",U,i(l.value.totalCouponsIssued),1),o[1]||(o[1]=t("div",{class:"stat-label"},"优惠券发放总量",-1))])]),_:1})]),_:1}),s(n,{span:6},{default:a(()=>[s(d,{shadow:"hover",class:"stat-card"},{default:a(()=>[t("div",V,[s(c,{size:28},{default:a(()=>[s(v)]),_:1})]),t("div",B,[t("div",F,i(l.value.totalVerified),1),o[2]||(o[2]=t("div",{class:"stat-label"},"核销总量",-1))])]),_:1})]),_:1}),s(n,{span:6},{default:a(()=>[s(d,{shadow:"hover",class:"stat-card"},{default:a(()=>[t("div",N,[s(c,{size:28},{default:a(()=>[s(f)]),_:1})]),t("div",P,[t("div",T,i(l.value.totalPointsIssued),1),o[3]||(o[3]=t("div",{class:"stat-label"},"积分发放总量",-1))])]),_:1})]),_:1})]),_:1})])}}},q=m(E,[["__scopeId","data-v-449edbaf"]]);export{q as default};

View File

@ -0,0 +1 @@
.stat-card[data-v-449edbaf]{display:flex;align-items:center;padding:20px}.stat-card[data-v-449edbaf] .el-card__body{display:flex;align-items:center;gap:16px;width:100%}.stat-icon[data-v-449edbaf]{width:56px;height:56px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#fff;flex-shrink:0}.stat-value[data-v-449edbaf]{font-size:28px;font-weight:700;color:#303133}.stat-label[data-v-449edbaf]{font-size:14px;color:#909399;margin-top:4px}

1
admin/dist/assets/Login-DAOdJnjQ.js vendored Normal file
View File

@ -0,0 +1 @@
import{_ as v,o as y,c as V,a as o,w as a,r as t,u as h,b,d as k,e as x,f as L,s as U,g as B,E as C,h as E,i as m}from"./index-DZCMG0nr.js";import{a as N}from"./index-BIlGw-iH.js";const R={class:"login-container"},q={__name:"Login",setup(K){const p=h(),u=m(null),r=m(!1),s=E({username:"",password:""}),c={username:[{required:!0,message:"请输入管理员账号",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"}]},l=async()=>{if(await u.value.validate().catch(()=>!1)){r.value=!0;try{const e=await N(s);U(e.data.token),B(e.data.username),C.success("登录成功"),p.push("/dashboard")}catch{}finally{r.value=!1}}};return(f,e)=>{const i=t("el-input"),n=t("el-form-item"),_=t("el-button"),g=t("el-form"),w=t("el-card");return y(),V("div",R,[o(w,{class:"login-card"},{default:a(()=>[e[3]||(e[3]=b("h2",{class:"login-title"},"黄岩停车积分 - 管理后台",-1)),o(g,{ref_key:"formRef",ref:u,model:s,rules:c,onSubmit:k(l,["prevent"])},{default:a(()=>[o(n,{prop:"username"},{default:a(()=>[o(i,{modelValue:s.username,"onUpdate:modelValue":e[0]||(e[0]=d=>s.username=d),placeholder:"请输入管理员账号","prefix-icon":"User"},null,8,["modelValue"])]),_:1}),o(n,{prop:"password"},{default:a(()=>[o(i,{modelValue:s.password,"onUpdate:modelValue":e[1]||(e[1]=d=>s.password=d),type:"password",placeholder:"请输入密码","prefix-icon":"Lock","show-password":"",onKeyup:x(l,["enter"])},null,8,["modelValue"])]),_:1}),o(n,null,{default:a(()=>[o(_,{type:"primary",loading:r.value,style:{width:"100%"},onClick:l},{default:a(()=>[...e[2]||(e[2]=[L("登 录",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])]),_:1})])}}},I=v(q,[["__scopeId","data-v-4130620f"]]);export{I as default};

1
admin/dist/assets/Login-DfrzHvfx.css vendored Normal file
View File

@ -0,0 +1 @@
.login-container[data-v-4130620f]{height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#667eea,#764ba2)}.login-card[data-v-4130620f]{width:400px;padding:20px}.login-title[data-v-4130620f]{text-align:center;margin-bottom:30px;color:#303133}

View File

@ -0,0 +1 @@
import{l as S,m as j,n as q,h as z}from"./index-BIlGw-iH.js";import{n as L,o as c,c as g,a as l,w as t,r as o,i as d,p as T,q as A,k as w,f as p,b as V,F as G,v as H,l as J,E as h}from"./index-DZCMG0nr.js";const K={style:{display:"flex","justify-content":"space-between","align-items":"center"}},W={__name:"Merchants",setup(O){const v=d([]),b=d([]),m=d(!1),u=d(!1),f=d(!1),n=d({phone:"",storeId:null}),_=async()=>{m.value=!0;try{const s=await S();v.value=s.data}catch{}finally{m.value=!1}},k=async()=>{try{const s=await z();b.value=s.data}catch{}},x=()=>{n.value={phone:"",storeId:null},u.value=!0,k()},C=async()=>{f.value=!0;try{await q(n.value),h.success("绑定成功"),u.value=!1,_()}catch{}finally{f.value=!1}},M=s=>{J.confirm("确定要解绑该商户员工吗?","提示",{type:"warning"}).then(async()=>{await j(s),h.success("解绑成功"),_()}).catch(()=>{})};return L(_),(s,e)=>{const i=o("el-button"),r=o("el-table-column"),B=o("el-table"),D=o("el-card"),I=o("el-input"),y=o("el-form-item"),E=o("el-option"),N=o("el-select"),U=o("el-form"),$=o("el-dialog"),F=T("loading");return c(),g("div",null,[l(D,null,{header:t(()=>[V("div",K,[e[6]||(e[6]=V("span",null,"商户员工管理",-1)),l(i,{type:"primary",onClick:e[0]||(e[0]=a=>x())},{default:t(()=>[...e[5]||(e[5]=[p("绑定商户员工",-1)])]),_:1})])]),default:t(()=>[A((c(),w(B,{data:v.value},{default:t(()=>[l(r,{prop:"id",label:"ID",width:"80"}),l(r,{prop:"phone",label:"手机号",width:"140"}),l(r,{prop:"nickname",label:"昵称"}),l(r,{prop:"storeName",label:"关联门店"}),l(r,{label:"操作",width:"120"},{default:t(({row:a})=>[l(i,{size:"small",type:"danger",onClick:P=>M(a.id)},{default:t(()=>[...e[7]||(e[7]=[p("解绑",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])),[[F,m.value]])]),_:1}),l($,{modelValue:u.value,"onUpdate:modelValue":e[4]||(e[4]=a=>u.value=a),title:"绑定商户员工",width:"450px"},{footer:t(()=>[l(i,{onClick:e[3]||(e[3]=a=>u.value=!1)},{default:t(()=>[...e[8]||(e[8]=[p("取消",-1)])]),_:1}),l(i,{type:"primary",loading:f.value,onClick:C},{default:t(()=>[...e[9]||(e[9]=[p("确定",-1)])]),_:1},8,["loading"])]),default:t(()=>[l(U,{model:n.value,"label-width":"80px"},{default:t(()=>[l(y,{label:"手机号"},{default:t(()=>[l(I,{modelValue:n.value.phone,"onUpdate:modelValue":e[1]||(e[1]=a=>n.value.phone=a),placeholder:"请输入员工手机号"},null,8,["modelValue"])]),_:1}),l(y,{label:"关联门店"},{default:t(()=>[l(N,{modelValue:n.value.storeId,"onUpdate:modelValue":e[2]||(e[2]=a=>n.value.storeId=a),placeholder:"请选择门店",style:{width:"100%"}},{default:t(()=>[(c(!0),g(G,null,H(b.value,a=>(c(),w(E,{key:a.id,label:a.name,value:a.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])])}}};export{W as default};

View File

@ -0,0 +1 @@
import{w,x}from"./index-BIlGw-iH.js";import{n as h,o as m,c as k,a as l,w as a,r as o,i as c,p as B,q as D,k as C,b as E,t as p,f as v,E as N}from"./index-DZCMG0nr.js";const P={style:{color:"#909399"}},S={__name:"PointsRule",setup(R){const i=c(!1),r=c(!1),e=c({chargeAmount:1,pointsValue:1,isActive:!0}),_=async()=>{i.value=!0;try{const u=await w();e.value={chargeAmount:u.data.chargeAmount,pointsValue:u.data.pointsValue,isActive:u.data.isActive}}catch{}finally{i.value=!1}},f=async()=>{r.value=!0;try{await x(e.value),N.success("保存成功")}catch{}finally{r.value=!1}};return h(_),(u,t)=>{const d=o("el-input-number"),n=o("el-form-item"),V=o("el-switch"),g=o("el-button"),b=o("el-form"),y=o("el-card"),A=B("loading");return m(),k("div",null,[l(y,null,{header:a(()=>[...t[3]||(t[3]=[v("积分规则配置",-1)])]),default:a(()=>[D((m(),C(b,{model:e.value,"label-width":"140px",style:{"max-width":"500px"}},{default:a(()=>[l(n,{label:"充电金额(元)"},{default:a(()=>[l(d,{modelValue:e.value.chargeAmount,"onUpdate:modelValue":t[0]||(t[0]=s=>e.value.chargeAmount=s),min:0,precision:2},null,8,["modelValue"])]),_:1}),l(n,{label:"对应积分"},{default:a(()=>[l(d,{modelValue:e.value.pointsValue,"onUpdate:modelValue":t[1]||(t[1]=s=>e.value.pointsValue=s),min:0},null,8,["modelValue"])]),_:1}),l(n,{label:"说明"},{default:a(()=>[E("span",P,"每充电 "+p(e.value.chargeAmount)+" 元获得 "+p(e.value.pointsValue)+" 积分",1)]),_:1}),l(n,{label:"状态"},{default:a(()=>[l(V,{modelValue:e.value.isActive,"onUpdate:modelValue":t[2]||(t[2]=s=>e.value.isActive=s),"active-text":"启用","inactive-text":"禁用"},null,8,["modelValue"])]),_:1}),l(n,null,{default:a(()=>[l(g,{type:"primary",loading:r.value,onClick:f},{default:a(()=>[...t[4]||(t[4]=[v("保存",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model"])),[[A,i.value]])]),_:1})])}}};export{S as default};

1
admin/dist/assets/Popups-CGrQ01iQ.js vendored Normal file
View File

@ -0,0 +1 @@
import{e as V,f as w}from"./index-BIlGw-iH.js";import{n as x,o as h,c as C,a,w as n,r as l,i as s,p as T,q as k,b as B,f as v,E as D}from"./index-DZCMG0nr.js";const E={style:{"margin-top":"16px","text-align":"right"}},U={__name:"Popups",setup(M){const o=s("verify-flow"),t=s(""),u=s(!1),r=s(!1),c=async()=>{u.value=!0;try{const p=await V(o.value);t.value=p.data.content}catch{t.value=""}finally{u.value=!1}},m=async()=>{r.value=!0;try{await w(o.value,{content:t.value}),D.success("保存成功")}catch{}finally{r.value=!1}};return x(c),(p,e)=>{const d=l("el-tab-pane"),_=l("el-tabs"),f=l("el-input"),b=l("el-button"),g=l("el-card"),y=T("loading");return h(),C("div",null,[a(g,null,{header:n(()=>[...e[2]||(e[2]=[v("弹窗内容管理",-1)])]),default:n(()=>[a(_,{modelValue:o.value,"onUpdate:modelValue":e[0]||(e[0]=i=>o.value=i),onTabChange:c},{default:n(()=>[a(d,{label:"核销流程说明",name:"verify-flow"}),a(d,{label:"积分说明",name:"points-desc"})]),_:1},8,["modelValue"]),k(a(f,{modelValue:t.value,"onUpdate:modelValue":e[1]||(e[1]=i=>t.value=i),type:"textarea",rows:15,placeholder:"请输入富文本内容支持HTML"},null,8,["modelValue"]),[[y,u.value]]),B("div",E,[a(b,{type:"primary",loading:r.value,onClick:m},{default:n(()=>[...e[3]||(e[3]=[v("保存",-1)])]),_:1},8,["loading"])])]),_:1})])}}};export{U as default};

1
admin/dist/assets/Stores-CoU8jSOf.js vendored Normal file

File diff suppressed because one or more lines are too long

1
admin/dist/assets/Users-C0j1-JQR.js vendored Normal file
View File

@ -0,0 +1 @@
import{v as h}from"./index-BIlGw-iH.js";import{n as v,o as c,c as b,a as e,w as l,r as n,i,p as w,q as D,k as g,f as p,t as k}from"./index-DZCMG0nr.js";const N={__name:"Users",setup(x){const s=i([]),o=i(!1),d=a=>a?new Date(a).toLocaleString("zh-CN"):"-";return v(async()=>{o.value=!0;try{const a=await h();s.value=a.data}catch{}finally{o.value=!1}}),(a,r)=>{const t=n("el-table-column"),u=n("el-table"),_=n("el-card"),f=w("loading");return c(),b("div",null,[e(_,null,{header:l(()=>[...r[0]||(r[0]=[p("用户管理",-1)])]),default:l(()=>[D((c(),g(u,{data:s.value},{default:l(()=>[e(t,{prop:"id",label:"ID",width:"60"}),e(t,{prop:"uid",label:"UID",width:"100"}),e(t,{prop:"phone",label:"手机号",width:"130"}),e(t,{prop:"nickname",label:"昵称"}),e(t,{prop:"points",label:"积分余额",width:"100"}),e(t,{prop:"couponCount",label:"持有优惠券",width:"100"}),e(t,{label:"注册时间",width:"170"},{default:l(({row:m})=>[p(k(d(m.createdAt)),1)]),_:1})]),_:1},8,["data"])),[[f,o.value]])]),_:1})])}}};export{N as default};

View File

@ -0,0 +1 @@
import{h as x,t as N}from"./index-BIlGw-iH.js";import{n as B,o as m,c as h,a as e,w as a,i as f,r as n,h as R,p as U,F,v as L,k as V,f as c,q as O,t as v}from"./index-DZCMG0nr.js";const E={__name:"VerifyRecords",setup(q){const y=f([]),b=f([]),_=f(!1),d=f([]),o=R({storeId:null,verifyType:""}),w=r=>r?new Date(r).toLocaleString("zh-CN"):"-",i=async()=>{var r;_.value=!0;try{const l={};o.storeId&&(l.storeId=o.storeId),o.verifyType&&(l.verifyType=o.verifyType),((r=d.value)==null?void 0:r.length)===2&&(l.startDate=d.value[0].toISOString(),l.endDate=d.value[1].toISOString());const u=await N(l);y.value=u.data}catch{}finally{_.value=!1}};return B(async()=>{try{const r=await x();b.value=r.data}catch{}i()}),(r,l)=>{const u=n("el-option"),g=n("el-select"),p=n("el-form-item"),D=n("el-date-picker"),I=n("el-button"),T=n("el-form"),s=n("el-table-column"),k=n("el-table"),C=n("el-card"),S=U("loading");return m(),h("div",null,[e(C,null,{header:a(()=>[...l[3]||(l[3]=[c("核销记录",-1)])]),default:a(()=>[e(T,{inline:!0,model:o,style:{"margin-bottom":"16px"}},{default:a(()=>[e(p,{label:"门店"},{default:a(()=>[e(g,{modelValue:o.storeId,"onUpdate:modelValue":l[0]||(l[0]=t=>o.storeId=t),placeholder:"全部门店",clearable:"",onChange:i},{default:a(()=>[(m(!0),h(F,null,L(b.value,t=>(m(),V(u,{key:t.id,label:t.name,value:t.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1}),e(p,{label:"核销类型"},{default:a(()=>[e(g,{modelValue:o.verifyType,"onUpdate:modelValue":l[1]||(l[1]=t=>o.verifyType=t),placeholder:"全部类型",clearable:"",onChange:i},{default:a(()=>[e(u,{label:"扫码",value:"scan"}),e(u,{label:"券码",value:"code"})]),_:1},8,["modelValue"])]),_:1}),e(p,{label:"时间范围"},{default:a(()=>[e(D,{modelValue:d.value,"onUpdate:modelValue":l[2]||(l[2]=t=>d.value=t),type:"daterange","start-placeholder":"开始日期","end-placeholder":"结束日期",onChange:i},null,8,["modelValue"])]),_:1}),e(p,null,{default:a(()=>[e(I,{type:"primary",onClick:i},{default:a(()=>[...l[4]||(l[4]=[c("查询",-1)])]),_:1})]),_:1})]),_:1},8,["model"]),O((m(),V(k,{data:y.value},{default:a(()=>[e(s,{prop:"id",label:"ID",width:"60"}),e(s,{prop:"couponName",label:"优惠券名称"}),e(s,{prop:"couponCode",label:"券码",width:"120"}),e(s,{label:"优惠券类型",width:"100"},{default:a(({row:t})=>[c(v(t.couponType==="free"?"免费券":"抵扣券"),1)]),_:1}),e(s,{prop:"storeName",label:"门店"}),e(s,{label:"核销类型",width:"90"},{default:a(({row:t})=>[c(v(t.verifyType==="scan"?"扫码":"券码"),1)]),_:1}),e(s,{prop:"userPhone",label:"用户手机号",width:"130"}),e(s,{label:"核销时间",width:"170"},{default:a(({row:t})=>[c(v(w(t.verifiedAt)),1)]),_:1})]),_:1},8,["data"])),[[S,_.value]])]),_:1})])}}};export{E as default};

6
admin/dist/assets/index-BIlGw-iH.js vendored Normal file

File diff suppressed because one or more lines are too long

1
admin/dist/assets/index-CnG6cTCG.css vendored Normal file

File diff suppressed because one or more lines are too long

66
admin/dist/assets/index-DZCMG0nr.js vendored Normal file

File diff suppressed because one or more lines are too long

13
admin/dist/index.html vendored Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>黄岩停车积分 - 管理后台</title>
<script type="module" crossorigin src="/assets/index-DZCMG0nr.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CnG6cTCG.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

12
admin/index.html Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>黄岩停车积分 - 管理后台</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

16
admin/node_modules/.bin/esbuild generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../esbuild/bin/esbuild" "$@"
else
exec node "$basedir/../esbuild/bin/esbuild" "$@"
fi

17
admin/node_modules/.bin/esbuild.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\esbuild\bin\esbuild" %*

28
admin/node_modules/.bin/esbuild.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../esbuild/bin/esbuild" $args
} else {
& "$basedir/node$exe" "$basedir/../esbuild/bin/esbuild" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../esbuild/bin/esbuild" $args
} else {
& "node$exe" "$basedir/../esbuild/bin/esbuild" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
admin/node_modules/.bin/nanoid generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../nanoid/bin/nanoid.cjs" "$@"
else
exec node "$basedir/../nanoid/bin/nanoid.cjs" "$@"
fi

17
admin/node_modules/.bin/nanoid.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nanoid\bin\nanoid.cjs" %*

28
admin/node_modules/.bin/nanoid.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
} else {
& "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
} else {
& "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
admin/node_modules/.bin/parser generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../@babel/parser/bin/babel-parser.js" "$@"
else
exec node "$basedir/../@babel/parser/bin/babel-parser.js" "$@"
fi

17
admin/node_modules/.bin/parser.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@babel\parser\bin\babel-parser.js" %*

28
admin/node_modules/.bin/parser.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
} else {
& "$basedir/node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
} else {
& "node$exe" "$basedir/../@babel/parser/bin/babel-parser.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
admin/node_modules/.bin/rollup generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../rollup/dist/bin/rollup" "$@"
else
exec node "$basedir/../rollup/dist/bin/rollup" "$@"
fi

17
admin/node_modules/.bin/rollup.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\rollup\dist\bin\rollup" %*

28
admin/node_modules/.bin/rollup.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../rollup/dist/bin/rollup" $args
} else {
& "$basedir/node$exe" "$basedir/../rollup/dist/bin/rollup" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../rollup/dist/bin/rollup" $args
} else {
& "node$exe" "$basedir/../rollup/dist/bin/rollup" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
admin/node_modules/.bin/vite generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../vite/bin/vite.js" "$@"
else
exec node "$basedir/../vite/bin/vite.js" "$@"
fi

17
admin/node_modules/.bin/vite.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\vite\bin\vite.js" %*

28
admin/node_modules/.bin/vite.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args
} else {
& "$basedir/node$exe" "$basedir/../vite/bin/vite.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../vite/bin/vite.js" $args
} else {
& "node$exe" "$basedir/../vite/bin/vite.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
admin/node_modules/.bin/vue-demi-fix generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../vue-demi/bin/vue-demi-fix.js" "$@"
else
exec node "$basedir/../vue-demi/bin/vue-demi-fix.js" "$@"
fi

17
admin/node_modules/.bin/vue-demi-fix.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\vue-demi\bin\vue-demi-fix.js" %*

28
admin/node_modules/.bin/vue-demi-fix.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../vue-demi/bin/vue-demi-fix.js" $args
} else {
& "$basedir/node$exe" "$basedir/../vue-demi/bin/vue-demi-fix.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../vue-demi/bin/vue-demi-fix.js" $args
} else {
& "node$exe" "$basedir/../vue-demi/bin/vue-demi-fix.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

16
admin/node_modules/.bin/vue-demi-switch generated vendored Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../vue-demi/bin/vue-demi-switch.js" "$@"
else
exec node "$basedir/../vue-demi/bin/vue-demi-switch.js" "$@"
fi

17
admin/node_modules/.bin/vue-demi-switch.cmd generated vendored Normal file
View File

@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\vue-demi\bin\vue-demi-switch.js" %*

28
admin/node_modules/.bin/vue-demi-switch.ps1 generated vendored Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../vue-demi/bin/vue-demi-switch.js" $args
} else {
& "$basedir/node$exe" "$basedir/../vue-demi/bin/vue-demi-switch.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../vue-demi/bin/vue-demi-switch.js" $args
} else {
& "node$exe" "$basedir/../vue-demi/bin/vue-demi-switch.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

1021
admin/node_modules/.package-lock.json generated vendored Normal file

File diff suppressed because it is too large Load Diff

22
admin/node_modules/@babel/helper-string-parser/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,19 @@
# @babel/helper-string-parser
> A utility package to parse strings
See our website [@babel/helper-string-parser](https://babeljs.io/docs/babel-helper-string-parser) for more information.
## Install
Using npm:
```sh
npm install --save @babel/helper-string-parser
```
or using yarn:
```sh
yarn add @babel/helper-string-parser
```

View File

@ -0,0 +1,295 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.readCodePoint = readCodePoint;
exports.readInt = readInt;
exports.readStringContents = readStringContents;
var _isDigit = function isDigit(code) {
return code >= 48 && code <= 57;
};
const forbiddenNumericSeparatorSiblings = {
decBinOct: new Set([46, 66, 69, 79, 95, 98, 101, 111]),
hex: new Set([46, 88, 95, 120])
};
const isAllowedNumericSeparatorSibling = {
bin: ch => ch === 48 || ch === 49,
oct: ch => ch >= 48 && ch <= 55,
dec: ch => ch >= 48 && ch <= 57,
hex: ch => ch >= 48 && ch <= 57 || ch >= 65 && ch <= 70 || ch >= 97 && ch <= 102
};
function readStringContents(type, input, pos, lineStart, curLine, errors) {
const initialPos = pos;
const initialLineStart = lineStart;
const initialCurLine = curLine;
let out = "";
let firstInvalidLoc = null;
let chunkStart = pos;
const {
length
} = input;
for (;;) {
if (pos >= length) {
errors.unterminated(initialPos, initialLineStart, initialCurLine);
out += input.slice(chunkStart, pos);
break;
}
const ch = input.charCodeAt(pos);
if (isStringEnd(type, ch, input, pos)) {
out += input.slice(chunkStart, pos);
break;
}
if (ch === 92) {
out += input.slice(chunkStart, pos);
const res = readEscapedChar(input, pos, lineStart, curLine, type === "template", errors);
if (res.ch === null && !firstInvalidLoc) {
firstInvalidLoc = {
pos,
lineStart,
curLine
};
} else {
out += res.ch;
}
({
pos,
lineStart,
curLine
} = res);
chunkStart = pos;
} else if (ch === 8232 || ch === 8233) {
++pos;
++curLine;
lineStart = pos;
} else if (ch === 10 || ch === 13) {
if (type === "template") {
out += input.slice(chunkStart, pos) + "\n";
++pos;
if (ch === 13 && input.charCodeAt(pos) === 10) {
++pos;
}
++curLine;
chunkStart = lineStart = pos;
} else {
errors.unterminated(initialPos, initialLineStart, initialCurLine);
}
} else {
++pos;
}
}
return {
pos,
str: out,
firstInvalidLoc,
lineStart,
curLine,
containsInvalid: !!firstInvalidLoc
};
}
function isStringEnd(type, ch, input, pos) {
if (type === "template") {
return ch === 96 || ch === 36 && input.charCodeAt(pos + 1) === 123;
}
return ch === (type === "double" ? 34 : 39);
}
function readEscapedChar(input, pos, lineStart, curLine, inTemplate, errors) {
const throwOnInvalid = !inTemplate;
pos++;
const res = ch => ({
pos,
ch,
lineStart,
curLine
});
const ch = input.charCodeAt(pos++);
switch (ch) {
case 110:
return res("\n");
case 114:
return res("\r");
case 120:
{
let code;
({
code,
pos
} = readHexChar(input, pos, lineStart, curLine, 2, false, throwOnInvalid, errors));
return res(code === null ? null : String.fromCharCode(code));
}
case 117:
{
let code;
({
code,
pos
} = readCodePoint(input, pos, lineStart, curLine, throwOnInvalid, errors));
return res(code === null ? null : String.fromCodePoint(code));
}
case 116:
return res("\t");
case 98:
return res("\b");
case 118:
return res("\u000b");
case 102:
return res("\f");
case 13:
if (input.charCodeAt(pos) === 10) {
++pos;
}
case 10:
lineStart = pos;
++curLine;
case 8232:
case 8233:
return res("");
case 56:
case 57:
if (inTemplate) {
return res(null);
} else {
errors.strictNumericEscape(pos - 1, lineStart, curLine);
}
default:
if (ch >= 48 && ch <= 55) {
const startPos = pos - 1;
const match = /^[0-7]+/.exec(input.slice(startPos, pos + 2));
let octalStr = match[0];
let octal = parseInt(octalStr, 8);
if (octal > 255) {
octalStr = octalStr.slice(0, -1);
octal = parseInt(octalStr, 8);
}
pos += octalStr.length - 1;
const next = input.charCodeAt(pos);
if (octalStr !== "0" || next === 56 || next === 57) {
if (inTemplate) {
return res(null);
} else {
errors.strictNumericEscape(startPos, lineStart, curLine);
}
}
return res(String.fromCharCode(octal));
}
return res(String.fromCharCode(ch));
}
}
function readHexChar(input, pos, lineStart, curLine, len, forceLen, throwOnInvalid, errors) {
const initialPos = pos;
let n;
({
n,
pos
} = readInt(input, pos, lineStart, curLine, 16, len, forceLen, false, errors, !throwOnInvalid));
if (n === null) {
if (throwOnInvalid) {
errors.invalidEscapeSequence(initialPos, lineStart, curLine);
} else {
pos = initialPos - 1;
}
}
return {
code: n,
pos
};
}
function readInt(input, pos, lineStart, curLine, radix, len, forceLen, allowNumSeparator, errors, bailOnError) {
const start = pos;
const forbiddenSiblings = radix === 16 ? forbiddenNumericSeparatorSiblings.hex : forbiddenNumericSeparatorSiblings.decBinOct;
const isAllowedSibling = radix === 16 ? isAllowedNumericSeparatorSibling.hex : radix === 10 ? isAllowedNumericSeparatorSibling.dec : radix === 8 ? isAllowedNumericSeparatorSibling.oct : isAllowedNumericSeparatorSibling.bin;
let invalid = false;
let total = 0;
for (let i = 0, e = len == null ? Infinity : len; i < e; ++i) {
const code = input.charCodeAt(pos);
let val;
if (code === 95 && allowNumSeparator !== "bail") {
const prev = input.charCodeAt(pos - 1);
const next = input.charCodeAt(pos + 1);
if (!allowNumSeparator) {
if (bailOnError) return {
n: null,
pos
};
errors.numericSeparatorInEscapeSequence(pos, lineStart, curLine);
} else if (Number.isNaN(next) || !isAllowedSibling(next) || forbiddenSiblings.has(prev) || forbiddenSiblings.has(next)) {
if (bailOnError) return {
n: null,
pos
};
errors.unexpectedNumericSeparator(pos, lineStart, curLine);
}
++pos;
continue;
}
if (code >= 97) {
val = code - 97 + 10;
} else if (code >= 65) {
val = code - 65 + 10;
} else if (_isDigit(code)) {
val = code - 48;
} else {
val = Infinity;
}
if (val >= radix) {
if (val <= 9 && bailOnError) {
return {
n: null,
pos
};
} else if (val <= 9 && errors.invalidDigit(pos, lineStart, curLine, radix)) {
val = 0;
} else if (forceLen) {
val = 0;
invalid = true;
} else {
break;
}
}
++pos;
total = total * radix + val;
}
if (pos === start || len != null && pos - start !== len || invalid) {
return {
n: null,
pos
};
}
return {
n: total,
pos
};
}
function readCodePoint(input, pos, lineStart, curLine, throwOnInvalid, errors) {
const ch = input.charCodeAt(pos);
let code;
if (ch === 123) {
++pos;
({
code,
pos
} = readHexChar(input, pos, lineStart, curLine, input.indexOf("}", pos) - pos, true, throwOnInvalid, errors));
++pos;
if (code !== null && code > 0x10ffff) {
if (throwOnInvalid) {
errors.invalidCodePoint(pos, lineStart, curLine);
} else {
return {
code: null,
pos
};
}
}
} else {
({
code,
pos
} = readHexChar(input, pos, lineStart, curLine, 4, false, throwOnInvalid, errors));
}
return {
code,
pos
};
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,31 @@
{
"name": "@babel/helper-string-parser",
"version": "7.27.1",
"description": "A utility package to parse strings",
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-helper-string-parser"
},
"homepage": "https://babel.dev/docs/en/next/babel-helper-string-parser",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"main": "./lib/index.js",
"devDependencies": {
"charcodes": "^0.2.0"
},
"engines": {
"node": ">=6.9.0"
},
"author": "The Babel Team (https://babel.dev/team)",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
},
"./package.json": "./package.json"
},
"type": "commonjs"
}

View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,19 @@
# @babel/helper-validator-identifier
> Validate identifier/keywords name
See our website [@babel/helper-validator-identifier](https://babeljs.io/docs/babel-helper-validator-identifier) for more information.
## Install
Using npm:
```sh
npm install --save @babel/helper-validator-identifier
```
or using yarn:
```sh
yarn add @babel/helper-validator-identifier
```

View File

@ -0,0 +1,70 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isIdentifierChar = isIdentifierChar;
exports.isIdentifierName = isIdentifierName;
exports.isIdentifierStart = isIdentifierStart;
let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088f\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5c\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdc-\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7dc\ua7f1-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
let nonASCIIidentifierChars = "\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1add\u1ae0-\u1aeb\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65";
const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 4, 51, 13, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 7, 25, 39, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 39, 27, 10, 22, 251, 41, 7, 1, 17, 5, 57, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 20, 1, 64, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 31, 9, 2, 0, 3, 0, 2, 37, 2, 0, 26, 0, 2, 0, 45, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 200, 32, 32, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 24, 43, 261, 18, 16, 0, 2, 12, 2, 33, 125, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1071, 18, 5, 26, 3994, 6, 582, 6842, 29, 1763, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 433, 44, 212, 63, 33, 24, 3, 24, 45, 74, 6, 0, 67, 12, 65, 1, 2, 0, 15, 4, 10, 7381, 42, 31, 98, 114, 8702, 3, 2, 6, 2, 1, 2, 290, 16, 0, 30, 2, 3, 0, 15, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 7, 5, 262, 61, 147, 44, 11, 6, 17, 0, 322, 29, 19, 43, 485, 27, 229, 29, 3, 0, 208, 30, 2, 2, 2, 1, 2, 6, 3, 4, 10, 1, 225, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4381, 3, 5773, 3, 7472, 16, 621, 2467, 541, 1507, 4938, 6, 8489];
const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 7, 9, 32, 4, 318, 1, 78, 5, 71, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 3, 0, 158, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 68, 8, 2, 0, 3, 0, 2, 3, 2, 4, 2, 0, 15, 1, 83, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 7, 19, 58, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 199, 7, 137, 9, 54, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 55, 9, 266, 3, 10, 1, 2, 0, 49, 6, 4, 4, 14, 10, 5350, 0, 7, 14, 11465, 27, 2343, 9, 87, 9, 39, 4, 60, 6, 26, 9, 535, 9, 470, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4178, 9, 519, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 101, 0, 161, 6, 10, 9, 357, 0, 62, 13, 499, 13, 245, 1, 2, 9, 233, 0, 3, 0, 8, 1, 6, 0, 475, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];
function isInAstralSet(code, set) {
let pos = 0x10000;
for (let i = 0, length = set.length; i < length; i += 2) {
pos += set[i];
if (pos > code) return false;
pos += set[i + 1];
if (pos >= code) return true;
}
return false;
}
function isIdentifierStart(code) {
if (code < 65) return code === 36;
if (code <= 90) return true;
if (code < 97) return code === 95;
if (code <= 122) return true;
if (code <= 0xffff) {
return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
}
return isInAstralSet(code, astralIdentifierStartCodes);
}
function isIdentifierChar(code) {
if (code < 48) return code === 36;
if (code < 58) return true;
if (code < 65) return false;
if (code <= 90) return true;
if (code < 97) return code === 95;
if (code <= 122) return true;
if (code <= 0xffff) {
return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
}
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
}
function isIdentifierName(name) {
let isFirst = true;
for (let i = 0; i < name.length; i++) {
let cp = name.charCodeAt(i);
if ((cp & 0xfc00) === 0xd800 && i + 1 < name.length) {
const trail = name.charCodeAt(++i);
if ((trail & 0xfc00) === 0xdc00) {
cp = 0x10000 + ((cp & 0x3ff) << 10) + (trail & 0x3ff);
}
}
if (isFirst) {
isFirst = false;
if (!isIdentifierStart(cp)) {
return false;
}
} else if (!isIdentifierChar(cp)) {
return false;
}
}
return !isFirst;
}
//# sourceMappingURL=identifier.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "isIdentifierChar", {
enumerable: true,
get: function () {
return _identifier.isIdentifierChar;
}
});
Object.defineProperty(exports, "isIdentifierName", {
enumerable: true,
get: function () {
return _identifier.isIdentifierName;
}
});
Object.defineProperty(exports, "isIdentifierStart", {
enumerable: true,
get: function () {
return _identifier.isIdentifierStart;
}
});
Object.defineProperty(exports, "isKeyword", {
enumerable: true,
get: function () {
return _keyword.isKeyword;
}
});
Object.defineProperty(exports, "isReservedWord", {
enumerable: true,
get: function () {
return _keyword.isReservedWord;
}
});
Object.defineProperty(exports, "isStrictBindOnlyReservedWord", {
enumerable: true,
get: function () {
return _keyword.isStrictBindOnlyReservedWord;
}
});
Object.defineProperty(exports, "isStrictBindReservedWord", {
enumerable: true,
get: function () {
return _keyword.isStrictBindReservedWord;
}
});
Object.defineProperty(exports, "isStrictReservedWord", {
enumerable: true,
get: function () {
return _keyword.isStrictReservedWord;
}
});
var _identifier = require("./identifier.js");
var _keyword = require("./keyword.js");
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_identifier","require","_keyword"],"sources":["../src/index.ts"],"sourcesContent":["export {\n isIdentifierName,\n isIdentifierChar,\n isIdentifierStart,\n} from \"./identifier.ts\";\nexport {\n isReservedWord,\n isStrictBindOnlyReservedWord,\n isStrictBindReservedWord,\n isStrictReservedWord,\n isKeyword,\n} from \"./keyword.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,WAAA,GAAAC,OAAA;AAKA,IAAAC,QAAA,GAAAD,OAAA","ignoreList":[]}

View File

@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isKeyword = isKeyword;
exports.isReservedWord = isReservedWord;
exports.isStrictBindOnlyReservedWord = isStrictBindOnlyReservedWord;
exports.isStrictBindReservedWord = isStrictBindReservedWord;
exports.isStrictReservedWord = isStrictReservedWord;
const reservedWords = {
keyword: ["break", "case", "catch", "continue", "debugger", "default", "do", "else", "finally", "for", "function", "if", "return", "switch", "throw", "try", "var", "const", "while", "with", "new", "this", "super", "class", "extends", "export", "import", "null", "true", "false", "in", "instanceof", "typeof", "void", "delete"],
strict: ["implements", "interface", "let", "package", "private", "protected", "public", "static", "yield"],
strictBind: ["eval", "arguments"]
};
const keywords = new Set(reservedWords.keyword);
const reservedWordsStrictSet = new Set(reservedWords.strict);
const reservedWordsStrictBindSet = new Set(reservedWords.strictBind);
function isReservedWord(word, inModule) {
return inModule && word === "await" || word === "enum";
}
function isStrictReservedWord(word, inModule) {
return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);
}
function isStrictBindOnlyReservedWord(word) {
return reservedWordsStrictBindSet.has(word);
}
function isStrictBindReservedWord(word, inModule) {
return isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word);
}
function isKeyword(word) {
return keywords.has(word);
}
//# sourceMappingURL=keyword.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["reservedWords","keyword","strict","strictBind","keywords","Set","reservedWordsStrictSet","reservedWordsStrictBindSet","isReservedWord","word","inModule","isStrictReservedWord","has","isStrictBindOnlyReservedWord","isStrictBindReservedWord","isKeyword"],"sources":["../src/keyword.ts"],"sourcesContent":["const reservedWords = {\n keyword: [\n \"break\",\n \"case\",\n \"catch\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"do\",\n \"else\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"return\",\n \"switch\",\n \"throw\",\n \"try\",\n \"var\",\n \"const\",\n \"while\",\n \"with\",\n \"new\",\n \"this\",\n \"super\",\n \"class\",\n \"extends\",\n \"export\",\n \"import\",\n \"null\",\n \"true\",\n \"false\",\n \"in\",\n \"instanceof\",\n \"typeof\",\n \"void\",\n \"delete\",\n ],\n strict: [\n \"implements\",\n \"interface\",\n \"let\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"static\",\n \"yield\",\n ],\n strictBind: [\"eval\", \"arguments\"],\n};\nconst keywords = new Set(reservedWords.keyword);\nconst reservedWordsStrictSet = new Set(reservedWords.strict);\nconst reservedWordsStrictBindSet = new Set(reservedWords.strictBind);\n\n/**\n * Checks if word is a reserved word in non-strict mode\n */\nexport function isReservedWord(word: string, inModule: boolean): boolean {\n return (inModule && word === \"await\") || word === \"enum\";\n}\n\n/**\n * Checks if word is a reserved word in non-binding strict mode\n *\n * Includes non-strict reserved words\n */\nexport function isStrictReservedWord(word: string, inModule: boolean): boolean {\n return isReservedWord(word, inModule) || reservedWordsStrictSet.has(word);\n}\n\n/**\n * Checks if word is a reserved word in binding strict mode, but it is allowed as\n * a normal identifier.\n */\nexport function isStrictBindOnlyReservedWord(word: string): boolean {\n return reservedWordsStrictBindSet.has(word);\n}\n\n/**\n * Checks if word is a reserved word in binding strict mode\n *\n * Includes non-strict reserved words and non-binding strict reserved words\n */\nexport function isStrictBindReservedWord(\n word: string,\n inModule: boolean,\n): boolean {\n return (\n isStrictReservedWord(word, inModule) || isStrictBindOnlyReservedWord(word)\n );\n}\n\nexport function isKeyword(word: string): boolean {\n return keywords.has(word);\n}\n"],"mappings":";;;;;;;;;;AAAA,MAAMA,aAAa,GAAG;EACpBC,OAAO,EAAE,CACP,OAAO,EACP,MAAM,EACN,OAAO,EACP,UAAU,EACV,UAAU,EACV,SAAS,EACT,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,KAAK,EACL,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,MAAM,EACN,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,QAAQ,CACT;EACDC,MAAM,EAAE,CACN,YAAY,EACZ,WAAW,EACX,KAAK,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,OAAO,CACR;EACDC,UAAU,EAAE,CAAC,MAAM,EAAE,WAAW;AAClC,CAAC;AACD,MAAMC,QAAQ,GAAG,IAAIC,GAAG,CAACL,aAAa,CAACC,OAAO,CAAC;AAC/C,MAAMK,sBAAsB,GAAG,IAAID,GAAG,CAACL,aAAa,CAACE,MAAM,CAAC;AAC5D,MAAMK,0BAA0B,GAAG,IAAIF,GAAG,CAACL,aAAa,CAACG,UAAU,CAAC;AAK7D,SAASK,cAAcA,CAACC,IAAY,EAAEC,QAAiB,EAAW;EACvE,OAAQA,QAAQ,IAAID,IAAI,KAAK,OAAO,IAAKA,IAAI,KAAK,MAAM;AAC1D;AAOO,SAASE,oBAAoBA,CAACF,IAAY,EAAEC,QAAiB,EAAW;EAC7E,OAAOF,cAAc,CAACC,IAAI,EAAEC,QAAQ,CAAC,IAAIJ,sBAAsB,CAACM,GAAG,CAACH,IAAI,CAAC;AAC3E;AAMO,SAASI,4BAA4BA,CAACJ,IAAY,EAAW;EAClE,OAAOF,0BAA0B,CAACK,GAAG,CAACH,IAAI,CAAC;AAC7C;AAOO,SAASK,wBAAwBA,CACtCL,IAAY,EACZC,QAAiB,EACR;EACT,OACEC,oBAAoB,CAACF,IAAI,EAAEC,QAAQ,CAAC,IAAIG,4BAA4B,CAACJ,IAAI,CAAC;AAE9E;AAEO,SAASM,SAASA,CAACN,IAAY,EAAW;EAC/C,OAAOL,QAAQ,CAACQ,GAAG,CAACH,IAAI,CAAC;AAC3B","ignoreList":[]}

View File

@ -0,0 +1,31 @@
{
"name": "@babel/helper-validator-identifier",
"version": "7.28.5",
"description": "Validate identifier/keywords name",
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-helper-validator-identifier"
},
"license": "MIT",
"publishConfig": {
"access": "public"
},
"main": "./lib/index.js",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
},
"./package.json": "./package.json"
},
"devDependencies": {
"@unicode/unicode-17.0.0": "^1.6.10",
"charcodes": "^0.2.0"
},
"engines": {
"node": ">=6.9.0"
},
"author": "The Babel Team (https://babel.dev/team)",
"type": "commonjs"
}

1073
admin/node_modules/@babel/parser/CHANGELOG.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

19
admin/node_modules/@babel/parser/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (C) 2012-2014 by various contributors (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

19
admin/node_modules/@babel/parser/README.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# @babel/parser
> A JavaScript parser
See our website [@babel/parser](https://babeljs.io/docs/babel-parser) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20parser%22+is%3Aopen) associated with this package.
## Install
Using npm:
```sh
npm install --save-dev @babel/parser
```
or using yarn:
```sh
yarn add @babel/parser --dev
```

15
admin/node_modules/@babel/parser/bin/babel-parser.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env node
/* eslint-disable no-var, unicorn/prefer-node-protocol */
var parser = require("..");
var fs = require("fs");
var filename = process.argv[2];
if (!filename) {
console.error("no filename specified");
} else {
var file = fs.readFileSync(filename, "utf8");
var ast = parser.parse(file);
console.log(JSON.stringify(ast, null, " "));
}

14582
admin/node_modules/@babel/parser/lib/index.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
admin/node_modules/@babel/parser/lib/index.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

50
admin/node_modules/@babel/parser/package.json generated vendored Normal file
View File

@ -0,0 +1,50 @@
{
"name": "@babel/parser",
"version": "7.29.0",
"description": "A JavaScript parser",
"author": "The Babel Team (https://babel.dev/team)",
"homepage": "https://babel.dev/docs/en/next/babel-parser",
"bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A+parser+%28babylon%29%22+is%3Aopen",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"keywords": [
"babel",
"javascript",
"parser",
"tc39",
"ecmascript",
"@babel/parser"
],
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-parser"
},
"main": "./lib/index.js",
"types": "./typings/babel-parser.d.ts",
"files": [
"bin",
"lib",
"typings/babel-parser.d.ts",
"index.cjs"
],
"engines": {
"node": ">=6.0.0"
},
"# dependencies": "This package doesn't actually have runtime dependencies. @babel/types is only needed for type definitions.",
"dependencies": {
"@babel/types": "^7.29.0"
},
"devDependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/helper-check-duplicate-nodes": "^7.28.6",
"@babel/helper-fixtures": "^7.28.6",
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5",
"charcodes": "^0.2.0"
},
"bin": "./bin/babel-parser.js",
"type": "commonjs"
}

View File

@ -0,0 +1,262 @@
// This file is auto-generated! Do not modify it directly.
// Run `yarn gulp bundle-dts` to re-generate it.
/* eslint-disable @typescript-eslint/consistent-type-imports, @typescript-eslint/no-redundant-type-constituents */
import { File, Expression } from '@babel/types';
declare class Position {
line: number;
column: number;
index: number;
constructor(line: number, col: number, index: number);
}
type SyntaxPlugin = "flow" | "typescript" | "jsx" | "pipelineOperator" | "placeholders";
type ParseErrorCode = "BABEL_PARSER_SYNTAX_ERROR" | "BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED";
interface ParseErrorSpecification<ErrorDetails> {
code: ParseErrorCode;
reasonCode: string;
syntaxPlugin?: SyntaxPlugin;
missingPlugin?: string | string[];
loc: Position;
details: ErrorDetails;
pos: number;
}
type ParseError$1<ErrorDetails> = SyntaxError & ParseErrorSpecification<ErrorDetails>;
type BABEL_8_BREAKING = false;
type IF_BABEL_7<V> = false extends BABEL_8_BREAKING ? V : never;
type Plugin$1 =
| "asyncDoExpressions"
| IF_BABEL_7<"asyncGenerators">
| IF_BABEL_7<"bigInt">
| IF_BABEL_7<"classPrivateMethods">
| IF_BABEL_7<"classPrivateProperties">
| IF_BABEL_7<"classProperties">
| IF_BABEL_7<"classStaticBlock">
| IF_BABEL_7<"decimal">
| "decorators-legacy"
| "deferredImportEvaluation"
| "decoratorAutoAccessors"
| "destructuringPrivate"
| IF_BABEL_7<"deprecatedImportAssert">
| "doExpressions"
| IF_BABEL_7<"dynamicImport">
| IF_BABEL_7<"explicitResourceManagement">
| "exportDefaultFrom"
| IF_BABEL_7<"exportNamespaceFrom">
| "flow"
| "flowComments"
| "functionBind"
| "functionSent"
| "importMeta"
| "jsx"
| IF_BABEL_7<"jsonStrings">
| IF_BABEL_7<"logicalAssignment">
| IF_BABEL_7<"importAssertions">
| IF_BABEL_7<"importReflection">
| "moduleBlocks"
| IF_BABEL_7<"moduleStringNames">
| IF_BABEL_7<"nullishCoalescingOperator">
| IF_BABEL_7<"numericSeparator">
| IF_BABEL_7<"objectRestSpread">
| IF_BABEL_7<"optionalCatchBinding">
| IF_BABEL_7<"optionalChaining">
| "partialApplication"
| "placeholders"
| IF_BABEL_7<"privateIn">
| IF_BABEL_7<"regexpUnicodeSets">
| "sourcePhaseImports"
| "throwExpressions"
| IF_BABEL_7<"topLevelAwait">
| "v8intrinsic"
| ParserPluginWithOptions[0];
type ParserPluginWithOptions =
| ["decorators", DecoratorsPluginOptions]
| ["discardBinding", { syntaxType: "void" }]
| ["estree", { classFeatures?: boolean }]
| IF_BABEL_7<["importAttributes", { deprecatedAssertSyntax: boolean }]>
| IF_BABEL_7<["moduleAttributes", { version: "may-2020" }]>
| ["optionalChainingAssign", { version: "2023-07" }]
| ["pipelineOperator", PipelineOperatorPluginOptions]
| ["recordAndTuple", RecordAndTuplePluginOptions]
| ["flow", FlowPluginOptions]
| ["typescript", TypeScriptPluginOptions];
type PluginConfig = Plugin$1 | ParserPluginWithOptions;
interface DecoratorsPluginOptions {
decoratorsBeforeExport?: boolean;
allowCallParenthesized?: boolean;
}
interface PipelineOperatorPluginOptions {
proposal: BABEL_8_BREAKING extends false
? "minimal" | "fsharp" | "hack" | "smart"
: "fsharp" | "hack";
topicToken?: "%" | "#" | "@@" | "^^" | "^";
}
interface RecordAndTuplePluginOptions {
syntaxType: "bar" | "hash";
}
type FlowPluginOptions = BABEL_8_BREAKING extends true
? {
all?: boolean;
enums?: boolean;
}
: {
all?: boolean;
};
interface TypeScriptPluginOptions {
dts?: boolean;
disallowAmbiguousJSXLike?: boolean;
}
type Plugin = PluginConfig;
type SourceType = "script" | "commonjs" | "module" | "unambiguous";
interface Options {
/**
* By default, import and export declarations can only appear at a program's top level.
* Setting this option to true allows them anywhere where a statement is allowed.
*/
allowImportExportEverywhere?: boolean;
/**
* By default, await use is not allowed outside of an async function.
* Set this to true to accept such code.
*/
allowAwaitOutsideFunction?: boolean;
/**
* By default, a return statement at the top level raises an error.
* Set this to true to accept such code.
*/
allowReturnOutsideFunction?: boolean;
/**
* By default, new.target use is not allowed outside of a function or class.
* Set this to true to accept such code.
*/
allowNewTargetOutsideFunction?: boolean;
/**
* By default, super calls are not allowed outside of a method.
* Set this to true to accept such code.
*/
allowSuperOutsideMethod?: boolean;
/**
* By default, exported identifiers must refer to a declared variable.
* Set this to true to allow export statements to reference undeclared variables.
*/
allowUndeclaredExports?: boolean;
/**
* By default, yield use is not allowed outside of a generator function.
* Set this to true to accept such code.
*/
allowYieldOutsideFunction?: boolean;
/**
* By default, Babel parser JavaScript code according to Annex B syntax.
* Set this to `false` to disable such behavior.
*/
annexB?: boolean;
/**
* By default, Babel attaches comments to adjacent AST nodes.
* When this option is set to false, comments are not attached.
* It can provide up to 30% performance improvement when the input code has many comments.
* @babel/eslint-parser will set it for you.
* It is not recommended to use attachComment: false with Babel transform,
* as doing so removes all the comments in output code, and renders annotations such as
* /* istanbul ignore next *\/ nonfunctional.
*/
attachComment?: boolean;
/**
* By default, Babel always throws an error when it finds some invalid code.
* When this option is set to true, it will store the parsing error and
* try to continue parsing the invalid input file.
*/
errorRecovery?: boolean;
/**
* Indicate the mode the code should be parsed in.
* Can be one of "script", "commonjs", "module", or "unambiguous". Defaults to "script".
* "unambiguous" will make @babel/parser attempt to guess, based on the presence
* of ES6 import or export statements.
* Files with ES6 imports and exports are considered "module" and are otherwise "script".
*
* Use "commonjs" to parse code that is intended to be run in a CommonJS environment such as Node.js.
*/
sourceType?: SourceType;
/**
* Correlate output AST nodes with their source filename.
* Useful when generating code and source maps from the ASTs of multiple input files.
*/
sourceFilename?: string;
/**
* By default, all source indexes start from 0.
* You can provide a start index to alternatively start with.
* Useful for integration with other source tools.
*/
startIndex?: number;
/**
* By default, the first line of code parsed is treated as line 1.
* You can provide a line number to alternatively start with.
* Useful for integration with other source tools.
*/
startLine?: number;
/**
* By default, the parsed code is treated as if it starts from line 1, column 0.
* You can provide a column number to alternatively start with.
* Useful for integration with other source tools.
*/
startColumn?: number;
/**
* Array containing the plugins that you want to enable.
*/
plugins?: Plugin[];
/**
* Should the parser work in strict mode.
* Defaults to true if sourceType === 'module'. Otherwise, false.
*/
strictMode?: boolean;
/**
* Adds a ranges property to each node: [node.start, node.end]
*/
ranges?: boolean;
/**
* Adds all parsed tokens to a tokens property on the File node.
*/
tokens?: boolean;
/**
* By default, the parser adds information about parentheses by setting
* `extra.parenthesized` to `true` as needed.
* When this option is `true` the parser creates `ParenthesizedExpression`
* AST nodes instead of using the `extra` property.
*/
createParenthesizedExpressions?: boolean;
/**
* The default is false in Babel 7 and true in Babel 8
* Set this to true to parse it as an `ImportExpression` node.
* Otherwise `import(foo)` is parsed as `CallExpression(Import, [Identifier(foo)])`.
*/
createImportExpressions?: boolean;
}
type ParserOptions = Partial<Options>;
type ParseError = ParseError$1<object>;
type ParseResult<Result extends File | Expression = File> = Result & {
comments: File["comments"];
errors: null | ParseError[];
tokens?: File["tokens"];
};
/**
* Parse the provided code as an entire ECMAScript program.
*/
declare function parse(input: string, options?: ParserOptions): ParseResult<File>;
declare function parseExpression(input: string, options?: ParserOptions): ParseResult<Expression>;
declare const tokTypes: {
// todo(flow->ts) real token type
[name: string]: any;
};
export { DecoratorsPluginOptions, FlowPluginOptions, ParseError, ParseResult, ParserOptions, PluginConfig as ParserPlugin, ParserPluginWithOptions, PipelineOperatorPluginOptions, RecordAndTuplePluginOptions, TypeScriptPluginOptions, parse, parseExpression, tokTypes };

22
admin/node_modules/@babel/types/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

19
admin/node_modules/@babel/types/README.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# @babel/types
> Babel Types is a Lodash-esque utility library for AST nodes
See our website [@babel/types](https://babeljs.io/docs/babel-types) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20types%22+is%3Aopen) associated with this package.
## Install
Using npm:
```sh
npm install --save-dev @babel/types
```
or using yarn:
```sh
yarn add @babel/types --dev
```

View File

@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = assertNode;
var _isNode = require("../validators/isNode.js");
function assertNode(node) {
if (!(0, _isNode.default)(node)) {
var _node$type;
const type = (_node$type = node == null ? void 0 : node.type) != null ? _node$type : JSON.stringify(node);
throw new TypeError(`Not a valid node of type "${type}"`);
}
}
//# sourceMappingURL=assertNode.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_isNode","require","assertNode","node","isNode","_node$type","type","JSON","stringify","TypeError"],"sources":["../../src/asserts/assertNode.ts"],"sourcesContent":["import isNode from \"../validators/isNode.ts\";\nimport type * as t from \"../index.ts\";\n\nexport default function assertNode(node?: any): asserts node is t.Node {\n if (!isNode(node)) {\n const type = node?.type ?? JSON.stringify(node);\n throw new TypeError(`Not a valid node of type \"${type}\"`);\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAGe,SAASC,UAAUA,CAACC,IAAU,EAA0B;EACrE,IAAI,CAAC,IAAAC,eAAM,EAACD,IAAI,CAAC,EAAE;IAAA,IAAAE,UAAA;IACjB,MAAMC,IAAI,IAAAD,UAAA,GAAGF,IAAI,oBAAJA,IAAI,CAAEG,IAAI,YAAAD,UAAA,GAAIE,IAAI,CAACC,SAAS,CAACL,IAAI,CAAC;IAC/C,MAAM,IAAIM,SAAS,CAAC,6BAA6BH,IAAI,GAAG,CAAC;EAC3D;AACF","ignoreList":[]}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
"use strict";
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createFlowUnionType;
var _index = require("../generated/index.js");
var _removeTypeDuplicates = require("../../modifications/flow/removeTypeDuplicates.js");
function createFlowUnionType(types) {
const flattened = (0, _removeTypeDuplicates.default)(types);
if (flattened.length === 1) {
return flattened[0];
} else {
return (0, _index.unionTypeAnnotation)(flattened);
}
}
//# sourceMappingURL=createFlowUnionType.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_index","require","_removeTypeDuplicates","createFlowUnionType","types","flattened","removeTypeDuplicates","length","unionTypeAnnotation"],"sources":["../../../src/builders/flow/createFlowUnionType.ts"],"sourcesContent":["import { unionTypeAnnotation } from \"../generated/index.ts\";\nimport removeTypeDuplicates from \"../../modifications/flow/removeTypeDuplicates.ts\";\nimport type * as t from \"../../index.ts\";\n\n/**\n * Takes an array of `types` and flattens them, removing duplicates and\n * returns a `UnionTypeAnnotation` node containing them.\n */\nexport default function createFlowUnionType<T extends t.FlowType>(\n types: [T] | T[],\n): T | t.UnionTypeAnnotation {\n const flattened = removeTypeDuplicates(types);\n\n if (flattened.length === 1) {\n return flattened[0] as T;\n } else {\n return unionTypeAnnotation(flattened);\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,qBAAA,GAAAD,OAAA;AAOe,SAASE,mBAAmBA,CACzCC,KAAgB,EACW;EAC3B,MAAMC,SAAS,GAAG,IAAAC,6BAAoB,EAACF,KAAK,CAAC;EAE7C,IAAIC,SAAS,CAACE,MAAM,KAAK,CAAC,EAAE;IAC1B,OAAOF,SAAS,CAAC,CAAC,CAAC;EACrB,CAAC,MAAM;IACL,OAAO,IAAAG,0BAAmB,EAACH,SAAS,CAAC;EACvC;AACF","ignoreList":[]}

View File

@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _index = require("../generated/index.js");
var _default = exports.default = createTypeAnnotationBasedOnTypeof;
function createTypeAnnotationBasedOnTypeof(type) {
switch (type) {
case "string":
return (0, _index.stringTypeAnnotation)();
case "number":
return (0, _index.numberTypeAnnotation)();
case "undefined":
return (0, _index.voidTypeAnnotation)();
case "boolean":
return (0, _index.booleanTypeAnnotation)();
case "function":
return (0, _index.genericTypeAnnotation)((0, _index.identifier)("Function"));
case "object":
return (0, _index.genericTypeAnnotation)((0, _index.identifier)("Object"));
case "symbol":
return (0, _index.genericTypeAnnotation)((0, _index.identifier)("Symbol"));
case "bigint":
return (0, _index.anyTypeAnnotation)();
}
throw new Error("Invalid typeof value: " + type);
}
//# sourceMappingURL=createTypeAnnotationBasedOnTypeof.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_index","require","_default","exports","default","createTypeAnnotationBasedOnTypeof","type","stringTypeAnnotation","numberTypeAnnotation","voidTypeAnnotation","booleanTypeAnnotation","genericTypeAnnotation","identifier","anyTypeAnnotation","Error"],"sources":["../../../src/builders/flow/createTypeAnnotationBasedOnTypeof.ts"],"sourcesContent":["import {\n anyTypeAnnotation,\n stringTypeAnnotation,\n numberTypeAnnotation,\n voidTypeAnnotation,\n booleanTypeAnnotation,\n genericTypeAnnotation,\n identifier,\n} from \"../generated/index.ts\";\nimport type * as t from \"../../index.ts\";\n\nexport default createTypeAnnotationBasedOnTypeof as {\n (type: \"string\"): t.StringTypeAnnotation;\n (type: \"number\"): t.NumberTypeAnnotation;\n (type: \"undefined\"): t.VoidTypeAnnotation;\n (type: \"boolean\"): t.BooleanTypeAnnotation;\n (type: \"function\"): t.GenericTypeAnnotation;\n (type: \"object\"): t.GenericTypeAnnotation;\n (type: \"symbol\"): t.GenericTypeAnnotation;\n (type: \"bigint\"): t.AnyTypeAnnotation;\n};\n\n/**\n * Create a type annotation based on typeof expression.\n */\nfunction createTypeAnnotationBasedOnTypeof(type: string): t.FlowType {\n switch (type) {\n case \"string\":\n return stringTypeAnnotation();\n case \"number\":\n return numberTypeAnnotation();\n case \"undefined\":\n return voidTypeAnnotation();\n case \"boolean\":\n return booleanTypeAnnotation();\n case \"function\":\n return genericTypeAnnotation(identifier(\"Function\"));\n case \"object\":\n return genericTypeAnnotation(identifier(\"Object\"));\n case \"symbol\":\n return genericTypeAnnotation(identifier(\"Symbol\"));\n case \"bigint\":\n // todo: use BigInt annotation when Flow supports BigInt\n // https://github.com/facebook/flow/issues/6639\n return anyTypeAnnotation();\n }\n throw new Error(\"Invalid typeof value: \" + type);\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAQ+B,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAGhBC,iCAAiC;AAchD,SAASA,iCAAiCA,CAACC,IAAY,EAAc;EACnE,QAAQA,IAAI;IACV,KAAK,QAAQ;MACX,OAAO,IAAAC,2BAAoB,EAAC,CAAC;IAC/B,KAAK,QAAQ;MACX,OAAO,IAAAC,2BAAoB,EAAC,CAAC;IAC/B,KAAK,WAAW;MACd,OAAO,IAAAC,yBAAkB,EAAC,CAAC;IAC7B,KAAK,SAAS;MACZ,OAAO,IAAAC,4BAAqB,EAAC,CAAC;IAChC,KAAK,UAAU;MACb,OAAO,IAAAC,4BAAqB,EAAC,IAAAC,iBAAU,EAAC,UAAU,CAAC,CAAC;IACtD,KAAK,QAAQ;MACX,OAAO,IAAAD,4BAAqB,EAAC,IAAAC,iBAAU,EAAC,QAAQ,CAAC,CAAC;IACpD,KAAK,QAAQ;MACX,OAAO,IAAAD,4BAAqB,EAAC,IAAAC,iBAAU,EAAC,QAAQ,CAAC,CAAC;IACpD,KAAK,QAAQ;MAGX,OAAO,IAAAC,wBAAiB,EAAC,CAAC;EAC9B;EACA,MAAM,IAAIC,KAAK,CAAC,wBAAwB,GAAGR,IAAI,CAAC;AAClD","ignoreList":[]}

View File

@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lowercase = require("./lowercase.js");
Object.keys(_lowercase).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _lowercase[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _lowercase[key];
}
});
});
var _uppercase = require("./uppercase.js");
Object.keys(_uppercase).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _uppercase[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _uppercase[key];
}
});
});
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,272 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.JSXIdentifier = exports.JSXFragment = exports.JSXExpressionContainer = exports.JSXEmptyExpression = exports.JSXElement = exports.JSXClosingFragment = exports.JSXClosingElement = exports.JSXAttribute = exports.IntersectionTypeAnnotation = exports.InterpreterDirective = exports.InterfaceTypeAnnotation = exports.InterfaceExtends = exports.InterfaceDeclaration = exports.InferredPredicate = exports.IndexedAccessType = exports.ImportSpecifier = exports.ImportNamespaceSpecifier = exports.ImportExpression = exports.ImportDefaultSpecifier = exports.ImportDeclaration = exports.ImportAttribute = exports.Import = exports.IfStatement = exports.Identifier = exports.GenericTypeAnnotation = exports.FunctionTypeParam = exports.FunctionTypeAnnotation = exports.FunctionExpression = exports.FunctionDeclaration = exports.ForStatement = exports.ForOfStatement = exports.ForInStatement = exports.File = exports.ExpressionStatement = exports.ExportSpecifier = exports.ExportNamespaceSpecifier = exports.ExportNamedDeclaration = exports.ExportDefaultSpecifier = exports.ExportDefaultDeclaration = exports.ExportAllDeclaration = exports.ExistsTypeAnnotation = exports.EnumSymbolBody = exports.EnumStringMember = exports.EnumStringBody = exports.EnumNumberMember = exports.EnumNumberBody = exports.EnumDefaultedMember = exports.EnumDeclaration = exports.EnumBooleanMember = exports.EnumBooleanBody = exports.EmptyTypeAnnotation = exports.EmptyStatement = exports.DoWhileStatement = exports.DoExpression = exports.DirectiveLiteral = exports.Directive = exports.Decorator = exports.DeclaredPredicate = exports.DeclareVariable = exports.DeclareTypeAlias = exports.DeclareOpaqueType = exports.DeclareModuleExports = exports.DeclareModule = exports.DeclareInterface = exports.DeclareFunction = exports.DeclareExportDeclaration = exports.DeclareExportAllDeclaration = exports.DeclareClass = exports.DecimalLiteral = exports.DebuggerStatement = exports.ContinueStatement = exports.ConditionalExpression = exports.ClassProperty = exports.ClassPrivateProperty = exports.ClassPrivateMethod = exports.ClassMethod = exports.ClassImplements = exports.ClassExpression = exports.ClassDeclaration = exports.ClassBody = exports.ClassAccessorProperty = exports.CatchClause = exports.CallExpression = exports.BreakStatement = exports.BooleanTypeAnnotation = exports.BooleanLiteralTypeAnnotation = exports.BooleanLiteral = exports.BlockStatement = exports.BindExpression = exports.BinaryExpression = exports.BigIntLiteral = exports.AwaitExpression = exports.AssignmentPattern = exports.AssignmentExpression = exports.ArrowFunctionExpression = exports.ArrayTypeAnnotation = exports.ArrayPattern = exports.ArrayExpression = exports.ArgumentPlaceholder = exports.AnyTypeAnnotation = void 0;
exports.TSNumberKeyword = exports.TSNullKeyword = exports.TSNonNullExpression = exports.TSNeverKeyword = exports.TSNamespaceExportDeclaration = exports.TSNamedTupleMember = exports.TSModuleDeclaration = exports.TSModuleBlock = exports.TSMethodSignature = exports.TSMappedType = exports.TSLiteralType = exports.TSIntrinsicKeyword = exports.TSIntersectionType = exports.TSInterfaceDeclaration = exports.TSInterfaceBody = exports.TSInstantiationExpression = exports.TSInferType = exports.TSIndexedAccessType = exports.TSIndexSignature = exports.TSImportType = exports.TSImportEqualsDeclaration = exports.TSFunctionType = exports.TSExternalModuleReference = exports.TSExpressionWithTypeArguments = exports.TSExportAssignment = exports.TSEnumMember = exports.TSEnumDeclaration = exports.TSEnumBody = exports.TSDeclareMethod = exports.TSDeclareFunction = exports.TSConstructorType = exports.TSConstructSignatureDeclaration = exports.TSConditionalType = exports.TSCallSignatureDeclaration = exports.TSBooleanKeyword = exports.TSBigIntKeyword = exports.TSAsExpression = exports.TSArrayType = exports.TSAnyKeyword = exports.SymbolTypeAnnotation = exports.SwitchStatement = exports.SwitchCase = exports.Super = exports.StringTypeAnnotation = exports.StringLiteralTypeAnnotation = exports.StringLiteral = exports.StaticBlock = exports.SpreadProperty = exports.SpreadElement = exports.SequenceExpression = exports.ReturnStatement = exports.RestProperty = exports.RestElement = exports.RegexLiteral = exports.RegExpLiteral = exports.RecordExpression = exports.QualifiedTypeIdentifier = exports.Program = exports.PrivateName = exports.Placeholder = exports.PipelineTopicExpression = exports.PipelinePrimaryTopicReference = exports.PipelineBareFunction = exports.ParenthesizedExpression = exports.OptionalMemberExpression = exports.OptionalIndexedAccessType = exports.OptionalCallExpression = exports.OpaqueType = exports.ObjectTypeSpreadProperty = exports.ObjectTypeProperty = exports.ObjectTypeInternalSlot = exports.ObjectTypeIndexer = exports.ObjectTypeCallProperty = exports.ObjectTypeAnnotation = exports.ObjectProperty = exports.ObjectPattern = exports.ObjectMethod = exports.ObjectExpression = exports.NumericLiteral = exports.NumberTypeAnnotation = exports.NumberLiteralTypeAnnotation = exports.NumberLiteral = exports.NullableTypeAnnotation = exports.NullLiteralTypeAnnotation = exports.NullLiteral = exports.Noop = exports.NewExpression = exports.ModuleExpression = exports.MixedTypeAnnotation = exports.MetaProperty = exports.MemberExpression = exports.LogicalExpression = exports.LabeledStatement = exports.JSXText = exports.JSXSpreadChild = exports.JSXSpreadAttribute = exports.JSXOpeningFragment = exports.JSXOpeningElement = exports.JSXNamespacedName = exports.JSXMemberExpression = void 0;
exports.YieldExpression = exports.WithStatement = exports.WhileStatement = exports.VoidTypeAnnotation = exports.VoidPattern = exports.Variance = exports.VariableDeclarator = exports.VariableDeclaration = exports.V8IntrinsicIdentifier = exports.UpdateExpression = exports.UnionTypeAnnotation = exports.UnaryExpression = exports.TypeofTypeAnnotation = exports.TypeParameterInstantiation = exports.TypeParameterDeclaration = exports.TypeParameter = exports.TypeCastExpression = exports.TypeAnnotation = exports.TypeAlias = exports.TupleTypeAnnotation = exports.TupleExpression = exports.TryStatement = exports.TopicReference = exports.ThrowStatement = exports.ThisTypeAnnotation = exports.ThisExpression = exports.TemplateLiteral = exports.TemplateElement = exports.TaggedTemplateExpression = exports.TSVoidKeyword = exports.TSUnknownKeyword = exports.TSUnionType = exports.TSUndefinedKeyword = exports.TSTypeReference = exports.TSTypeQuery = exports.TSTypePredicate = exports.TSTypeParameterInstantiation = exports.TSTypeParameterDeclaration = exports.TSTypeParameter = exports.TSTypeOperator = exports.TSTypeLiteral = exports.TSTypeAssertion = exports.TSTypeAnnotation = exports.TSTypeAliasDeclaration = exports.TSTupleType = exports.TSThisType = exports.TSTemplateLiteralType = exports.TSSymbolKeyword = exports.TSStringKeyword = exports.TSSatisfiesExpression = exports.TSRestType = exports.TSQualifiedName = exports.TSPropertySignature = exports.TSParenthesizedType = exports.TSParameterProperty = exports.TSOptionalType = exports.TSObjectKeyword = void 0;
var b = require("./lowercase.js");
var _deprecationWarning = require("../../utils/deprecationWarning.js");
function alias(lowercase) {
return b[lowercase];
}
const ArrayExpression = exports.ArrayExpression = alias("arrayExpression"),
AssignmentExpression = exports.AssignmentExpression = alias("assignmentExpression"),
BinaryExpression = exports.BinaryExpression = alias("binaryExpression"),
InterpreterDirective = exports.InterpreterDirective = alias("interpreterDirective"),
Directive = exports.Directive = alias("directive"),
DirectiveLiteral = exports.DirectiveLiteral = alias("directiveLiteral"),
BlockStatement = exports.BlockStatement = alias("blockStatement"),
BreakStatement = exports.BreakStatement = alias("breakStatement"),
CallExpression = exports.CallExpression = alias("callExpression"),
CatchClause = exports.CatchClause = alias("catchClause"),
ConditionalExpression = exports.ConditionalExpression = alias("conditionalExpression"),
ContinueStatement = exports.ContinueStatement = alias("continueStatement"),
DebuggerStatement = exports.DebuggerStatement = alias("debuggerStatement"),
DoWhileStatement = exports.DoWhileStatement = alias("doWhileStatement"),
EmptyStatement = exports.EmptyStatement = alias("emptyStatement"),
ExpressionStatement = exports.ExpressionStatement = alias("expressionStatement"),
File = exports.File = alias("file"),
ForInStatement = exports.ForInStatement = alias("forInStatement"),
ForStatement = exports.ForStatement = alias("forStatement"),
FunctionDeclaration = exports.FunctionDeclaration = alias("functionDeclaration"),
FunctionExpression = exports.FunctionExpression = alias("functionExpression"),
Identifier = exports.Identifier = alias("identifier"),
IfStatement = exports.IfStatement = alias("ifStatement"),
LabeledStatement = exports.LabeledStatement = alias("labeledStatement"),
StringLiteral = exports.StringLiteral = alias("stringLiteral"),
NumericLiteral = exports.NumericLiteral = alias("numericLiteral"),
NullLiteral = exports.NullLiteral = alias("nullLiteral"),
BooleanLiteral = exports.BooleanLiteral = alias("booleanLiteral"),
RegExpLiteral = exports.RegExpLiteral = alias("regExpLiteral"),
LogicalExpression = exports.LogicalExpression = alias("logicalExpression"),
MemberExpression = exports.MemberExpression = alias("memberExpression"),
NewExpression = exports.NewExpression = alias("newExpression"),
Program = exports.Program = alias("program"),
ObjectExpression = exports.ObjectExpression = alias("objectExpression"),
ObjectMethod = exports.ObjectMethod = alias("objectMethod"),
ObjectProperty = exports.ObjectProperty = alias("objectProperty"),
RestElement = exports.RestElement = alias("restElement"),
ReturnStatement = exports.ReturnStatement = alias("returnStatement"),
SequenceExpression = exports.SequenceExpression = alias("sequenceExpression"),
ParenthesizedExpression = exports.ParenthesizedExpression = alias("parenthesizedExpression"),
SwitchCase = exports.SwitchCase = alias("switchCase"),
SwitchStatement = exports.SwitchStatement = alias("switchStatement"),
ThisExpression = exports.ThisExpression = alias("thisExpression"),
ThrowStatement = exports.ThrowStatement = alias("throwStatement"),
TryStatement = exports.TryStatement = alias("tryStatement"),
UnaryExpression = exports.UnaryExpression = alias("unaryExpression"),
UpdateExpression = exports.UpdateExpression = alias("updateExpression"),
VariableDeclaration = exports.VariableDeclaration = alias("variableDeclaration"),
VariableDeclarator = exports.VariableDeclarator = alias("variableDeclarator"),
WhileStatement = exports.WhileStatement = alias("whileStatement"),
WithStatement = exports.WithStatement = alias("withStatement"),
AssignmentPattern = exports.AssignmentPattern = alias("assignmentPattern"),
ArrayPattern = exports.ArrayPattern = alias("arrayPattern"),
ArrowFunctionExpression = exports.ArrowFunctionExpression = alias("arrowFunctionExpression"),
ClassBody = exports.ClassBody = alias("classBody"),
ClassExpression = exports.ClassExpression = alias("classExpression"),
ClassDeclaration = exports.ClassDeclaration = alias("classDeclaration"),
ExportAllDeclaration = exports.ExportAllDeclaration = alias("exportAllDeclaration"),
ExportDefaultDeclaration = exports.ExportDefaultDeclaration = alias("exportDefaultDeclaration"),
ExportNamedDeclaration = exports.ExportNamedDeclaration = alias("exportNamedDeclaration"),
ExportSpecifier = exports.ExportSpecifier = alias("exportSpecifier"),
ForOfStatement = exports.ForOfStatement = alias("forOfStatement"),
ImportDeclaration = exports.ImportDeclaration = alias("importDeclaration"),
ImportDefaultSpecifier = exports.ImportDefaultSpecifier = alias("importDefaultSpecifier"),
ImportNamespaceSpecifier = exports.ImportNamespaceSpecifier = alias("importNamespaceSpecifier"),
ImportSpecifier = exports.ImportSpecifier = alias("importSpecifier"),
ImportExpression = exports.ImportExpression = alias("importExpression"),
MetaProperty = exports.MetaProperty = alias("metaProperty"),
ClassMethod = exports.ClassMethod = alias("classMethod"),
ObjectPattern = exports.ObjectPattern = alias("objectPattern"),
SpreadElement = exports.SpreadElement = alias("spreadElement"),
Super = exports.Super = alias("super"),
TaggedTemplateExpression = exports.TaggedTemplateExpression = alias("taggedTemplateExpression"),
TemplateElement = exports.TemplateElement = alias("templateElement"),
TemplateLiteral = exports.TemplateLiteral = alias("templateLiteral"),
YieldExpression = exports.YieldExpression = alias("yieldExpression"),
AwaitExpression = exports.AwaitExpression = alias("awaitExpression"),
Import = exports.Import = alias("import"),
BigIntLiteral = exports.BigIntLiteral = alias("bigIntLiteral"),
ExportNamespaceSpecifier = exports.ExportNamespaceSpecifier = alias("exportNamespaceSpecifier"),
OptionalMemberExpression = exports.OptionalMemberExpression = alias("optionalMemberExpression"),
OptionalCallExpression = exports.OptionalCallExpression = alias("optionalCallExpression"),
ClassProperty = exports.ClassProperty = alias("classProperty"),
ClassAccessorProperty = exports.ClassAccessorProperty = alias("classAccessorProperty"),
ClassPrivateProperty = exports.ClassPrivateProperty = alias("classPrivateProperty"),
ClassPrivateMethod = exports.ClassPrivateMethod = alias("classPrivateMethod"),
PrivateName = exports.PrivateName = alias("privateName"),
StaticBlock = exports.StaticBlock = alias("staticBlock"),
ImportAttribute = exports.ImportAttribute = alias("importAttribute"),
AnyTypeAnnotation = exports.AnyTypeAnnotation = alias("anyTypeAnnotation"),
ArrayTypeAnnotation = exports.ArrayTypeAnnotation = alias("arrayTypeAnnotation"),
BooleanTypeAnnotation = exports.BooleanTypeAnnotation = alias("booleanTypeAnnotation"),
BooleanLiteralTypeAnnotation = exports.BooleanLiteralTypeAnnotation = alias("booleanLiteralTypeAnnotation"),
NullLiteralTypeAnnotation = exports.NullLiteralTypeAnnotation = alias("nullLiteralTypeAnnotation"),
ClassImplements = exports.ClassImplements = alias("classImplements"),
DeclareClass = exports.DeclareClass = alias("declareClass"),
DeclareFunction = exports.DeclareFunction = alias("declareFunction"),
DeclareInterface = exports.DeclareInterface = alias("declareInterface"),
DeclareModule = exports.DeclareModule = alias("declareModule"),
DeclareModuleExports = exports.DeclareModuleExports = alias("declareModuleExports"),
DeclareTypeAlias = exports.DeclareTypeAlias = alias("declareTypeAlias"),
DeclareOpaqueType = exports.DeclareOpaqueType = alias("declareOpaqueType"),
DeclareVariable = exports.DeclareVariable = alias("declareVariable"),
DeclareExportDeclaration = exports.DeclareExportDeclaration = alias("declareExportDeclaration"),
DeclareExportAllDeclaration = exports.DeclareExportAllDeclaration = alias("declareExportAllDeclaration"),
DeclaredPredicate = exports.DeclaredPredicate = alias("declaredPredicate"),
ExistsTypeAnnotation = exports.ExistsTypeAnnotation = alias("existsTypeAnnotation"),
FunctionTypeAnnotation = exports.FunctionTypeAnnotation = alias("functionTypeAnnotation"),
FunctionTypeParam = exports.FunctionTypeParam = alias("functionTypeParam"),
GenericTypeAnnotation = exports.GenericTypeAnnotation = alias("genericTypeAnnotation"),
InferredPredicate = exports.InferredPredicate = alias("inferredPredicate"),
InterfaceExtends = exports.InterfaceExtends = alias("interfaceExtends"),
InterfaceDeclaration = exports.InterfaceDeclaration = alias("interfaceDeclaration"),
InterfaceTypeAnnotation = exports.InterfaceTypeAnnotation = alias("interfaceTypeAnnotation"),
IntersectionTypeAnnotation = exports.IntersectionTypeAnnotation = alias("intersectionTypeAnnotation"),
MixedTypeAnnotation = exports.MixedTypeAnnotation = alias("mixedTypeAnnotation"),
EmptyTypeAnnotation = exports.EmptyTypeAnnotation = alias("emptyTypeAnnotation"),
NullableTypeAnnotation = exports.NullableTypeAnnotation = alias("nullableTypeAnnotation"),
NumberLiteralTypeAnnotation = exports.NumberLiteralTypeAnnotation = alias("numberLiteralTypeAnnotation"),
NumberTypeAnnotation = exports.NumberTypeAnnotation = alias("numberTypeAnnotation"),
ObjectTypeAnnotation = exports.ObjectTypeAnnotation = alias("objectTypeAnnotation"),
ObjectTypeInternalSlot = exports.ObjectTypeInternalSlot = alias("objectTypeInternalSlot"),
ObjectTypeCallProperty = exports.ObjectTypeCallProperty = alias("objectTypeCallProperty"),
ObjectTypeIndexer = exports.ObjectTypeIndexer = alias("objectTypeIndexer"),
ObjectTypeProperty = exports.ObjectTypeProperty = alias("objectTypeProperty"),
ObjectTypeSpreadProperty = exports.ObjectTypeSpreadProperty = alias("objectTypeSpreadProperty"),
OpaqueType = exports.OpaqueType = alias("opaqueType"),
QualifiedTypeIdentifier = exports.QualifiedTypeIdentifier = alias("qualifiedTypeIdentifier"),
StringLiteralTypeAnnotation = exports.StringLiteralTypeAnnotation = alias("stringLiteralTypeAnnotation"),
StringTypeAnnotation = exports.StringTypeAnnotation = alias("stringTypeAnnotation"),
SymbolTypeAnnotation = exports.SymbolTypeAnnotation = alias("symbolTypeAnnotation"),
ThisTypeAnnotation = exports.ThisTypeAnnotation = alias("thisTypeAnnotation"),
TupleTypeAnnotation = exports.TupleTypeAnnotation = alias("tupleTypeAnnotation"),
TypeofTypeAnnotation = exports.TypeofTypeAnnotation = alias("typeofTypeAnnotation"),
TypeAlias = exports.TypeAlias = alias("typeAlias"),
TypeAnnotation = exports.TypeAnnotation = alias("typeAnnotation"),
TypeCastExpression = exports.TypeCastExpression = alias("typeCastExpression"),
TypeParameter = exports.TypeParameter = alias("typeParameter"),
TypeParameterDeclaration = exports.TypeParameterDeclaration = alias("typeParameterDeclaration"),
TypeParameterInstantiation = exports.TypeParameterInstantiation = alias("typeParameterInstantiation"),
UnionTypeAnnotation = exports.UnionTypeAnnotation = alias("unionTypeAnnotation"),
Variance = exports.Variance = alias("variance"),
VoidTypeAnnotation = exports.VoidTypeAnnotation = alias("voidTypeAnnotation"),
EnumDeclaration = exports.EnumDeclaration = alias("enumDeclaration"),
EnumBooleanBody = exports.EnumBooleanBody = alias("enumBooleanBody"),
EnumNumberBody = exports.EnumNumberBody = alias("enumNumberBody"),
EnumStringBody = exports.EnumStringBody = alias("enumStringBody"),
EnumSymbolBody = exports.EnumSymbolBody = alias("enumSymbolBody"),
EnumBooleanMember = exports.EnumBooleanMember = alias("enumBooleanMember"),
EnumNumberMember = exports.EnumNumberMember = alias("enumNumberMember"),
EnumStringMember = exports.EnumStringMember = alias("enumStringMember"),
EnumDefaultedMember = exports.EnumDefaultedMember = alias("enumDefaultedMember"),
IndexedAccessType = exports.IndexedAccessType = alias("indexedAccessType"),
OptionalIndexedAccessType = exports.OptionalIndexedAccessType = alias("optionalIndexedAccessType"),
JSXAttribute = exports.JSXAttribute = alias("jsxAttribute"),
JSXClosingElement = exports.JSXClosingElement = alias("jsxClosingElement"),
JSXElement = exports.JSXElement = alias("jsxElement"),
JSXEmptyExpression = exports.JSXEmptyExpression = alias("jsxEmptyExpression"),
JSXExpressionContainer = exports.JSXExpressionContainer = alias("jsxExpressionContainer"),
JSXSpreadChild = exports.JSXSpreadChild = alias("jsxSpreadChild"),
JSXIdentifier = exports.JSXIdentifier = alias("jsxIdentifier"),
JSXMemberExpression = exports.JSXMemberExpression = alias("jsxMemberExpression"),
JSXNamespacedName = exports.JSXNamespacedName = alias("jsxNamespacedName"),
JSXOpeningElement = exports.JSXOpeningElement = alias("jsxOpeningElement"),
JSXSpreadAttribute = exports.JSXSpreadAttribute = alias("jsxSpreadAttribute"),
JSXText = exports.JSXText = alias("jsxText"),
JSXFragment = exports.JSXFragment = alias("jsxFragment"),
JSXOpeningFragment = exports.JSXOpeningFragment = alias("jsxOpeningFragment"),
JSXClosingFragment = exports.JSXClosingFragment = alias("jsxClosingFragment"),
Noop = exports.Noop = alias("noop"),
Placeholder = exports.Placeholder = alias("placeholder"),
V8IntrinsicIdentifier = exports.V8IntrinsicIdentifier = alias("v8IntrinsicIdentifier"),
ArgumentPlaceholder = exports.ArgumentPlaceholder = alias("argumentPlaceholder"),
BindExpression = exports.BindExpression = alias("bindExpression"),
Decorator = exports.Decorator = alias("decorator"),
DoExpression = exports.DoExpression = alias("doExpression"),
ExportDefaultSpecifier = exports.ExportDefaultSpecifier = alias("exportDefaultSpecifier"),
RecordExpression = exports.RecordExpression = alias("recordExpression"),
TupleExpression = exports.TupleExpression = alias("tupleExpression"),
DecimalLiteral = exports.DecimalLiteral = alias("decimalLiteral"),
ModuleExpression = exports.ModuleExpression = alias("moduleExpression"),
TopicReference = exports.TopicReference = alias("topicReference"),
PipelineTopicExpression = exports.PipelineTopicExpression = alias("pipelineTopicExpression"),
PipelineBareFunction = exports.PipelineBareFunction = alias("pipelineBareFunction"),
PipelinePrimaryTopicReference = exports.PipelinePrimaryTopicReference = alias("pipelinePrimaryTopicReference"),
VoidPattern = exports.VoidPattern = alias("voidPattern"),
TSParameterProperty = exports.TSParameterProperty = alias("tsParameterProperty"),
TSDeclareFunction = exports.TSDeclareFunction = alias("tsDeclareFunction"),
TSDeclareMethod = exports.TSDeclareMethod = alias("tsDeclareMethod"),
TSQualifiedName = exports.TSQualifiedName = alias("tsQualifiedName"),
TSCallSignatureDeclaration = exports.TSCallSignatureDeclaration = alias("tsCallSignatureDeclaration"),
TSConstructSignatureDeclaration = exports.TSConstructSignatureDeclaration = alias("tsConstructSignatureDeclaration"),
TSPropertySignature = exports.TSPropertySignature = alias("tsPropertySignature"),
TSMethodSignature = exports.TSMethodSignature = alias("tsMethodSignature"),
TSIndexSignature = exports.TSIndexSignature = alias("tsIndexSignature"),
TSAnyKeyword = exports.TSAnyKeyword = alias("tsAnyKeyword"),
TSBooleanKeyword = exports.TSBooleanKeyword = alias("tsBooleanKeyword"),
TSBigIntKeyword = exports.TSBigIntKeyword = alias("tsBigIntKeyword"),
TSIntrinsicKeyword = exports.TSIntrinsicKeyword = alias("tsIntrinsicKeyword"),
TSNeverKeyword = exports.TSNeverKeyword = alias("tsNeverKeyword"),
TSNullKeyword = exports.TSNullKeyword = alias("tsNullKeyword"),
TSNumberKeyword = exports.TSNumberKeyword = alias("tsNumberKeyword"),
TSObjectKeyword = exports.TSObjectKeyword = alias("tsObjectKeyword"),
TSStringKeyword = exports.TSStringKeyword = alias("tsStringKeyword"),
TSSymbolKeyword = exports.TSSymbolKeyword = alias("tsSymbolKeyword"),
TSUndefinedKeyword = exports.TSUndefinedKeyword = alias("tsUndefinedKeyword"),
TSUnknownKeyword = exports.TSUnknownKeyword = alias("tsUnknownKeyword"),
TSVoidKeyword = exports.TSVoidKeyword = alias("tsVoidKeyword"),
TSThisType = exports.TSThisType = alias("tsThisType"),
TSFunctionType = exports.TSFunctionType = alias("tsFunctionType"),
TSConstructorType = exports.TSConstructorType = alias("tsConstructorType"),
TSTypeReference = exports.TSTypeReference = alias("tsTypeReference"),
TSTypePredicate = exports.TSTypePredicate = alias("tsTypePredicate"),
TSTypeQuery = exports.TSTypeQuery = alias("tsTypeQuery"),
TSTypeLiteral = exports.TSTypeLiteral = alias("tsTypeLiteral"),
TSArrayType = exports.TSArrayType = alias("tsArrayType"),
TSTupleType = exports.TSTupleType = alias("tsTupleType"),
TSOptionalType = exports.TSOptionalType = alias("tsOptionalType"),
TSRestType = exports.TSRestType = alias("tsRestType"),
TSNamedTupleMember = exports.TSNamedTupleMember = alias("tsNamedTupleMember"),
TSUnionType = exports.TSUnionType = alias("tsUnionType"),
TSIntersectionType = exports.TSIntersectionType = alias("tsIntersectionType"),
TSConditionalType = exports.TSConditionalType = alias("tsConditionalType"),
TSInferType = exports.TSInferType = alias("tsInferType"),
TSParenthesizedType = exports.TSParenthesizedType = alias("tsParenthesizedType"),
TSTypeOperator = exports.TSTypeOperator = alias("tsTypeOperator"),
TSIndexedAccessType = exports.TSIndexedAccessType = alias("tsIndexedAccessType"),
TSMappedType = exports.TSMappedType = alias("tsMappedType"),
TSTemplateLiteralType = exports.TSTemplateLiteralType = alias("tsTemplateLiteralType"),
TSLiteralType = exports.TSLiteralType = alias("tsLiteralType"),
TSExpressionWithTypeArguments = exports.TSExpressionWithTypeArguments = alias("tsExpressionWithTypeArguments"),
TSInterfaceDeclaration = exports.TSInterfaceDeclaration = alias("tsInterfaceDeclaration"),
TSInterfaceBody = exports.TSInterfaceBody = alias("tsInterfaceBody"),
TSTypeAliasDeclaration = exports.TSTypeAliasDeclaration = alias("tsTypeAliasDeclaration"),
TSInstantiationExpression = exports.TSInstantiationExpression = alias("tsInstantiationExpression"),
TSAsExpression = exports.TSAsExpression = alias("tsAsExpression"),
TSSatisfiesExpression = exports.TSSatisfiesExpression = alias("tsSatisfiesExpression"),
TSTypeAssertion = exports.TSTypeAssertion = alias("tsTypeAssertion"),
TSEnumBody = exports.TSEnumBody = alias("tsEnumBody"),
TSEnumDeclaration = exports.TSEnumDeclaration = alias("tsEnumDeclaration"),
TSEnumMember = exports.TSEnumMember = alias("tsEnumMember"),
TSModuleDeclaration = exports.TSModuleDeclaration = alias("tsModuleDeclaration"),
TSModuleBlock = exports.TSModuleBlock = alias("tsModuleBlock"),
TSImportType = exports.TSImportType = alias("tsImportType"),
TSImportEqualsDeclaration = exports.TSImportEqualsDeclaration = alias("tsImportEqualsDeclaration"),
TSExternalModuleReference = exports.TSExternalModuleReference = alias("tsExternalModuleReference"),
TSNonNullExpression = exports.TSNonNullExpression = alias("tsNonNullExpression"),
TSExportAssignment = exports.TSExportAssignment = alias("tsExportAssignment"),
TSNamespaceExportDeclaration = exports.TSNamespaceExportDeclaration = alias("tsNamespaceExportDeclaration"),
TSTypeAnnotation = exports.TSTypeAnnotation = alias("tsTypeAnnotation"),
TSTypeParameterInstantiation = exports.TSTypeParameterInstantiation = alias("tsTypeParameterInstantiation"),
TSTypeParameterDeclaration = exports.TSTypeParameterDeclaration = alias("tsTypeParameterDeclaration"),
TSTypeParameter = exports.TSTypeParameter = alias("tsTypeParameter");
const NumberLiteral = exports.NumberLiteral = b.numberLiteral,
RegexLiteral = exports.RegexLiteral = b.regexLiteral,
RestProperty = exports.RestProperty = b.restProperty,
SpreadProperty = exports.SpreadProperty = b.spreadProperty;
//# sourceMappingURL=uppercase.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildUndefinedNode = buildUndefinedNode;
var _index = require("./generated/index.js");
function buildUndefinedNode() {
return (0, _index.unaryExpression)("void", (0, _index.numericLiteral)(0), true);
}
//# sourceMappingURL=productions.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_index","require","buildUndefinedNode","unaryExpression","numericLiteral"],"sources":["../../src/builders/productions.ts"],"sourcesContent":["import { numericLiteral, unaryExpression } from \"./generated/index.ts\";\n\nexport function buildUndefinedNode() {\n return unaryExpression(\"void\", numericLiteral(0), true);\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEO,SAASC,kBAAkBA,CAAA,EAAG;EACnC,OAAO,IAAAC,sBAAe,EAAC,MAAM,EAAE,IAAAC,qBAAc,EAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AACzD","ignoreList":[]}

View File

@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = buildChildren;
var _index = require("../../validators/generated/index.js");
var _cleanJSXElementLiteralChild = require("../../utils/react/cleanJSXElementLiteralChild.js");
function buildChildren(node) {
const elements = [];
for (let i = 0; i < node.children.length; i++) {
let child = node.children[i];
if ((0, _index.isJSXText)(child)) {
(0, _cleanJSXElementLiteralChild.default)(child, elements);
continue;
}
if ((0, _index.isJSXExpressionContainer)(child)) child = child.expression;
if ((0, _index.isJSXEmptyExpression)(child)) continue;
elements.push(child);
}
return elements;
}
//# sourceMappingURL=buildChildren.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_index","require","_cleanJSXElementLiteralChild","buildChildren","node","elements","i","children","length","child","isJSXText","cleanJSXElementLiteralChild","isJSXExpressionContainer","expression","isJSXEmptyExpression","push"],"sources":["../../../src/builders/react/buildChildren.ts"],"sourcesContent":["import {\n isJSXText,\n isJSXExpressionContainer,\n isJSXEmptyExpression,\n} from \"../../validators/generated/index.ts\";\nimport cleanJSXElementLiteralChild from \"../../utils/react/cleanJSXElementLiteralChild.ts\";\nimport type * as t from \"../../index.ts\";\n\ntype ReturnedChild =\n | t.JSXSpreadChild\n | t.JSXElement\n | t.JSXFragment\n | t.Expression;\n\nexport default function buildChildren(\n node: t.JSXElement | t.JSXFragment,\n): ReturnedChild[] {\n const elements = [];\n\n for (let i = 0; i < node.children.length; i++) {\n let child: any = node.children[i];\n\n if (isJSXText(child)) {\n cleanJSXElementLiteralChild(child, elements);\n continue;\n }\n\n if (isJSXExpressionContainer(child)) child = child.expression;\n if (isJSXEmptyExpression(child)) continue;\n\n elements.push(child);\n }\n\n return elements;\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAKA,IAAAC,4BAAA,GAAAD,OAAA;AASe,SAASE,aAAaA,CACnCC,IAAkC,EACjB;EACjB,MAAMC,QAAQ,GAAG,EAAE;EAEnB,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGF,IAAI,CAACG,QAAQ,CAACC,MAAM,EAAEF,CAAC,EAAE,EAAE;IAC7C,IAAIG,KAAU,GAAGL,IAAI,CAACG,QAAQ,CAACD,CAAC,CAAC;IAEjC,IAAI,IAAAI,gBAAS,EAACD,KAAK,CAAC,EAAE;MACpB,IAAAE,oCAA2B,EAACF,KAAK,EAAEJ,QAAQ,CAAC;MAC5C;IACF;IAEA,IAAI,IAAAO,+BAAwB,EAACH,KAAK,CAAC,EAAEA,KAAK,GAAGA,KAAK,CAACI,UAAU;IAC7D,IAAI,IAAAC,2BAAoB,EAACL,KAAK,CAAC,EAAE;IAEjCJ,QAAQ,CAACU,IAAI,CAACN,KAAK,CAAC;EACtB;EAEA,OAAOJ,QAAQ;AACjB","ignoreList":[]}

View File

@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createTSUnionType;
var _index = require("../generated/index.js");
var _removeTypeDuplicates = require("../../modifications/typescript/removeTypeDuplicates.js");
var _index2 = require("../../validators/generated/index.js");
function createTSUnionType(typeAnnotations) {
const types = typeAnnotations.map(type => {
return (0, _index2.isTSTypeAnnotation)(type) ? type.typeAnnotation : type;
});
const flattened = (0, _removeTypeDuplicates.default)(types);
if (flattened.length === 1) {
return flattened[0];
} else {
return (0, _index.tsUnionType)(flattened);
}
}
//# sourceMappingURL=createTSUnionType.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_index","require","_removeTypeDuplicates","_index2","createTSUnionType","typeAnnotations","types","map","type","isTSTypeAnnotation","typeAnnotation","flattened","removeTypeDuplicates","length","tsUnionType"],"sources":["../../../src/builders/typescript/createTSUnionType.ts"],"sourcesContent":["import { tsUnionType } from \"../generated/index.ts\";\nimport removeTypeDuplicates from \"../../modifications/typescript/removeTypeDuplicates.ts\";\nimport { isTSTypeAnnotation } from \"../../validators/generated/index.ts\";\nimport type * as t from \"../../index.ts\";\n\n/**\n * Takes an array of `types` and flattens them, removing duplicates and\n * returns a `UnionTypeAnnotation` node containing them.\n */\nexport default function createTSUnionType(\n typeAnnotations: (t.TSTypeAnnotation | t.TSType)[],\n): t.TSType {\n const types = typeAnnotations.map(type => {\n return isTSTypeAnnotation(type) ? type.typeAnnotation : type;\n });\n const flattened = removeTypeDuplicates(types);\n\n if (flattened.length === 1) {\n return flattened[0];\n } else {\n return tsUnionType(flattened);\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,qBAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AAOe,SAASG,iBAAiBA,CACvCC,eAAkD,EACxC;EACV,MAAMC,KAAK,GAAGD,eAAe,CAACE,GAAG,CAACC,IAAI,IAAI;IACxC,OAAO,IAAAC,0BAAkB,EAACD,IAAI,CAAC,GAAGA,IAAI,CAACE,cAAc,GAAGF,IAAI;EAC9D,CAAC,CAAC;EACF,MAAMG,SAAS,GAAG,IAAAC,6BAAoB,EAACN,KAAK,CAAC;EAE7C,IAAIK,SAAS,CAACE,MAAM,KAAK,CAAC,EAAE;IAC1B,OAAOF,SAAS,CAAC,CAAC,CAAC;EACrB,CAAC,MAAM;IACL,OAAO,IAAAG,kBAAW,EAACH,SAAS,CAAC;EAC/B;AACF","ignoreList":[]}

View File

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = validateNode;
var _validate = require("../validators/validate.js");
var _index = require("../index.js");
function validateNode(node) {
if (node == null || typeof node !== "object") return;
const fields = _index.NODE_FIELDS[node.type];
if (!fields) return;
const keys = _index.BUILDER_KEYS[node.type];
for (const key of keys) {
const field = fields[key];
if (field != null) (0, _validate.validateInternal)(field, node, key, node[key]);
}
return node;
}
//# sourceMappingURL=validateNode.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_validate","require","_index","validateNode","node","fields","NODE_FIELDS","type","keys","BUILDER_KEYS","key","field","validateInternal"],"sources":["../../src/builders/validateNode.ts"],"sourcesContent":["import { validateInternal } from \"../validators/validate.ts\";\nimport type * as t from \"../index.ts\";\nimport { BUILDER_KEYS, NODE_FIELDS } from \"../index.ts\";\n\nexport default function validateNode<N extends t.Node>(node: N) {\n if (node == null || typeof node !== \"object\") return;\n const fields = NODE_FIELDS[node.type];\n if (!fields) return;\n\n // todo: because keys not in BUILDER_KEYS are not validated - this actually allows invalid nodes in some cases\n const keys = BUILDER_KEYS[node.type] as (keyof N & string)[];\n for (const key of keys) {\n const field = fields[key];\n if (field != null) validateInternal(field, node, key, node[key]);\n }\n return node;\n}\n"],"mappings":";;;;;;AAAA,IAAAA,SAAA,GAAAC,OAAA;AAEA,IAAAC,MAAA,GAAAD,OAAA;AAEe,SAASE,YAAYA,CAAmBC,IAAO,EAAE;EAC9D,IAAIA,IAAI,IAAI,IAAI,IAAI,OAAOA,IAAI,KAAK,QAAQ,EAAE;EAC9C,MAAMC,MAAM,GAAGC,kBAAW,CAACF,IAAI,CAACG,IAAI,CAAC;EACrC,IAAI,CAACF,MAAM,EAAE;EAGb,MAAMG,IAAI,GAAGC,mBAAY,CAACL,IAAI,CAACG,IAAI,CAAyB;EAC5D,KAAK,MAAMG,GAAG,IAAIF,IAAI,EAAE;IACtB,MAAMG,KAAK,GAAGN,MAAM,CAACK,GAAG,CAAC;IACzB,IAAIC,KAAK,IAAI,IAAI,EAAE,IAAAC,0BAAgB,EAACD,KAAK,EAAEP,IAAI,EAAEM,GAAG,EAAEN,IAAI,CAACM,GAAG,CAAC,CAAC;EAClE;EACA,OAAON,IAAI;AACb","ignoreList":[]}

12
admin/node_modules/@babel/types/lib/clone/clone.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = clone;
var _cloneNode = require("./cloneNode.js");
function clone(node) {
return (0, _cloneNode.default)(node, false);
}
//# sourceMappingURL=clone.js.map

View File

@ -0,0 +1 @@
{"version":3,"names":["_cloneNode","require","clone","node","cloneNode"],"sources":["../../src/clone/clone.ts"],"sourcesContent":["import cloneNode from \"./cloneNode.ts\";\nimport type * as t from \"../index.ts\";\n\n/**\n * Create a shallow clone of a `node`, including only\n * properties belonging to the node.\n * @deprecated Use t.cloneNode instead.\n */\nexport default function clone<T extends t.Node>(node: T): T {\n return cloneNode(node, /* deep */ false);\n}\n"],"mappings":";;;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA;AAQe,SAASC,KAAKA,CAAmBC,IAAO,EAAK;EAC1D,OAAO,IAAAC,kBAAS,EAACD,IAAI,EAAa,KAAK,CAAC;AAC1C","ignoreList":[]}

12
admin/node_modules/@babel/types/lib/clone/cloneDeep.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = cloneDeep;
var _cloneNode = require("./cloneNode.js");
function cloneDeep(node) {
return (0, _cloneNode.default)(node);
}
//# sourceMappingURL=cloneDeep.js.map

Some files were not shown because too many files have changed in this diff Show More