New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@hylid/call

Package Overview
Dependencies
Maintainers
0
Versions
125
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hylid/call - npm Package Compare versions

Comparing version 3.2.0-alpha.0 to 3.2.0-alpha.1

16

lib/mpWebCall.d.ts

@@ -1,5 +0,11 @@

import { PickMPArgs, PickMpReturns, MPApi } from '@hylid/types';
import { MpWebJsApiConfig } from './types';
declare type Callback<T> = (result?: T) => void;
export declare const mpWebCall: <T extends keyof MPApi>(api: ({} & string) | T, options?: PickMPArgs<T> | Callback<ReturnType<MPApi[T]>> | undefined, config?: MpWebJsApiConfig) => void;
export {};
import { MPApi } from '@hylid/types';
import { MpWebJsApiConfig, MpWebJsApiOptions } from './types';
import { mpWebOnMessage, mpWebPostMessage } from './mpWebBridge';
export declare function mpWebCall<T extends keyof MPApi>(api: T | ({} & string), options?: MpWebJsApiOptions<T>, config?: MpWebJsApiConfig): void;
export declare namespace mpWebCall {
var onMessage: typeof mpWebOnMessage;
var postMessage: typeof mpWebPostMessage;
var broadcastGlobalData: (key: string, payload: any) => void;
var onReceiveGlobalData: (key: string, callback: (data: any, form: string) => void) => () => void;
var onPageEvent: (event: ({} & string) | "onShow" | "onHide" | "onTitleClick" | "onOptionMenuClick" | "onTabItemTap", callback: (data: any) => void) => () => void;
}

@@ -1,37 +0,24 @@

