@wevu/api 0.1.0 → 0.1.1

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 CHANGED
@@ -11,6 +11,51 @@
11
11
  - Promise 风格优先,回调风格可用
12
12
  - 支持显式注入平台适配器
13
13
 
14
+ ## 类型对齐与平台支持
15
+
16
+ `@wevu/api` 的默认导出 `wpi` 会同时对齐:
17
+
18
+ - 微信类型:`miniprogram-api-typings`
19
+ - 支付宝类型:`@mini-types/alipay`
20
+ - 抖音类型:`@douyin-microapp/typings`
21
+
22
+ <!-- prettier-ignore-start -->
23
+ <!-- @generated weapi-support-matrix:start -->
24
+ ### 平台类型对齐矩阵
25
+
26
+ | 平台 | 全局对象 | 类型来源 | 支持度 |
27
+ | --- | --- | --- | --- |
28
+ | 微信小程序 | `wx` | `miniprogram-api-typings` | ✅ 全量 |
29
+ | 支付宝小程序 | `my` | `@mini-types/alipay` | ✅ 全量 |
30
+ | 抖音小程序 | `tt` | `@douyin-microapp/typings` | ✅ 全量 |
31
+ | 其他平台(swan/jd/xhs 等) | 运行时宿主对象 | 运行时透传 | ⚠️ 按宿主能力支持 |
32
+
33
+ ### API 支持覆盖率报告
34
+
35
+ | 平台 | 已支持 API 数 | API 总数 | 覆盖率 |
36
+ | --- | --- | --- | --- |
37
+ | 微信小程序 (`wx`) | 8 | 8 | 100.00% |
38
+ | 支付宝小程序 (`my`) | 8 | 8 | 100.00% |
39
+ | 抖音小程序 (`tt`) | 8 | 8 | 100.00% |
40
+ | 三端完全对齐 (wx/my/tt) | 8 | 8 | 100.00% |
41
+
42
+ > 该报告由 `WEAPI_METHOD_SUPPORT_MATRIX` 与映射规则自动计算生成。
43
+
44
+ ### 核心跨端映射矩阵
45
+
46
+ | API | 说明 | 微信策略 | 支付宝策略 | 抖音策略 | 支持度 |
47
+ | --- | --- | --- | --- | --- | --- |
48
+ | `showToast` | 显示消息提示框。 | 直连 `wx.showToast` | `title/icon` 映射到 `content/type` 后调用 `my.showToast` | `icon=error` 映射为 `fail` 后调用 `tt.showToast` | ✅ |
49
+ | `showLoading` | 显示 loading 提示框。 | 直连 `wx.showLoading` | `title` 映射到 `content` 后调用 `my.showLoading` | 直连 `tt.showLoading` | ✅ |
50
+ | `showActionSheet` | 显示操作菜单。 | 直连 `wx.showActionSheet` | `itemList` ↔ `items`、`index` ↔ `tapIndex` 双向对齐 | 直连 `tt.showActionSheet`,并兼容 `index` → `tapIndex` | ✅ |
51
+ | `showModal` | 显示模态弹窗。 | 直连 `wx.showModal` | 调用 `my.confirm` 并对齐按钮字段与 `cancel` 结果 | 直连 `tt.showModal` | ✅ |
52
+ | `chooseImage` | 选择图片。 | 直连 `wx.chooseImage` | 返回值 `apFilePaths` 映射到 `tempFilePaths` | `tempFilePaths` 字符串转数组,缺失时从 `tempFiles.path` 兜底 | ✅ |
53
+ | `saveFile` | 保存文件。 | 直连 `wx.saveFile` | 请求参数 `tempFilePath` ↔ `apFilePath`、结果映射为 `savedFilePath` | 直连 `tt.saveFile`,并在缺失时用 `filePath` 兜底 `savedFilePath` | ✅ |
54
+ | `setClipboardData` | 设置剪贴板内容。 | 直连 `wx.setClipboardData` | 转调 `my.setClipboard` 并映射 `data` → `text` | 直连 `tt.setClipboardData` | ✅ |
55
+ | `getClipboardData` | 获取剪贴板内容。 | 直连 `wx.getClipboardData` | 转调 `my.getClipboard` 并映射 `text` → `data` | 直连 `tt.getClipboardData` | ✅ |
56
+ <!-- @generated weapi-support-matrix:end -->
57
+ <!-- prettier-ignore-end -->
58
+
14
59
  ## 安装
15
60
 
