@vqh2602/mini-app-sdk 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -29
- package/bin/miniapp.js +6 -0
- package/bin/simulator.js +95 -0
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +65 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/create.d.ts +5 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +220 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +8 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +41 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +47 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/simulator.d.ts +6 -0
- package/dist/cli/commands/simulator.d.ts.map +1 -0
- package/dist/cli/commands/simulator.js +14 -0
- package/dist/cli/commands/simulator.js.map +1 -0
- package/dist/cli/commands/upload.d.ts +9 -0
- package/dist/cli/commands/upload.d.ts.map +1 -0
- package/dist/cli/commands/upload.js +107 -0
- package/dist/cli/commands/upload.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +63 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/config.d.ts +13 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/config.js +26 -0
- package/dist/cli/utils/config.js.map +1 -0
- package/dist/cli/utils/logger.d.ts +9 -0
- package/dist/cli/utils/logger.d.ts.map +1 -0
- package/dist/cli/utils/logger.js +18 -0
- package/dist/cli/utils/logger.js.map +1 -0
- package/dist/cli/utils/server.d.ts +3 -0
- package/dist/cli/utils/server.d.ts.map +1 -0
- package/dist/cli/utils/server.js +81 -0
- package/dist/cli/utils/server.js.map +1 -0
- package/dist/{client.d.ts → core/client.d.ts} +3 -3
- package/dist/core/client.d.ts.map +1 -0
- package/dist/{client.js → core/client.js} +3 -3
- package/dist/core/client.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/{modules → core/modules}/auth.d.ts +1 -1
- package/dist/core/modules/auth.d.ts.map +1 -0
- package/dist/core/modules/auth.js.map +1 -0
- package/dist/{modules → core/modules}/device.d.ts +1 -1
- package/dist/core/modules/device.d.ts.map +1 -0
- package/dist/core/modules/device.js.map +1 -0
- package/dist/{modules → core/modules}/lifecycle.d.ts +1 -1
- package/dist/core/modules/lifecycle.d.ts.map +1 -0
- package/dist/core/modules/lifecycle.js.map +1 -0
- package/dist/{modules → core/modules}/media.d.ts +1 -1
- package/dist/core/modules/media.d.ts.map +1 -0
- package/dist/core/modules/media.js.map +1 -0
- package/dist/{modules → core/modules}/navigation.d.ts +1 -1
- package/dist/core/modules/navigation.d.ts.map +1 -0
- package/dist/core/modules/navigation.js.map +1 -0
- package/dist/{modules → core/modules}/storage.d.ts +1 -1
- package/dist/core/modules/storage.d.ts.map +1 -0
- package/dist/core/modules/storage.js.map +1 -0
- package/dist/{modules → core/modules}/ui.d.ts +1 -1
- package/dist/core/modules/ui.d.ts.map +1 -0
- package/dist/core/modules/ui.js.map +1 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/{types → core/types}/index.js.map +1 -1
- package/dist/index.d.ts +7 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -12
- package/dist/index.js.map +1 -1
- package/dist/mock/handlers/auth.handler.d.ts +24 -0
- package/dist/mock/handlers/auth.handler.d.ts.map +1 -0
- package/dist/mock/handlers/auth.handler.js +106 -0
- package/dist/mock/handlers/auth.handler.js.map +1 -0
- package/dist/mock/handlers/device.handler.d.ts +16 -0
- package/dist/mock/handlers/device.handler.d.ts.map +1 -0
- package/dist/mock/handlers/device.handler.js +53 -0
- package/dist/mock/handlers/device.handler.js.map +1 -0
- package/dist/mock/handlers/media.handler.d.ts +9 -0
- package/dist/mock/handlers/media.handler.d.ts.map +1 -0
- package/dist/mock/handlers/media.handler.js +20 -0
- package/dist/mock/handlers/media.handler.js.map +1 -0
- package/dist/mock/handlers/payment.handler.d.ts +27 -0
- package/dist/mock/handlers/payment.handler.d.ts.map +1 -0
- package/dist/mock/handlers/payment.handler.js +62 -0
- package/dist/mock/handlers/payment.handler.js.map +1 -0
- package/dist/mock/handlers/storage.handler.d.ts +18 -0
- package/dist/mock/handlers/storage.handler.d.ts.map +1 -0
- package/dist/mock/handlers/storage.handler.js +40 -0
- package/dist/mock/handlers/storage.handler.js.map +1 -0
- package/dist/mock/handlers/ui.handler.d.ts +34 -0
- package/dist/mock/handlers/ui.handler.d.ts.map +1 -0
- package/dist/mock/handlers/ui.handler.js +59 -0
- package/dist/mock/handlers/ui.handler.js.map +1 -0
- package/dist/mock/index.d.ts +11 -0
- package/dist/mock/index.d.ts.map +1 -0
- package/dist/mock/index.js +11 -0
- package/dist/mock/index.js.map +1 -0
- package/dist/mock/mock-engine.d.ts +41 -0
- package/dist/mock/mock-engine.d.ts.map +1 -0
- package/dist/mock/mock-engine.js +325 -0
- package/dist/mock/mock-engine.js.map +1 -0
- package/dist/mock/presets.d.ts +3 -0
- package/dist/mock/presets.d.ts.map +1 -0
- package/dist/mock/presets.js +43 -0
- package/dist/mock/presets.js.map +1 -0
- package/dist/mock/store.d.ts +36 -0
- package/dist/mock/store.d.ts.map +1 -0
- package/dist/mock/store.js +133 -0
- package/dist/mock/store.js.map +1 -0
- package/dist/mock/types.d.ts +60 -0
- package/dist/mock/types.d.ts.map +1 -0
- package/dist/mock/types.js +2 -0
- package/dist/mock/types.js.map +1 -0
- package/dist/transport/index.d.ts +7 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +7 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/mock-transport.d.ts +20 -0
- package/dist/transport/mock-transport.d.ts.map +1 -0
- package/dist/transport/mock-transport.js +79 -0
- package/dist/transport/mock-transport.js.map +1 -0
- package/dist/transport/native-transport.d.ts +19 -0
- package/dist/transport/native-transport.d.ts.map +1 -0
- package/dist/transport/native-transport.js +151 -0
- package/dist/transport/native-transport.js.map +1 -0
- package/dist/transport/postmessage-transport.d.ts +20 -0
- package/dist/transport/postmessage-transport.d.ts.map +1 -0
- package/dist/transport/postmessage-transport.js +130 -0
- package/dist/transport/postmessage-transport.js.map +1 -0
- package/dist/transport/resolver.d.ts +11 -0
- package/dist/transport/resolver.d.ts.map +1 -0
- package/dist/transport/resolver.js +41 -0
- package/dist/transport/resolver.js.map +1 -0
- package/dist/transport/transport.interface.d.ts +10 -0
- package/dist/transport/transport.interface.d.ts.map +1 -0
- package/dist/transport/transport.interface.js +2 -0
- package/dist/transport/transport.interface.js.map +1 -0
- package/dist/transport/types.d.ts +46 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +2 -0
- package/dist/transport/types.js.map +1 -0
- package/package.json +47 -11
- package/simulator-dist/assets/index-kRVYB6or.js +199 -0
- package/simulator-dist/index.html +15 -0
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/modules/auth.d.ts.map +0 -1
- package/dist/modules/auth.js.map +0 -1
- package/dist/modules/device.d.ts.map +0 -1
- package/dist/modules/device.js.map +0 -1
- package/dist/modules/lifecycle.d.ts.map +0 -1
- package/dist/modules/lifecycle.js.map +0 -1
- package/dist/modules/media.d.ts.map +0 -1
- package/dist/modules/media.js.map +0 -1
- package/dist/modules/navigation.d.ts.map +0 -1
- package/dist/modules/navigation.js.map +0 -1
- package/dist/modules/payment.d.ts +0 -15
- package/dist/modules/payment.d.ts.map +0 -1
- package/dist/modules/payment.js +0 -25
- package/dist/modules/payment.js.map +0 -1
- package/dist/modules/storage.d.ts.map +0 -1
- package/dist/modules/storage.js.map +0 -1
- package/dist/modules/ui.d.ts.map +0 -1
- package/dist/modules/ui.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- /package/dist/{modules → core/modules}/auth.js +0 -0
- /package/dist/{modules → core/modules}/device.js +0 -0
- /package/dist/{modules → core/modules}/lifecycle.js +0 -0
- /package/dist/{modules → core/modules}/media.js +0 -0
- /package/dist/{modules → core/modules}/navigation.js +0 -0
- /package/dist/{modules → core/modules}/storage.js +0 -0
- /package/dist/{modules → core/modules}/ui.js +0 -0
- /package/dist/{types → core/types}/index.d.ts +0 -0
- /package/dist/{types → core/types}/index.js +0 -0
package/README.md
CHANGED
|
@@ -1,58 +1,210 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SuperApp Mini App Developer SDK Ecosystem
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Hệ sinh thái bộ công cụ SDK, Bridge Transport, Mock Engine, CLI và Browser Simulator dành riêng cho các nhà phát triển thứ ba (3rd-party developers) xây dựng, kiểm thử và xuất bản Mini App trên nền tảng SuperApp.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Tự động chuyển đổi môi trường**: Chạy mượt mà trên cả Flutter WebView thật, trong iframe Browser Simulator, hay độc lập (Mock Engine tự động).
|
|
9
|
-
- **Hỗ trợ đầy đủ nghiệp vụ SuperApp**:
|
|
10
|
-
- `auth`: Đăng nhập, cấp quyền OAuth, lấy User Profile, quản lý token.
|
|
11
|
-
- `payment`: Tích hợp thanh toán trực tiếp qua ví SuperApp.
|
|
12
|
-
- `device`: Pin, thông tin mạng, rung xúc giác haptic feedback, thông số màn hình.
|
|
13
|
-
- `storage`: Lưu trữ key-value cách ly và an toàn theo từng Mini App.
|
|
14
|
-
- `ui`: Toast thông báo, Alert, Confirm, đổi tiêu đề thanh điều hướng.
|
|
15
|
-
- `media`: Quét QR code camera, chọn ảnh.
|
|
16
|
-
- `lifecycle`: Bắt sự kiện app vào nền (Background) hoặc ra màn hình (Foreground).
|
|
7
|
+
## 🏗️ 1. Kiến Trúc Hợp Nhất (All-in-One Package: `@vqh2602/mini-app-sdk`)
|
|
17
8
|
|
|
18
|
-
|
|
9
|
+
Toàn bộ hệ thống SDK, Mock Engine, Bridge Transport, CLI và Browser Simulator đã được hợp nhất vào **1 gói npm duy nhất**:
|
|
19
10
|
|
|
11
|
+
| Khối chức năng | Thư mục source | Vai trò & Trách nhiệm |
|
|
12
|
+
| :--- | :--- | :--- |
|
|
13
|
+
| **Mini App Core SDK** | `src/core/` | Bộ API chính thức cho bên thứ ba (`npm install @vqh2602/mini-app-sdk`): `auth`, `payment`, `device`, `storage`, `ui`, `media`, `lifecycle`. |
|
|
14
|
+
| **Bridge Transport** | `src/transport/` | Lớp trừu tượng hoá Bridge: chuyển đổi linh hoạt giữa Flutter WebView Native (`FlutterBridge`), PostMessage trong iframe Simulator, hoặc Mock cục bộ. |
|
|
15
|
+
| **SDK Mock Engine** | `src/mock/` | Động cơ giả lập Native: sinh mã `authCode`, cấp `accessToken`, hồ sơ người dùng, quản lý số dư ví, trừ tiền thanh toán, giả lập pin, mạng, độ trễ và lưu trữ cách ly. |
|
|
16
|
+
| **Mini App CLI** | `src/cli/` & `bin/` | Công cụ dòng lệnh: `create` (tạo dự án mẫu), `dev` (khởi chạy dev server + simulator), `build` (biên dịch + checksum), `upload` (gửi lên Registry), `simulator`. |
|
|
17
|
+
| **Browser Simulator** | `simulator/` & `simulator-dist/` | Giao diện web giả lập điện thoại đã được build sẵn tĩnh, tích hợp trực tiếp vào lệnh `miniapp dev` và `miniapp simulator`. |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ⚡ 2. Hướng Dẫn Vận Hành Cho Nhà Phát Triển (Quickstart)
|
|
22
|
+
|
|
23
|
+
### Bước 1: Khởi tạo Mini App mới bằng CLI
|
|
24
|
+
Lập trình viên bên thứ ba có thể chạy trực tiếp thông qua `npx`:
|
|
25
|
+
```bash
|
|
26
|
+
npx @vqh2602/mini-app-sdk create my_awesome_app
|
|
27
|
+
```
|
|
28
|
+
Hoặc nếu đã cài đặt toàn cục (`npm install -g @vqh2602/mini-app-sdk`):
|
|
20
29
|
```bash
|
|
21
|
-
|
|
30
|
+
miniapp create my_awesome_app
|
|
22
31
|
```
|
|
32
|
+
Lệnh này sẽ tự động sinh:
|
|
33
|
+
- `app.json`: Manifest khai báo `appId`, `name`, `version`, `permissions`, `themeColor`.
|
|
34
|
+
- `package.json`: Cài đặt sẵn `@vqh2602/mini-app-sdk`.
|
|
35
|
+
- `src/main.ts`: Code mẫu gọi các hàm đăng nhập, thanh toán, pin, toast.
|
|
36
|
+
- `index.html` & `vite.config.ts`.
|
|
23
37
|
|
|
24
|
-
|
|
38
|
+
### Bước 2: Chạy Dev Server & Browser Simulator đồng thời
|
|
39
|
+
```bash
|
|
40
|
+
cd my_awesome_app
|
|
41
|
+
npx miniapp dev
|
|
42
|
+
```
|
|
43
|
+
Lệnh `miniapp dev` sẽ khởi chạy cả:
|
|
44
|
+
* Vite dev server của Mini App (Port 3000)
|
|
45
|
+
* Browser Simulator tích hợp sẵn (Port 5175 tại `http://localhost:5175/?url=http://localhost:3000`)
|
|
25
46
|
|
|
47
|
+
### Bước 3: Đóng gói và xuất bản Mini App
|
|
48
|
+
```bash
|
|
49
|
+
# Đóng gói và kiểm tra checksum
|
|
50
|
+
npx miniapp build
|
|
51
|
+
|
|
52
|
+
# Tải lên SuperApp Dynamic Registry và gửi xét duyệt
|
|
53
|
+
npx miniapp upload --submit --notes "Phát hành phiên bản 1.0.0"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 📖 3. Bảng Tra Cứu API Mini App SDK (`@vqh2602/mini-app-sdk`)
|
|
59
|
+
|
|
60
|
+
### 🔐 3.1. Xác thực & Người dùng (`superApp.auth`)
|
|
26
61
|
```typescript
|
|
27
62
|
import superApp from '@vqh2602/mini-app-sdk';
|
|
28
63
|
|
|
29
|
-
//
|
|
30
|
-
const
|
|
64
|
+
// Đăng nhập và xin cấp quyền profile + phone
|
|
65
|
+
const loginRes = await superApp.auth.login({
|
|
31
66
|
scopes: ['user.profile', 'user.phone'],
|
|
32
67
|
});
|
|
33
|
-
console.log('
|
|
68
|
+
console.log('User Name:', loginRes.user.name);
|
|
69
|
+
console.log('Access Token:', loginRes.accessToken);
|
|
70
|
+
|
|
71
|
+
// Lấy thông tin người dùng hiện tại
|
|
72
|
+
const profile = await superApp.auth.getUserProfile();
|
|
73
|
+
|
|
74
|
+
// Lấy Access Token
|
|
75
|
+
const token = await superApp.auth.getAccessToken();
|
|
34
76
|
|
|
35
|
-
//
|
|
77
|
+
// Đăng xuất
|
|
78
|
+
await superApp.auth.logout();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 💳 3.2. Thanh toán SuperApp Pay (`superApp.payment`)
|
|
82
|
+
```typescript
|
|
36
83
|
try {
|
|
37
84
|
const result = await superApp.payment.requestPayment({
|
|
38
|
-
orderId: '
|
|
39
|
-
amount:
|
|
40
|
-
description: 'Thanh toán
|
|
85
|
+
orderId: 'ORDER_2026_001',
|
|
86
|
+
amount: 150000,
|
|
87
|
+
description: 'Thanh toán Combo Cơm Trưa',
|
|
41
88
|
});
|
|
42
89
|
|
|
43
90
|
if (result.status === 'SUCCESS') {
|
|
44
|
-
await superApp.ui.showToast('Thanh toán thành công!');
|
|
91
|
+
await superApp.ui.showToast('Thanh toán thành công qua Ví SuperApp!');
|
|
92
|
+
}
|
|
93
|
+
} catch (error: any) {
|
|
94
|
+
if (error.code === 'INSUFFICIENT_FUNDS') {
|
|
95
|
+
await superApp.ui.showAlert({ title: 'Lỗi', message: 'Số dư ví không đủ' });
|
|
96
|
+
} else if (error.code === 'USER_CANCELLED') {
|
|
97
|
+
await superApp.ui.showToast('Bạn đã huỷ thanh toán');
|
|
45
98
|
}
|
|
46
|
-
} catch (error) {
|
|
47
|
-
await superApp.ui.showToast('Giao dịch thất bại');
|
|
48
99
|
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 📱 3.3. Thiết bị & Phần cứng (`superApp.device`)
|
|
103
|
+
```typescript
|
|
104
|
+
// Mức pin và trạng thái sạc
|
|
105
|
+
const battery = await superApp.device.getBatteryInfo();
|
|
106
|
+
console.log(`Pin: ${battery.batteryLevel}%, Đang sạc: ${battery.isCharging}`);
|
|
107
|
+
|
|
108
|
+
// Trạng thái mạng
|
|
109
|
+
const network = await superApp.device.getNetworkInfo();
|
|
110
|
+
console.log(`Kết nối: ${network.networkType}, WiFi: ${network.isWifi}`);
|
|
49
111
|
|
|
50
|
-
//
|
|
51
|
-
await superApp.
|
|
112
|
+
// Rung xúc giác haptic feedback
|
|
113
|
+
await superApp.device.vibrate('light'); // 'light' | 'medium' | 'heavy'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 💾 3.4. Lưu trữ cách ly (`superApp.storage`)
|
|
117
|
+
```typescript
|
|
118
|
+
// Ghi dữ liệu
|
|
119
|
+
await superApp.storage.setItem('user_cart', { items: [{ id: 1, name: 'Trà Sữa' }] });
|
|
120
|
+
|
|
121
|
+
// Đọc dữ liệu (Tự động deserialize JSON)
|
|
52
122
|
const cart = await superApp.storage.getItem('user_cart');
|
|
53
123
|
|
|
54
|
-
//
|
|
124
|
+
// Xoá key
|
|
125
|
+
await superApp.storage.removeItem('user_cart');
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 🔔 3.5. Giao diện & Điều hướng (`superApp.ui` / `superApp.navigation`)
|
|
129
|
+
```typescript
|
|
130
|
+
// Toast
|
|
131
|
+
await superApp.ui.showToast('Cập nhật thành công!');
|
|
132
|
+
|
|
133
|
+
// Alert Dialog
|
|
134
|
+
await superApp.ui.showAlert({ title: 'Chúc mừng', message: 'Nhận được voucher 50%' });
|
|
135
|
+
|
|
136
|
+
// Confirm Dialog
|
|
137
|
+
const agreed = await superApp.ui.showConfirm({
|
|
138
|
+
title: 'Xoá giỏ hàng',
|
|
139
|
+
message: 'Bạn có chắc chắn muốn làm trống giỏ hàng?',
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Đặt tiêu đề thanh điều hướng
|
|
143
|
+
await superApp.ui.setNavigationBarTitle('Menu Quán Cà Phê');
|
|
144
|
+
|
|
145
|
+
// Đóng Mini App về màn hình chính SuperApp
|
|
146
|
+
await superApp.closeApp();
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 🔄 3.6. Vòng đời ứng dụng (`superApp.lifecycle`)
|
|
150
|
+
```typescript
|
|
151
|
+
// Bắt sự kiện khi app ra màn hình (Foreground)
|
|
55
152
|
superApp.lifecycle.onAppShow(() => {
|
|
56
153
|
console.log('Mini App hiển thị trở lại');
|
|
57
154
|
});
|
|
155
|
+
|
|
156
|
+
// Bắt sự kiện khi app bị ẩn xuống nền (Background)
|
|
157
|
+
superApp.lifecycle.onAppHide(() => {
|
|
158
|
+
console.log('Mini App tạm dừng');
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 🧩 4. Sub-path Exports Nâng Cao
|
|
165
|
+
|
|
166
|
+
Ngoài entrypoint mặc định `superApp`, package cung cấp các sub-path để lập trình viên tùy biến sâu:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// 1. Tầng Transport Bridge
|
|
170
|
+
import {
|
|
171
|
+
TransportResolver,
|
|
172
|
+
NativeBridgeTransport,
|
|
173
|
+
PostMessageTransport,
|
|
174
|
+
MockBridgeTransport,
|
|
175
|
+
} from '@vqh2602/mini-app-sdk/transport';
|
|
176
|
+
|
|
177
|
+
// 2. Động cơ Mock Engine & Dữ liệu mẫu
|
|
178
|
+
import {
|
|
179
|
+
SDKMockEngine,
|
|
180
|
+
MockStateStore,
|
|
181
|
+
MOCK_USER_PRESETS,
|
|
182
|
+
} from '@vqh2602/mini-app-sdk/mock';
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 🛠️ 5. Dành Cho Quản Trị Viên (Maintainer Guide)
|
|
188
|
+
|
|
189
|
+
### Biên dịch & Kiểm tra gói đóng gói
|
|
190
|
+
```bash
|
|
191
|
+
cd mini_app_sdk
|
|
192
|
+
|
|
193
|
+
# Cài đặt dependencies
|
|
194
|
+
npm install
|
|
195
|
+
|
|
196
|
+
# Biên dịch Phone Simulator + TypeScript SDK
|
|
197
|
+
npm run build
|
|
198
|
+
|
|
199
|
+
# Chạy Phone Simulator cục bộ
|
|
200
|
+
npm run simulator
|
|
201
|
+
|
|
202
|
+
# Kiểm tra nội dung đóng gói trước khi xuất bản (Dry Run)
|
|
203
|
+
npm pack --dry-run
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Phát hành phiên bản mới lên npm Public Registry
|
|
207
|
+
```bash
|
|
208
|
+
# Xuất bản trực tiếp lên npm
|
|
209
|
+
npm publish --access public
|
|
58
210
|
```
|
package/bin/miniapp.js
ADDED
package/bin/simulator.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import http from 'node:http';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
let distDir = path.resolve(__dirname, '../simulator-dist');
|
|
11
|
+
if (!fs.existsSync(distDir)) {
|
|
12
|
+
distDir = path.resolve(__dirname, '../dist/simulator');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
17
|
+
console.log(`
|
|
18
|
+
Usage: superapp-simulator [options]
|
|
19
|
+
|
|
20
|
+
Options:
|
|
21
|
+
--port <number> Port to run simulator on (default: 5175)
|
|
22
|
+
-h, --help Show this help message
|
|
23
|
+
`);
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const portIndex = args.indexOf('--port');
|
|
28
|
+
const port = portIndex !== -1 && args[portIndex + 1] ? parseInt(args[portIndex + 1], 10) : 5175;
|
|
29
|
+
|
|
30
|
+
const MIME_TYPES = {
|
|
31
|
+
'.html': 'text/html; charset=utf-8',
|
|
32
|
+
'.js': 'application/javascript; charset=utf-8',
|
|
33
|
+
'.css': 'text/css; charset=utf-8',
|
|
34
|
+
'.json': 'application/json',
|
|
35
|
+
'.png': 'image/png',
|
|
36
|
+
'.jpg': 'image/jpeg',
|
|
37
|
+
'.svg': 'image/svg+xml',
|
|
38
|
+
'.ico': 'image/x-icon',
|
|
39
|
+
'.woff2': 'font/woff2',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const server = http.createServer((req, res) => {
|
|
43
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
44
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
|
|
45
|
+
|
|
46
|
+
if (req.method === 'OPTIONS') {
|
|
47
|
+
res.writeHead(204);
|
|
48
|
+
res.end();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const parsedUrl = new URL(req.url, `http://localhost:${port}`);
|
|
53
|
+
let pathname = parsedUrl.pathname;
|
|
54
|
+
let filePath = path.join(distDir, pathname);
|
|
55
|
+
|
|
56
|
+
if (!filePath.startsWith(distDir)) {
|
|
57
|
+
res.writeHead(403);
|
|
58
|
+
res.end('Forbidden');
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fs.stat(filePath, (err, stats) => {
|
|
63
|
+
if (err || !stats.isFile()) {
|
|
64
|
+
filePath = path.join(distDir, 'index.html');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
68
|
+
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
|
|
69
|
+
|
|
70
|
+
fs.readFile(filePath, (readErr, data) => {
|
|
71
|
+
if (readErr) {
|
|
72
|
+
res.writeHead(404);
|
|
73
|
+
res.end('Not Found');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
res.writeHead(200, { 'Content-Type': contentType });
|
|
77
|
+
res.end(data);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
server.on('error', (err) => {
|
|
83
|
+
if (err.code === 'EADDRINUSE') {
|
|
84
|
+
console.error(`\n❌ \x1b[31mError: Port ${port} is already in use.\x1b[0m Try passing a different port with: \x1b[33m--port <port>\x1b[0m\n`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
} else {
|
|
87
|
+
console.error(`\n❌ Server error: ${err.message}\n`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
server.listen(port, () => {
|
|
93
|
+
console.log(`\n📱 \x1b[36mSuperApp Browser Simulator\x1b[0m is running at: \x1b[1mhttp://localhost:${port}\x1b[0m`);
|
|
94
|
+
console.log(`🔗 Open with target Mini App: \x1b[32mhttp://localhost:${port}/?url=http://localhost:3000\x1b[0m\n`);
|
|
95
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgEnF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { loadManifest } from '../utils/config.js';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
export async function buildProject(options = {}) {
|
|
8
|
+
const manifest = loadManifest();
|
|
9
|
+
const outDir = options.outDir || 'dist';
|
|
10
|
+
logger.title(`Đóng gói Mini App: ${manifest.name} (v${manifest.version})`);
|
|
11
|
+
logger.step(1, 3, 'Xác thực cấu hình app.json và các quyền permissions...');
|
|
12
|
+
if (manifest.permissions) {
|
|
13
|
+
logger.info(`Permissions: ${manifest.permissions.join(', ')}`);
|
|
14
|
+
}
|
|
15
|
+
logger.step(2, 3, 'Biên dịch mã nguồn với Vite & TypeScript...');
|
|
16
|
+
try {
|
|
17
|
+
execSync('npx vite build', { stdio: 'inherit' });
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
logger.error('Lỗi khi biên dịch mã nguồn Mini App', err);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const distPath = path.resolve(process.cwd(), outDir);
|
|
24
|
+
const indexPath = path.join(distPath, manifest.entry || 'index.html');
|
|
25
|
+
if (!fs.existsSync(indexPath)) {
|
|
26
|
+
logger.error(`Không tìm thấy file entry "${manifest.entry}" trong thư mục build: ${distPath}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
logger.step(3, 3, 'Tính toán checksum và tạo metadata gói phát hành...');
|
|
30
|
+
// Compute checksum of dist files
|
|
31
|
+
const hash = crypto.createHash('sha256');
|
|
32
|
+
function hashDirectory(dir) {
|
|
33
|
+
const files = fs.readdirSync(dir);
|
|
34
|
+
for (const file of files) {
|
|
35
|
+
const fullPath = path.join(dir, file);
|
|
36
|
+
const stat = fs.statSync(fullPath);
|
|
37
|
+
if (stat.isDirectory()) {
|
|
38
|
+
hashDirectory(fullPath);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
hash.update(fs.readFileSync(fullPath));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
hashDirectory(distPath);
|
|
46
|
+
const bundleChecksum = hash.digest('hex');
|
|
47
|
+
const bundleMeta = {
|
|
48
|
+
appId: manifest.appId,
|
|
49
|
+
name: manifest.name,
|
|
50
|
+
version: manifest.version,
|
|
51
|
+
description: manifest.description,
|
|
52
|
+
entry: manifest.entry,
|
|
53
|
+
category: manifest.category,
|
|
54
|
+
themeColor: manifest.themeColor,
|
|
55
|
+
permissions: manifest.permissions,
|
|
56
|
+
checksum: bundleChecksum,
|
|
57
|
+
builtAt: new Date().toISOString(),
|
|
58
|
+
};
|
|
59
|
+
fs.writeFileSync(path.join(distPath, 'bundle-meta.json'), JSON.stringify(bundleMeta, null, 2));
|
|
60
|
+
logger.success(`Đóng gói thành công gói phát hành Mini App!`);
|
|
61
|
+
logger.info(`Thư mục output: ${distPath}`);
|
|
62
|
+
logger.info(`Bundle SHA256: ${bundleChecksum}`);
|
|
63
|
+
console.log(`\nSẵn sàng tải lên với lệnh:\n npx miniapp upload\n`);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmO1G"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
export async function createProject(projectName, options = {}) {
|
|
5
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
6
|
+
if (fs.existsSync(targetDir)) {
|
|
7
|
+
logger.error(`Thư mục "${projectName}" đã tồn tại. Vui lòng chọn tên khác hoặc xoá thư mục cũ.`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
logger.title(`Khởi tạo Mini App mới: ${projectName}`);
|
|
11
|
+
logger.step(1, 3, `Đang tạo cấu trúc thư mục tại: ${targetDir}`);
|
|
12
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
13
|
+
fs.mkdirSync(path.join(targetDir, 'src'), { recursive: true });
|
|
14
|
+
fs.mkdirSync(path.join(targetDir, 'public'), { recursive: true });
|
|
15
|
+
const sanitizedId = projectName.toLowerCase().replace(/[^a-z0-9_-]/g, '_');
|
|
16
|
+
// 1. app.json manifest
|
|
17
|
+
const appJson = {
|
|
18
|
+
appId: sanitizedId,
|
|
19
|
+
name: projectName.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()),
|
|
20
|
+
version: '1.0.0',
|
|
21
|
+
description: `SuperApp Mini App: ${projectName}`,
|
|
22
|
+
entry: 'index.html',
|
|
23
|
+
category: 'utilities',
|
|
24
|
+
themeColor: '#0068FF',
|
|
25
|
+
permissions: [
|
|
26
|
+
'auth.userProfile',
|
|
27
|
+
'device.battery',
|
|
28
|
+
'device.network',
|
|
29
|
+
'storage',
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
fs.writeFileSync(path.join(targetDir, 'app.json'), JSON.stringify(appJson, null, 2));
|
|
33
|
+
// 2. package.json
|
|
34
|
+
const packageJson = {
|
|
35
|
+
name: projectName,
|
|
36
|
+
private: true,
|
|
37
|
+
version: '1.0.0',
|
|
38
|
+
type: 'module',
|
|
39
|
+
scripts: {
|
|
40
|
+
dev: 'vite',
|
|
41
|
+
build: 'tsc && vite build',
|
|
42
|
+
preview: 'vite preview',
|
|
43
|
+
},
|
|
44
|
+
dependencies: {
|
|
45
|
+
'@vqh2602/mini-app-sdk': '^1.0.0',
|
|
46
|
+
},
|
|
47
|
+
devDependencies: {
|
|
48
|
+
typescript: '^5.6.3',
|
|
49
|
+
vite: '^5.4.11',
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
fs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
53
|
+
// 3. tsconfig.json
|
|
54
|
+
const tsconfig = {
|
|
55
|
+
compilerOptions: {
|
|
56
|
+
target: 'ES2020',
|
|
57
|
+
useDefineForClassFields: true,
|
|
58
|
+
module: 'ESNext',
|
|
59
|
+
lib: ['ES2020', 'DOM', 'DOM.Iterable'],
|
|
60
|
+
skipLibCheck: true,
|
|
61
|
+
moduleResolution: 'bundler',
|
|
62
|
+
allowImportingTsExtensions: true,
|
|
63
|
+
resolveJsonModule: true,
|
|
64
|
+
isolatedModules: true,
|
|
65
|
+
noEmit: true,
|
|
66
|
+
strict: true,
|
|
67
|
+
noUnusedLocals: true,
|
|
68
|
+
noUnusedParameters: true,
|
|
69
|
+
noFallthroughCasesInSwitch: true,
|
|
70
|
+
},
|
|
71
|
+
include: ['src'],
|
|
72
|
+
};
|
|
73
|
+
fs.writeFileSync(path.join(targetDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2));
|
|
74
|
+
// 4. vite.config.ts
|
|
75
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
76
|
+
|
|
77
|
+
export default defineConfig({
|
|
78
|
+
base: './',
|
|
79
|
+
server: {
|
|
80
|
+
port: 3000,
|
|
81
|
+
},
|
|
82
|
+
build: {
|
|
83
|
+
outDir: 'dist',
|
|
84
|
+
assetsDir: 'assets',
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
`;
|
|
88
|
+
fs.writeFileSync(path.join(targetDir, 'vite.config.ts'), viteConfig);
|
|
89
|
+
// 5. index.html
|
|
90
|
+
const indexHtml = `<!DOCTYPE html>
|
|
91
|
+
<html lang="vi">
|
|
92
|
+
<head>
|
|
93
|
+
<meta charset="UTF-8" />
|
|
94
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
|
95
|
+
<title>${appJson.name}</title>
|
|
96
|
+
<style>
|
|
97
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
98
|
+
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f8fafc; color: #0f172a; padding: 16px; }
|
|
99
|
+
.card { background: white; border-radius: 12px; padding: 16px; margin-bottom: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
|
|
100
|
+
.btn { display: block; width: 100%; padding: 12px; border-radius: 8px; border: none; font-weight: 600; font-size: 14px; cursor: pointer; margin-bottom: 8px; }
|
|
101
|
+
.btn-primary { background: #0068FF; color: white; }
|
|
102
|
+
.btn-success { background: #10B981; color: white; }
|
|
103
|
+
.btn-secondary { background: #e2e8f0; color: #334155; }
|
|
104
|
+
h1 { font-size: 20px; font-weight: 700; margin-bottom: 4px; }
|
|
105
|
+
p { font-size: 13px; color: #64748b; line-height: 1.5; }
|
|
106
|
+
pre { background: #0f172a; color: #38bdf8; padding: 12px; border-radius: 8px; font-size: 12px; overflow-x: auto; max-height: 200px; }
|
|
107
|
+
</style>
|
|
108
|
+
</head>
|
|
109
|
+
<body>
|
|
110
|
+
<div class="card">
|
|
111
|
+
<h1>🚀 ${appJson.name}</h1>
|
|
112
|
+
<p>SuperApp Mini App SDK Demo Starter</p>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<div class="card">
|
|
116
|
+
<button id="btnLogin" class="btn btn-primary">👤 1. Đăng nhập SuperApp</button>
|
|
117
|
+
<button id="btnPay" class="btn btn-success">💳 2. Thanh toán đơn hàng</button>
|
|
118
|
+
<button id="btnDevice" class="btn btn-secondary">📱 3. Kiểm tra thông tin thiết bị</button>
|
|
119
|
+
<button id="btnToast" class="btn btn-secondary">🔔 4. Hiển thị thông báo Toast</button>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div class="card">
|
|
123
|
+
<p style="font-weight: 600; margin-bottom: 8px;">Kết quả phản hồi:</p>
|
|
124
|
+
<pre id="output">Sẵn sàng gọi SDK...</pre>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<script type="module" src="/src/main.ts"></script>
|
|
128
|
+
</body>
|
|
129
|
+
</html>
|
|
130
|
+
`;
|
|
131
|
+
fs.writeFileSync(path.join(targetDir, 'index.html'), indexHtml);
|
|
132
|
+
// 6. src/main.ts
|
|
133
|
+
const mainTs = `import superApp from '@vqh2602/mini-app-sdk';
|
|
134
|
+
|
|
135
|
+
const outputEl = document.getElementById('output') as HTMLPreElement;
|
|
136
|
+
|
|
137
|
+
function log(data: any) {
|
|
138
|
+
outputEl.textContent = JSON.stringify(data, null, 2);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 1. Đăng nhập
|
|
142
|
+
document.getElementById('btnLogin')?.addEventListener('click', async () => {
|
|
143
|
+
try {
|
|
144
|
+
const res = await superApp.auth.login({ scopes: ['user.profile', 'user.phone'] });
|
|
145
|
+
log(res);
|
|
146
|
+
await superApp.ui.showToast(\`Xin chào \${res.user.name}!\`);
|
|
147
|
+
} catch (err: any) {
|
|
148
|
+
log({ error: err });
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// 2. Thanh toán
|
|
153
|
+
document.getElementById('btnPay')?.addEventListener('click', async () => {
|
|
154
|
+
try {
|
|
155
|
+
const res = await superApp.payment.requestPayment({
|
|
156
|
+
orderId: 'ORDER_' + Date.now(),
|
|
157
|
+
amount: 45000,
|
|
158
|
+
description: 'Thanh toán đơn hàng mẫu Mini App',
|
|
159
|
+
});
|
|
160
|
+
log(res);
|
|
161
|
+
await superApp.ui.showToast('Thanh toán thành công!');
|
|
162
|
+
} catch (err: any) {
|
|
163
|
+
log({ error: err });
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// 3. Thông tin thiết bị
|
|
168
|
+
document.getElementById('btnDevice')?.addEventListener('click', async () => {
|
|
169
|
+
try {
|
|
170
|
+
const battery = await superApp.device.getBatteryInfo();
|
|
171
|
+
const network = await superApp.device.getNetworkInfo();
|
|
172
|
+
const system = await superApp.device.getSystemInfo();
|
|
173
|
+
log({ battery, network, system });
|
|
174
|
+
} catch (err: any) {
|
|
175
|
+
log({ error: err });
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// 4. Toast & Rung
|
|
180
|
+
document.getElementById('btnToast')?.addEventListener('click', async () => {
|
|
181
|
+
await superApp.device.vibrate('light');
|
|
182
|
+
await superApp.ui.showToast('Thông báo Toast từ SuperApp SDK');
|
|
183
|
+
});
|
|
184
|
+
`;
|
|
185
|
+
fs.writeFileSync(path.join(targetDir, 'src/main.ts'), mainTs);
|
|
186
|
+
// 7. .gitignore
|
|
187
|
+
const gitignore = `node_modules
|
|
188
|
+
dist
|
|
189
|
+
.DS_Store
|
|
190
|
+
*.local
|
|
191
|
+
`;
|
|
192
|
+
fs.writeFileSync(path.join(targetDir, '.gitignore'), gitignore);
|
|
193
|
+
// 8. README.md
|
|
194
|
+
const readme = `# ${projectName}
|
|
195
|
+
|
|
196
|
+
Dự án Mini App chạy trên nền tảng SuperApp.
|
|
197
|
+
|
|
198
|
+
## Bắt đầu
|
|
199
|
+
|
|
200
|
+
\`\`\`bash
|
|
201
|
+
# 1. Cài đặt thư viện
|
|
202
|
+
npm install
|
|
203
|
+
|
|
204
|
+
# 2. Khởi chạy dev server & simulator
|
|
205
|
+
npx miniapp dev
|
|
206
|
+
|
|
207
|
+
# 3. Đóng gói sản phẩm
|
|
208
|
+
npx miniapp build
|
|
209
|
+
|
|
210
|
+
# 4. Xuất bản lên SuperApp Dynamic Registry
|
|
211
|
+
npx miniapp upload
|
|
212
|
+
\`\`\`
|
|
213
|
+
`;
|
|
214
|
+
fs.writeFileSync(path.join(targetDir, 'README.md'), readme);
|
|
215
|
+
logger.step(2, 3, 'Khởi tạo mã nguồn và file cấu hình manifest app.json thành công!');
|
|
216
|
+
logger.step(3, 3, 'Hoàn tất.');
|
|
217
|
+
logger.success(`Mini App "${projectName}" đã sẵn sàng!`);
|
|
218
|
+
console.log(`\nTiếp theo, hãy thực hiện:\n cd ${projectName}\n npm install\n npx miniapp dev\n`);
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/cli/commands/create.ts"],"names":[],"mappings":"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"}
|