@proteus-vue/compat-miniprogram 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -0
- package/dist/codemod.d.ts +17 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +233 -0
- package/dist/route-table.d.ts +20 -0
- package/dist/tags.d.ts +8 -0
- package/dist/wx-compat.d.ts +53 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @proteus-vue/compat-miniprogram
|
|
2
|
+
|
|
3
|
+
> **G-31 B6 Layer 1 兼容层**(`docs/proteus-component-semantics-plan/migration.md`)
|
|
4
|
+
|
|
5
|
+
## 一句话
|
|
6
|
+
|
|
7
|
+
**旧小程序不用重写就能渐进迁移到 Proteus**(三步走):compat 运行时桥让 `wx.*` 旧代码跑通 → codemod 批量转语义(标签/存储自动 + 复杂项标注 manual)→ 人工收尾语义还原。
|
|
8
|
+
|
|
9
|
+
## 三位一体(migration.md §4 三步对应)
|
|
10
|
+
|
|
11
|
+
| 能力 | 对应 Step | 说明 |
|
|
12
|
+
|------|----------|------|
|
|
13
|
+
| `createWxCompat(platform, cap)` | Step 1 | 运行时桥:`wx.request/navigateTo/setStorageSync/showModal/...` 委托 Proteus PlatformAPI + CapabilityHooks——旧代码原样跑通 |
|
|
14
|
+
| `migrateMpSource(source)` | Step 2 | codemod 纯函数(幂等):① 标签自动(view→p-box/text→p-text/button→p-button/input→p-input...)② 同步存储直改(`wx.setStorageSync` → `useStorage().set`)③ 回调式 API 标注(`wx.request({success})` → `[proteus-migrate:manual]` 注释)④ 语义识别标签标注(scroll-view/swiper → manual) |
|
|
15
|
+
| `useStorage()` + `bindCompatPlatform()` | Step 2 目标 | codemod 输出 `useStorage().set(...)` 的运行时绑定(委托 platform.storage) |
|
|
16
|
+
|
|
17
|
+
## 用法
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createPlatformAPI, createCapabilityHooks } from '@proteus-vue/api'
|
|
21
|
+
import { installCompat, migrateMpSource } from '@proteus-vue/compat-miniprogram'
|
|
22
|
+
|
|
23
|
+
// Step 1:旧代码兜底(wx.* 可用)
|
|
24
|
+
const platform = createPlatformAPI()
|
|
25
|
+
installCompat(platform, createCapabilityHooks())
|
|
26
|
+
|
|
27
|
+
// Step 2:codemod 迁移
|
|
28
|
+
const migrated = migrateMpSource(`
|
|
29
|
+
<view><text>标题</text></view>
|
|
30
|
+
wx.setStorageSync('k', v)
|
|
31
|
+
wx.request({ url: '/x', success: (r) => {} })
|
|
32
|
+
`)
|
|
33
|
+
// → <p-box><p-text>标题</p-text></p-box>
|
|
34
|
+
// useStorage().set('k', v)
|
|
35
|
+
// // [proteus-migrate:manual] wx.request → await useFetch(url)
|
|
36
|
+
// wx.request({ url: '/x', success: (r) => {} })
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## CLI
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
proteus migrate:mp <file|dir> [--dry-run] # 批量迁移(幂等;--dry-run 只报告不写回)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 严格规则
|
|
46
|
+
|
|
47
|
+
- **G-31.1**:compat 层只做「兜底」,新代码必须 Layer 0 语义(p-* / useXxx)——不反向污染
|
|
48
|
+
- **幂等**:codemod 跑两次结果一致(migrate-types 同款文本级规则集)
|
|
49
|
+
- **包名**:`@proteus-vue/compat-miniprogram`(组织 scope 收口,决策 #215a;plan 文档写 `@proteus/compat-miniprogram`)
|
|
50
|
+
|
|
51
|
+
## 路线
|
|
52
|
+
|
|
53
|
+
B6 ✅ 兼容桥 + codemod(标签/存储自动 70-90% + manual 标注)→ B6 续(路由名表 + scroll-view/swiper AI 语义还原 + codemod 完善)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const MANUAL_MARK = "[proteus-migrate:manual]";
|
|
2
|
+
/**
|
|
3
|
+
* 迁移单个文件文本(幂等——跑两次结果一致):
|
|
4
|
+
* 1) 标签自动替换(view/button/input 等 1:1 → p-*)
|
|
5
|
+
* 2) 同步存储 → useStorage()
|
|
6
|
+
* 3) 回调式 API(wx.request({success}) 等)→ manual 标注(原代码保留,compat 层兜底可跑)
|
|
7
|
+
* 4) 语义识别标签(scroll-view/swiper)→ manual 标注(AI 辅助还原布局语义)
|
|
8
|
+
*/
|
|
9
|
+
export declare function migrateMpSource(source: string): string;
|
|
10
|
+
/** 迁移统计(报告用) */
|
|
11
|
+
export interface MigrationStats {
|
|
12
|
+
tagsReplaced: number;
|
|
13
|
+
storageReplaced: number;
|
|
14
|
+
manualAnnotations: number;
|
|
15
|
+
}
|
|
16
|
+
/** 统计迁移量(在 migrateMpSource 后调用——基于前后差异计数) */
|
|
17
|
+
export declare function countMigration(source: string, migrated: string): MigrationStats;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CapabilityHooks, PlatformAPI } from '@proteus-vue/api';
|
|
2
|
+
import type { WxCompat } from './wx-compat';
|
|
3
|
+
export { AUTO_CODEMOD_TAGS, MANUAL_TAGS, isAutoCodeable, isManualTag } from './tags';
|
|
4
|
+
export { migrateMpSource, countMigration, MANUAL_MARK } from './codemod';
|
|
5
|
+
export type { MigrationStats } from './codemod';
|
|
6
|
+
export { collectRouteTargets, routeNameFromPath, buildRouteTable, NAVIGATION_APIS } from './route-table';
|
|
7
|
+
export type { RouteTarget } from './route-table';
|
|
8
|
+
export { createWxCompat } from './wx-compat';
|
|
9
|
+
export type { WxCompat } from './wx-compat';
|
|
10
|
+
/** 绑定平台实例(迁移期入口:bindCompatPlatform(createPlatformAPI())——旧代码 useStorage/wx 可用) */
|
|
11
|
+
export declare function bindCompatPlatform(platform: PlatformAPI): void;
|
|
12
|
+
export interface CompatStorage {
|
|
13
|
+
get<T = unknown>(key: string): T | undefined;
|
|
14
|
+
set(key: string, value: unknown): void;
|
|
15
|
+
remove(key: string): void;
|
|
16
|
+
clear(): void;
|
|
17
|
+
}
|
|
18
|
+
/** ★G-32 C15 目标 Hook(codemod 输出形态):useStorage() → 平台 storage(绑定后可用) */
|
|
19
|
+
export declare function useStorage(): CompatStorage;
|
|
20
|
+
/** 一键绑定(迁移入口常用形态) */
|
|
21
|
+
export declare function installCompat(platform: PlatformAPI, cap: CapabilityHooks): WxCompatLegacy;
|
|
22
|
+
/** 兼容桥(类型包装——installCompat 返回值) */
|
|
23
|
+
export type WxCompatLegacy = WxCompat;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// src/wx-compat.ts
|
|
2
|
+
function createWxCompat(platform, cap) {
|
|
3
|
+
return {
|
|
4
|
+
// request:回调式 → platform.request Promise 桥(async 成功后调 success)
|
|
5
|
+
request(options) {
|
|
6
|
+
void platform.request({ url: options.url, method: options.method ?? "GET" }).then(
|
|
7
|
+
(res) => options.success?.({ statusCode: res.status ?? 200, data: res.data }),
|
|
8
|
+
(err) => options.fail?.(err)
|
|
9
|
+
);
|
|
10
|
+
},
|
|
11
|
+
navigateTo(options) {
|
|
12
|
+
platform.router.push(options.url ?? "");
|
|
13
|
+
options.success?.();
|
|
14
|
+
},
|
|
15
|
+
redirectTo(options) {
|
|
16
|
+
platform.router.replace(options.url ?? "");
|
|
17
|
+
},
|
|
18
|
+
navigateBack(options) {
|
|
19
|
+
platform.router.back(options.delta ?? 1);
|
|
20
|
+
},
|
|
21
|
+
switchTab(options) {
|
|
22
|
+
platform.router.switchTab(options.url ?? "");
|
|
23
|
+
},
|
|
24
|
+
setStorageSync(key, value) {
|
|
25
|
+
platform.storage.set(key, value);
|
|
26
|
+
},
|
|
27
|
+
getStorageSync(key) {
|
|
28
|
+
return platform.storage.get(key);
|
|
29
|
+
},
|
|
30
|
+
removeStorageSync(key) {
|
|
31
|
+
platform.storage.remove(key);
|
|
32
|
+
},
|
|
33
|
+
clearStorageSync() {
|
|
34
|
+
platform.storage.clear();
|
|
35
|
+
},
|
|
36
|
+
showToast(options) {
|
|
37
|
+
platform.ui.showToast(options.title ?? "", options.duration);
|
|
38
|
+
},
|
|
39
|
+
showModal(options) {
|
|
40
|
+
void platform.ui.showModal({ title: options.title, content: options.content }).then((r) => {
|
|
41
|
+
options.success?.({ confirm: r.confirm });
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
vibrateShort() {
|
|
45
|
+
void cap.useVibrate(15);
|
|
46
|
+
},
|
|
47
|
+
getSystemInfoSync() {
|
|
48
|
+
return { platform: "web", screenWidth: 390, screenHeight: 844 };
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// src/tags.ts
|
|
54
|
+
var AUTO_CODEMOD_TAGS = {
|
|
55
|
+
view: "p-box",
|
|
56
|
+
text: "p-text",
|
|
57
|
+
button: "p-button",
|
|
58
|
+
image: "p-image",
|
|
59
|
+
input: "p-input",
|
|
60
|
+
textarea: "p-textarea",
|
|
61
|
+
switch: "p-switch",
|
|
62
|
+
slider: "p-slider",
|
|
63
|
+
checkbox: "p-checkbox",
|
|
64
|
+
radio: "p-radio",
|
|
65
|
+
form: "p-form",
|
|
66
|
+
picker: "p-picker"
|
|
67
|
+
};
|
|
68
|
+
var MANUAL_TAGS = {
|
|
69
|
+
"scroll-view": "p-scroll\uFF08\u6216 p-stack direction\u2014\u2014\u8BED\u4E49\u8BC6\u522B\uFF09",
|
|
70
|
+
swiper: 'p-stack snap="mandatory" loop\uFF08\u8F6E\u64AD\u8BED\u4E49\uFF09',
|
|
71
|
+
"swiper-item": "p-stack \u5B50\u9879",
|
|
72
|
+
"movable-area": "gesture.scrollable \u5BB9\u5668",
|
|
73
|
+
"movable-view": "gesture.draggable",
|
|
74
|
+
navigator: "router-link\uFF08url \u2192 to \u6620\u5C04\uFF09",
|
|
75
|
+
label: "p-label\uFF08L2\uFF09",
|
|
76
|
+
progress: "p-progress\uFF08L2\uFF09",
|
|
77
|
+
"rich-text": "p-rich-text",
|
|
78
|
+
icon: "p-icon",
|
|
79
|
+
canvas: "p-canvas",
|
|
80
|
+
video: 'p-media kind="video"\uFF08\u6D88\u706D\u4E3A\u5C5E\u6027\uFF09',
|
|
81
|
+
audio: 'p-media kind="audio"\uFF08\u6D88\u706D\u4E3A\u5C5E\u6027\uFF09',
|
|
82
|
+
camera: "p-camera + useCamera\uFF08L2\uFF09",
|
|
83
|
+
map: "p-map + useMap\uFF08L2\uFF09",
|
|
84
|
+
"web-view": "p-webview\uFF08L2\uFF09"
|
|
85
|
+
};
|
|
86
|
+
function isManualTag(tag) {
|
|
87
|
+
return tag in MANUAL_TAGS;
|
|
88
|
+
}
|
|
89
|
+
function isAutoCodeable(tag) {
|
|
90
|
+
return tag in AUTO_CODEMOD_TAGS;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/codemod.ts
|
|
94
|
+
var MANUAL_MARK = "[proteus-migrate:manual]";
|
|
95
|
+
var COMMENT_MARK = "[proteus-migrate:manual]";
|
|
96
|
+
var CALLBACK_APIS = [
|
|
97
|
+
{ re: /\bwx\.request\s*\(/, target: () => "wx.request \u2192 await useFetch(url)" },
|
|
98
|
+
{ re: /\bwx\.navigateTo\s*\(/, target: () => "wx.navigateTo \u2192 router.push({ name, params })\uFF08\u8DEF\u7531\u540D\u9700\u5EFA\u8868\uFF09" },
|
|
99
|
+
{ re: /\bwx\.scanCode\s*\(/, target: () => "wx.scanCode \u2192 native.scanQR()\uFF08awaitify\uFF09" },
|
|
100
|
+
{ re: /\bwx\.login\s*\(/, target: () => "wx.login \u2192 auth.login()\uFF08\u94FE\u8DEF\u5408\u5E76\uFF09" },
|
|
101
|
+
{ re: /\bwx\.getLocation\s*\(/, target: () => "wx.getLocation \u2192 useLocation()" },
|
|
102
|
+
{ re: /\bwx\.showModal\s*\(/, target: () => "wx.showModal \u2192 platform.ui.showModal\uFF08Promise\uFF09" },
|
|
103
|
+
{ re: /\bwx\.showActionSheet\s*\(/, target: () => "wx.showActionSheet \u2192 platform.ui.showActionSheet\uFF08Promise\uFF09" }
|
|
104
|
+
];
|
|
105
|
+
function findManualTag(line) {
|
|
106
|
+
const m = line.match(/<([a-zA-Z][\w-]*)[\s/>]/);
|
|
107
|
+
if (!m) return null;
|
|
108
|
+
return isManualTag(m[1]) ? m[1] : null;
|
|
109
|
+
}
|
|
110
|
+
function migrateMpSource(source) {
|
|
111
|
+
let out = source;
|
|
112
|
+
for (const [mpTag, proteusTag] of Object.entries(AUTO_CODEMOD_TAGS)) {
|
|
113
|
+
out = out.replace(new RegExp(`<${mpTag}(?=[\\s>/])`, "g"), `<${proteusTag}`);
|
|
114
|
+
out = out.replace(new RegExp(`</${mpTag}\\s*>`, "g"), `</${proteusTag}>`);
|
|
115
|
+
}
|
|
116
|
+
out = out.replace(/\bwx\.setStorageSync\s*\(([^;]+)\)/g, "useStorage().set($1)");
|
|
117
|
+
out = out.replace(/\bwx\.getStorageSync\s*\(([^;]+)\)/g, "useStorage().get($1)");
|
|
118
|
+
out = out.replace(/\bwx\.removeStorageSync\s*\(([^;]+)\)/g, "useStorage().remove($1)");
|
|
119
|
+
out = out.replace(/\bwx\.clearStorageSync\s*\(/g, "useStorage().clear()");
|
|
120
|
+
const lines = out.split("\n");
|
|
121
|
+
const result = [];
|
|
122
|
+
for (const line of lines) {
|
|
123
|
+
if (line.includes(COMMENT_MARK)) {
|
|
124
|
+
result.push(line);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const prevIsMark = result.length > 0 && result[result.length - 1].includes(COMMENT_MARK);
|
|
128
|
+
const indent = line.match(/^\s*/)?.[0] ?? "";
|
|
129
|
+
let annotated = false;
|
|
130
|
+
for (const { re, target } of CALLBACK_APIS) {
|
|
131
|
+
if (re.test(line) && /success\s*[:=]/.test(line)) {
|
|
132
|
+
if (!prevIsMark) result.push(`${indent}// ${COMMENT_MARK} ${target(line)}`);
|
|
133
|
+
annotated = true;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (annotated) {
|
|
138
|
+
result.push(line);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const manualTag = findManualTag(line);
|
|
142
|
+
if (manualTag && !prevIsMark) {
|
|
143
|
+
result.push(`${indent}<!-- ${COMMENT_MARK} <${manualTag}> \u2192 ${MANUAL_TAGS[manualTag]}\uFF08\u8BED\u4E49\u8BC6\u522B\uFF0CAI \u8F85\u52A9\uFF09 -->`);
|
|
144
|
+
}
|
|
145
|
+
result.push(line);
|
|
146
|
+
}
|
|
147
|
+
return result.join("\n");
|
|
148
|
+
}
|
|
149
|
+
function countMigration(source, migrated) {
|
|
150
|
+
const manualAnnotations = migrated.split(COMMENT_MARK).length - 1;
|
|
151
|
+
let tagsReplaced = 0;
|
|
152
|
+
for (const mpTag of Object.keys(AUTO_CODEMOD_TAGS)) {
|
|
153
|
+
const before = (source.match(new RegExp(`<${mpTag}(?=[\\s>/])`, "g")) ?? []).length;
|
|
154
|
+
const after = (migrated.match(new RegExp(`<${mpTag}(?=[\\s>/])`, "g")) ?? []).length;
|
|
155
|
+
tagsReplaced += before - after;
|
|
156
|
+
}
|
|
157
|
+
const storageReplaced = (migrated.match(/useStorage\(\)\.(set|get|remove|clear)\(/g) ?? []).length;
|
|
158
|
+
return { tagsReplaced, storageReplaced, manualAnnotations };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/route-table.ts
|
|
162
|
+
var NAVIGATION_APIS = ["navigateTo", "switchTab", "reLaunch", "redirectTo"];
|
|
163
|
+
function routeNameFromPath(path) {
|
|
164
|
+
const clean = path.replace(/^\/+/, "").replace(/\.vue$/, "").split("?")[0];
|
|
165
|
+
let segs = clean.split("/").filter(Boolean);
|
|
166
|
+
if (segs[0] === "pages" || segs[0] === "subpackages") segs = segs.slice(1);
|
|
167
|
+
if (segs.length === 0) return "index";
|
|
168
|
+
if (segs[segs.length - 1] === "index") segs = segs.slice(0, -1);
|
|
169
|
+
if (segs.length === 0) return "index";
|
|
170
|
+
const kebab = segs.join("-");
|
|
171
|
+
return kebab.split("-").filter(Boolean).map((s, i) => i === 0 ? s.toLowerCase() : s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()).join("");
|
|
172
|
+
}
|
|
173
|
+
function collectRouteTargets(source) {
|
|
174
|
+
const out = [];
|
|
175
|
+
const re = /\bwx\.(navigateTo|switchTab|reLaunch|redirectTo)\s*\(\s*\{[^}]*?\burl\s*:\s*['"]([^'"]+)['"]/g;
|
|
176
|
+
let m;
|
|
177
|
+
while ((m = re.exec(source)) !== null) {
|
|
178
|
+
const url = m[2];
|
|
179
|
+
const path = url.split("?")[0].replace(/^\/+/, "");
|
|
180
|
+
out.push({ api: m[1], url, path });
|
|
181
|
+
}
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
function buildRouteTable(sources) {
|
|
185
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
186
|
+
for (const src of sources) {
|
|
187
|
+
for (const t of collectRouteTargets(src)) {
|
|
188
|
+
const entry = byPath.get(t.path);
|
|
189
|
+
if (entry) entry.apis.add(t.api);
|
|
190
|
+
else byPath.set(t.path, { path: t.path, name: routeNameFromPath(t.path), apis: /* @__PURE__ */ new Set([t.api]) });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return [...byPath.values()].map((e) => ({ path: e.path, name: e.name, apis: [...e.apis].sort() })).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/index.ts
|
|
197
|
+
var boundPlatform = null;
|
|
198
|
+
function bindCompatPlatform(platform) {
|
|
199
|
+
boundPlatform = platform;
|
|
200
|
+
}
|
|
201
|
+
function useStorage() {
|
|
202
|
+
if (!boundPlatform) {
|
|
203
|
+
throw new Error("[compat-miniprogram] useStorage \u672A\u7ED1\u5B9A\u5E73\u53F0\u2014\u2014\u8BF7\u5148 bindCompatPlatform(createPlatformAPI())");
|
|
204
|
+
}
|
|
205
|
+
return boundPlatform.storage;
|
|
206
|
+
}
|
|
207
|
+
function installCompat(platform, cap) {
|
|
208
|
+
bindCompatPlatform(platform);
|
|
209
|
+
const wx = createWxCompat(platform, cap);
|
|
210
|
+
const g = globalThis;
|
|
211
|
+
if (!g.wx) g.wx = wx;
|
|
212
|
+
return wxCompatLegacy(wx);
|
|
213
|
+
}
|
|
214
|
+
function wxCompatLegacy(wx) {
|
|
215
|
+
return wx;
|
|
216
|
+
}
|
|
217
|
+
export {
|
|
218
|
+
AUTO_CODEMOD_TAGS,
|
|
219
|
+
MANUAL_MARK,
|
|
220
|
+
MANUAL_TAGS,
|
|
221
|
+
NAVIGATION_APIS,
|
|
222
|
+
bindCompatPlatform,
|
|
223
|
+
buildRouteTable,
|
|
224
|
+
collectRouteTargets,
|
|
225
|
+
countMigration,
|
|
226
|
+
createWxCompat,
|
|
227
|
+
installCompat,
|
|
228
|
+
isAutoCodeable,
|
|
229
|
+
isManualTag,
|
|
230
|
+
migrateMpSource,
|
|
231
|
+
routeNameFromPath,
|
|
232
|
+
useStorage
|
|
233
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** wx 导航 API(目标收集面) */
|
|
2
|
+
export declare const NAVIGATION_APIS: readonly ["navigateTo", "switchTab", "reLaunch", "redirectTo"];
|
|
3
|
+
export interface RouteTarget {
|
|
4
|
+
/** 导航 API 名(wx.navigateTo 等) */
|
|
5
|
+
api: string;
|
|
6
|
+
/** 原始 url(可能带 query) */
|
|
7
|
+
url: string;
|
|
8
|
+
/** 路径(去 query / 去 .vue / 去前导斜杠) */
|
|
9
|
+
path: string;
|
|
10
|
+
}
|
|
11
|
+
/** 路径 → 路由名候选(小驼峰;index 归并目录名——对齐 deriveNameFromFile + NAME_RE) */
|
|
12
|
+
export declare function routeNameFromPath(path: string): string;
|
|
13
|
+
/** 从单份源码收集导航目标(纯函数) */
|
|
14
|
+
export declare function collectRouteTargets(source: string): RouteTarget[];
|
|
15
|
+
/** 批量源码 → 去重排序路由名表(按 path) */
|
|
16
|
+
export declare function buildRouteTable(sources: string[]): Array<{
|
|
17
|
+
path: string;
|
|
18
|
+
name: string;
|
|
19
|
+
apis: string[];
|
|
20
|
+
}>;
|
package/dist/tags.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** codemod 自动替换:小程序标签 → p-* 语义组件(1:1;migration.md §2 自动集) */
|
|
2
|
+
export declare const AUTO_CODEMOD_TAGS: Record<string, string>;
|
|
3
|
+
/** 需语义识别(manual 标注——scroll-view→p-stack 等语义还原;AI Agent G-23 辅助) */
|
|
4
|
+
export declare const MANUAL_TAGS: Record<string, string>;
|
|
5
|
+
/** 判定一个标签是否需要 manual 标注(有效小程序组件标签) */
|
|
6
|
+
export declare function isManualTag(tag: string): boolean;
|
|
7
|
+
/** 判定一个标签是否自动可替换 */
|
|
8
|
+
export declare function isAutoCodeable(tag: string): boolean;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { CapabilityHooks } from '@proteus-vue/api';
|
|
2
|
+
import type { PlatformAPI } from '@proteus-vue/api';
|
|
3
|
+
/** wx 兼容面(旧代码可用子集——委托 Proteus) */
|
|
4
|
+
export interface WxCompat {
|
|
5
|
+
request(options: {
|
|
6
|
+
url: string;
|
|
7
|
+
method?: string;
|
|
8
|
+
success?: (res: {
|
|
9
|
+
statusCode: number;
|
|
10
|
+
data: unknown;
|
|
11
|
+
}) => void;
|
|
12
|
+
fail?: (err: unknown) => void;
|
|
13
|
+
}): void;
|
|
14
|
+
navigateTo(options: {
|
|
15
|
+
url: string;
|
|
16
|
+
success?: () => void;
|
|
17
|
+
}): void;
|
|
18
|
+
redirectTo(options: {
|
|
19
|
+
url: string;
|
|
20
|
+
}): void;
|
|
21
|
+
navigateBack(options: {
|
|
22
|
+
delta?: number;
|
|
23
|
+
}): void;
|
|
24
|
+
switchTab(options: {
|
|
25
|
+
url: string;
|
|
26
|
+
}): void;
|
|
27
|
+
setStorageSync(key: string, value: unknown): void;
|
|
28
|
+
getStorageSync(key: string): unknown;
|
|
29
|
+
removeStorageSync(key: string): void;
|
|
30
|
+
clearStorageSync(): void;
|
|
31
|
+
showToast(options: {
|
|
32
|
+
title: string;
|
|
33
|
+
duration?: number;
|
|
34
|
+
}): void;
|
|
35
|
+
showModal(options: {
|
|
36
|
+
title?: string;
|
|
37
|
+
content?: string;
|
|
38
|
+
success?: (res: {
|
|
39
|
+
confirm: boolean;
|
|
40
|
+
}) => void;
|
|
41
|
+
}): void;
|
|
42
|
+
vibrateShort(): void;
|
|
43
|
+
getSystemInfoSync(): {
|
|
44
|
+
platform: string;
|
|
45
|
+
screenWidth: number;
|
|
46
|
+
screenHeight: number;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 创建 wx 兼容桥(平台无关——委托 Proteus PlatformAPI + CapabilityHooks)
|
|
51
|
+
* 用法(迁移期入口):globalThis.wx = createWxCompat(platform, cap)
|
|
52
|
+
*/
|
|
53
|
+
export declare function createWxCompat(platform: PlatformAPI, cap: CapabilityHooks): WxCompat;
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proteus-vue/compat-miniprogram",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "G-31 B6 Layer 1 兼容层(proteus-component-semantics-plan migration.md):旧小程序迁移三步走——createWxCompat 运行时桥(wx.* 委托 Proteus)+ migrateMpSource codemod(标签自动/存储直改/manual 标注)+ useStorage 迁移目标",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p tsconfig.build.json --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=neutral --outfile=dist/index.js --external:@proteus-vue/api"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@proteus-vue/api": "0.1.0"
|
|
26
|
+
}
|
|
27
|
+
}
|