16
61
  ```bash
package/dist/index.cjs CHANGED
@@ -96,6 +96,243 @@ function createNotSupportedError(methodName, platform) {
96
96
  return { errMsg: `${platform ? `${platform}.${methodName}` : methodName}:fail method not supported` };
97
97
  }
98
98
 
99
+ //#endregion
100
+ //#region src/core/methodMapping.ts
101
+ const PLATFORM_ALIASES$1 = {
102
+ alipay: "my",
103
+ douyin: "tt"
104
+ };
105
+ function mapToastType(type) {
106
+ if (type === "error") return "fail";
107
+ if (type === "loading") return "none";
108
+ return type;
109
+ }
110
+ function mapToastArgs(args) {
111
+ if (args.length === 0) return args;
112
+ const nextArgs = [...args];
113
+ const lastIndex = nextArgs.length - 1;
114
+ const lastArg = nextArgs[lastIndex];
115
+ if (!isPlainObject(lastArg)) return nextArgs;
116
+ const nextOptions = { ...lastArg };
117
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "content") && Object.prototype.hasOwnProperty.call(nextOptions, "title")) nextOptions.content = nextOptions.title;
118
+ if (Object.prototype.hasOwnProperty.call(nextOptions, "icon")) nextOptions.type = mapToastType(nextOptions.icon);
119
+ nextArgs[lastIndex] = nextOptions;
120
+ return nextArgs;
121
+ }
122
+ function mapDouyinToastArgs(args) {
123
+ if (args.length === 0) return args;
124
+ const nextArgs = [...args];
125
+ const lastIndex = nextArgs.length - 1;
126
+ const lastArg = nextArgs[lastIndex];
127
+ if (!isPlainObject(lastArg)) return nextArgs;
128
+ const nextOptions = { ...lastArg };
129
+ if (nextOptions.icon === "error") nextOptions.icon = "fail";
130
+ nextArgs[lastIndex] = nextOptions;
131
+ return nextArgs;
132
+ }
133
+ function mapLoadingArgs(args) {
134
+ if (args.length === 0) return args;
135
+ const nextArgs = [...args];
136
+ const lastIndex = nextArgs.length - 1;
137
+ const lastArg = nextArgs[lastIndex];
138
+ if (!isPlainObject(lastArg)) return nextArgs;
139
+ const nextOptions = { ...lastArg };
140
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "content") && Object.prototype.hasOwnProperty.call(nextOptions, "title")) nextOptions.content = nextOptions.title;
141
+ nextArgs[lastIndex] = nextOptions;
142
+ return nextArgs;
143
+ }
144
+ function mapActionSheetArgs(args) {
145
+ if (args.length === 0) return args;
146
+ const nextArgs = [...args];
147
+ const lastIndex = nextArgs.length - 1;
148
+ const lastArg = nextArgs[lastIndex];
149
+ if (!isPlainObject(lastArg)) return nextArgs;
150
+ const nextOptions = { ...lastArg };
151
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "items") && Array.isArray(nextOptions.itemList)) nextOptions.items = nextOptions.itemList;
152
+ nextArgs[lastIndex] = nextOptions;
153
+ return nextArgs;
154
+ }
155
+ function mapActionSheetResult(result) {
156
+ if (!isPlainObject(result)) return result;
157
+ if (!Object.prototype.hasOwnProperty.call(result, "tapIndex") && Object.prototype.hasOwnProperty.call(result, "index")) return {
158
+ ...result,
159
+ tapIndex: result.index
160
+ };
161
+ return result;
162
+ }
163
+ function mapModalArgs(args) {
164
+ if (args.length === 0) return args;
165
+ const nextArgs = [...args];
166
+ const lastIndex = nextArgs.length - 1;
167
+ const lastArg = nextArgs[lastIndex];
168
+ if (!isPlainObject(lastArg)) return nextArgs;
169
+ const nextOptions = { ...lastArg };
170
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "confirmButtonText") && Object.prototype.hasOwnProperty.call(nextOptions, "confirmText")) nextOptions.confirmButtonText = nextOptions.confirmText;
171
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "cancelButtonText") && Object.prototype.hasOwnProperty.call(nextOptions, "cancelText")) nextOptions.cancelButtonText = nextOptions.cancelText;
172
+ nextArgs[lastIndex] = nextOptions;
173
+ return nextArgs;
174
+ }
175
+ function mapModalResult(result) {
176
+ if (!isPlainObject(result)) return result;
177
+ if (!Object.prototype.hasOwnProperty.call(result, "cancel") && Object.prototype.hasOwnProperty.call(result, "confirm")) return {
178
+ ...result,
179
+ cancel: !result.confirm
180
+ };
181
+ return result;
182
+ }
183
+ function mapChooseImageResult(result) {
184
+ if (!isPlainObject(result)) return result;
185
+ if (!Object.prototype.hasOwnProperty.call(result, "tempFilePaths") && Array.isArray(result.apFilePaths)) return {
186
+ ...result,
187
+ tempFilePaths: result.apFilePaths
188
+ };
189
+ return result;
190
+ }
191
+ function mapDouyinChooseImageResult(result) {
192
+ if (!isPlainObject(result)) return result;
193
+ if (typeof result.tempFilePaths === "string") return {
194
+ ...result,
195
+ tempFilePaths: [result.tempFilePaths]
196
+ };
197
+ if (!Array.isArray(result.tempFilePaths) && Array.isArray(result.tempFiles)) {
198
+ const fallbackPaths = result.tempFiles.map((item) => {
199
+ if (!isPlainObject(item)) return;
200
+ const path = item.path;
201
+ if (typeof path === "string" && path) return path;
202
+ const filePath = item.filePath;
203
+ if (typeof filePath === "string" && filePath) return filePath;
204
+ }).filter((item) => typeof item === "string");
205
+ if (fallbackPaths.length > 0) return {
206
+ ...result,
207
+ tempFilePaths: fallbackPaths
208
+ };
209
+ }
210
+ return result;
211
+ }
212
+ function mapSaveFileArgs(args) {
213
+ if (args.length === 0) return args;
214
+ const nextArgs = [...args];
215
+ const lastIndex = nextArgs.length - 1;
216
+ const lastArg = nextArgs[lastIndex];
217
+ if (!isPlainObject(lastArg)) return nextArgs;
218
+ const nextOptions = { ...lastArg };
219
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "apFilePath") && Object.prototype.hasOwnProperty.call(nextOptions, "tempFilePath")) nextOptions.apFilePath = nextOptions.tempFilePath;
220
+ nextArgs[lastIndex] = nextOptions;
221
+ return nextArgs;
222
+ }
223
+ function mapSaveFileResult(result) {
224
+ if (!isPlainObject(result)) return result;
225
+ if (!Object.prototype.hasOwnProperty.call(result, "savedFilePath") && Object.prototype.hasOwnProperty.call(result, "apFilePath")) return {
226
+ ...result,
227
+ savedFilePath: result.apFilePath
228
+ };
229
+ return result;
230
+ }
231
+ function mapDouyinSaveFileResult(result) {
232
+ if (!isPlainObject(result)) return result;
233
+ if (!Object.prototype.hasOwnProperty.call(result, "savedFilePath") && Object.prototype.hasOwnProperty.call(result, "filePath")) return {
234
+ ...result,
235
+ savedFilePath: result.filePath
236
+ };
237
+ return result;
238
+ }
239
+ function normalizePlatformName$1(value) {
240
+ if (!value) return;
241
+ const normalized = value.trim().toLowerCase();
242
+ if (!normalized) return;
243
+ return PLATFORM_ALIASES$1[normalized] ?? normalized;
244
+ }
245
+ function mapSetClipboardArgs(args) {
246
+ if (args.length === 0) return args;
247
+ const nextArgs = [...args];
248
+ const lastIndex = nextArgs.length - 1;
249
+ const lastArg = nextArgs[lastIndex];
250
+ if (!isPlainObject(lastArg)) return nextArgs;
251
+ const nextOptions = { ...lastArg };
252
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "text") && Object.prototype.hasOwnProperty.call(nextOptions, "data")) nextOptions.text = nextOptions.data;
253
+ nextArgs[lastIndex] = nextOptions;
254
+ return nextArgs;
255
+ }
256
+ function mapClipboardResult(result) {
257
+ if (!isPlainObject(result)) return result;
258
+ if (!Object.prototype.hasOwnProperty.call(result, "data") && Object.prototype.hasOwnProperty.call(result, "text")) return {
259
+ ...result,
260
+ data: result.text
261
+ };
262
+ return result;
263
+ }
264
+ const METHOD_MAPPINGS = {
265
+ my: {
266
+ showToast: {
267
+ target: "showToast",
268
+ mapArgs: mapToastArgs
269
+ },
270
+ showLoading: {
271
+ target: "showLoading",
272
+ mapArgs: mapLoadingArgs
273
+ },
274
+ showActionSheet: {
275
+ target: "showActionSheet",
276
+ mapArgs: mapActionSheetArgs,
277
+ mapResult: mapActionSheetResult
278
+ },
279
+ showModal: {
280
+ target: "confirm",
281
+ mapArgs: mapModalArgs,
282
+ mapResult: mapModalResult
283
+ },
284
+ chooseImage: {
285
+ target: "chooseImage",
286
+ mapResult: mapChooseImageResult
287
+ },
288
+ saveFile: {
289
+ target: "saveFile",
290
+ mapArgs: mapSaveFileArgs,
291
+ mapResult: mapSaveFileResult
292
+ },
293
+ setClipboardData: {
294
+ target: "setClipboard",
295
+ mapArgs: mapSetClipboardArgs
296
+ },
297
+ getClipboardData: {
298
+ target: "getClipboard",
299
+ mapResult: mapClipboardResult
300
+ }
301
+ },
302
+ tt: {
303
+ showToast: {
304
+ target: "showToast",
305
+ mapArgs: mapDouyinToastArgs
306
+ },
307
+ showLoading: { target: "showLoading" },
308
+ showActionSheet: {
309
+ target: "showActionSheet",
310
+ mapResult: mapActionSheetResult
311
+ },
312
+ showModal: { target: "showModal" },
313
+ chooseImage: {
314
+ target: "chooseImage",
315
+ mapResult: mapDouyinChooseImageResult
316
+ },
317
+ saveFile: {
318
+ target: "saveFile",
319
+ mapResult: mapDouyinSaveFileResult
320
+ },
321
+ setClipboardData: { target: "setClipboardData" },
322
+ getClipboardData: { target: "getClipboardData" }
323
+ }
324
+ };
325
+ /**
326
+ * @description 解析平台 API 映射规则
327
+ */
328
+ function resolveMethodMapping(platform, methodName) {
329
+ const normalizedPlatform = normalizePlatformName$1(platform);
330
+ if (!normalizedPlatform) return;
331
+ const platformMappings = METHOD_MAPPINGS[normalizedPlatform];
332
+ if (!platformMappings) return;
333
+ return platformMappings[methodName];
334
+ }
335
+
99
336
  //#endregion
100
337
  //#region src/core/createWeapi.ts
101
338
  const INTERNAL_KEYS = new Set([
@@ -104,8 +341,15 @@ const INTERNAL_KEYS = new Set([
104
341
  "platform",
105
342
  "raw"
106
343
  ]);
344
+ const PLATFORM_ALIASES = {
345
+ alipay: "my",
346
+ douyin: "tt"
347
+ };
107
348
  function normalizePlatformName(value) {
108
- return value || void 0;
349
+ if (!value) return;
350
+ const normalized = value.trim().toLowerCase();
351
+ if (!normalized) return;
352
+ return PLATFORM_ALIASES[normalized] ?? normalized;
109
353
  }
110
354
  function resolveOptionsArg(args) {
111
355
  const nextArgs = args.slice();
@@ -125,20 +369,20 @@ function resolveOptionsArg(args) {
125
369
  options
126
370
  };
127
371
  }
128
- function callWithPromise(context, method, args) {
372
+ function callWithPromise(context, method, args, mapResult) {
129
373
  return new Promise((resolve, reject) => {
130
374
  const { args: nextArgs, options } = resolveOptionsArg(args);
131
375
  let settled = false;
132
376
  options.success = (res) => {
133
377
  settled = true;
134
- resolve(res);
378
+ resolve(mapResult ? mapResult(res) : res);
135
379
  };
136
380
  options.fail = (err) => {
137
381
  settled = true;
138
382
  reject(err);
139
383
  };
140
384
  options.complete = (res) => {
141
- if (!settled) resolve(res);
385
+ if (!settled) resolve(mapResult ? mapResult(res) : res);
142
386
  };
143
387
  try {
144
388
  method.apply(context, nextArgs);
@@ -201,7 +445,8 @@ function createWeapi(options = {}) {
201
445
  if (typeof prop !== "string") return;
202
446
  return (...args) => callMissingApi(prop, getPlatform(), args);
203
447
  }
204
- const value = currentAdapter[prop];
448
+ const platform = getPlatform();
449
+ const value = currentAdapter[(typeof prop === "string" ? resolveMethodMapping(platform, prop) : void 0)?.target ?? prop];
205
450
  if (typeof value !== "function") {
206
451
  if (value === void 0 && typeof prop === "string") {
207
452
  const missing = (...args) => callMissingApi(prop, getPlatform(), args);
@@ -213,11 +458,32 @@ function createWeapi(options = {}) {
213
458
  }
214
459
  const wrapped = (...args) => {
215
460
  const runtimeAdapter = resolveAdapter();
216
- const runtimeMethod = runtimeAdapter ? runtimeAdapter[prop] : void 0;
461
+ const mappingRule = resolveMethodMapping(getPlatform(), prop);
462
+ const methodName = mappingRule?.target ?? prop;
463
+ const runtimeMethod = runtimeAdapter ? runtimeAdapter[methodName] : void 0;
464
+ const runtimeArgs = mappingRule?.mapArgs ? mappingRule.mapArgs(args) : args;
217
465
  if (typeof runtimeMethod !== "function") return callMissingApi(prop, getPlatform(), args);
218
- if (shouldSkipPromise(prop)) return runtimeMethod.apply(runtimeAdapter, args);
219
- if (hasCallbacks(args.length > 0 ? args[args.length - 1] : void 0)) return runtimeMethod.apply(runtimeAdapter, args);
220
- return callWithPromise(runtimeAdapter, runtimeMethod, args);
466
+ if (shouldSkipPromise(prop)) {
467
+ const result = runtimeMethod.apply(runtimeAdapter, runtimeArgs);
468
+ return mappingRule?.mapResult ? mappingRule.mapResult(result) : result;
469
+ }
470
+ const lastArg = runtimeArgs.length > 0 ? runtimeArgs[runtimeArgs.length - 1] : void 0;
471
+ if (hasCallbacks(lastArg)) {
472
+ if (mappingRule?.mapResult && isPlainObject(lastArg)) {
473
+ const options = lastArg;
474
+ const originalSuccess = options.success;
475
+ const originalComplete = options.complete;
476
+ options.success = (res) => {
477
+ originalSuccess?.(mappingRule.mapResult(res));
478
+ };
479
+ options.complete = (res) => {
480
+ originalComplete?.(mappingRule.mapResult(res));
481
+ };
482
+ }
483
+ const result = runtimeMethod.apply(runtimeAdapter, runtimeArgs);
484
+ return mappingRule?.mapResult ? mappingRule.mapResult(result) : result;
485
+ }
486
+ return callWithPromise(runtimeAdapter, runtimeMethod, runtimeArgs, mappingRule?.mapResult);
221
487
  };
222
488
  cache.set(prop, wrapped);
223
489
  return wrapped;
@@ -228,6 +494,15 @@ function createWeapi(options = {}) {
228
494
  //#region src/index.ts
229
495
  /**
230
496
  * @description 默认跨平台 API 实例(推荐使用)
497
+ *
498
+ * @generated weapi-platform-matrix:start
499
+ * | 平台 | 类型来源 | 支持度 |
500
+ * | --- | --- | --- |
501
+ * | 微信小程序 (`wx`) | `miniprogram-api-typings` | ✅ 全量 |
502
+ * | 支付宝小程序 (`my`) | `@mini-types/alipay` | ✅ 全量 |
503
+ * | 抖音小程序 (`tt`) | `@douyin-microapp/typings` | ✅ 全量 |
504
+ * | 其他平台对象 (`swan/jd/xhs/...`) | 运行时对象透传 | ⚠️ 按宿主能力支持 |
505
+ * @generated weapi-platform-matrix:end
231
506
  */
232
507
  const wpi = createWeapi();
233
508
 
package/dist/index.d.cts CHANGED
@@ -4,6 +4,28 @@ type WeapiAdapter = Record<string, any>;
4
4
  * @description 微信小程序 API 原始适配器类型
5
5
  */
6
6
  type WeapiWxRawAdapter = WechatMiniprogram.Wx;
7
+ /**
8
+ * @description 支付宝小程序 API 原始适配器类型
9
+ */
10
+ type WeapiAlipayRawAdapter = typeof my;
11
+ /**
12
+ * @description 抖音小程序 API 原始适配器类型
13
+ */
14
+ type WeapiDouyinRawAdapter = typeof tt;
15
+ type MergeAdapters<Primary extends WeapiAdapter, Secondary extends WeapiAdapter> = Primary & Omit<Secondary, keyof Primary>;
16
+ /**
17
+ * @description weapi 对齐后的跨平台原始 API 类型
18
+ *
19
+ * @generated weapi-platform-matrix:start
20
+ * | 平台 | 全局对象 | 类型来源 | 对齐状态 |
21
+ * | --- | --- | --- | --- |
22
+ * | 微信小程序 | `wx` | `miniprogram-api-typings` | ✅ 全量 |
23
+ * | 支付宝小程序 | `my` | `@mini-types/alipay` | ✅ 全量 |
24
+ * | 抖音小程序 | `tt` | `@douyin-microapp/typings` | ✅ 全量 |
25
+ * | 其他平台(swan/jd/xhs 等) | 运行时宿主对象 | 运行时透传 | ⚠️ 按宿主能力支持 |
26
+ * @generated weapi-platform-matrix:end
27
+ */
28
+ type WeapiCrossPlatformRawAdapter = MergeAdapters<MergeAdapters<WeapiWxRawAdapter, WeapiAlipayRawAdapter>, WeapiDouyinRawAdapter>;
7
29
  type HasCallbackKey<T> = T extends object ? 'success' extends keyof T ? true : 'fail' extends keyof T ? true : 'complete' extends keyof T ? true : false : false;
8
30
  type HasCallbackOption<T> = T extends {
9
31
  success: unknown;
@@ -21,13 +43,112 @@ type PromisifyOptionMethod<Prefix extends any[], Option extends object, Result,
21
43
  } : {
22
44
  <TOption extends Option>(...args: [...Prefix, TOption]): HasCallbackOption<TOption> extends true ? Result : Promise<ExtractSuccessResult<Option>>;
23
45
  };
24
- type PromisifyMethod<TMethod> = TMethod extends ((...args: infer Args) => infer Result) ? Args extends [] ? (...args: Args) => Promise<Result> : Args extends [...infer Prefix, infer Last] ? true extends HasCallbackKey<NonNullable<Last>> ? PromisifyOptionMethod<Prefix, NonNullable<Last>, Result, undefined extends Last ? true : false> : (...args: Args) => Promise<Result> : (...args: Args) => Promise<Result> : TMethod;
46
+ type NormalizePromisifyReturn<T> = T extends Promise<any> ? T : Promise<T>;
47
+ type PromisifyMethod<TMethod> = TMethod extends ((...args: infer Args) => infer Result) ? Args extends [] ? (...args: Args) => NormalizePromisifyReturn<Result> : Args extends [...infer Prefix, infer Last] ? true extends HasCallbackKey<NonNullable<Last>> ? PromisifyOptionMethod<Prefix, NonNullable<Last>, Result, undefined extends Last ? true : false> : (...args: Args) => NormalizePromisifyReturn<Result> : (...args: Args) => NormalizePromisifyReturn<Result> : TMethod;
25
48
  type WeapiPromisify<TAdapter extends WeapiAdapter> = { [Key in keyof TAdapter]: Key extends string ? Key extends `${string}Sync` ? TAdapter[Key] : Key extends `on${Capitalize<string>}` | `off${Capitalize<string>}` ? TAdapter[Key] : PromisifyMethod<TAdapter[Key]> : TAdapter[Key] };
26
49
  /**
27
50
  * @description 微信小程序 API 适配器类型
28
51
  */
29
52
  type WeapiWxAdapter = WeapiPromisify<WeapiWxRawAdapter>;
30
- interface CreateWeapiOptions<TAdapter extends WeapiAdapter = WeapiWxRawAdapter> {
53
+ /**
54
+ * @description 支付宝小程序 API 适配器类型
55
+ */
56
+ type WeapiAlipayAdapter = WeapiPromisify<WeapiAlipayRawAdapter>;
57
+ /**
58
+ * @description 抖音小程序 API 适配器类型
59
+ */
60
+ type WeapiDouyinAdapter = WeapiPromisify<WeapiDouyinRawAdapter>;
61
+ /**
62
+ * @description weapi 默认导出的跨平台 API 适配器类型
63
+ */
64
+ type WeapiCrossPlatformAdapter = WeapiPromisify<WeapiCrossPlatformRawAdapter>;
65
+ /**
66
+ * @description weapi 核心映射 API 的平台支持度说明
67
+ */
68
+ interface WeapiCrossPlatformMethodDocs {
69
+ /**
70
+ * 显示消息提示框。
71
+ *
72
+ * | 平台 | 对齐策略 | 支持度 |
73
+ * | --- | --- | --- |
74
+ * | 微信 | 直连 `wx.showToast` | ✅ |
75
+ * | 支付宝 | `title/icon` 映射到 `content/type` 后调用 `my.showToast` | ✅ |
76
+ * | 抖音 | `icon=error` 映射为 `fail` 后调用 `tt.showToast` | ✅ |
77
+ */
78
+ showToast: WeapiCrossPlatformAdapter['showToast'];
79
+ /**
80
+ * 显示 loading 提示框。
81
+ *
82
+ * | 平台 | 对齐策略 | 支持度 |
83
+ * | --- | --- | --- |
84
+ * | 微信 | 直连 `wx.showLoading` | ✅ |
85
+ * | 支付宝 | `title` 映射到 `content` 后调用 `my.showLoading` | ✅ |
86
+ * | 抖音 | 直连 `tt.showLoading` | ✅ |
87
+ */
88
+ showLoading: WeapiCrossPlatformAdapter['showLoading'];
89
+ /**
90
+ * 显示操作菜单。
91
+ *
92
+ * | 平台 | 对齐策略 | 支持度 |
93
+ * | --- | --- | --- |
94
+ * | 微信 | 直连 `wx.showActionSheet` | ✅ |
95
+ * | 支付宝 | `itemList` ↔ `items`、`index` ↔ `tapIndex` 双向对齐 | ✅ |
96
+ * | 抖音 | 直连 `tt.showActionSheet`,并兼容 `index` → `tapIndex` | ✅ |
97
+ */
98
+ showActionSheet: WeapiCrossPlatformAdapter['showActionSheet'];
99
+ /**
100
+ * 显示模态弹窗。
101
+ *
102
+ * | 平台 | 对齐策略 | 支持度 |
103
+ * | --- | --- | --- |
104
+ * | 微信 | 直连 `wx.showModal` | ✅ |
105
+ * | 支付宝 | 调用 `my.confirm` 并对齐按钮字段与 `cancel` 结果 | ✅ |
106
+ * | 抖音 | 直连 `tt.showModal` | ✅ |
107
+ */
108
+ showModal: WeapiCrossPlatformAdapter['showModal'];
109
+ /**
110
+ * 选择图片。
111
+ *
112
+ * | 平台 | 对齐策略 | 支持度 |
113
+ * | --- | --- | --- |
114
+ * | 微信 | 直连 `wx.chooseImage` | ✅ |
115
+ * | 支付宝 | 返回值 `apFilePaths` 映射到 `tempFilePaths` | ✅ |
116
+ * | 抖音 | `tempFilePaths` 字符串转数组,缺失时从 `tempFiles.path` 兜底 | ✅ |
117
+ */
118
+ chooseImage: WeapiCrossPlatformAdapter['chooseImage'];
119
+ /**
120
+ * 保存文件。
121
+ *
122
+ * | 平台 | 对齐策略 | 支持度 |
123
+ * | --- | --- | --- |
124
+ * | 微信 | 直连 `wx.saveFile` | ✅ |
125
+ * | 支付宝 | 请求参数 `tempFilePath` ↔ `apFilePath`、结果映射为 `savedFilePath` | ✅ |
126
+ * | 抖音 | 直连 `tt.saveFile`,并在缺失时用 `filePath` 兜底 `savedFilePath` | ✅ |
127
+ */
128
+ saveFile: WeapiCrossPlatformAdapter['saveFile'];
129
+ /**
130
+ * 设置剪贴板内容。
131
+ *
132
+ * | 平台 | 对齐策略 | 支持度 |
133
+ * | --- | --- | --- |
134
+ * | 微信 | 直连 `wx.setClipboardData` | ✅ |
135
+ * | 支付宝 | 转调 `my.setClipboard` 并映射 `data` → `text` | ✅ |
136
+ * | 抖音 | 直连 `tt.setClipboardData` | ✅ |
137
+ */
138
+ setClipboardData: WeapiCrossPlatformAdapter['setClipboardData'];
139
+ /**
140
+ * 获取剪贴板内容。
141
+ *
142
+ * | 平台 | 对齐策略 | 支持度 |
143
+ * | --- | --- | --- |
144
+ * | 微信 | 直连 `wx.getClipboardData` | ✅ |
145
+ * | 支付宝 | 转调 `my.getClipboard` 并映射 `text` → `data` | ✅ |
146
+ * | 抖音 | 直连 `tt.getClipboardData` | ✅ |
147
+ */
148
+ getClipboardData: WeapiCrossPlatformAdapter['getClipboardData'];
149
+ }
150
+ type WeapiMethodDocOverlay<TAdapter extends WeapiAdapter> = TAdapter extends WeapiCrossPlatformRawAdapter ? WeapiCrossPlatformMethodDocs : object;
151
+ interface CreateWeapiOptions<TAdapter extends WeapiAdapter = WeapiCrossPlatformRawAdapter> {
31
152
  /**
32
153
  * @description 手动指定平台适配器(优先级高于自动探测)
33
154
  */
@@ -37,7 +158,7 @@ interface CreateWeapiOptions<TAdapter extends WeapiAdapter = WeapiWxRawAdapter>
37
158
  */
38
159
  platform?: string;
39
160
  }
40
- type WeapiInstance<TAdapter extends WeapiAdapter = WeapiWxRawAdapter> = WeapiPromisify<TAdapter> & {
161
+ type WeapiInstance<TAdapter extends WeapiAdapter = WeapiCrossPlatformRawAdapter> = WeapiPromisify<TAdapter> & TAdapter & WeapiMethodDocOverlay<TAdapter> & {
41
162
  /**
42
163
  * @description 当前平台标识
43
164
  */
@@ -60,12 +181,21 @@ type WeapiInstance<TAdapter extends WeapiAdapter = WeapiWxRawAdapter> = WeapiPro
60
181
  /**
61
182
  * @description 创建跨平台 API 实例
62
183
  */
63
- declare function createWeapi<TAdapter extends WeapiAdapter = WeapiWxRawAdapter>(options?: CreateWeapiOptions<TAdapter>): WeapiInstance<TAdapter>;
184
+ declare function createWeapi<TAdapter extends WeapiAdapter = WeapiCrossPlatformRawAdapter>(options?: CreateWeapiOptions<TAdapter>): WeapiInstance<TAdapter>;
64
185
  //#endregion
65
186
  //#region src/index.d.ts
66
187
  /**
67
188
  * @description 默认跨平台 API 实例(推荐使用)
189
+ *
190
+ * @generated weapi-platform-matrix:start
191
+ * | 平台 | 类型来源 | 支持度 |
192
+ * | --- | --- | --- |
193
+ * | 微信小程序 (`wx`) | `miniprogram-api-typings` | ✅ 全量 |
194
+ * | 支付宝小程序 (`my`) | `@mini-types/alipay` | ✅ 全量 |
195
+ * | 抖音小程序 (`tt`) | `@douyin-microapp/typings` | ✅ 全量 |
196
+ * | 其他平台对象 (`swan/jd/xhs/...`) | 运行时对象透传 | ⚠️ 按宿主能力支持 |
197
+ * @generated weapi-platform-matrix:end
68
198
  */
69
- declare const wpi: WeapiInstance<WechatMiniprogram.Wx>;
199
+ declare const wpi: WeapiInstance<WeapiCrossPlatformRawAdapter>;
70
200
  //#endregion
71
- export { type CreateWeapiOptions, type WeapiAdapter, type WeapiInstance, type WeapiPromisify, type WeapiWxAdapter, type WeapiWxRawAdapter, createWeapi, wpi };
201
+ export { type CreateWeapiOptions, type WeapiAdapter, type WeapiAlipayAdapter, type WeapiAlipayRawAdapter, type WeapiCrossPlatformAdapter, type WeapiCrossPlatformRawAdapter, type WeapiDouyinAdapter, type WeapiDouyinRawAdapter, type WeapiInstance, type WeapiPromisify, type WeapiWxAdapter, type WeapiWxRawAdapter, createWeapi, wpi };
package/dist/index.d.mts CHANGED
@@ -4,6 +4,28 @@ type WeapiAdapter = Record<string, any>;
4
4
  * @description 微信小程序 API 原始适配器类型
5
5
  */
6
6
  type WeapiWxRawAdapter = WechatMiniprogram.Wx;
7
+ /**
8
+ * @description 支付宝小程序 API 原始适配器类型
9
+ */
10
+ type WeapiAlipayRawAdapter = typeof my;
11
+ /**
12
+ * @description 抖音小程序 API 原始适配器类型
13
+ */
14
+ type WeapiDouyinRawAdapter = typeof tt;
15
+ type MergeAdapters<Primary extends WeapiAdapter, Secondary extends WeapiAdapter> = Primary & Omit<Secondary, keyof Primary>;
16
+ /**
17
+ * @description weapi 对齐后的跨平台原始 API 类型
18
+ *
19
+ * @generated weapi-platform-matrix:start
20
+ * | 平台 | 全局对象 | 类型来源 | 对齐状态 |
21
+ * | --- | --- | --- | --- |
22
+ * | 微信小程序 | `wx` | `miniprogram-api-typings` | ✅ 全量 |
23
+ * | 支付宝小程序 | `my` | `@mini-types/alipay` | ✅ 全量 |
24
+ * | 抖音小程序 | `tt` | `@douyin-microapp/typings` | ✅ 全量 |
25
+ * | 其他平台(swan/jd/xhs 等) | 运行时宿主对象 | 运行时透传 | ⚠️ 按宿主能力支持 |
26
+ * @generated weapi-platform-matrix:end
27
+ */
28
+ type WeapiCrossPlatformRawAdapter = MergeAdapters<MergeAdapters<WeapiWxRawAdapter, WeapiAlipayRawAdapter>, WeapiDouyinRawAdapter>;
7
29
  type HasCallbackKey<T> = T extends object ? 'success' extends keyof T ? true : 'fail' extends keyof T ? true : 'complete' extends keyof T ? true : false : false;
8
30
  type HasCallbackOption<T> = T extends {
9
31
  success: unknown;
@@ -21,13 +43,112 @@ type PromisifyOptionMethod<Prefix extends any[], Option extends object, Result,
21
43
  } : {
22
44
  <TOption extends Option>(...args: [...Prefix, TOption]): HasCallbackOption<TOption> extends true ? Result : Promise<ExtractSuccessResult<Option>>;
23
45
  };
24
- type PromisifyMethod<TMethod> = TMethod extends ((...args: infer Args) => infer Result) ? Args extends [] ? (...args: Args) => Promise<Result> : Args extends [...infer Prefix, infer Last] ? true extends HasCallbackKey<NonNullable<Last>> ? PromisifyOptionMethod<Prefix, NonNullable<Last>, Result, undefined extends Last ? true : false> : (...args: Args) => Promise<Result> : (...args: Args) => Promise<Result> : TMethod;
46
+ type NormalizePromisifyReturn<T> = T extends Promise<any> ? T : Promise<T>;
47
+ type PromisifyMethod<TMethod> = TMethod extends ((...args: infer Args) => infer Result) ? Args extends [] ? (...args: Args) => NormalizePromisifyReturn<Result> : Args extends [...infer Prefix, infer Last] ? true extends HasCallbackKey<NonNullable<Last>> ? PromisifyOptionMethod<Prefix, NonNullable<Last>, Result, undefined extends Last ? true : false> : (...args: Args) => NormalizePromisifyReturn<Result> : (...args: Args) => NormalizePromisifyReturn<Result> : TMethod;
25
48
  type WeapiPromisify<TAdapter extends WeapiAdapter> = { [Key in keyof TAdapter]: Key extends string ? Key extends `${string}Sync` ? TAdapter[Key] : Key extends `on${Capitalize<string>}` | `off${Capitalize<string>}` ? TAdapter[Key] : PromisifyMethod<TAdapter[Key]> : TAdapter[Key] };
26
49
  /**
27
50
  * @description 微信小程序 API 适配器类型
28
51
  */
29
52
  type WeapiWxAdapter = WeapiPromisify<WeapiWxRawAdapter>;
30
- interface CreateWeapiOptions<TAdapter extends WeapiAdapter = WeapiWxRawAdapter> {
53
+ /**
54
+ * @description 支付宝小程序 API 适配器类型
55
+ */
56
+ type WeapiAlipayAdapter = WeapiPromisify<WeapiAlipayRawAdapter>;
57
+ /**
58
+ * @description 抖音小程序 API 适配器类型
59
+ */
60
+ type WeapiDouyinAdapter = WeapiPromisify<WeapiDouyinRawAdapter>;
61
+ /**
62
+ * @description weapi 默认导出的跨平台 API 适配器类型
63
+ */
64
+ type WeapiCrossPlatformAdapter = WeapiPromisify<WeapiCrossPlatformRawAdapter>;
65
+ /**
66
+ * @description weapi 核心映射 API 的平台支持度说明
67
+ */
68
+ interface WeapiCrossPlatformMethodDocs {
69
+ /**
70
+ * 显示消息提示框。
71
+ *
72
+ * | 平台 | 对齐策略 | 支持度 |
73
+ * | --- | --- | --- |
74
+ * | 微信 | 直连 `wx.showToast` | ✅ |
75
+ * | 支付宝 | `title/icon` 映射到 `content/type` 后调用 `my.showToast` | ✅ |
76
+ * | 抖音 | `icon=error` 映射为 `fail` 后调用 `tt.showToast` | ✅ |
77
+ */
78
+ showToast: WeapiCrossPlatformAdapter['showToast'];
79
+ /**
80
+ * 显示 loading 提示框。
81
+ *
82
+ * | 平台 | 对齐策略 | 支持度 |
83
+ * | --- | --- | --- |
84
+ * | 微信 | 直连 `wx.showLoading` | ✅ |
85
+ * | 支付宝 | `title` 映射到 `content` 后调用 `my.showLoading` | ✅ |
86
+ * | 抖音 | 直连 `tt.showLoading` | ✅ |
87
+ */
88
+ showLoading: WeapiCrossPlatformAdapter['showLoading'];
89
+ /**
90
+ * 显示操作菜单。
91
+ *
92
+ * | 平台 | 对齐策略 | 支持度 |
93
+ * | --- | --- | --- |
94
+ * | 微信 | 直连 `wx.showActionSheet` | ✅ |
95
+ * | 支付宝 | `itemList` ↔ `items`、`index` ↔ `tapIndex` 双向对齐 | ✅ |
96
+ * | 抖音 | 直连 `tt.showActionSheet`,并兼容 `index` → `tapIndex` | ✅ |
97
+ */
98
+ showActionSheet: WeapiCrossPlatformAdapter['showActionSheet'];
99
+ /**
100
+ * 显示模态弹窗。
101
+ *
102
+ * | 平台 | 对齐策略 | 支持度 |
103
+ * | --- | --- | --- |
104
+ * | 微信 | 直连 `wx.showModal` | ✅ |
105
+ * | 支付宝 | 调用 `my.confirm` 并对齐按钮字段与 `cancel` 结果 | ✅ |
106
+ * | 抖音 | 直连 `tt.showModal` | ✅ |
107
+ */
108
+ showModal: WeapiCrossPlatformAdapter['showModal'];
109
+ /**
110
+ * 选择图片。
111
+ *
112
+ * | 平台 | 对齐策略 | 支持度 |
113
+ * | --- | --- | --- |
114
+ * | 微信 | 直连 `wx.chooseImage` | ✅ |
115
+ * | 支付宝 | 返回值 `apFilePaths` 映射到 `tempFilePaths` | ✅ |
116
+ * | 抖音 | `tempFilePaths` 字符串转数组,缺失时从 `tempFiles.path` 兜底 | ✅ |
117
+ */
118
+ chooseImage: WeapiCrossPlatformAdapter['chooseImage'];
119
+ /**
120
+ * 保存文件。
121
+ *
122
+ * | 平台 | 对齐策略 | 支持度 |
123
+ * | --- | --- | --- |
124
+ * | 微信 | 直连 `wx.saveFile` | ✅ |
125
+ * | 支付宝 | 请求参数 `tempFilePath` ↔ `apFilePath`、结果映射为 `savedFilePath` | ✅ |
126
+ * | 抖音 | 直连 `tt.saveFile`,并在缺失时用 `filePath` 兜底 `savedFilePath` | ✅ |
127
+ */
128
+ saveFile: WeapiCrossPlatformAdapter['saveFile'];
129
+ /**
130
+ * 设置剪贴板内容。
131
+ *
132
+ * | 平台 | 对齐策略 | 支持度 |
133
+ * | --- | --- | --- |
134
+ * | 微信 | 直连 `wx.setClipboardData` | ✅ |
135
+ * | 支付宝 | 转调 `my.setClipboard` 并映射 `data` → `text` | ✅ |
136
+ * | 抖音 | 直连 `tt.setClipboardData` | ✅ |
137
+ */
138
+ setClipboardData: WeapiCrossPlatformAdapter['setClipboardData'];
139
+ /**
140
+ * 获取剪贴板内容。
141
+ *
142
+ * | 平台 | 对齐策略 | 支持度 |
143
+ * | --- | --- | --- |
144
+ * | 微信 | 直连 `wx.getClipboardData` | ✅ |
145
+ * | 支付宝 | 转调 `my.getClipboard` 并映射 `text` → `data` | ✅ |
146
+ * | 抖音 | 直连 `tt.getClipboardData` | ✅ |
147
+ */
148
+ getClipboardData: WeapiCrossPlatformAdapter['getClipboardData'];
149
+ }
150
+ type WeapiMethodDocOverlay<TAdapter extends WeapiAdapter> = TAdapter extends WeapiCrossPlatformRawAdapter ? WeapiCrossPlatformMethodDocs : object;
151
+ interface CreateWeapiOptions<TAdapter extends WeapiAdapter = WeapiCrossPlatformRawAdapter> {
31
152
  /**
32
153
  * @description 手动指定平台适配器(优先级高于自动探测)
33
154
  */
@@ -37,7 +158,7 @@ interface CreateWeapiOptions<TAdapter extends WeapiAdapter = WeapiWxRawAdapter>
37
158
  */
38
159
  platform?: string;
39
160
  }
40
- type WeapiInstance<TAdapter extends WeapiAdapter = WeapiWxRawAdapter> = WeapiPromisify<TAdapter> & {
161
+ type WeapiInstance<TAdapter extends WeapiAdapter = WeapiCrossPlatformRawAdapter> = WeapiPromisify<TAdapter> & TAdapter & WeapiMethodDocOverlay<TAdapter> & {
41
162
  /**
42
163
  * @description 当前平台标识
43
164
  */
@@ -60,12 +181,21 @@ type WeapiInstance<TAdapter extends WeapiAdapter = WeapiWxRawAdapter> = WeapiPro
60
181
  /**
61
182
  * @description 创建跨平台 API 实例
62
183
  */
63
- declare function createWeapi<TAdapter extends WeapiAdapter = WeapiWxRawAdapter>(options?: CreateWeapiOptions<TAdapter>): WeapiInstance<TAdapter>;
184
+ declare function createWeapi<TAdapter extends WeapiAdapter = WeapiCrossPlatformRawAdapter>(options?: CreateWeapiOptions<TAdapter>): WeapiInstance<TAdapter>;
64
185
  //#endregion
65
186
  //#region src/index.d.ts
66
187
  /**
67
188
  * @description 默认跨平台 API 实例(推荐使用)
189
+ *
190
+ * @generated weapi-platform-matrix:start
191
+ * | 平台 | 类型来源 | 支持度 |
192
+ * | --- | --- | --- |
193
+ * | 微信小程序 (`wx`) | `miniprogram-api-typings` | ✅ 全量 |
194
+ * | 支付宝小程序 (`my`) | `@mini-types/alipay` | ✅ 全量 |
195
+ * | 抖音小程序 (`tt`) | `@douyin-microapp/typings` | ✅ 全量 |
196
+ * | 其他平台对象 (`swan/jd/xhs/...`) | 运行时对象透传 | ⚠️ 按宿主能力支持 |
197
+ * @generated weapi-platform-matrix:end
68
198
  */
69
- declare const wpi: WeapiInstance<WechatMiniprogram.Wx>;
199
+ declare const wpi: WeapiInstance<WeapiCrossPlatformRawAdapter>;
70
200
  //#endregion
71
- export { type CreateWeapiOptions, type WeapiAdapter, type WeapiInstance, type WeapiPromisify, type WeapiWxAdapter, type WeapiWxRawAdapter, createWeapi, wpi };
201
+ export { type CreateWeapiOptions, type WeapiAdapter, type WeapiAlipayAdapter, type WeapiAlipayRawAdapter, type WeapiCrossPlatformAdapter, type WeapiCrossPlatformRawAdapter, type WeapiDouyinAdapter, type WeapiDouyinRawAdapter, type WeapiInstance, type WeapiPromisify, type WeapiWxAdapter, type WeapiWxRawAdapter, createWeapi, wpi };
package/dist/index.mjs CHANGED
@@ -94,6 +94,243 @@ function createNotSupportedError(methodName, platform) {
94
94
  return { errMsg: `${platform ? `${platform}.${methodName}` : methodName}:fail method not supported` };
95
95
  }
96
96
 
97
+ //#endregion
98
+ //#region src/core/methodMapping.ts
99
+ const PLATFORM_ALIASES$1 = {
100
+ alipay: "my",
101
+ douyin: "tt"
102
+ };
103
+ function mapToastType(type) {
104
+ if (type === "error") return "fail";
105
+ if (type === "loading") return "none";
106
+ return type;
107
+ }
108
+ function mapToastArgs(args) {
109
+ if (args.length === 0) return args;
110
+ const nextArgs = [...args];
111
+ const lastIndex = nextArgs.length - 1;
112
+ const lastArg = nextArgs[lastIndex];
113
+ if (!isPlainObject(lastArg)) return nextArgs;
114
+ const nextOptions = { ...lastArg };
115
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "content") && Object.prototype.hasOwnProperty.call(nextOptions, "title")) nextOptions.content = nextOptions.title;
116
+ if (Object.prototype.hasOwnProperty.call(nextOptions, "icon")) nextOptions.type = mapToastType(nextOptions.icon);
117
+ nextArgs[lastIndex] = nextOptions;
118
+ return nextArgs;
119
+ }
120
+ function mapDouyinToastArgs(args) {
121
+ if (args.length === 0) return args;
122
+ const nextArgs = [...args];
123
+ const lastIndex = nextArgs.length - 1;
124
+ const lastArg = nextArgs[lastIndex];
125
+ if (!isPlainObject(lastArg)) return nextArgs;
126
+ const nextOptions = { ...lastArg };
127
+ if (nextOptions.icon === "error") nextOptions.icon = "fail";
128
+ nextArgs[lastIndex] = nextOptions;
129
+ return nextArgs;
130
+ }
131
+ function mapLoadingArgs(args) {
132
+ if (args.length === 0) return args;
133
+ const nextArgs = [...args];
134
+ const lastIndex = nextArgs.length - 1;
135
+ const lastArg = nextArgs[lastIndex];
136
+ if (!isPlainObject(lastArg)) return nextArgs;
137
+ const nextOptions = { ...lastArg };
138
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "content") && Object.prototype.hasOwnProperty.call(nextOptions, "title")) nextOptions.content = nextOptions.title;
139
+ nextArgs[lastIndex] = nextOptions;
140
+ return nextArgs;
141
+ }
142
+ function mapActionSheetArgs(args) {
143
+ if (args.length === 0) return args;
144
+ const nextArgs = [...args];
145
+ const lastIndex = nextArgs.length - 1;
146
+ const lastArg = nextArgs[lastIndex];
147
+ if (!isPlainObject(lastArg)) return nextArgs;
148
+ const nextOptions = { ...lastArg };
149
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "items") && Array.isArray(nextOptions.itemList)) nextOptions.items = nextOptions.itemList;
150
+ nextArgs[lastIndex] = nextOptions;
151
+ return nextArgs;
152
+ }
153
+ function mapActionSheetResult(result) {
154
+ if (!isPlainObject(result)) return result;
155
+ if (!Object.prototype.hasOwnProperty.call(result, "tapIndex") && Object.prototype.hasOwnProperty.call(result, "index")) return {
156
+ ...result,
157
+ tapIndex: result.index
158
+ };
159
+ return result;
160
+ }
161
+ function mapModalArgs(args) {
162
+ if (args.length === 0) return args;
163
+ const nextArgs = [...args];
164
+ const lastIndex = nextArgs.length - 1;
165
+ const lastArg = nextArgs[lastIndex];
166
+ if (!isPlainObject(lastArg)) return nextArgs;
167
+ const nextOptions = { ...lastArg };
168
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "confirmButtonText") && Object.prototype.hasOwnProperty.call(nextOptions, "confirmText")) nextOptions.confirmButtonText = nextOptions.confirmText;
169
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "cancelButtonText") && Object.prototype.hasOwnProperty.call(nextOptions, "cancelText")) nextOptions.cancelButtonText = nextOptions.cancelText;
170
+ nextArgs[lastIndex] = nextOptions;
171
+ return nextArgs;
172
+ }
173
+ function mapModalResult(result) {
174
+ if (!isPlainObject(result)) return result;
175
+ if (!Object.prototype.hasOwnProperty.call(result, "cancel") && Object.prototype.hasOwnProperty.call(result, "confirm")) return {
176
+ ...result,
177
+ cancel: !result.confirm
178
+ };
179
+ return result;
180
+ }
181
+ function mapChooseImageResult(result) {
182
+ if (!isPlainObject(result)) return result;
183
+ if (!Object.prototype.hasOwnProperty.call(result, "tempFilePaths") && Array.isArray(result.apFilePaths)) return {
184
+ ...result,
185
+ tempFilePaths: result.apFilePaths
186
+ };
187
+ return result;
188
+ }
189
+ function mapDouyinChooseImageResult(result) {
190
+ if (!isPlainObject(result)) return result;
191
+ if (typeof result.tempFilePaths === "string") return {
192
+ ...result,
193
+ tempFilePaths: [result.tempFilePaths]
194
+ };
195
+ if (!Array.isArray(result.tempFilePaths) && Array.isArray(result.tempFiles)) {
196
+ const fallbackPaths = result.tempFiles.map((item) => {
197
+ if (!isPlainObject(item)) return;
198
+ const path = item.path;
199
+ if (typeof path === "string" && path) return path;
200
+ const filePath = item.filePath;
201
+ if (typeof filePath === "string" && filePath) return filePath;
202
+ }).filter((item) => typeof item === "string");
203
+ if (fallbackPaths.length > 0) return {
204
+ ...result,
205
+ tempFilePaths: fallbackPaths
206
+ };
207
+ }
208
+ return result;
209
+ }
210
+ function mapSaveFileArgs(args) {
211
+ if (args.length === 0) return args;
212
+ const nextArgs = [...args];
213
+ const lastIndex = nextArgs.length - 1;
214
+ const lastArg = nextArgs[lastIndex];
215
+ if (!isPlainObject(lastArg)) return nextArgs;
216
+ const nextOptions = { ...lastArg };
217
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "apFilePath") && Object.prototype.hasOwnProperty.call(nextOptions, "tempFilePath")) nextOptions.apFilePath = nextOptions.tempFilePath;
218
+ nextArgs[lastIndex] = nextOptions;
219
+ return nextArgs;
220
+ }
221
+ function mapSaveFileResult(result) {
222
+ if (!isPlainObject(result)) return result;
223
+ if (!Object.prototype.hasOwnProperty.call(result, "savedFilePath") && Object.prototype.hasOwnProperty.call(result, "apFilePath")) return {
224
+ ...result,
225
+ savedFilePath: result.apFilePath
226
+ };
227
+ return result;
228
+ }
229
+ function mapDouyinSaveFileResult(result) {
230
+ if (!isPlainObject(result)) return result;
231
+ if (!Object.prototype.hasOwnProperty.call(result, "savedFilePath") && Object.prototype.hasOwnProperty.call(result, "filePath")) return {
232
+ ...result,
233
+ savedFilePath: result.filePath
234
+ };
235
+ return result;
236
+ }
237
+ function normalizePlatformName$1(value) {
238
+ if (!value) return;
239
+ const normalized = value.trim().toLowerCase();
240
+ if (!normalized) return;
241
+ return PLATFORM_ALIASES$1[normalized] ?? normalized;
242
+ }
243
+ function mapSetClipboardArgs(args) {
244
+ if (args.length === 0) return args;
245
+ const nextArgs = [...args];
246
+ const lastIndex = nextArgs.length - 1;
247
+ const lastArg = nextArgs[lastIndex];
248
+ if (!isPlainObject(lastArg)) return nextArgs;
249
+ const nextOptions = { ...lastArg };
250
+ if (!Object.prototype.hasOwnProperty.call(nextOptions, "text") && Object.prototype.hasOwnProperty.call(nextOptions, "data")) nextOptions.text = nextOptions.data;
251
+ nextArgs[lastIndex] = nextOptions;
252
+ return nextArgs;
253
+ }
254
+ function mapClipboardResult(result) {
255
+ if (!isPlainObject(result)) return result;
256
+ if (!Object.prototype.hasOwnProperty.call(result, "data") && Object.prototype.hasOwnProperty.call(result, "text")) return {
257
+ ...result,
258
+ data: result.text
259
+ };
260
+ return result;
261
+ }
262
+ const METHOD_MAPPINGS = {
263
+ my: {
264
+ showToast: {
265
+ target: "showToast",
266
+ mapArgs: mapToastArgs
267
+ },
268
+ showLoading: {
269
+ target: "showLoading",
270
+ mapArgs: mapLoadingArgs
271
+ },
272
+ showActionSheet: {
273
+ target: "showActionSheet",
274
+ mapArgs: mapActionSheetArgs,
275
+ mapResult: mapActionSheetResult
276
+ },
277
+ showModal: {
278
+ target: "confirm",
279
+ mapArgs: mapModalArgs,
280
+ mapResult: mapModalResult
281
+ },
282
+ chooseImage: {
283
+ target: "chooseImage",
284
+ mapResult: mapChooseImageResult
285
+ },
286
+ saveFile: {
287
+ target: "saveFile",
288
+ mapArgs: mapSaveFileArgs,
289
+ mapResult: mapSaveFileResult
290
+ },
291
+ setClipboardData: {
292
+ target: "setClipboard",
293
+ mapArgs: mapSetClipboardArgs
294
+ },
295
+ getClipboardData: {
296
+ target: "getClipboard",
297
+ mapResult: mapClipboardResult
298
+ }
299
+ },
300
+ tt: {
301
+ showToast: {
302
+ target: "showToast",
303
+ mapArgs: mapDouyinToastArgs
304
+ },
305
+ showLoading: { target: "showLoading" },
306
+ showActionSheet: {
307
+ target: "showActionSheet",
308
+ mapResult: mapActionSheetResult
309
+ },
310
+ showModal: { target: "showModal" },
311
+ chooseImage: {
312
+ target: "chooseImage",
313
+ mapResult: mapDouyinChooseImageResult
314
+ },
315
+ saveFile: {
316
+ target: "saveFile",
317
+ mapResult: mapDouyinSaveFileResult
318
+ },
319
+ setClipboardData: { target: "setClipboardData" },
320
+ getClipboardData: { target: "getClipboardData" }
321
+ }
322
+ };
323
+ /**
324
+ * @description 解析平台 API 映射规则
325
+ */
326
+ function resolveMethodMapping(platform, methodName) {
327
+ const normalizedPlatform = normalizePlatformName$1(platform);
328
+ if (!normalizedPlatform) return;
329
+ const platformMappings = METHOD_MAPPINGS[normalizedPlatform];
330
+ if (!platformMappings) return;
331
+ return platformMappings[methodName];
332
+ }
333
+
97
334
  //#endregion
98
335
  //#region src/core/createWeapi.ts
99
336
  const INTERNAL_KEYS = new Set([
@@ -102,8 +339,15 @@ const INTERNAL_KEYS = new Set([
102
339
  "platform",
103
340
  "raw"
104
341
  ]);
342
+ const PLATFORM_ALIASES = {
343
+ alipay: "my",
344
+ douyin: "tt"
345
+ };
105
346
  function normalizePlatformName(value) {
106
- return value || void 0;
347
+ if (!value) return;
348
+ const normalized = value.trim().toLowerCase();
349
+ if (!normalized) return;
350
+ return PLATFORM_ALIASES[normalized] ?? normalized;
107
351
  }
108
352
  function resolveOptionsArg(args) {
109
353
  const nextArgs = args.slice();
@@ -123,20 +367,20 @@ function resolveOptionsArg(args) {
123
367
  options
124
368
  };
125
369
  }
126
- function callWithPromise(context, method, args) {
370
+ function callWithPromise(context, method, args, mapResult) {
127
371
  return new Promise((resolve, reject) => {
128
372
  const { args: nextArgs, options } = resolveOptionsArg(args);
129
373
  let settled = false;
130
374
  options.success = (res) => {
131
375
  settled = true;
132
- resolve(res);
376
+ resolve(mapResult ? mapResult(res) : res);
133
377
  };
134
378
  options.fail = (err) => {
135
379
  settled = true;
136
380
  reject(err);
137
381
  };
138
382
  options.complete = (res) => {
139
- if (!settled) resolve(res);
383
+ if (!settled) resolve(mapResult ? mapResult(res) : res);
140
384
  };
141
385
  try {
142
386
  method.apply(context, nextArgs);
@@ -199,7 +443,8 @@ function createWeapi(options = {}) {
199
443
  if (typeof prop !== "string") return;
200
444
  return (...args) => callMissingApi(prop, getPlatform(), args);
201
445
  }
202
- const value = currentAdapter[prop];
446
+ const platform = getPlatform();
447
+ const value = currentAdapter[(typeof prop === "string" ? resolveMethodMapping(platform, prop) : void 0)?.target ?? prop];
203
448
  if (typeof value !== "function") {
204
449
  if (value === void 0 && typeof prop === "string") {
205
450
  const missing = (...args) => callMissingApi(prop, getPlatform(), args);
@@ -211,11 +456,32 @@ function createWeapi(options = {}) {
211
456
  }
212
457
  const wrapped = (...args) => {
213
458
  const runtimeAdapter = resolveAdapter();
214
- const runtimeMethod = runtimeAdapter ? runtimeAdapter[prop] : void 0;
459
+ const mappingRule = resolveMethodMapping(getPlatform(), prop);
460
+ const methodName = mappingRule?.target ?? prop;
461
+ const runtimeMethod = runtimeAdapter ? runtimeAdapter[methodName] : void 0;
462
+ const runtimeArgs = mappingRule?.mapArgs ? mappingRule.mapArgs(args) : args;
215
463
  if (typeof runtimeMethod !== "function") return callMissingApi(prop, getPlatform(), args);
216
- if (shouldSkipPromise(prop)) return runtimeMethod.apply(runtimeAdapter, args);
217
- if (hasCallbacks(args.length > 0 ? args[args.length - 1] : void 0)) return runtimeMethod.apply(runtimeAdapter, args);
218
- return callWithPromise(runtimeAdapter, runtimeMethod, args);
464
+ if (shouldSkipPromise(prop)) {
465
+ const result = runtimeMethod.apply(runtimeAdapter, runtimeArgs);
466
+ return mappingRule?.mapResult ? mappingRule.mapResult(result) : result;
467
+ }
468
+ const lastArg = runtimeArgs.length > 0 ? runtimeArgs[runtimeArgs.length - 1] : void 0;
469
+ if (hasCallbacks(lastArg)) {
470
+ if (mappingRule?.mapResult && isPlainObject(lastArg)) {
471
+ const options = lastArg;
472
+ const originalSuccess = options.success;
473
+ const originalComplete = options.complete;
474
+ options.success = (res) => {
475
+ originalSuccess?.(mappingRule.mapResult(res));
476
+ };
477
+ options.complete = (res) => {
478
+ originalComplete?.(mappingRule.mapResult(res));
479
+ };
480
+ }
481
+ const result = runtimeMethod.apply(runtimeAdapter, runtimeArgs);
482
+ return mappingRule?.mapResult ? mappingRule.mapResult(result) : result;
483
+ }
484
+ return callWithPromise(runtimeAdapter, runtimeMethod, runtimeArgs, mappingRule?.mapResult);
219
485
  };
220
486
  cache.set(prop, wrapped);
221
487
  return wrapped;
@@ -226,6 +492,15 @@ function createWeapi(options = {}) {
226
492
  //#region src/index.ts
227
493
  /**
228
494
  * @description 默认跨平台 API 实例(推荐使用)
495
+ *
496
+ * @generated weapi-platform-matrix:start
497
+ * | 平台 | 类型来源 | 支持度 |
498
+ * | --- | --- | --- |
499
+ * | 微信小程序 (`wx`) | `miniprogram-api-typings` | ✅ 全量 |
500
+ * | 支付宝小程序 (`my`) | `@mini-types/alipay` | ✅ 全量 |
501
+ * | 抖音小程序 (`tt`) | `@douyin-microapp/typings` | ✅ 全量 |
502
+ * | 其他平台对象 (`swan/jd/xhs/...`) | 运行时对象透传 | ⚠️ 按宿主能力支持 |
503
+ * @generated weapi-platform-matrix:end
229
504
  */
230
505
  const wpi = createWeapi();
231
506
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wevu/api",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "description": "tsdown bundler template",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -36,6 +36,8 @@
36
36
  "types"
37
37
  ],
38
38
  "dependencies": {
39
+ "@douyin-microapp/typings": "^1.3.1",
40
+ "@mini-types/alipay": "^3.0.14",
39
41
  "miniprogram-api-typings": "^5.0.0"
40
42
  },
41
43
  "publishConfig": {
@@ -49,6 +51,9 @@
49
51
  "test:types": "tsd",
50
52
  "release": "pnpm publish",
51
53
  "lint": "eslint .",
52
- "lint:fix": "eslint . --fix"
54
+ "lint:fix": "eslint . --fix",
55
+ "docs:sync": "node --experimental-strip-types ./scripts/sync-support-matrix.ts",
56
+ "docs:check": "node --experimental-strip-types ./scripts/sync-support-matrix.ts --check",
57
+ "prebuild": "pnpm run docs:check"
53
58
  }
54
59
  }
package/types/index.d.ts CHANGED
@@ -1,9 +1,17 @@
1
1
  /// <reference types="miniprogram-api-typings" />
2
+ /// <reference types="@mini-types/alipay" />
3
+ /// <reference types="@douyin-microapp/typings" />
2
4
 
3
5
  // eslint-disable-next-line antfu/no-import-dist
4
6
  import type {
5
7
  CreateWeapiOptions,
6
8
  WeapiAdapter,
9
+ WeapiAlipayAdapter,
10
+ WeapiAlipayRawAdapter,
11
+ WeapiCrossPlatformAdapter,
12
+ WeapiCrossPlatformRawAdapter,
13
+ WeapiDouyinAdapter,
14
+ WeapiDouyinRawAdapter,
7
15
  WeapiInstance,
8
16
  WeapiPromisify,
9
17
  WeapiWxAdapter,
@@ -13,14 +21,34 @@ import type {
13
21
  export type {
14
22
  CreateWeapiOptions,
15
23
  WeapiAdapter,
24
+ WeapiAlipayAdapter,
25
+ WeapiAlipayRawAdapter,
26
+ WeapiCrossPlatformAdapter,
27
+ WeapiCrossPlatformRawAdapter,
28
+ WeapiDouyinAdapter,
29
+ WeapiDouyinRawAdapter,
16
30
  WeapiInstance,
17
31
  WeapiPromisify,
18
32
  WeapiWxAdapter,
19
33
  WeapiWxRawAdapter,
20
34
  }
21
35
 
22
- export function createWeapi<TAdapter extends WeapiAdapter = WeapiWxRawAdapter>(
36
+ export function createWeapi<TAdapter extends WeapiAdapter = WeapiCrossPlatformRawAdapter>(
23
37
  options?: CreateWeapiOptions<TAdapter>,
24
38
  ): WeapiInstance<TAdapter>
25
39
 
26
- export const wpi: WeapiInstance<WechatMiniprogram.Wx>
40
+ export type WeapiDefaultInstance = WeapiInstance<WeapiCrossPlatformRawAdapter>
41
+
42
+ /**
43
+ * 默认跨平台 API 实例。
44
+ *
45
+ * @generated weapi-platform-matrix:start
46
+ * | 平台 | 全局对象 | 类型来源 | 对齐状态 |
47
+ * | --- | --- | --- | --- |
48
+ * | 微信小程序 | `wx` | `miniprogram-api-typings` | ✅ 全量 |
49
+ * | 支付宝小程序 | `my` | `@mini-types/alipay` | ✅ 全量 |
50
+ * | 抖音小程序 | `tt` | `@douyin-microapp/typings` | ✅ 全量 |
51
+ * | 其他平台(swan/jd/xhs 等) | 运行时宿主对象 | 运行时透传 | ⚠️ 按宿主能力支持 |
52
+ * @generated weapi-platform-matrix:end
53
+ */
54
+ export const wpi: WeapiDefaultInstance