var loadAppxBridge = function loadAppxBridge(cb) {
import { mpWebOnMessage, mpWebPostMessage } from "./mpWebBridge";
// 关联 postMessage 和 onMessage,根据 serialId 执行回调
var callMap = {};
// 注册 jsapi 的 message 处理器
mpWebOnMessage(function (msg) {
var _a;
try {
// umd 包用的 IFF 模式,会立即向 window.my 上注入 jsapi,所以不能使用 window.my 判断是否已经加载了 appx 脚本
// umd 版本和 modules 版本不能混用
if ((_a = window.my) === null || _a === void 0 ? void 0 : _a.__hy_mounted__) {
cb && cb("ready" /* BridgeReady.READY */);
return;
}
var hyMy_1 = window.my || {};
var script_1 = document.createElement('script');
script_1.src = 'https://appx/web-view.min.js';
script_1.onload = function onload() {
var readyState = script_1['readyState'];
if (typeof readyState === 'undefined' || /^(loaded|complete)$/.test(readyState)) {
script_1.onload = null;
Object.assign(window.my, hyMy_1, {
__hy_mounted__: true
});
cb && cb("loaded" /* BridgeReady.LOADED */);
}
};
var head = document.getElementsByTagName('head')[0] || document.body;
head.appendChild(script_1);
} catch (e) {
cb && cb(null);
}
};
var callbackFn = function callbackFn(res, callback) {
var _a = callback || {},
success = _a.success,
fail = _a.fail,
complete = _a.complete;
var _b = res || {},
_data_ = _b._data_,
_type_ = _b._type_;
var message = msg;
var serialId = message.serialId;
// 不是 jsapi 的调用的消息
if (message.type !== 'apiCall') return;
if (!serialId) return;
if (!callMap[serialId]) return;
var callback = callMap[serialId];
var data = message.result;
var type = (_a = message.config) === null || _a === void 0 ? void 0 : _a.type; // JsApi 的类型
if (type === 'callback') return callback(data);
var _b = callback || {},
success = _b.success,
fail = _b.fail,
complete = _b.complete;
var _c = data || {},
_data_ = _c._data_,
_type_ = _c._type_;
// 新版本协议

@@ -41,79 +28,74 @@ if (_type_) {

if (_type_ === 'fail') fail === null || fail === void 0 ? void 0 : fail(_data_);
return complete === null || complete === void 0 ? void 0 : complete(_data_);
}
// 下面兼容老版本(老版本消息识别不明确,导致 H5 中走 success/fail 逻辑可能岔了)
// @ts-ignore
if (res === null || res === void 0 ? void 0 : res.error) {
fail === null || fail === void 0 ? void 0 : fail(res);
complete === null || complete === void 0 ? void 0 : complete(_data_);
} else {
success === null || success === void 0 ? void 0 : success(res);
// 下面兼容老版本(老版本消息识别不明确,导致 H5 中走 success/fail 逻辑可能岔了)
// @ts-ignore
if (data === null || data === void 0 ? void 0 : data.error) {
fail === null || fail === void 0 ? void 0 : fail(data);
} else {
success === null || success === void 0 ? void 0 : success(data);
}
complete === null || complete === void 0 ? void 0 : complete(data);
}
complete === null || complete === void 0 ? void 0 : complete(res);
};
export var mpWebCall = function () {
var callMap = {};
var WAITING_QUEUE = [];
var isListening = false;
function onMessage() {
var messageHandler = window.my.onMessage;
window.my.onMessage = function (message) {
var _a;
var serialId = message.serialId;
var data = message.result;
var type = (_a = message.config) === null || _a === void 0 ? void 0 : _a.type; // JsApi 的类型
if (serialId) {
var callback = callMap[serialId];
if (!callback) return;
if (type === 'callback') {
callback(data);
} else {
callbackFn(data, callback);
delete callMap[serialId];
}
} else if (messageHandler) {
messageHandler(message);
}
};
delete callMap[serialId];
});
export function mpWebCall(api, options, config) {
var random = Math.floor(Math.random() * 1000000);
var serialId = api + '_' + random;
// 只调用,没有参数,不需要接收 jsapi 执行结果
if (options) {
callMap[serialId] = options;
}
function fireMessage(_a) {
var api = _a.api,
options = _a.options,
config = _a.config;
var random = Math.floor(Math.random() * 1000000);
var serialId = api + '_' + random;
if (options) {
callMap[serialId] = options;
var message = {
source: 'hylid',
type: 'apiCall',
api: api,
serialId: serialId,
options: options,
config: config
};
mpWebPostMessage(message);
}
function broadcastGlobalData(key, payload) {
var message = {
source: 'hylid',
type: 'broadcast',
from: window.location.href,
result: {
key: key,
payload: payload
}
var params = {
source: 'hylid',
type: 'apiCall',
api: api,
serialId: serialId,
options: options,
config: config
};
window.my.postMessage(params);
}
return function call(api, options, config) {
loadAppxBridge(function (bridgeReady) {
var params = {
api: api,
options: options,
config: config
};
if (bridgeReady) {
if (!isListening) {
onMessage();
isListening = true;
}
if (WAITING_QUEUE.length) {
WAITING_QUEUE.forEach(fireMessage);
WAITING_QUEUE = [];
}
fireMessage(params);
} else {
WAITING_QUEUE.push(params);
}
});
};
}();
mpWebPostMessage(message);
}
function onReceiveGlobalData(key, callback) {
return mpWebOnMessage(function (msg) {
var _a, _b;
var message = msg;
if (message.source !== 'hylid') return;
if (message.type !== 'broadcast') return;
// 不是接收的目标消息
if (((_a = message.result) === null || _a === void 0 ? void 0 : _a.key) !== key) return;
callback((_b = message.result) === null || _b === void 0 ? void 0 : _b.payload, message.from);
});
}
function onPageEvent(event, callback) {
// 告诉小程序侧,监听 event 事件
mpWebPostMessage({
source: 'hylid',
type: 'pageEvent',
event: event
});
return mpWebOnMessage(function (msg) {
var message = msg;
if (message.source !== 'hylid') return;
if (message.type !== 'pageEvent') return;
if (message.event !== event) return;
callback(message.result);
});
}
mpWebCall.onMessage = mpWebOnMessage;
mpWebCall.postMessage = mpWebPostMessage;
mpWebCall.broadcastGlobalData = broadcastGlobalData;
mpWebCall.onReceiveGlobalData = onReceiveGlobalData;
mpWebCall.onPageEvent = onPageEvent;

@@ -1,2 +0,2 @@

import { JsApiType, MPApi } from '@hylid/types';
import { JsApiType, MPApi, PickMPArgs, PickMpReturns } from '@hylid/types';
export declare type JsApi = keyof MPApi;

@@ -7,7 +7,7 @@ export interface MpWebJsApiConfig {

export declare type Config = MpWebJsApiConfig;
export interface MpWebMessageResult {
export interface MpWebJsApiMessageResult {
_type_: 'success' | 'fail';
_data_: any;
}
export interface MpWebMessage {
export interface MpWebJsApiMessage {
source: 'hylid';

@@ -19,4 +19,23 @@ type: 'apiCall';

config?: MpWebJsApiConfig;
result?: MpWebMessageResult;
result?: MpWebJsApiMessageResult;
}
export declare type JsApiInfo = Pick<MpWebMessage, 'api' | 'options' | 'config'>;
export interface MpWebBroadcastMessage {
source: 'hylid';
type: 'broadcast';
from: string;
result?: {
key: string;
payload: any;
};
}
export interface MpWebPageEventMessage {
source: 'hylid';
type: 'pageEvent';
event: 'onShow' | 'onHide' | 'onTitleClick' | 'onOptionMenuClick' | 'onTabItemTap' | ({} & string);
result?: any;
}
export declare type Message = MpWebJsApiMessage | MpWebBroadcastMessage | MpWebPageEventMessage;
export declare type MessageHandler = (message: Message) => void;
declare type Callback<T> = (result?: T) => void;
export declare type MpWebJsApiOptions<T extends keyof MPApi> = PickMPArgs<T> | Callback<PickMpReturns<T>>;
export {};
/// <reference types="miniprogram" />
import { MpWebMessage } from './types';
import { Message, MessageHandler, MpWebBroadcastMessage, MpWebJsApiMessage, MpWebPageEventMessage } from './types';
interface Config {
/** 允许调用 jsApi 的白名单 */
whitelist?: string[];
/** 禁止调用 jsApi 的黑名单 */
blacklist?: string[];
/** 自定义 jsApi [ 优先级比较高,可以覆盖原生的 jsApi ] */
customApi?: CustomApi;

@@ -17,9 +20,20 @@ }

config: Config;
constructor(ctx: WebViewContext, config?: Config);
context: any;
MESSAGE_HANDLER: MessageHandler[];
/**
*
* @param webviewId webview 组件的 id,可传字符串,或者 my.createWebViewContext 创建出的实例
* @param config Config 配置
* @param context 页面上下文,传 this 即可。传入后,H5 侧可以使用广播、可以监听页面事件
*/
constructor(webviewId: string | WebViewContext, config?: Config, context?: any);
listen: (data: {
detail: MpWebMessage;
}) => Promise<true | undefined>;
detail: Message;
}) => void;
isAllowed(api: string): boolean;
handleApi: (data: MpWebMessage) => Promise<unknown>;
jsApiHandler: (command: MpWebJsApiMessage) => void;
broadcastHandler: (data: MpWebBroadcastMessage) => void;
pageEventHandler: (data: MpWebPageEventMessage) => void;
bindCtxEvent(event: string, callback: (...rest: any) => void): void;
}
export {};

@@ -11,119 +11,11 @@ var __assign = this && this.__assign || function () {

};
var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function (resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = this && this.__generator || function (thisArg, body) {
var _ = {
label: 0,
sent: function sent() {
if (t[0] & 1) throw t[1];
return t[1];
},
trys: [],
ops: []
},
f,
y,
t,
g;
return g = {
next: verb(0),
"throw": verb(1),
"return": verb(2)
}, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
return this;
}), g;
function verb(n) {
return function (v) {
return step([n, v]);
};
}
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return {
value: op[1],
done: false
};
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2]) _.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
} catch (e) {
op = [6, e];
y = 0;
} finally {
f = t = 0;
}
if (op[0] & 5) throw op[1];
return {
value: op[0] ? op[1] : void 0,
done: true
};
}
};
var broadcastTargets = [];
var WebViewBridge = /** @class */function () {
function WebViewBridge(ctx, config) {
/**
*
* @param webviewId webview 组件的 id,可传字符串,或者 my.createWebViewContext 创建出的实例
* @param config Config 配置
* @param context 页面上下文,传 this 即可。传入后,H5 侧可以使用广播、可以监听页面事件
*/
function WebViewBridge(webviewId, config, context) {
if (config === void 0) {

@@ -134,98 +26,153 @@ config = {};

this.config = {};
this.MESSAGE_HANDLER = [];
this.listen = function (data) {
return __awaiter(_this, void 0, void 0, function () {
var command, config, api, type, notAllowedMessage;
var _this = this;
return __generator(this, function (_a) {
command = data.detail;
if (command.source === 'hylid') {
config = command.config, api = command.api;
type = (config || {}).type;
// 权限管控不允许调用 JSAPI
if (!this.isAllowed(api)) {
notAllowedMessage = __assign(__assign({}, command), {
result: {
_type_: 'fail',
_data_: {
errorCode: -2,
errorMessage: 'api is not allowed'
}
}
if (data.detail.source !== 'hylid') return;
_this.MESSAGE_HANDLER.forEach(function (fn) {
return fn(data.detail);
});
};
this.jsApiHandler = function (command) {
if (command.type !== 'apiCall') return;
var getApiResult = function getApiResult(data) {
var api = data.api,
_options = data.options,
config = data.config;
var _a = (config || {}).type,
type = _a === void 0 ? 'async' : _a;
return new Promise(function (resolve) {
var _a;
var options = __assign(__assign({}, _options), {
success: function success(res) {
resolve({
_type_: 'success',
_data_: res
});
this.webview.postMessage(notAllowedMessage);
return [2 /*return*/];
},
fail: function fail(res) {
resolve({
_type_: 'fail',
_data_: res
});
}
if (type === 'callback') {
});
// @ts-ignore
var mpApi = ((_a = _this.config.customApi) === null || _a === void 0 ? void 0 : _a[api]) || my[api];
if (type === 'sync') {
var data_1 = mpApi(_options);
resolve({
_type_: 'success',
_data_: data_1
});
}
if (type === 'async') {
if (!mpApi) {
// @ts-ignore
my[api](function (result) {
_this.webview.postMessage(__assign(__assign({}, command), {
result: result
}));
});
my.call(api, options);
} else {
this.handleApi(command).then(function (result) {
_this.webview.postMessage(__assign(__assign({}, command), {
result: result
}));
});
mpApi(options);
}
// 表示被 hylid-bridge 消费了
return [2 /*return*/, true];
}
return [2 /*return*/];
});
});
};
this.handleApi = function (data) {
var api = data.api,
_options = data.options,
config = data.config;
var _a = (config || {}).type,
type = _a === void 0 ? 'async' : _a;
return new Promise(function (resolve) {
var _a;
var options = __assign(__assign({}, _options), {
success: function success(res) {
resolve({
_type_: 'success',
_data_: res
});
},
fail: function fail(res) {
resolve({
_type_: 'fail',
_data_: res
});
};
var config = command.config,
api = command.api;
var type = (config || {}).type;
// 权限管控不允许调用 JSAPI
if (!_this.isAllowed(api)) {
var notAllowedMessage = __assign(__assign({}, command), {
result: {
_type_: 'fail',
_data_: {
errorCode: -2,
errorMessage: 'api is not allowed'
}
}
});
_this.webview.postMessage(notAllowedMessage);
return;
}
if (type === 'callback') {
// @ts-ignore
var mpApi = ((_a = _this.config.customApi) === null || _a === void 0 ? void 0 : _a[api]) || my[api];
if (type === 'sync') {
var data_1 = mpApi(_options);
resolve({
_type_: 'success',
_data_: data_1
});
}
if (type === 'async') {
if (!mpApi) {
// @ts-ignore
my.call(api, options);
} else {
mpApi(options);
}
}
my[api](function (result) {
_this.webview.postMessage(__assign(__assign({}, command), {
result: result
}));
});
} else {
getApiResult(command).then(function (result) {
_this.webview.postMessage(__assign(__assign({}, command), {
result: result
}));
});
}
};
this.broadcastHandler = function (data) {
if (data.type !== 'broadcast') return;
broadcastTargets.forEach(function (target) {
if (target === _this) return;
target.webview.postMessage(data);
});
};
this.webview = ctx;
this.pageEventHandler = function (data) {
var _a;
if (data.type !== 'pageEvent') return;
var event = data.event;
if (!event) return;
if (!_this.context) {
console.info("[hylid-call]: context \u5728\u5C0F\u7A0B\u5E8F\u4FA7\u672A\u4F20\u5165\uFF0C".concat(event, " \u76D1\u542C\u5931\u8D25"));
return;
}
// 已经监听过了
if ((_a = _this.context[event]) === null || _a === void 0 ? void 0 : _a._hy_listener_) return;
_this.bindCtxEvent(event, function (payload) {
_this.webview.postMessage(__assign(__assign({}, data), {
result: payload
}));
});
_this.context[event]._hy_listener_ = true;
};
if (typeof webviewId === 'string') {
this.webview = my.createWebViewContext(webviewId);
} else {
this.webview = webviewId;
}
this.config = config;
this.context = context;
this.MESSAGE_HANDLER.push(this.jsApiHandler);
this.MESSAGE_HANDLER.push(this.broadcastHandler);
this.MESSAGE_HANDLER.push(this.pageEventHandler);
if (context) {
broadcastTargets.push(this);
this.bindCtxEvent('onUnload', function () {
broadcastTargets = broadcastTargets.filter(function (target) {
return target !== _this;
});
});
} else {
console.info("[hylid-call]: context \u5728\u5C0F\u7A0B\u5E8F\u4FA7\u672A\u4F20\u5165\uFF0Cbroadcast \u529F\u80FD\u3001\u9875\u9762\u76D1\u542C\u5C06\u65E0\u6CD5\u4F7F\u7528");
}
}
WebViewBridge.prototype.isAllowed = function (api) {
var _a = this.config || {},
whitelist = _a.whitelist,
blacklist = _a.blacklist;
// 黑白名单校验
if (this.config.whitelist && !this.config.whitelist.includes(api)) return false;
if (this.config.blacklist && this.config.blacklist.includes(api)) return false;
if (whitelist && !whitelist.includes(api)) return false;
if (blacklist && blacklist.includes(api)) return false;
return true;
};
WebViewBridge.prototype.bindCtxEvent = function (event, callback) {
if (!this.context) return;
var userEvent = this.context[event];
this.context[event] = function () {
var rest = [];
for (var _i = 0; _i < arguments.length; _i++) {
rest[_i] = arguments[_i];
}
if (userEvent) userEvent.apply(void 0, rest);
callback.apply(void 0, rest);
}.bind(this.context);
};
return WebViewBridge;
}();
export { WebViewBridge };
{
"name": "@hylid/call",
"version": "3.2.0-alpha.0",
"version": "3.2.0-alpha.1",
"main": "lib/index.js",

@@ -9,4 +9,4 @@ "files": [

"dependencies": {
"@hylid/env": "^3.2.0-alpha.0",
"@hylid/types": "^3.2.0-alpha.0"
"@hylid/env": "^3.2.0-alpha.1",
"@hylid/types": "^3.2.0-alpha.1"
},

@@ -13,0 +13,0 @@ "publishConfig": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc