parent
2a21352354
commit
69639d5a5e
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Eslint config file
|
||||
* Documentation: https://eslint.org/docs/user-guide/configuring/
|
||||
* Install the Eslint extension before using this feature.
|
||||
*/
|
||||
module.exports = {
|
||||
env: {
|
||||
es6: true,
|
||||
browser: true,
|
||||
node: true,
|
||||
},
|
||||
ecmaFeatures: {
|
||||
modules: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
},
|
||||
globals: {
|
||||
wx: true,
|
||||
App: true,
|
||||
Page: true,
|
||||
getCurrentPages: true,
|
||||
getApp: true,
|
||||
Component: true,
|
||||
requirePlugin: true,
|
||||
requireMiniProgram: true,
|
||||
},
|
||||
// extends: 'eslint:recommended',
|
||||
rules: {},
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
需要安装两个npm依赖
|
||||
npm install mina-request
|
||||
npm i mobx-miniprogram mobx-miniprogram-bindings
|
@ -0,0 +1,57 @@
|
||||
{
|
||||
"pages": [
|
||||
|
||||
"pages/login/login",
|
||||
"pages/upteach/upteach",
|
||||
"pages/addlesson/addlesson",
|
||||
"pages/home/home",
|
||||
"pages/rank/rank",
|
||||
"pages/attend/attend",
|
||||
|
||||
"pages/teacherinfo/teacherinfo",
|
||||
"pages/identify/identify",
|
||||
"pages/index/index",
|
||||
"pages/logs/logs",
|
||||
"pages/mine/mine"
|
||||
],
|
||||
"window": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "classRoll",
|
||||
"navigationBarBackgroundColor": "#ffffff"
|
||||
},
|
||||
"style": "v2",
|
||||
"enablePullDownRefresh":true,
|
||||
"componentFramework": "glass-easel",
|
||||
"sitemapLocation": "sitemap.json",
|
||||
"lazyCodeLoading": "requiredComponents",
|
||||
"tabBar": {
|
||||
"borderStyle":"white",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/home/home",
|
||||
"text": "课程",
|
||||
"color": "#7A7E83",
|
||||
"iconPath": "/images/icon/class.png",
|
||||
"selectedIconPath": "/images/icon/class_selected.png",
|
||||
"selectedColor": "#3cc51f"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/rank/rank",
|
||||
"text": "排行榜",
|
||||
"color": "#7A7E83",
|
||||
"iconPath": "/images/icon/rank.png",
|
||||
"selectedIconPath": "/images/icon/rank_selected.png",
|
||||
"selectedColor": "#3cc51f"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/mine/mine",
|
||||
"text": "我的",
|
||||
"color": "#7A7E83",
|
||||
"iconPath": "/images/icon/user_01.png",
|
||||
"selectedIconPath": "/images/icon/user_01_selected.png",
|
||||
"selectedColor": "#3cc51f"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
/**app.wxss**/
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 200rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
module.exports = (function() {
|
||||
var __MODS__ = {};
|
||||
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
|
||||
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
|
||||
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
|
||||
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
|
||||
__DEFINE__(1728655564987, function(require, module, exports) {
|
||||
|
||||
|
||||
// do not edit .js files directly - edit src/index.jst
|
||||
|
||||
|
||||
|
||||
module.exports = function equal(a, b) {
|
||||
if (a === b) return true;
|
||||
|
||||
if (a && b && typeof a == 'object' && typeof b == 'object') {
|
||||
if (a.constructor !== b.constructor) return false;
|
||||
|
||||
var length, i, keys;
|
||||
if (Array.isArray(a)) {
|
||||
length = a.length;
|
||||
if (length != b.length) return false;
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!equal(a[i], b[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
||||
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
||||
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
||||
|
||||
keys = Object.keys(a);
|
||||
length = keys.length;
|
||||
if (length !== Object.keys(b).length) return false;
|
||||
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
||||
|
||||
for (i = length; i-- !== 0;) {
|
||||
var key = keys[i];
|
||||
|
||||
if (!equal(a[key], b[key])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// true if both NaN, false otherwise
|
||||
return a!==a && b!==b;
|
||||
};
|
||||
|
||||
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
|
||||
return __REQUIRE__(1728655564987);
|
||||
})()
|
||||
//miniprogram-npm-outsideDeps=[]
|
||||
//# sourceMappingURL=index.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["\n\n// do not edit .js files directly - edit src/index.jst\n\n\n\nmodule.exports = function equal(a, b) {\n if (a === b) return true;\n\n if (a && b && typeof a == 'object' && typeof b == 'object') {\n if (a.constructor !== b.constructor) return false;\n\n var length, i, keys;\n if (Array.isArray(a)) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0;)\n if (!equal(a[i], b[i])) return false;\n return true;\n }\n\n\n\n if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;\n if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();\n if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();\n\n keys = Object.keys(a);\n length = keys.length;\n if (length !== Object.keys(b).length) return false;\n\n for (i = length; i-- !== 0;)\n if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;\n\n for (i = length; i-- !== 0;) {\n var key = keys[i];\n\n if (!equal(a[key], b[key])) return false;\n }\n\n return true;\n }\n\n // true if both NaN, false otherwise\n return a!==a && b!==b;\n};\n"]}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,211 @@
|
||||
module.exports = (function() {
|
||||
var __MODS__ = {};
|
||||
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
|
||||
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
|
||||
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
|
||||
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
|
||||
__DEFINE__(1728655564989, function(require, module, exports) {
|
||||
|
||||
module.exports = rfdc
|
||||
|
||||
function copyBuffer (cur) {
|
||||
if (cur instanceof Buffer) {
|
||||
return Buffer.from(cur)
|
||||
}
|
||||
|
||||
return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)
|
||||
}
|
||||
|
||||
function rfdc (opts) {
|
||||
opts = opts || {}
|
||||
if (opts.circles) return rfdcCircles(opts)
|
||||
|
||||
const constructorHandlers = new Map()
|
||||
constructorHandlers.set(Date, (o) => new Date(o))
|
||||
constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))
|
||||
constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))
|
||||
if (opts.constructorHandlers) {
|
||||
for (const handler of opts.constructorHandlers) {
|
||||
constructorHandlers.set(handler[0], handler[1])
|
||||
}
|
||||
}
|
||||
|
||||
let handler = null
|
||||
|
||||
return opts.proto ? cloneProto : clone
|
||||
|
||||
function cloneArray (a, fn) {
|
||||
const keys = Object.keys(a)
|
||||
const a2 = new Array(keys.length)
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const k = keys[i]
|
||||
const cur = a[k]
|
||||
if (typeof cur !== 'object' || cur === null) {
|
||||
a2[k] = cur
|
||||
} else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
|
||||
a2[k] = handler(cur, fn)
|
||||
} else if (ArrayBuffer.isView(cur)) {
|
||||
a2[k] = copyBuffer(cur)
|
||||
} else {
|
||||
a2[k] = fn(cur)
|
||||
}
|
||||
}
|
||||
return a2
|
||||
}
|
||||
|
||||
function clone (o) {
|
||||
if (typeof o !== 'object' || o === null) return o
|
||||
if (Array.isArray(o)) return cloneArray(o, clone)
|
||||
if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
|
||||
return handler(o, clone)
|
||||
}
|
||||
const o2 = {}
|
||||
for (const k in o) {
|
||||
if (Object.hasOwnProperty.call(o, k) === false) continue
|
||||
const cur = o[k]
|
||||
if (typeof cur !== 'object' || cur === null) {
|
||||
o2[k] = cur
|
||||
} else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
|
||||
o2[k] = handler(cur, clone)
|
||||
} else if (ArrayBuffer.isView(cur)) {
|
||||
o2[k] = copyBuffer(cur)
|
||||
} else {
|
||||
o2[k] = clone(cur)
|
||||
}
|
||||
}
|
||||
return o2
|
||||
}
|
||||
|
||||
function cloneProto (o) {
|
||||
if (typeof o !== 'object' || o === null) return o
|
||||
if (Array.isArray(o)) return cloneArray(o, cloneProto)
|
||||
if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
|
||||
return handler(o, cloneProto)
|
||||
}
|
||||
const o2 = {}
|
||||
for (const k in o) {
|
||||
const cur = o[k]
|
||||
if (typeof cur !== 'object' || cur === null) {
|
||||
o2[k] = cur
|
||||
} else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
|
||||
o2[k] = handler(cur, cloneProto)
|
||||
} else if (ArrayBuffer.isView(cur)) {
|
||||
o2[k] = copyBuffer(cur)
|
||||
} else {
|
||||
o2[k] = cloneProto(cur)
|
||||
}
|
||||
}
|
||||
return o2
|
||||
}
|
||||
}
|
||||
|
||||
function rfdcCircles (opts) {
|
||||
const refs = []
|
||||
const refsNew = []
|
||||
|
||||
const constructorHandlers = new Map()
|
||||
constructorHandlers.set(Date, (o) => new Date(o))
|
||||
constructorHandlers.set(Map, (o, fn) => new Map(cloneArray(Array.from(o), fn)))
|
||||
constructorHandlers.set(Set, (o, fn) => new Set(cloneArray(Array.from(o), fn)))
|
||||
if (opts.constructorHandlers) {
|
||||
for (const handler of opts.constructorHandlers) {
|
||||
constructorHandlers.set(handler[0], handler[1])
|
||||
}
|
||||
}
|
||||
|
||||
let handler = null
|
||||
return opts.proto ? cloneProto : clone
|
||||
|
||||
function cloneArray (a, fn) {
|
||||
const keys = Object.keys(a)
|
||||
const a2 = new Array(keys.length)
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const k = keys[i]
|
||||
const cur = a[k]
|
||||
if (typeof cur !== 'object' || cur === null) {
|
||||
a2[k] = cur
|
||||
} else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
|
||||
a2[k] = handler(cur, fn)
|
||||
} else if (ArrayBuffer.isView(cur)) {
|
||||
a2[k] = copyBuffer(cur)
|
||||
} else {
|
||||
const index = refs.indexOf(cur)
|
||||
if (index !== -1) {
|
||||
a2[k] = refsNew[index]
|
||||
} else {
|
||||
a2[k] = fn(cur)
|
||||
}
|
||||
}
|
||||
}
|
||||
return a2
|
||||
}
|
||||
|
||||
function clone (o) {
|
||||
if (typeof o !== 'object' || o === null) return o
|
||||
if (Array.isArray(o)) return cloneArray(o, clone)
|
||||
if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
|
||||
return handler(o, clone)
|
||||
}
|
||||
const o2 = {}
|
||||
refs.push(o)
|
||||
refsNew.push(o2)
|
||||
for (const k in o) {
|
||||
if (Object.hasOwnProperty.call(o, k) === false) continue
|
||||
const cur = o[k]
|
||||
if (typeof cur !== 'object' || cur === null) {
|
||||
o2[k] = cur
|
||||
} else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
|
||||
o2[k] = handler(cur, clone)
|
||||
} else if (ArrayBuffer.isView(cur)) {
|
||||
o2[k] = copyBuffer(cur)
|
||||
} else {
|
||||
const i = refs.indexOf(cur)
|
||||
if (i !== -1) {
|
||||
o2[k] = refsNew[i]
|
||||
} else {
|
||||
o2[k] = clone(cur)
|
||||
}
|
||||
}
|
||||
}
|
||||
refs.pop()
|
||||
refsNew.pop()
|
||||
return o2
|
||||
}
|
||||
|
||||
function cloneProto (o) {
|
||||
if (typeof o !== 'object' || o === null) return o
|
||||
if (Array.isArray(o)) return cloneArray(o, cloneProto)
|
||||
if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor))) {
|
||||
return handler(o, cloneProto)
|
||||
}
|
||||
const o2 = {}
|
||||
refs.push(o)
|
||||
refsNew.push(o2)
|
||||
for (const k in o) {
|
||||
const cur = o[k]
|
||||
if (typeof cur !== 'object' || cur === null) {
|
||||
o2[k] = cur
|
||||
} else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {
|
||||
o2[k] = handler(cur, cloneProto)
|
||||
} else if (ArrayBuffer.isView(cur)) {
|
||||
o2[k] = copyBuffer(cur)
|
||||
} else {
|
||||
const i = refs.indexOf(cur)
|
||||
if (i !== -1) {
|
||||
o2[k] = refsNew[i]
|
||||
} else {
|
||||
o2[k] = cloneProto(cur)
|
||||
}
|
||||
}
|
||||
}
|
||||
refs.pop()
|
||||
refsNew.pop()
|
||||
return o2
|
||||
}
|
||||
}
|
||||
|
||||
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
|
||||
return __REQUIRE__(1728655564989);
|
||||
})()
|
||||
//miniprogram-npm-outsideDeps=[]
|
||||
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "classRoll",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"node_modules/mina-request": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/mina-request/-/mina-request-1.0.8.tgz",
|
||||
"integrity": "sha512-IzsnzZEAJOyQnYMKhut7+m6EygiiZOd5yvspNplVlVT026ucaaJrie92k0K0Umw0jkASvJn1WXjSq+FntYj/GQ=="
|
||||
},
|
||||
"node_modules/miniprogram-api-typings": {
|
||||
"version": "3.12.3",
|
||||
"resolved": "https://registry.npmmirror.com/miniprogram-api-typings/-/miniprogram-api-typings-3.12.3.tgz",
|
||||
"integrity": "sha512-o7bOfrU28MEMCBWo83nXv0ROQSBFxJcfCl4f2wTYqah64ipC5RGqLJfvWJTWhlQt2ECVwspSzM8LgvnfMo7TEQ=="
|
||||
},
|
||||
"node_modules/miniprogram-computed": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/miniprogram-computed/-/miniprogram-computed-5.1.0.tgz",
|
||||
"integrity": "sha512-sA2Kx9N8xYnZtOlZogSzCUdy+e6wTztnnAzbY2yRksdXL5Zo2Zs2BGzHMTLvn1JlDyyS5K9QD0L4ksohfxNOYg==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"miniprogram-api-typings": "^3.12.2",
|
||||
"rfdc": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/mobx-miniprogram": {
|
||||
"version": "6.12.3",
|
||||
"resolved": "https://registry.npmmirror.com/mobx-miniprogram/-/mobx-miniprogram-6.12.3.tgz",
|
||||
"integrity": "sha512-GEq1EG7jZPnrHYV43oppa6jY9lgbNRuGPiXyOFRoluHjd5LIGBf3a+zXMjzO1AVwrFOWvVRazxtzfiRXMUUqZw==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mobx"
|
||||
}
|
||||
},
|
||||
"node_modules/mobx-miniprogram-bindings": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/mobx-miniprogram-bindings/-/mobx-miniprogram-bindings-4.0.1.tgz",
|
||||
"integrity": "sha512-K2abvA+tGdEj70SD0hPEGCwTUgMLCZhdgHxO17B18TN5GhGNlUnj09BwXauqdWONwq4OuODYCrZwjAIadPQXFw==",
|
||||
"peerDependencies": {
|
||||
"mobx-miniprogram": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
|
||||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Evgeny Poberezkin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,96 @@
|
||||
# fast-deep-equal
|
||||
The fastest deep equal with ES6 Map, Set and Typed arrays support.
|
||||
|
||||
[![Build Status](https://travis-ci.org/epoberezkin/fast-deep-equal.svg?branch=master)](https://travis-ci.org/epoberezkin/fast-deep-equal)
|
||||
[![npm](https://img.shields.io/npm/v/fast-deep-equal.svg)](https://www.npmjs.com/package/fast-deep-equal)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/epoberezkin/fast-deep-equal/badge.svg?branch=master)](https://coveralls.io/github/epoberezkin/fast-deep-equal?branch=master)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install fast-deep-equal
|
||||
```
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- ES5 compatible
|
||||
- works in node.js (8+) and browsers (IE9+)
|
||||
- checks equality of Date and RegExp objects by value.
|
||||
|
||||
ES6 equal (`require('fast-deep-equal/es6')`) also supports:
|
||||
- Maps
|
||||
- Sets
|
||||
- Typed arrays
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var equal = require('fast-deep-equal');
|
||||
console.log(equal({foo: 'bar'}, {foo: 'bar'})); // true
|
||||
```
|
||||
|
||||
To support ES6 Maps, Sets and Typed arrays equality use:
|
||||
|
||||
```javascript
|
||||
var equal = require('fast-deep-equal/es6');
|
||||
console.log(equal(Int16Array([1, 2]), Int16Array([1, 2]))); // true
|
||||
```
|
||||
|
||||
To use with React (avoiding the traversal of React elements' _owner
|
||||
property that contains circular references and is not needed when
|
||||
comparing the elements - borrowed from [react-fast-compare](https://github.com/FormidableLabs/react-fast-compare)):
|
||||
|
||||
```javascript
|
||||
var equal = require('fast-deep-equal/react');
|
||||
var equal = require('fast-deep-equal/es6/react');
|
||||
```
|
||||
|
||||
|
||||
## Performance benchmark
|
||||
|
||||
Node.js v12.6.0:
|
||||
|
||||
```
|
||||
fast-deep-equal x 261,950 ops/sec ±0.52% (89 runs sampled)
|
||||
fast-deep-equal/es6 x 212,991 ops/sec ±0.34% (92 runs sampled)
|
||||
fast-equals x 230,957 ops/sec ±0.83% (85 runs sampled)
|
||||
nano-equal x 187,995 ops/sec ±0.53% (88 runs sampled)
|
||||
shallow-equal-fuzzy x 138,302 ops/sec ±0.49% (90 runs sampled)
|
||||
underscore.isEqual x 74,423 ops/sec ±0.38% (89 runs sampled)
|
||||
lodash.isEqual x 36,637 ops/sec ±0.72% (90 runs sampled)
|
||||
deep-equal x 2,310 ops/sec ±0.37% (90 runs sampled)
|
||||
deep-eql x 35,312 ops/sec ±0.67% (91 runs sampled)
|
||||
ramda.equals x 12,054 ops/sec ±0.40% (91 runs sampled)
|
||||
util.isDeepStrictEqual x 46,440 ops/sec ±0.43% (90 runs sampled)
|
||||
assert.deepStrictEqual x 456 ops/sec ±0.71% (88 runs sampled)
|
||||
|
||||
The fastest is fast-deep-equal
|
||||
```
|
||||
|
||||
To run benchmark (requires node.js 6+):
|
||||
|
||||
```bash
|
||||
npm run benchmark
|
||||
```
|
||||
|
||||
__Please note__: this benchmark runs against the available test cases. To choose the most performant library for your application, it is recommended to benchmark against your data and to NOT expect this benchmark to reflect the performance difference in your application.
|
||||
|
||||
|
||||
## Enterprise support
|
||||
|
||||
fast-deep-equal package is a part of [Tidelift enterprise subscription](https://tidelift.com/subscription/pkg/npm-fast-deep-equal?utm_source=npm-fast-deep-equal&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) - it provides a centralised commercial support to open-source software users, in addition to the support provided by software maintainers.
|
||||
|
||||
|
||||
## Security contact
|
||||
|
||||
To report a security vulnerability, please use the
|
||||
[Tidelift security contact](https://tidelift.com/security).
|
||||
Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerability via GitHub issues.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/epoberezkin/fast-deep-equal/blob/master/LICENSE)
|
@ -0,0 +1,2 @@
|
||||
declare const equal: (a: any, b: any) => boolean;
|
||||
export = equal;
|
@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
|
||||
// do not edit .js files directly - edit src/index.jst
|
||||
|
||||
|
||||
var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';
|
||||
|
||||
|
||||
module.exports = function equal(a, b) {
|
||||
if (a === b) return true;
|
||||
|
||||
if (a && b && typeof a == 'object' && typeof b == 'object') {
|
||||
if (a.constructor !== b.constructor) return false;
|
||||
|
||||
var length, i, keys;
|
||||
if (Array.isArray(a)) {
|
||||
length = a.length;
|
||||
if (length != b.length) return false;
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!equal(a[i], b[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if ((a instanceof Map) && (b instanceof Map)) {
|
||||
if (a.size !== b.size) return false;
|
||||
for (i of a.entries())
|
||||
if (!b.has(i[0])) return false;
|
||||
for (i of a.entries())
|
||||
if (!equal(i[1], b.get(i[0]))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((a instanceof Set) && (b instanceof Set)) {
|
||||
if (a.size !== b.size) return false;
|
||||
for (i of a.entries())
|
||||
if (!b.has(i[0])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
||||
length = a.length;
|
||||
if (length != b.length) return false;
|
||||
for (i = length; i-- !== 0;)
|
||||
if (a[i] !== b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
||||
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
||||
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
||||
|
||||
keys = Object.keys(a);
|
||||
length = keys.length;
|
||||
if (length !== Object.keys(b).length) return false;
|
||||
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
||||
|
||||
for (i = length; i-- !== 0;) {
|
||||
var key = keys[i];
|
||||
|
||||
if (!equal(a[key], b[key])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// true if both NaN, false otherwise
|
||||
return a!==a && b!==b;
|
||||
};
|
@ -0,0 +1,2 @@
|
||||
declare const equal: (a: any, b: any) => boolean;
|
||||
export = equal;
|
@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
// do not edit .js files directly - edit src/index.jst
|
||||
|
||||
|
||||
var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';
|
||||
|
||||
|
||||
module.exports = function equal(a, b) {
|
||||
if (a === b) return true;
|
||||
|
||||
if (a && b && typeof a == 'object' && typeof b == 'object') {
|
||||
if (a.constructor !== b.constructor) return false;
|
||||
|
||||
var length, i, keys;
|
||||
if (Array.isArray(a)) {
|
||||
length = a.length;
|
||||
if (length != b.length) return false;
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!equal(a[i], b[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if ((a instanceof Map) && (b instanceof Map)) {
|
||||
if (a.size !== b.size) return false;
|
||||
for (i of a.entries())
|
||||
if (!b.has(i[0])) return false;
|
||||
for (i of a.entries())
|
||||
if (!equal(i[1], b.get(i[0]))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((a instanceof Set) && (b instanceof Set)) {
|
||||
if (a.size !== b.size) return false;
|
||||
for (i of a.entries())
|
||||
if (!b.has(i[0])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
||||
length = a.length;
|
||||
if (length != b.length) return false;
|
||||
for (i = length; i-- !== 0;)
|
||||
if (a[i] !== b[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
||||
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
||||
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
||||
|
||||
keys = Object.keys(a);
|
||||
length = keys.length;
|
||||
if (length !== Object.keys(b).length) return false;
|
||||
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
||||
|
||||
for (i = length; i-- !== 0;) {
|
||||
var key = keys[i];
|
||||
|
||||
if (key === '_owner' && a.$$typeof) {
|
||||
// React-specific: avoid traversing React elements' _owner.
|
||||
// _owner contains circular references
|
||||
// and is not needed when comparing the actual elements (and not their owners)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!equal(a[key], b[key])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// true if both NaN, false otherwise
|
||||
return a!==a && b!==b;
|
||||
};
|
@ -0,0 +1,4 @@
|
||||
declare module 'fast-deep-equal' {
|
||||
const equal: (a: any, b: any) => boolean;
|
||||
export = equal;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
// do not edit .js files directly - edit src/index.jst
|
||||
|
||||
|
||||
|
||||
module.exports = function equal(a, b) {
|
||||
if (a === b) return true;
|
||||
|
||||
if (a && b && typeof a == 'object' && typeof b == 'object') {
|
||||
if (a.constructor !== b.constructor) return false;
|
||||
|
||||
var length, i, keys;
|
||||
if (Array.isArray(a)) {
|
||||
length = a.length;
|
||||
if (length != b.length) return false;
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!equal(a[i], b[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
||||
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
||||
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
||||
|
||||
keys = Object.keys(a);
|
||||
length = keys.length;
|
||||
if (length !== Object.keys(b).length) return false;
|
||||
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
||||
|
||||
for (i = length; i-- !== 0;) {
|
||||
var key = keys[i];
|
||||
|
||||
if (!equal(a[key], b[key])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// true if both NaN, false otherwise
|
||||
return a!==a && b!==b;
|
||||
};
|
@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "fast-deep-equal",
|
||||
"version": "3.1.3",
|
||||
"description": "Fast deep equal",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"eslint": "eslint *.js benchmark/*.js spec/*.js",
|
||||
"build": "node build",
|
||||
"benchmark": "npm i && npm run build && cd ./benchmark && npm i && node ./",
|
||||
"test-spec": "mocha spec/*.spec.js -R spec",
|
||||
"test-cov": "nyc npm run test-spec",
|
||||
"test-ts": "tsc --target ES5 --noImplicitAny index.d.ts",
|
||||
"test": "npm run build && npm run eslint && npm run test-ts && npm run test-cov",
|
||||
"prepublish": "npm run build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/epoberezkin/fast-deep-equal.git"
|
||||
},
|
||||
"keywords": [
|
||||
"fast",
|
||||
"equal",
|
||||
"deep-equal"
|
||||
],
|
||||
"author": "Evgeny Poberezkin",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/epoberezkin/fast-deep-equal/issues"
|
||||
},
|
||||
"homepage": "https://github.com/epoberezkin/fast-deep-equal#readme",
|
||||
"devDependencies": {
|
||||
"coveralls": "^3.1.0",
|
||||
"dot": "^1.1.2",
|
||||
"eslint": "^7.2.0",
|
||||
"mocha": "^7.2.0",
|
||||
"nyc": "^15.1.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"react": "^16.12.0",
|
||||
"react-test-renderer": "^16.12.0",
|
||||
"sinon": "^9.0.2",
|
||||
"typescript": "^3.9.5"
|
||||
},
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
"**/spec/**",
|
||||
"node_modules"
|
||||
],
|
||||
"reporter": [
|
||||
"lcov",
|
||||
"text-summary"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"react.js",
|
||||
"react.d.ts",
|
||||
"es6/"
|
||||
],
|
||||
"types": "index.d.ts"
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
declare const equal: (a: any, b: any) => boolean;
|
||||
export = equal;
|
@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
// do not edit .js files directly - edit src/index.jst
|
||||
|
||||
|
||||
|
||||
module.exports = function equal(a, b) {
|
||||
if (a === b) return true;
|
||||
|
||||
if (a && b && typeof a == 'object' && typeof b == 'object') {
|
||||
if (a.constructor !== b.constructor) return false;
|
||||
|
||||
var length, i, keys;
|
||||
if (Array.isArray(a)) {
|
||||
length = a.length;
|
||||
if (length != b.length) return false;
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!equal(a[i], b[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
|
||||
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
|
||||
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
|
||||
|
||||
keys = Object.keys(a);
|
||||
length = keys.length;
|
||||
if (length !== Object.keys(b).length) return false;
|
||||
|
||||
for (i = length; i-- !== 0;)
|
||||
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
|
||||
|
||||
for (i = length; i-- !== 0;) {
|
||||
var key = keys[i];
|
||||
|
||||
if (key === '_owner' && a.$$typeof) {
|
||||
// React-specific: avoid traversing React elements' _owner.
|
||||
// _owner contains circular references
|
||||
// and is not needed when comparing the actual elements (and not their owners)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!equal(a[key], b[key])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// true if both NaN, false otherwise
|
||||
return a!==a && b!==b;
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "mina-request",
|
||||
"version": "1.0.8",
|
||||
"description": "小程序网络请求工具,包含:请求拦截器、响应拦截器、并发请求、文件上传 API 封装等功能",
|
||||
"main": "index.js",
|
||||
"miniprogram": "miniprogram_dist",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": ["wx.request", "wx.uploadFile", "request", "小程序网络请求", "小程序请求"],
|
||||
"author": "zdkhero",
|
||||
"license": "ISC"
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,68 @@
|
||||
# Wechat Mini Program API Typings
|
||||
|
||||
> [中文版本](./README.md)
|
||||
|
||||
[![Published on DefinitelyTyped](https://img.shields.io/npm/v/@types/wechat-miniprogram?label=%40types)](https://www.npmjs.com/package/@types/wechat-miniprogram)
|
||||
[![Published on NPM](https://img.shields.io/npm/v/miniprogram-api-typings.svg?style=flat)](https://www.npmjs.com/package/miniprogram-api-typings)
|
||||
[![MIT License](https://img.shields.io/github/license/wechat-miniprogram/api-typings.svg)](https://github.com/wechat-miniprogram/api-typings)
|
||||
[![GitHub Actions Test Status](https://github.com/wechat-miniprogram/api-typings/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/wechat-miniprogram/api-typings/actions/workflows/test.yml)
|
||||
|
||||
Type definitions for APIs of Wechat Mini Program in TypeScript
|
||||
|
||||
## Install
|
||||
|
||||
### By standalone npm package
|
||||
|
||||
```bash
|
||||
npm install miniprogram-api-typings
|
||||
```
|
||||
|
||||
Manually import it after installed:
|
||||
|
||||
- `import 'miniprogram-api-typings';`
|
||||
|
||||
Or specify types in typescript config:
|
||||
|
||||
- Specify `types: ["miniprogram-api-typings"]` in `tsconfig.json`
|
||||
|
||||
Or reference by [Triple-Slash Directives](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html):
|
||||
|
||||
- `/// <reference path="node_modules/miniprogram-api-typings/index.d.ts" />`
|
||||
|
||||
or:
|
||||
|
||||
### By DefinitelyTyped
|
||||
|
||||
```bash
|
||||
npm install @types/wechat-miniprogram
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
See [CHANGELOG.md](https://github.com/wechat-miniprogram/api-typings/blob/master/CHANGELOG.md) (Chinese only)
|
||||
|
||||
## Contribution
|
||||
|
||||
Definitions of Wechat APIs (`lib.wx.api.d.ts`) are auto-generated together with our [documentations](https://developers.weixin.qq.com/miniprogram/en/dev/api/), therefore PRs including that file will __not__ be merged. If you found some APIs defined wrongly, create an issue instead.
|
||||
|
||||
Both PR and issue are welcomed for definitions of pages (`Page`), custom components (`Component`) and other else, since they are written manually. Help us improve this definition if you have any bug reports or suggestions! Thanks for contributing!
|
||||
|
||||
### Contributors
|
||||
|
||||
- [Baran](https://github.com/baranwang)
|
||||
- [MinLiang Zeng](https://github.com/zenml/)
|
||||
- [Garfield Lee](https://github.com/Garfield550)
|
||||
- [Mr.Hope](https://github.com/Mister-Hope)
|
||||
- [chs97](https://github.com/chs97)
|
||||
- [Jelf](https://github.com/okxiaoliang4)
|
||||
- [xieyuhang](https://github.com/haiya6)
|
||||
- [苏杰豪](https://github.com/Megasu)
|
||||
- [Yang Mingshan](https://github.com/yangmingshan)
|
||||
|
||||
### Automated tests
|
||||
|
||||
We use [`tsd`](https://github.com/SamVerschueren/tsd) to check if this definition is working properly. All test cases are under folder `test`.
|
||||
|
||||
To perform an automated test, clone this repo, `npm install --save-dev` and `npm test`.
|
||||
|
||||
If you have test case that fails the test, an issue or PR will be great. Strong test case that passes are also welcomed.
|
@ -0,0 +1 @@
|
||||
/// <reference path="./types/index.d.ts" />
|
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "miniprogram-api-typings",
|
||||
"version": "3.12.3",
|
||||
"description": "Type definitions for APIs of Wechat Mini Program in TypeScript",
|
||||
"main": "./index.d.ts",
|
||||
"types": "./index.d.ts",
|
||||
"scripts": {
|
||||
"test": "npm run tsd && npm run eslint",
|
||||
"tsd": "tsd",
|
||||
"eslint": "eslint --config .eslintrc.js types/**/*.ts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wechat-miniprogram/api-typings.git"
|
||||
},
|
||||
"author": "Wechat Miniprogram <wx-miniprogram@qq.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/wechat-miniprogram/api-typings/issues"
|
||||
},
|
||||
"homepage": "https://github.com/wechat-miniprogram/api-typings#readme",
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.46.0",
|
||||
"@typescript-eslint/parser": "^5.46.0",
|
||||
"eslint": "^8.29.0",
|
||||
"tsd": "^0.25.0",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"tsd": {
|
||||
"directory": "test"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"CHANGELOG.md",
|
||||
"README.md",
|
||||
"README-en.md",
|
||||
"index.d.ts",
|
||||
"typings.json",
|
||||
"types/"
|
||||
]
|
||||
}
|
@ -0,0 +1 @@
|
||||
/// <reference path="./wx/index.d.ts" />
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,68 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) 2024 Tencent, Inc. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
declare namespace WechatMiniprogram.Behavior {
|
||||
type BehaviorIdentifier = string
|
||||
type Instance<
|
||||
TData extends DataOption,
|
||||
TProperty extends PropertyOption,
|
||||
TMethod extends MethodOption,
|
||||
TCustomInstanceProperty extends IAnyObject = Record<string, never>
|
||||
> = Component.Instance<TData, TProperty, TMethod, TCustomInstanceProperty>
|
||||
type TrivialInstance = Instance<IAnyObject, IAnyObject, IAnyObject>
|
||||
type TrivialOption = Options<IAnyObject, IAnyObject, IAnyObject>
|
||||
type Options<
|
||||
TData extends DataOption,
|
||||
TProperty extends PropertyOption,
|
||||
TMethod extends MethodOption,
|
||||
TCustomInstanceProperty extends IAnyObject = Record<string, never>
|
||||
> = Partial<Data<TData>> &
|
||||
Partial<Property<TProperty>> &
|
||||
Partial<Method<TMethod>> &
|
||||
Partial<OtherOption> &
|
||||
Partial<Lifetimes> &
|
||||
ThisType<Instance<TData, TProperty, TMethod, TCustomInstanceProperty>>
|
||||
interface Constructor {
|
||||
<
|
||||
TData extends DataOption,
|
||||
TProperty extends PropertyOption,
|
||||
TMethod extends MethodOption,
|
||||
TCustomInstanceProperty extends IAnyObject = Record<string, never>
|
||||
>(
|
||||
options: Options<TData, TProperty, TMethod, TCustomInstanceProperty>
|
||||
): BehaviorIdentifier
|
||||
}
|
||||
|
||||
type DataOption = Component.DataOption
|
||||
type PropertyOption = Component.PropertyOption
|
||||
type MethodOption = Component.MethodOption
|
||||
type Data<D extends DataOption> = Component.Data<D>
|
||||
type Property<P extends PropertyOption> = Component.Property<P>
|
||||
type Method<M extends MethodOption> = Component.Method<M>
|
||||
|
||||
type DefinitionFilter = Component.DefinitionFilter
|
||||
type Lifetimes = Component.Lifetimes
|
||||
|
||||
type OtherOption = Omit<Component.OtherOption, 'options'>
|
||||
}
|
||||
/** 注册一个 `behavior`,接受一个 `Object` 类型的参数。*/
|
||||
declare let Behavior: WechatMiniprogram.Behavior.Constructor
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,152 @@
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) 2024 Tencent, Inc. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
***************************************************************************** */
|
||||
|
||||
/** [WXWebAssembly](https://developers.weixin.qq.com/miniprogram/dev/framework/performance/wasm.html)
|
||||
*
|
||||
* WXWebAssembly */
|
||||
declare namespace WXWebAssembly {
|
||||
type BufferSource = ArrayBufferView | ArrayBuffer
|
||||
|
||||
type CompileError = Error
|
||||
|
||||
const CompileError: {
|
||||
prototype: CompileError
|
||||
new (message?: string): CompileError
|
||||
(message?: string): CompileError
|
||||
}
|
||||
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance) */
|
||||
interface Instance {
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance/exports) */
|
||||
readonly exports: Exports
|
||||
}
|
||||
|
||||
const Instance: {
|
||||
prototype: Instance
|
||||
new (module: Module, importObject?: Imports): Instance
|
||||
}
|
||||
|
||||
type LinkError = Error
|
||||
|
||||
const LinkError: {
|
||||
prototype: LinkError
|
||||
new (message?: string): LinkError
|
||||
(message?: string): LinkError
|
||||
}
|
||||
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) */
|
||||
interface Memory {
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/buffer) */
|
||||
readonly buffer: ArrayBuffer
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory/grow) */
|
||||
grow(delta: number): number
|
||||
}
|
||||
|
||||
const Memory: {
|
||||
prototype: Memory
|
||||
new (descriptor: MemoryDescriptor): Memory
|
||||
}
|
||||
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) */
|
||||
interface Module {}
|
||||
|
||||
const Module: {
|
||||
prototype: Module
|
||||
new (bytes: BufferSource): Module
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/customSections) */
|
||||
customSections(moduleObject: Module, sectionName: string): ArrayBuffer[]
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/exports) */
|
||||
exports(moduleObject: Module): ModuleExportDescriptor[]
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module/imports) */
|
||||
imports(moduleObject: Module): ModuleImportDescriptor[]
|
||||
}
|
||||
|
||||
interface RuntimeError extends Error {}
|
||||
|
||||
const RuntimeError: {
|
||||
prototype: RuntimeError
|
||||
new (message?: string): RuntimeError
|
||||
(message?: string): RuntimeError
|
||||
}
|
||||
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table) */
|
||||
interface Table {
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/length) */
|
||||
readonly length: number
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/get) */
|
||||
get(index: number): any
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/grow) */
|
||||
grow(delta: number, value?: any): number
|
||||
/** [MDN Reference](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table/set) */
|
||||
set(index: number, value?: any): void
|
||||
}
|
||||
|
||||
const Table: {
|
||||
prototype: Table
|
||||
new (descriptor: TableDescriptor, value?: any): Table
|
||||
}
|
||||
|
||||
interface MemoryDescriptor {
|
||||
initial: number
|
||||
maximum?: number
|
||||
shared?: boolean
|
||||
}
|
||||
|
||||
interface ModuleExportDescriptor {
|
||||
kind: ImportExportKind
|
||||
name: string
|
||||
}
|
||||
|
||||
interface ModuleImportDescriptor {
|
||||
kind: ImportExportKind
|
||||
module: string
|
||||
name: string
|
||||
}
|
||||
|
||||
interface TableDescriptor {
|
||||
element: TableKind
|
||||
initial: number
|
||||
maximum?: number
|
||||
}
|
||||
|
||||
type ImportExportKind = 'function' | 'global' | 'memory' | 'table'
|
||||
type TableKind = 'anyfunc' | 'externref'
|
||||
type ValueType =
|
||||
| 'anyfunc'
|
||||
| 'externref'
|
||||
| 'f32'
|
||||
| 'f64'
|
||||
| 'i32'
|
||||
| 'i64'
|
||||
| 'v128'
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
type ExportValue = Function | Memory | Table
|
||||
type Exports = Record<string, ExportValue>
|
||||
type ImportValue = ExportValue | number
|
||||
type Imports = Record<string, ModuleImports>
|
||||
type ModuleImports = Record<string, ImportValue>
|
||||
/** [WXWebAssembly](https://developers.weixin.qq.com/miniprogram/dev/framework/performance/wasm.html) */
|
||||
function instantiate(
|
||||
path: string,
|
||||
importObject?: Imports
|
||||
): Promise<Instance>
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "miniprogram-api-typings",
|
||||
"main": "index.d.ts"
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2024 wechat-miniprogram
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,44 @@
|
||||
## 0.0.6
|
||||
|
||||
- 支持 properties。
|
||||
|
||||
## 0.0.7
|
||||
|
||||
- 修复 setData 设置 properties 会报 can't call setData in computed getter function! 问题
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- 基于 observers 重构,开始支持 watch
|
||||
|
||||
## 2.1.0
|
||||
|
||||
- 支持 watch 的 `.**` 语法
|
||||
|
||||
## 3.0.0
|
||||
|
||||
- 修复 computed 中使用自定义 behavior 数据段时,初始化视图的 computed data 不渲染的问题。
|
||||
- 支持 mobx-miniprogram 扩展库。
|
||||
- 更新 computed 数据追踪方式。
|
||||
|
||||
## 4.0.0
|
||||
|
||||
- 使用 TypeScript 重构。
|
||||
- 优化部分生命周期逻辑。
|
||||
|
||||
## 4.1.1
|
||||
|
||||
- 优化打包方式
|
||||
- 优化 dev 开发流程
|
||||
|
||||
## 4.2.x
|
||||
|
||||
- 增加 polyfill
|
||||
|
||||
## 4.3.x
|
||||
|
||||
- 修复引用类型的部分问题
|
||||
|
||||
## 5.0.0
|
||||
|
||||
- 基于 glass-easel 重构
|
||||
- 支持 chaining API
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,83 @@
|
||||
{
|
||||
"name": "miniprogram-computed",
|
||||
"version": "5.1.0",
|
||||
"description": "Computed & watch - wechat miniprogram custom component extend behavior",
|
||||
"main": "dist/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"scripts": {
|
||||
"dev": "gulp dev",
|
||||
"watch": "gulp dev-watch",
|
||||
"build": "gulp",
|
||||
"gen_dts": "gulp dts",
|
||||
"test": "jest ./test/* --bail",
|
||||
"coverage": "jest ./test/* --coverage --bail",
|
||||
"lint": "eslint . --fix"
|
||||
},
|
||||
"miniprogram": "dist",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wechat-miniprogram/computed.git"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"dist",
|
||||
"types",
|
||||
"LICENSE",
|
||||
"package.json",
|
||||
"README.md",
|
||||
"UPDATE.md"
|
||||
],
|
||||
"author": "wechat-miniprogram",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@swc/cli": "^0.3.12",
|
||||
"@swc/core": "^1.5.7",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/rfdc": "^1.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.11.0",
|
||||
"@typescript-eslint/parser": "^7.11.0",
|
||||
"codecov": "^3.8.3",
|
||||
"colors": "^1.4.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-promise": "^6.2.0",
|
||||
"glass-easel": "~0.10.0",
|
||||
"glass-easel-miniprogram-adapter": "~0.10.0",
|
||||
"glass-easel-template-compiler": "~0.10.0",
|
||||
"gulp": "^5.0.0",
|
||||
"gulp-clean": "^0.4.0",
|
||||
"gulp-esbuild": "^0.12.0",
|
||||
"gulp-swc": "^2.1.0",
|
||||
"gulp-typescript": "6.0.0-alpha.1",
|
||||
"gulp-watch": "^5.0.1",
|
||||
"husky": "^9.0.11",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"proxy-polyfill": "^0.3.2",
|
||||
"ts-jest": "^29.1.4",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"miniprogram-api-typings": "^3.12.2",
|
||||
"rfdc": "^1.3.1"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm run lint"
|
||||
}
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"ansi-regex@>2.1.1 <5.0.1": ">=5.0.1",
|
||||
"braces@<2.3.1": ">=2.3.1",
|
||||
"glob-parent@<5.1.2": ">=5.1.2"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,487 @@
|
||||
import rfdc from 'rfdc'
|
||||
import deepEqual from 'fast-deep-equal'
|
||||
import * as dataPath from './data-path'
|
||||
import * as dataTracer from './data-tracer'
|
||||
import type { DataPathWithOptions } from './data-path'
|
||||
import type * as adapter from 'glass-easel-miniprogram-adapter'
|
||||
|
||||
const deepClone = rfdc({ proto: true })
|
||||
|
||||
interface BehaviorData {
|
||||
_computedWatchInit: ComputedWatchInitStatus
|
||||
[k: string]: any
|
||||
}
|
||||
|
||||
interface BehaviorExtend {
|
||||
// original
|
||||
data: BehaviorData
|
||||
setData(d: Record<string, any>): void
|
||||
_computedWatchInfo: Record<string, ComputedWatchInfo>
|
||||
}
|
||||
|
||||
interface ObserversItem {
|
||||
fields: string
|
||||
observer(): void
|
||||
}
|
||||
|
||||
interface ComputedWatchInfo {
|
||||
computedUpdaters: Array<(...args: unknown[]) => boolean>
|
||||
computedRelatedPathValues: Array<Array<dataTracer.RelatedPathValue>>
|
||||
watchCurVal: Array<unknown>
|
||||
_triggerFromComputedAttached: Record<string, boolean>
|
||||
}
|
||||
|
||||
enum ComputedWatchInitStatus {
|
||||
CREATED,
|
||||
ATTACHED,
|
||||
}
|
||||
|
||||
let computedWatchDefIdInc = 0
|
||||
|
||||
function equal(a: unknown, b: unknown) {
|
||||
if (a === b) {
|
||||
return true
|
||||
} else {
|
||||
// When a = b = NaN
|
||||
// NaN === NaN is false
|
||||
return a !== a && b !== b
|
||||
}
|
||||
}
|
||||
|
||||
class ComputedBuilder {
|
||||
observersItems: ObserversItem[] = []
|
||||
private computedWatchDefId = computedWatchDefIdInc++
|
||||
private computedList: Array<[string, (data: Record<string, unknown>) => unknown]> = []
|
||||
private watchList: Array<DataPathWithOptions[]> = []
|
||||
|
||||
constructor() {
|
||||
const computedWatchDefId = this.computedWatchDefId
|
||||
const computedList = this.computedList
|
||||
const watchList = this.watchList
|
||||
this.observersItems.push({
|
||||
fields: '_computedWatchInit',
|
||||
observer(this: BehaviorExtend) {
|
||||
const status = this.data._computedWatchInit
|
||||
if (status === ComputedWatchInitStatus.CREATED) {
|
||||
// init data fields
|
||||
const computedWatchInfo = {
|
||||
computedUpdaters: [],
|
||||
computedRelatedPathValues: new Array(computedList.length),
|
||||
watchCurVal: new Array(watchList.length),
|
||||
_triggerFromComputedAttached: Object.create(null),
|
||||
}
|
||||
if (!this._computedWatchInfo) this._computedWatchInfo = {}
|
||||
this._computedWatchInfo[computedWatchDefId] = computedWatchInfo
|
||||
// handling watch
|
||||
// 1. push to initFuncs
|
||||
watchList.forEach((paths, index) => {
|
||||
// record the original value of watch targets
|
||||
const curVal = paths.map(({ path, options }) => {
|
||||
const val = dataPath.getDataOnPath(this.data, path)
|
||||
return options.deepCmp ? deepClone(val) : val
|
||||
})
|
||||
computedWatchInfo.watchCurVal[index] = curVal
|
||||
})
|
||||
} else if (status === ComputedWatchInitStatus.ATTACHED) {
|
||||
// handling computed
|
||||
// 1. push to initFuncs
|
||||
// 2. push to computedUpdaters
|
||||
const computedWatchInfo = this._computedWatchInfo[computedWatchDefId]
|
||||
computedList.forEach(([targetField, updateMethod], index) => {
|
||||
const relatedPathValuesOnDef = [] as Array<dataTracer.RelatedPathValue>
|
||||
const val = updateMethod(dataTracer.create(this.data, relatedPathValuesOnDef))
|
||||
// here we can do small setDatas
|
||||
// because observer handlers will force grouping small setDatas together
|
||||
this.setData({
|
||||
[targetField]: dataTracer.unwrap(val),
|
||||
})
|
||||
computedWatchInfo._triggerFromComputedAttached[targetField] = true
|
||||
computedWatchInfo.computedRelatedPathValues[index] = relatedPathValuesOnDef
|
||||
|
||||
// will be invoked when setData is called
|
||||
const updateValueAndRelatedPaths = () => {
|
||||
const oldPathValues = computedWatchInfo.computedRelatedPathValues[index]
|
||||
let needUpdate = false
|
||||
// check whether its dependency updated
|
||||
for (let i = 0; i < oldPathValues.length; i++) {
|
||||
const item = oldPathValues[i]
|
||||
if (item.kind === 'keys') {
|
||||
const { path, keys: oldKeys } = item
|
||||
const curVal = dataPath.getDataOnPath(this.data, path)
|
||||
const keys = Object.keys(curVal).sort()
|
||||
if (keys.length !== oldKeys.length) {
|
||||
needUpdate = true
|
||||
break
|
||||
}
|
||||
for (let j = 0; j < keys.length; j += 1) {
|
||||
if (keys[j] !== oldKeys[j]) {
|
||||
needUpdate = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const { path, value: oldVal } = item
|
||||
const curVal = dataPath.getDataOnPath(this.data, path)
|
||||
if (!equal(oldVal, curVal)) {
|
||||
needUpdate = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!needUpdate) return false
|
||||
|
||||
const relatedPathValues = [] as Array<dataTracer.RelatedPathValue>
|
||||
const val = updateMethod(dataTracer.create(this.data, relatedPathValues))
|
||||
this.setData({
|
||||
[targetField]: dataTracer.unwrap(val),
|
||||
})
|
||||
computedWatchInfo.computedRelatedPathValues[index] = relatedPathValues
|
||||
return true
|
||||
}
|
||||
computedWatchInfo.computedUpdaters.push(updateValueAndRelatedPaths)
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
addComputed(targetField: string, updateMethod: (data: Record<string, unknown>) => unknown) {
|
||||
this.computedList.push([targetField, updateMethod])
|
||||
if (this.computedList.length !== 1) return
|
||||
const computedWatchDefId = this.computedWatchDefId
|
||||
this.observersItems.push({
|
||||
fields: '**',
|
||||
observer(this: BehaviorExtend) {
|
||||
if (!this._computedWatchInfo) return
|
||||
const computedWatchInfo = this._computedWatchInfo[computedWatchDefId]
|
||||
if (!computedWatchInfo) return
|
||||
|
||||
let changed: boolean
|
||||
do {
|
||||
try {
|
||||
changed = computedWatchInfo.computedUpdaters.some((func) => func.call(this))
|
||||
} catch (err) {
|
||||
console.error(err.stack)
|
||||
break
|
||||
}
|
||||
} while (changed)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
addWatch(watchPath: string, listener: (args: any) => void) {
|
||||
const paths = dataPath.parseMultiDataPaths(watchPath)
|
||||
const index = this.watchList.length
|
||||
this.watchList.push(paths)
|
||||
const computedWatchDefId = this.computedWatchDefId
|
||||
this.observersItems.push({
|
||||
fields: watchPath,
|
||||
observer(this: BehaviorExtend) {
|
||||
if (!this._computedWatchInfo) return
|
||||
const computedWatchInfo = this._computedWatchInfo[computedWatchDefId]
|
||||
if (!computedWatchInfo) return
|
||||
// (issue #58) ignore watch func when trigger by computed attached
|
||||
if (Object.keys(computedWatchInfo._triggerFromComputedAttached).length) {
|
||||
const pathsMap: Record<string, boolean> = {}
|
||||
paths.forEach((path) => (pathsMap[path.path[0]] = true))
|
||||
for (const computedVal in computedWatchInfo._triggerFromComputedAttached) {
|
||||
if (computedWatchInfo._triggerFromComputedAttached[computedVal]) {
|
||||
if (
|
||||
pathsMap[computedVal] &&
|
||||
computedWatchInfo._triggerFromComputedAttached[computedVal]
|
||||
) {
|
||||
computedWatchInfo._triggerFromComputedAttached[computedVal] = false
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const oldVal = computedWatchInfo.watchCurVal[index]
|
||||
|
||||
// get new watching field value
|
||||
const originalCurValWithOptions = paths.map(({ path, options }) => {
|
||||
const val = dataPath.getDataOnPath(this.data, path)
|
||||
return { val, options }
|
||||
})
|
||||
const curVal = originalCurValWithOptions.map(({ val, options }) =>
|
||||
options.deepCmp ? deepClone(val) : val,
|
||||
)
|
||||
computedWatchInfo.watchCurVal[index] = curVal
|
||||
|
||||
// compare
|
||||
let changed = false
|
||||
for (let i = 0; i < curVal.length; i++) {
|
||||
const options = paths[i].options
|
||||
const deepCmp = options.deepCmp
|
||||
if (deepCmp ? !deepEqual(oldVal[i], curVal[i]) : !equal(oldVal[i], curVal[i])) {
|
||||
changed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// if changed, update
|
||||
if (changed) {
|
||||
listener.apply(
|
||||
this,
|
||||
originalCurValWithOptions.map(({ val }) => val),
|
||||
)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const behavior = Behavior({
|
||||
lifetimes: {
|
||||
attached(this: BehaviorExtend) {
|
||||
this.setData({
|
||||
_computedWatchInit: ComputedWatchInitStatus.ATTACHED,
|
||||
})
|
||||
},
|
||||
created(this: BehaviorExtend) {
|
||||
this.setData({
|
||||
_computedWatchInit: ComputedWatchInitStatus.CREATED,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
definitionFilter(defFields: any & BehaviorExtend) {
|
||||
const computedDef = defFields.computed
|
||||
const watchDef = defFields.watch
|
||||
|
||||
const builder = new ComputedBuilder()
|
||||
if (computedDef) {
|
||||
Object.keys(computedDef).forEach((targetField) => {
|
||||
const updateMethod = computedDef[targetField]
|
||||
builder.addComputed(targetField, updateMethod)
|
||||
})
|
||||
}
|
||||
if (watchDef) {
|
||||
Object.keys(watchDef).forEach((watchPath) => {
|
||||
const listener = watchDef[watchPath]
|
||||
builder.addWatch(watchPath, listener)
|
||||
})
|
||||
}
|
||||
const observersItems = builder.observersItems
|
||||
|
||||
if (typeof defFields.observers !== 'object') {
|
||||
defFields.observers = {}
|
||||
}
|
||||
|
||||
if (Array.isArray(defFields.observers)) {
|
||||
defFields.observers.push(...observersItems)
|
||||
} else {
|
||||
observersItems.forEach((item) => {
|
||||
// defFields.observers[item.fields] = item.observer
|
||||
const f = defFields.observers[item.fields]
|
||||
if (!f) {
|
||||
defFields.observers[item.fields] = item.observer
|
||||
} else {
|
||||
defFields.observers[item.fields] = function () {
|
||||
item.observer.call(this)
|
||||
f.call(this)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const tryInitInCtx = (
|
||||
ctx: adapter.builder.BuilderContext<any, any, any> & { _computedWatchInit?: boolean },
|
||||
) => {
|
||||
if (ctx._computedWatchInit) return
|
||||
ctx._computedWatchInit = true
|
||||
const { lifetime, setData } = ctx
|
||||
lifetime('attached', function () {
|
||||
setData({
|
||||
_computedWatchInit: ComputedWatchInitStatus.ATTACHED,
|
||||
})
|
||||
})
|
||||
lifetime('created', function () {
|
||||
setData({
|
||||
_computedWatchInit: ComputedWatchInitStatus.CREATED,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function computed<
|
||||
TComputedDefinition1 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>,
|
||||
) => any
|
||||
},
|
||||
TPrevData extends adapter.glassEasel.typeUtils.DataList,
|
||||
TProperty extends adapter.glassEasel.typeUtils.PropertyList,
|
||||
>(
|
||||
ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>,
|
||||
computedDefinition1: TComputedDefinition1,
|
||||
): adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> },
|
||||
TProperty
|
||||
>
|
||||
export function computed<
|
||||
TComputedDefinition1 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>,
|
||||
) => any
|
||||
},
|
||||
TComputedDefinition2 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> },
|
||||
TProperty
|
||||
>,
|
||||
) => any
|
||||
},
|
||||
TPrevData extends adapter.glassEasel.typeUtils.DataList,
|
||||
TProperty extends adapter.glassEasel.typeUtils.PropertyList,
|
||||
>(
|
||||
ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>,
|
||||
computedDefinition1: TComputedDefinition1,
|
||||
computedDefinition2: TComputedDefinition2,
|
||||
): adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> } & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>
|
||||
},
|
||||
TProperty
|
||||
>
|
||||
export function computed<
|
||||
TComputedDefinition1 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>,
|
||||
) => any
|
||||
},
|
||||
TComputedDefinition2 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> },
|
||||
TProperty
|
||||
>,
|
||||
) => any
|
||||
},
|
||||
TComputedDefinition3 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> } & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>
|
||||
},
|
||||
TProperty
|
||||
>,
|
||||
) => any
|
||||
},
|
||||
TPrevData extends adapter.glassEasel.typeUtils.DataList,
|
||||
TProperty extends adapter.glassEasel.typeUtils.PropertyList,
|
||||
>(
|
||||
ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>,
|
||||
computedDefinition1: TComputedDefinition1,
|
||||
computedDefinition2: TComputedDefinition2,
|
||||
computedDefinition3: TComputedDefinition3,
|
||||
): adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> } & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>
|
||||
} & { [k in keyof TComputedDefinition3]: ReturnType<TComputedDefinition3[k]> },
|
||||
TProperty
|
||||
>
|
||||
export function computed<
|
||||
TComputedDefinition1 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>,
|
||||
) => any
|
||||
},
|
||||
TComputedDefinition2 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> },
|
||||
TProperty
|
||||
>,
|
||||
) => any
|
||||
},
|
||||
TComputedDefinition3 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> } & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>
|
||||
},
|
||||
TProperty
|
||||
>,
|
||||
) => any
|
||||
},
|
||||
TComputedDefinition4 extends {
|
||||
[k: string]: (
|
||||
data: adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> } & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>
|
||||
} & { [k in keyof TComputedDefinition3]: ReturnType<TComputedDefinition3[k]> },
|
||||
TProperty
|
||||
>,
|
||||
) => any
|
||||
},
|
||||
TPrevData extends adapter.glassEasel.typeUtils.DataList,
|
||||
TProperty extends adapter.glassEasel.typeUtils.PropertyList,
|
||||
>(
|
||||
ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>,
|
||||
computedDefinition1: TComputedDefinition1,
|
||||
computedDefinition2: TComputedDefinition2,
|
||||
computedDefinition3: TComputedDefinition3,
|
||||
computedDefinition4: TComputedDefinition4,
|
||||
): adapter.glassEasel.typeUtils.DataWithPropertyValues<
|
||||
TPrevData & { [k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]> } & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>
|
||||
} & { [k in keyof TComputedDefinition3]: ReturnType<TComputedDefinition3[k]> } & {
|
||||
[k in keyof TComputedDefinition4]: ReturnType<TComputedDefinition4[k]>
|
||||
},
|
||||
TProperty
|
||||
>
|
||||
export function computed<
|
||||
TPrevData extends adapter.glassEasel.typeUtils.DataList,
|
||||
TProperty extends adapter.glassEasel.typeUtils.PropertyList,
|
||||
>(
|
||||
ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>,
|
||||
computedDefinition1: any,
|
||||
computedDefinition2?: any,
|
||||
computedDefinition3?: any,
|
||||
computedDefinition4?: any,
|
||||
): unknown {
|
||||
tryInitInCtx(ctx)
|
||||
const builder = new ComputedBuilder()
|
||||
Object.keys(computedDefinition1).forEach((targetField) => {
|
||||
const updateMethod = computedDefinition1[targetField]
|
||||
builder.addComputed(targetField, updateMethod)
|
||||
})
|
||||
if (computedDefinition2) {
|
||||
Object.keys(computedDefinition2).forEach((targetField) => {
|
||||
const updateMethod = computedDefinition2[targetField]
|
||||
builder.addComputed(targetField, updateMethod)
|
||||
})
|
||||
}
|
||||
if (computedDefinition3) {
|
||||
Object.keys(computedDefinition3).forEach((targetField) => {
|
||||
const updateMethod = computedDefinition3[targetField]
|
||||
builder.addComputed(targetField, updateMethod)
|
||||
})
|
||||
}
|
||||
if (computedDefinition4) {
|
||||
Object.keys(computedDefinition4).forEach((targetField) => {
|
||||
const updateMethod = computedDefinition4[targetField]
|
||||
builder.addComputed(targetField, updateMethod)
|
||||
})
|
||||
}
|
||||
builder.observersItems.forEach(({ fields, observer }) => {
|
||||
ctx.observer(fields as any, observer)
|
||||
})
|
||||
return ctx.data as any
|
||||
}
|
||||
|
||||
export const watch = (
|
||||
ctx: adapter.builder.BuilderContext<any, any, any>,
|
||||
watchPath: string,
|
||||
listener: (...args: any[]) => void,
|
||||
) => {
|
||||
tryInitInCtx(ctx)
|
||||
const builder = new ComputedBuilder()
|
||||
builder.addWatch(watchPath, listener)
|
||||
builder.observersItems.forEach(({ fields, observer }) => {
|
||||
ctx.observer(fields as any, observer)
|
||||
})
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
const WHITE_SPACE_CHAR_REGEXP = /^\s/
|
||||
|
||||
export type DataPathWithOptions = {
|
||||
path: string[]
|
||||
options: { deepCmp: boolean }
|
||||
}
|
||||
|
||||
type ParserState = {
|
||||
index: number
|
||||
length: number
|
||||
}
|
||||
|
||||
const throwParsingError = (path: string, index: number) => {
|
||||
throw new Error(
|
||||
'Parsing data path "' + path + '" failed at char "' + path[index] + '" (index ' + index + ')',
|
||||
)
|
||||
}
|
||||
|
||||
const parseArrIndex = (path: string, state: ParserState) => {
|
||||
const startIndex = state.index
|
||||
while (state.index < state.length) {
|
||||
const ch = path[state.index]
|
||||
if (/^[0-9]/.test(ch)) {
|
||||
state.index++
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
if (startIndex === state.index) {
|
||||
throwParsingError(path, state.index)
|
||||
}
|
||||
return parseInt(path.slice(startIndex, state.index), 10)
|
||||
}
|
||||
|
||||
const parseIdent = (path: string, state: ParserState) => {
|
||||
const startIndex = state.index
|
||||
const ch = path[startIndex]
|
||||
if (/^[_a-zA-Z$]/.test(ch)) {
|
||||
state.index++
|
||||
while (state.index < state.length) {
|
||||
const ch = path[state.index]
|
||||
if (/^[_a-zA-Z0-9$]/.test(ch)) {
|
||||
state.index++
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
} else {
|
||||
throwParsingError(path, state.index)
|
||||
}
|
||||
return path.slice(startIndex, state.index)
|
||||
}
|
||||
|
||||
const parseSinglePath = (path: string, state: ParserState): DataPathWithOptions => {
|
||||
const paths = [parseIdent(path, state)]
|
||||
const options = {
|
||||
deepCmp: false,
|
||||
}
|
||||
while (state.index < state.length) {
|
||||
const ch = path[state.index]
|
||||
if (ch === '[') {
|
||||
state.index++
|
||||
paths.push(`${parseArrIndex(path, state)}`)
|
||||
const nextCh = path[state.index]
|
||||
if (nextCh !== ']') throwParsingError(path, state.index)
|
||||
state.index++
|
||||
} else if (ch === '.') {
|
||||
state.index++
|
||||
const ch = path[state.index]
|
||||
if (ch === '*') {
|
||||
state.index++
|
||||
const ch = path[state.index]
|
||||
if (ch === '*') {
|
||||
state.index++
|
||||
options.deepCmp = true
|
||||
break
|
||||
}
|
||||
throwParsingError(path, state.index)
|
||||
}
|
||||
paths.push(parseIdent(path, state))
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return { path: paths, options }
|
||||
}
|
||||
|
||||
const parseMultiPaths = (path: string, state: ParserState): DataPathWithOptions[] => {
|
||||
while (WHITE_SPACE_CHAR_REGEXP.test(path[state.index])) {
|
||||
state.index++
|
||||
}
|
||||
const ret = [parseSinglePath(path, state)]
|
||||
let splitted = false
|
||||
while (state.index < state.length) {
|
||||
const ch = path[state.index]
|
||||
if (WHITE_SPACE_CHAR_REGEXP.test(ch)) {
|
||||
state.index++
|
||||
} else if (ch === ',') {
|
||||
splitted = true
|
||||
state.index++
|
||||
} else if (splitted) {
|
||||
splitted = false
|
||||
ret.push(parseSinglePath(path, state))
|
||||
} else {
|
||||
throwParsingError(path, state.index)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
const parseEOF = (path: string, state: ParserState) => {
|
||||
if (state.index < state.length) throwParsingError(path, state.index)
|
||||
}
|
||||
|
||||
export const parseMultiDataPaths = (path: string): DataPathWithOptions[] => {
|
||||
const state = {
|
||||
length: path.length,
|
||||
index: 0,
|
||||
}
|
||||
const ret = parseMultiPaths(path, state)
|
||||
parseEOF(path, state)
|
||||
return ret
|
||||
}
|
||||
|
||||
export const getDataOnPath = (data: unknown, path: Array<string>) => {
|
||||
let ret = data
|
||||
path.forEach((s) => {
|
||||
if (typeof ret !== 'object' || ret === null) ret = undefined
|
||||
else ret = ret[s]
|
||||
})
|
||||
return ret
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
import ProxyPolyfillBuilder from 'proxy-polyfill/src/proxy'
|
||||
const ProxyPolyfill = ProxyPolyfillBuilder()
|
||||
|
||||
interface WrappedData {
|
||||
__rawObject__: unknown
|
||||
}
|
||||
|
||||
export type RelatedPathValue =
|
||||
| {
|
||||
kind: 'value'
|
||||
path: Array<string>
|
||||
value: unknown
|
||||
}
|
||||
| {
|
||||
kind: 'keys'
|
||||
path: Array<string>
|
||||
keys: Array<string>
|
||||
}
|
||||
|
||||
const wrapData = (
|
||||
data: unknown,
|
||||
relatedPathValues: Array<RelatedPathValue>,
|
||||
basePath: Array<string>,
|
||||
) => {
|
||||
if (typeof data !== 'object' || data === null) return data
|
||||
const handler = {
|
||||
get(obj: unknown, key: string) {
|
||||
if (key === '__rawObject__') return obj
|
||||
let keyWrapper = null
|
||||
const keyPath = basePath.concat(key)
|
||||
const value = obj[key]
|
||||
relatedPathValues.push({
|
||||
kind: 'value',
|
||||
path: keyPath,
|
||||
value,
|
||||
})
|
||||
keyWrapper = wrapData(value, relatedPathValues, keyPath)
|
||||
return keyWrapper
|
||||
},
|
||||
ownKeys(obj: unknown) {
|
||||
const keyPath = basePath.slice()
|
||||
const keys = Object.keys(obj).sort()
|
||||
relatedPathValues.push({
|
||||
kind: 'keys',
|
||||
path: keyPath,
|
||||
keys,
|
||||
})
|
||||
return keys
|
||||
},
|
||||
}
|
||||
try {
|
||||
return new Proxy(data, handler)
|
||||
} catch (e) {
|
||||
return new ProxyPolyfill(data, handler)
|
||||
}
|
||||
}
|
||||
|
||||
export function create(data: unknown, relatedPathValues: Array<RelatedPathValue>) {
|
||||
return wrapData(data, relatedPathValues, [])
|
||||
}
|
||||
|
||||
export function unwrap(wrapped: unknown) {
|
||||
// #70
|
||||
if (
|
||||
wrapped !== null &&
|
||||
typeof wrapped === 'object' &&
|
||||
typeof (wrapped as WrappedData).__rawObject__ !== 'object'
|
||||
) {
|
||||
if (Array.isArray(wrapped)) {
|
||||
return wrapped.map((i) => unwrap(i))
|
||||
}
|
||||
const ret = {}
|
||||
Object.keys(wrapped).forEach((k) => {
|
||||
ret[k] = unwrap(wrapped[k])
|
||||
})
|
||||
return ret
|
||||
}
|
||||
if (
|
||||
typeof wrapped !== 'object' ||
|
||||
wrapped === null ||
|
||||
typeof (wrapped as WrappedData).__rawObject__ !== 'object'
|
||||
) {
|
||||
return wrapped
|
||||
}
|
||||
return (wrapped as WrappedData).__rawObject__
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
import { behavior } from './behavior'
|
||||
|
||||
export { behavior, computed, watch } from './behavior'
|
||||
|
||||
type ComputedInstance<
|
||||
D extends WechatMiniprogram.Component.DataOption,
|
||||
P extends WechatMiniprogram.Component.PropertyOption,
|
||||
M extends WechatMiniprogram.Component.MethodOption,
|
||||
C extends Record<string, (data: D & { [K in keyof P]: any }) => any>,
|
||||
TCustomProperty extends WechatMiniprogram.IAnyObject = Record<string, never>,
|
||||
> = WechatMiniprogram.Component.Instance<D, P, M, TCustomProperty> & {
|
||||
data: { [K in keyof C]: ReturnType<C[K]> } & { [K in keyof P]: any }
|
||||
}
|
||||
|
||||
type ComputedOptions<
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TWatch extends Record<string, (...args: any[]) => void>,
|
||||
TComputed extends Record<
|
||||
string,
|
||||
(data: TData & WechatMiniprogram.Component.PropertyOptionToData<TProperty>) => any
|
||||
>,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
> = (Partial<WechatMiniprogram.Component.Data<TData>> &
|
||||
Partial<WechatMiniprogram.Component.Property<TProperty>> &
|
||||
Partial<WechatMiniprogram.Component.Method<TMethod>> &
|
||||
Partial<WechatMiniprogram.Component.OtherOption> &
|
||||
Partial<WechatMiniprogram.Component.Lifetimes> & {
|
||||
watch?: TWatch
|
||||
computed?: TComputed
|
||||
template?: string
|
||||
}) &
|
||||
ThisType<ComputedInstance<TData, TProperty, TMethod, TComputed, TCustomInstanceProperty>>
|
||||
|
||||
export function ComponentWithComputed<
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TWatch extends Record<string, (...args: any[]) => void>,
|
||||
TComputed extends Record<
|
||||
string,
|
||||
(data: TData & WechatMiniprogram.Component.PropertyOptionToData<TProperty>) => any
|
||||
>,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(
|
||||
options: ComputedOptions<TData, TProperty, TMethod, TWatch, TComputed, TCustomInstanceProperty>,
|
||||
): string {
|
||||
if (!Array.isArray(options.behaviors)) {
|
||||
options.behaviors = []
|
||||
}
|
||||
options.behaviors.unshift(behavior)
|
||||
return Component(options)
|
||||
}
|
||||
|
||||
export function BehaviorWithComputed<
|
||||
TData extends WechatMiniprogram.Behavior.DataOption,
|
||||
TProperty extends WechatMiniprogram.Behavior.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Behavior.MethodOption,
|
||||
TWatch extends Record<string, (...args: any[]) => void>,
|
||||
TComputed extends Record<
|
||||
string,
|
||||
(data: TData & WechatMiniprogram.Component.PropertyOptionToData<TProperty>) => any
|
||||
>,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(
|
||||
options: ComputedOptions<TData, TProperty, TMethod, TWatch, TComputed, TCustomInstanceProperty>,
|
||||
): string {
|
||||
if (!Array.isArray(options.behaviors)) {
|
||||
options.behaviors = []
|
||||
}
|
||||
options.behaviors.unshift(behavior)
|
||||
return Behavior(options)
|
||||
}
|
||||
|
||||
// data tracer mode
|
||||
export enum DataTracerMode {
|
||||
Auto,
|
||||
Proxy,
|
||||
DefineProperty,
|
||||
}
|
||||
|
||||
let currentDataTracerMode = DataTracerMode.Auto
|
||||
|
||||
export const getCurrentDataTracerMode = () => {
|
||||
return currentDataTracerMode
|
||||
}
|
||||
|
||||
export const setCurrentDataTracerMode = (mode: DataTracerMode) => {
|
||||
currentDataTracerMode = mode
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
import type * as adapter from 'glass-easel-miniprogram-adapter';
|
||||
export declare const behavior: string;
|
||||
export declare function computed<TComputedDefinition1 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>) => any;
|
||||
}, TPrevData extends adapter.glassEasel.typeUtils.DataList, TProperty extends adapter.glassEasel.typeUtils.PropertyList>(ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>, computedDefinition1: TComputedDefinition1): adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
}, TProperty>;
|
||||
export declare function computed<TComputedDefinition1 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>) => any;
|
||||
}, TComputedDefinition2 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
}, TProperty>) => any;
|
||||
}, TPrevData extends adapter.glassEasel.typeUtils.DataList, TProperty extends adapter.glassEasel.typeUtils.PropertyList>(ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>, computedDefinition1: TComputedDefinition1, computedDefinition2: TComputedDefinition2): adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>;
|
||||
}, TProperty>;
|
||||
export declare function computed<TComputedDefinition1 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>) => any;
|
||||
}, TComputedDefinition2 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
}, TProperty>) => any;
|
||||
}, TComputedDefinition3 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>;
|
||||
}, TProperty>) => any;
|
||||
}, TPrevData extends adapter.glassEasel.typeUtils.DataList, TProperty extends adapter.glassEasel.typeUtils.PropertyList>(ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>, computedDefinition1: TComputedDefinition1, computedDefinition2: TComputedDefinition2, computedDefinition3: TComputedDefinition3): adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition3]: ReturnType<TComputedDefinition3[k]>;
|
||||
}, TProperty>;
|
||||
export declare function computed<TComputedDefinition1 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData, TProperty>) => any;
|
||||
}, TComputedDefinition2 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
}, TProperty>) => any;
|
||||
}, TComputedDefinition3 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>;
|
||||
}, TProperty>) => any;
|
||||
}, TComputedDefinition4 extends {
|
||||
[k: string]: (data: adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition3]: ReturnType<TComputedDefinition3[k]>;
|
||||
}, TProperty>) => any;
|
||||
}, TPrevData extends adapter.glassEasel.typeUtils.DataList, TProperty extends adapter.glassEasel.typeUtils.PropertyList>(ctx: adapter.builder.BuilderContext<TPrevData, TProperty, any>, computedDefinition1: TComputedDefinition1, computedDefinition2: TComputedDefinition2, computedDefinition3: TComputedDefinition3, computedDefinition4: TComputedDefinition4): adapter.glassEasel.typeUtils.DataWithPropertyValues<TPrevData & {
|
||||
[k in keyof TComputedDefinition1]: ReturnType<TComputedDefinition1[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition2]: ReturnType<TComputedDefinition2[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition3]: ReturnType<TComputedDefinition3[k]>;
|
||||
} & {
|
||||
[k in keyof TComputedDefinition4]: ReturnType<TComputedDefinition4[k]>;
|
||||
}, TProperty>;
|
||||
export declare const watch: (ctx: adapter.builder.BuilderContext<any, any, any>, watchPath: string, listener: (...args: any[]) => void) => void;
|
@ -0,0 +1,8 @@
|
||||
export type DataPathWithOptions = {
|
||||
path: string[];
|
||||
options: {
|
||||
deepCmp: boolean;
|
||||
};
|
||||
};
|
||||
export declare const parseMultiDataPaths: (path: string) => DataPathWithOptions[];
|
||||
export declare const getDataOnPath: (data: unknown, path: Array<string>) => unknown;
|
@ -0,0 +1,11 @@
|
||||
export type RelatedPathValue = {
|
||||
kind: 'value';
|
||||
path: Array<string>;
|
||||
value: unknown;
|
||||
} | {
|
||||
kind: 'keys';
|
||||
path: Array<string>;
|
||||
keys: Array<string>;
|
||||
};
|
||||
export declare function create(data: unknown, relatedPathValues: Array<RelatedPathValue>): any;
|
||||
export declare function unwrap(wrapped: unknown): any;
|
@ -0,0 +1,24 @@
|
||||
export { behavior, computed, watch } from './behavior';
|
||||
type ComputedInstance<D extends WechatMiniprogram.Component.DataOption, P extends WechatMiniprogram.Component.PropertyOption, M extends WechatMiniprogram.Component.MethodOption, C extends Record<string, (data: D & {
|
||||
[K in keyof P]: any;
|
||||
}) => any>, TCustomProperty extends WechatMiniprogram.IAnyObject = Record<string, never>> = WechatMiniprogram.Component.Instance<D, P, M, TCustomProperty> & {
|
||||
data: {
|
||||
[K in keyof C]: ReturnType<C[K]>;
|
||||
} & {
|
||||
[K in keyof P]: any;
|
||||
};
|
||||
};
|
||||
type ComputedOptions<TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TWatch extends Record<string, (...args: any[]) => void>, TComputed extends Record<string, (data: TData & WechatMiniprogram.Component.PropertyOptionToData<TProperty>) => any>, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}> = (Partial<WechatMiniprogram.Component.Data<TData>> & Partial<WechatMiniprogram.Component.Property<TProperty>> & Partial<WechatMiniprogram.Component.Method<TMethod>> & Partial<WechatMiniprogram.Component.OtherOption> & Partial<WechatMiniprogram.Component.Lifetimes> & {
|
||||
watch?: TWatch;
|
||||
computed?: TComputed;
|
||||
template?: string;
|
||||
}) & ThisType<ComputedInstance<TData, TProperty, TMethod, TComputed, TCustomInstanceProperty>>;
|
||||
export declare function ComponentWithComputed<TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TWatch extends Record<string, (...args: any[]) => void>, TComputed extends Record<string, (data: TData & WechatMiniprogram.Component.PropertyOptionToData<TProperty>) => any>, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}>(options: ComputedOptions<TData, TProperty, TMethod, TWatch, TComputed, TCustomInstanceProperty>): string;
|
||||
export declare function BehaviorWithComputed<TData extends WechatMiniprogram.Behavior.DataOption, TProperty extends WechatMiniprogram.Behavior.PropertyOption, TMethod extends WechatMiniprogram.Behavior.MethodOption, TWatch extends Record<string, (...args: any[]) => void>, TComputed extends Record<string, (data: TData & WechatMiniprogram.Component.PropertyOptionToData<TProperty>) => any>, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}>(options: ComputedOptions<TData, TProperty, TMethod, TWatch, TComputed, TCustomInstanceProperty>): string;
|
||||
export declare enum DataTracerMode {
|
||||
Auto = 0,
|
||||
Proxy = 1,
|
||||
DefineProperty = 2
|
||||
}
|
||||
export declare const getCurrentDataTracerMode: () => DataTracerMode;
|
||||
export declare const setCurrentDataTracerMode: (mode: DataTracerMode) => void;
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 wechat-miniprogram
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,82 @@
|
||||
{
|
||||
"name": "mobx-miniprogram-bindings",
|
||||
"version": "4.0.1",
|
||||
"description": "Mobx binding utils for WeChat miniprogram",
|
||||
"main": "dist/index.js",
|
||||
"types": "types/src/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"types",
|
||||
"dist",
|
||||
"LICENSE",
|
||||
"package.json",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "gulp",
|
||||
"gen_dts": "gulp dts",
|
||||
"test": "jest ./test/* --bail",
|
||||
"coverage": "jest ./test/* --coverage --bail",
|
||||
"lint": "eslint . --fix"
|
||||
},
|
||||
"miniprogram": "dist",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wechat-miniprogram/mobx-miniprogram-bindings.git"
|
||||
},
|
||||
"keywords": [
|
||||
"mobx",
|
||||
"wechat",
|
||||
"miniprogram"
|
||||
],
|
||||
"author": "wechat-miniprogram",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/wechat-miniprogram/mobx-miniprogram-bindings/issues"
|
||||
},
|
||||
"homepage": "https://github.com/wechat-miniprogram/mobx-miniprogram-bindings#readme",
|
||||
"devDependencies": {
|
||||
"@babel/runtime": "^7.24.5",
|
||||
"@swc/core": "^1.5.2",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.12.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
||||
"@typescript-eslint/parser": "^7.8.0",
|
||||
"colors": "^1.4.0",
|
||||
"esbuild": "^0.20.2",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"glass-easel": "0.5.2",
|
||||
"glass-easel-miniprogram-adapter": "0.5.2",
|
||||
"glass-easel-template-compiler": "0.5.2",
|
||||
"gulp": "^5.0.0",
|
||||
"gulp-clean": "^0.4.0",
|
||||
"gulp-esbuild": "^0.12.0",
|
||||
"gulp-swc": "^2.1.0",
|
||||
"gulp-typescript": "6.0.0-alpha.1",
|
||||
"gulp-watch": "^5.0.1",
|
||||
"husky": "^9.0.11",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"miniprogram-api-typings": "^3.12.2",
|
||||
"miniprogram-computed": "^4.4.0",
|
||||
"mobx-miniprogram": "^6.0.0",
|
||||
"prettier": "3.2.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mobx-miniprogram": "^6.0.0"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm run lint"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
import 'miniprogram-api-typings'
|
||||
import { IStoreBindings } from './index'
|
||||
import { createActions, createDataFieldsReactions, StoreBindingsManager } from './core'
|
||||
|
||||
type TDefFields = WechatMiniprogram.Component.TrivialOption & {
|
||||
storeBindings?: IStoreBindings<any> | Array<IStoreBindings<any>>
|
||||
}
|
||||
|
||||
type UninitializedThis = {
|
||||
updateStoreBindings: () => void
|
||||
_mobxMiniprogramBindings: (() => IStoreBindings<any>) | StoreBindingsManager | StoreBindingsManager[] | null
|
||||
}
|
||||
|
||||
type InitializedThis = {
|
||||
updateStoreBindings: () => void
|
||||
_mobxMiniprogramBindings: StoreBindingsManager | StoreBindingsManager[] | null
|
||||
}
|
||||
|
||||
export const behavior = Behavior({
|
||||
definitionFilter: (defFields: TDefFields) => {
|
||||
defFields.methods = defFields.methods || {}
|
||||
const { storeBindings } = defFields
|
||||
defFields.methods._mobxMiniprogramBindings = () => {
|
||||
return storeBindings
|
||||
}
|
||||
if (storeBindings) {
|
||||
if (Array.isArray(storeBindings)) {
|
||||
storeBindings.forEach((binding) => {
|
||||
createActions(defFields.methods, binding)
|
||||
})
|
||||
} else {
|
||||
createActions(defFields.methods, storeBindings)
|
||||
}
|
||||
}
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
const self = this as unknown as UninitializedThis
|
||||
if (typeof self._mobxMiniprogramBindings !== 'function') return
|
||||
const storeBindings = self._mobxMiniprogramBindings()
|
||||
if (!storeBindings) {
|
||||
self._mobxMiniprogramBindings = null
|
||||
return
|
||||
}
|
||||
if (Array.isArray(storeBindings)) {
|
||||
self._mobxMiniprogramBindings = storeBindings.map((item) => {
|
||||
const ret = createDataFieldsReactions(self, item)
|
||||
ret.updateStoreBindings()
|
||||
return ret
|
||||
})
|
||||
} else {
|
||||
self._mobxMiniprogramBindings = createDataFieldsReactions(this, storeBindings)
|
||||
self._mobxMiniprogramBindings.updateStoreBindings()
|
||||
}
|
||||
},
|
||||
detached() {
|
||||
const self = this as unknown as InitializedThis
|
||||
if (self._mobxMiniprogramBindings) {
|
||||
if (Array.isArray(self._mobxMiniprogramBindings)) {
|
||||
self._mobxMiniprogramBindings.forEach((item) => {
|
||||
item.destroyStoreBindings()
|
||||
})
|
||||
} else {
|
||||
self._mobxMiniprogramBindings.destroyStoreBindings()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateStoreBindings() {
|
||||
const self = this as unknown as UninitializedThis
|
||||
if (self._mobxMiniprogramBindings && typeof self._mobxMiniprogramBindings !== 'function') {
|
||||
if (Array.isArray(self._mobxMiniprogramBindings)) {
|
||||
self._mobxMiniprogramBindings.forEach((item) => {
|
||||
item.updateStoreBindings()
|
||||
})
|
||||
} else {
|
||||
self._mobxMiniprogramBindings.updateStoreBindings()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
@ -0,0 +1,152 @@
|
||||
import { reaction, comparer, toJS } from 'mobx-miniprogram'
|
||||
import { IStoreBindings } from './index'
|
||||
|
||||
export const createActions = <TStore extends Record<string, any>>(methods, options: IStoreBindings<TStore>) => {
|
||||
const { store, actions } = options
|
||||
if (!actions) return
|
||||
|
||||
// for array-typed fields definition
|
||||
if (typeof store === 'undefined') {
|
||||
throw new Error('[mobx-miniprogram] no store specified')
|
||||
}
|
||||
|
||||
if (Array.isArray(actions)) {
|
||||
actions.forEach((field) => {
|
||||
if (methods[field]) {
|
||||
throw new Error('[mobx-miniprogram] multiple action definition')
|
||||
}
|
||||
methods[field] = (...args) => {
|
||||
return (store[field] as (...args: unknown[]) => unknown)(...args)
|
||||
}
|
||||
})
|
||||
} else if (typeof actions === 'object') {
|
||||
Object.keys(actions).forEach((field) => {
|
||||
const def = actions[field]
|
||||
if (typeof field !== 'string' && typeof field !== 'number') {
|
||||
throw new Error('[mobx-miniprogram] unrecognized field definition')
|
||||
}
|
||||
methods[field] = (...args) => {
|
||||
return (store[def] as (...args: unknown[]) => unknown)(...args)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export type StoreBindingsManager = {
|
||||
updateStoreBindings: () => void
|
||||
destroyStoreBindings: () => void
|
||||
}
|
||||
|
||||
export const createDataFieldsReactions = <TStore extends Record<string, any>>(
|
||||
target,
|
||||
options: Omit<IStoreBindings<TStore>, 'actions'>,
|
||||
): StoreBindingsManager => {
|
||||
const { store, fields, structuralComparison } = options
|
||||
|
||||
// if use namespace
|
||||
let namespace = options.namespace || ''
|
||||
if (namespace && typeof namespace !== 'string') {
|
||||
throw new Error('[mobx-miniprogram] namespace only expect string')
|
||||
}
|
||||
namespace = namespace.replace(new RegExp(' ', 'gm'), '')
|
||||
|
||||
let namespaceData = Object.assign({}, target[namespace])
|
||||
|
||||
const useNamespace = (): boolean => {
|
||||
return namespace !== ''
|
||||
}
|
||||
|
||||
// choose equal method
|
||||
const equals = structuralComparison ? comparer.structural : undefined
|
||||
|
||||
// setData combination
|
||||
let pendingSetData: Record<string, any> | null = null
|
||||
|
||||
const applySetData = () => {
|
||||
if (pendingSetData === null) return
|
||||
const data = pendingSetData
|
||||
pendingSetData = null
|
||||
target.setData(data)
|
||||
}
|
||||
|
||||
const scheduleSetData = (field, value) => {
|
||||
if (!pendingSetData) {
|
||||
pendingSetData = {}
|
||||
if (typeof wx !== 'undefined') wx.nextTick(applySetData)
|
||||
else Promise.resolve().then(applySetData)
|
||||
}
|
||||
if (useNamespace()) {
|
||||
namespaceData = {
|
||||
...namespaceData,
|
||||
[field]: toJS(value),
|
||||
}
|
||||
pendingSetData[namespace] = namespaceData
|
||||
} else {
|
||||
pendingSetData[field] = toJS(value)
|
||||
}
|
||||
}
|
||||
|
||||
// handling fields
|
||||
let reactions: (() => void)[] = []
|
||||
|
||||
if (Array.isArray(fields)) {
|
||||
// for array-typed fields definition
|
||||
if (typeof store === 'undefined') {
|
||||
throw new Error('[mobx-miniprogram] no store specified')
|
||||
}
|
||||
reactions = fields.map((field) => {
|
||||
return reaction(
|
||||
() => store[field],
|
||||
(value) => {
|
||||
scheduleSetData(field, value)
|
||||
},
|
||||
{
|
||||
equals,
|
||||
fireImmediately: true,
|
||||
},
|
||||
)
|
||||
})
|
||||
} else if (typeof fields === 'object' && fields) {
|
||||
// for object-typed fields definition
|
||||
reactions = Object.keys(fields).map((field) => {
|
||||
const def = fields[field]
|
||||
if (typeof def === 'function') {
|
||||
return reaction(
|
||||
() => def.call(target, store),
|
||||
(value) => {
|
||||
scheduleSetData(field, value)
|
||||
},
|
||||
{
|
||||
equals,
|
||||
fireImmediately: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
if (typeof field !== 'string' && typeof field !== 'number') {
|
||||
throw new Error('[mobx-miniprogram] unrecognized field definition')
|
||||
}
|
||||
if (typeof store === 'undefined') {
|
||||
throw new Error('[mobx-miniprogram] no store specified')
|
||||
}
|
||||
return reaction(
|
||||
() => store[def],
|
||||
(value) => {
|
||||
scheduleSetData(String(field), value)
|
||||
},
|
||||
{
|
||||
equals,
|
||||
fireImmediately: true,
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const destroyStoreBindings = () => {
|
||||
reactions.forEach((reaction) => reaction())
|
||||
}
|
||||
|
||||
return {
|
||||
updateStoreBindings: applySetData,
|
||||
destroyStoreBindings,
|
||||
}
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
import 'miniprogram-api-typings'
|
||||
import { behavior } from './behavior'
|
||||
import { StoreBindingsManager, createActions, createDataFieldsReactions } from './core'
|
||||
import type * as adapter from 'glass-easel-miniprogram-adapter'
|
||||
|
||||
type Action = string
|
||||
|
||||
export interface IStoreBindings<T extends Record<string, any>> {
|
||||
namespace?: string
|
||||
store: T
|
||||
fields: (keyof T)[] | { [k: string]: (keyof T | ((...args: any) => any)) }
|
||||
actions: (keyof T)[] | { [k: Action]: keyof T }
|
||||
structuralComparison?: boolean
|
||||
}
|
||||
|
||||
type StoreData<T extends IStoreBindings<any>> = T['fields'] extends string[]
|
||||
? { [k in T['fields'][number]]: T['store'][k] }
|
||||
: T['fields'] extends { [k: Action]: string | ((...args: any) => any) }
|
||||
? { [k in keyof T['fields']]: (
|
||||
T['fields'][k] extends (...args: any) => any
|
||||
? ReturnType<T['fields'][k]>
|
||||
: T['fields'][k] extends string
|
||||
? T['store'][T['fields'][k]]
|
||||
: unknown
|
||||
)}
|
||||
: unknown
|
||||
|
||||
type StoreAction<T extends IStoreBindings<any>> = T['actions'] extends string[]
|
||||
? { [k in T['actions'][number]]: T['store'][k] }
|
||||
: T['actions'] extends { [k: Action]: string }
|
||||
? { [k in keyof T['actions']]: T['store'][T['actions'][k]] }
|
||||
: unknown
|
||||
|
||||
type StoreOptions<
|
||||
TStoreBindings extends IStoreBindings<any>,
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
> = (Partial<WechatMiniprogram.Component.Data<TData>> &
|
||||
Partial<WechatMiniprogram.Component.Property<TProperty>> &
|
||||
Partial<WechatMiniprogram.Component.Method<TMethod>> &
|
||||
Partial<WechatMiniprogram.Component.OtherOption> &
|
||||
Partial<WechatMiniprogram.Component.Lifetimes> & {
|
||||
storeBindings: TStoreBindings
|
||||
}) &
|
||||
ThisType<
|
||||
WechatMiniprogram.Component.Instance<
|
||||
TData & StoreData<TStoreBindings>,
|
||||
TProperty,
|
||||
TMethod & StoreAction<TStoreBindings>,
|
||||
TCustomInstanceProperty
|
||||
>
|
||||
>
|
||||
|
||||
type StoreListOptions<
|
||||
TStoreBindings extends IStoreBindings<any>[],
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
> = (Partial<WechatMiniprogram.Component.Data<TData>> &
|
||||
Partial<WechatMiniprogram.Component.Property<TProperty>> &
|
||||
Partial<WechatMiniprogram.Component.Method<TMethod>> &
|
||||
Partial<WechatMiniprogram.Component.OtherOption> &
|
||||
Partial<WechatMiniprogram.Component.Lifetimes> & {
|
||||
storeBindings: TStoreBindings
|
||||
}) &
|
||||
ThisType<
|
||||
WechatMiniprogram.Component.Instance<
|
||||
TData
|
||||
& StoreData<TStoreBindings[0]>
|
||||
& StoreData<TStoreBindings[1]>
|
||||
& StoreData<TStoreBindings[2]>
|
||||
& StoreData<TStoreBindings[3]>
|
||||
& StoreData<TStoreBindings[4]>
|
||||
& StoreData<TStoreBindings[5]>
|
||||
& StoreData<TStoreBindings[6]>
|
||||
& StoreData<TStoreBindings[7]>,
|
||||
TProperty,
|
||||
TMethod
|
||||
& StoreAction<TStoreBindings[0]>
|
||||
& StoreAction<TStoreBindings[1]>
|
||||
& StoreAction<TStoreBindings[2]>
|
||||
& StoreAction<TStoreBindings[3]>
|
||||
& StoreAction<TStoreBindings[4]>
|
||||
& StoreAction<TStoreBindings[5]>
|
||||
& StoreAction<TStoreBindings[6]>
|
||||
& StoreAction<TStoreBindings[7]>,
|
||||
TCustomInstanceProperty
|
||||
>
|
||||
>
|
||||
|
||||
export function ComponentWithStore<
|
||||
TStoreBindings extends IStoreBindings<any>,
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(options: StoreOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export function ComponentWithStore<
|
||||
TStoreBindings extends IStoreBindings<any>[],
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(options: StoreListOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export function ComponentWithStore<
|
||||
TStoreBindings extends any,
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(options: StoreListOptions<any, TData, TProperty, TMethod, TCustomInstanceProperty>): string {
|
||||
if (!Array.isArray(options.behaviors)) {
|
||||
options.behaviors = []
|
||||
}
|
||||
options.behaviors.unshift(behavior)
|
||||
return Component(options)
|
||||
}
|
||||
|
||||
export function BehaviorWithStore<
|
||||
TStoreBindings extends IStoreBindings<any>,
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(options: StoreOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export function BehaviorWithStore<
|
||||
TStoreBindings extends IStoreBindings<any>[],
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(options: StoreListOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export function BehaviorWithStore<
|
||||
TStoreBindings extends any,
|
||||
TData extends WechatMiniprogram.Component.DataOption,
|
||||
TProperty extends WechatMiniprogram.Component.PropertyOption,
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption,
|
||||
TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {},
|
||||
>(options: StoreOptions<any, TData, TProperty, TMethod, TCustomInstanceProperty>): string {
|
||||
if (!Array.isArray(options.behaviors)) {
|
||||
options.behaviors = []
|
||||
}
|
||||
options.behaviors.unshift(behavior)
|
||||
return Behavior(options)
|
||||
}
|
||||
|
||||
export const createStoreBindings = <TStore extends Record<string, any>>(target, options: IStoreBindings<TStore>): StoreBindingsManager => {
|
||||
createActions(target, options)
|
||||
return createDataFieldsReactions(target, options)
|
||||
}
|
||||
|
||||
export const storeBindingsBehavior = behavior
|
||||
|
||||
export type InitializedStoreBindings = {
|
||||
updateStoreBindings: () => void
|
||||
}
|
||||
|
||||
export const initStoreBindings = <TStore extends Record<string, any>>(
|
||||
ctx: adapter.builder.BuilderContext<any, any, any>,
|
||||
options: Omit<IStoreBindings<TStore>, 'actions'>,
|
||||
): InitializedStoreBindings => {
|
||||
const { self, lifetime } = ctx
|
||||
|
||||
let storeBindings: StoreBindingsManager | undefined
|
||||
lifetime('attached', () => {
|
||||
storeBindings = createDataFieldsReactions(self, options)
|
||||
storeBindings.updateStoreBindings()
|
||||
})
|
||||
lifetime('detached', () => {
|
||||
storeBindings!.destroyStoreBindings()
|
||||
})
|
||||
|
||||
return {
|
||||
updateStoreBindings: () => {
|
||||
if (storeBindings) {
|
||||
storeBindings.updateStoreBindings()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
import 'miniprogram-api-typings';
|
||||
export declare const behavior: string;
|
@ -0,0 +1,7 @@
|
||||
import { IStoreBindings } from './index';
|
||||
export declare const createActions: <TStore extends Record<string, any>>(methods: any, options: IStoreBindings<TStore>) => void;
|
||||
export type StoreBindingsManager = {
|
||||
updateStoreBindings: () => void;
|
||||
destroyStoreBindings: () => void;
|
||||
};
|
||||
export declare const createDataFieldsReactions: <TStore extends Record<string, any>>(target: any, options: Omit<IStoreBindings<TStore>, "actions">) => StoreBindingsManager;
|
@ -0,0 +1,46 @@
|
||||
import 'miniprogram-api-typings';
|
||||
import { StoreBindingsManager } from './core';
|
||||
import type * as adapter from 'glass-easel-miniprogram-adapter';
|
||||
type Action = string;
|
||||
export interface IStoreBindings<T extends Record<string, any>> {
|
||||
namespace?: string;
|
||||
store: T;
|
||||
fields: (keyof T)[] | {
|
||||
[k: string]: (keyof T | ((...args: any) => any));
|
||||
};
|
||||
actions: (keyof T)[] | {
|
||||
[k: Action]: keyof T;
|
||||
};
|
||||
structuralComparison?: boolean;
|
||||
}
|
||||
type StoreData<T extends IStoreBindings<any>> = T['fields'] extends string[] ? {
|
||||
[k in T['fields'][number]]: T['store'][k];
|
||||
} : T['fields'] extends {
|
||||
[k: Action]: string | ((...args: any) => any);
|
||||
} ? {
|
||||
[k in keyof T['fields']]: (T['fields'][k] extends (...args: any) => any ? ReturnType<T['fields'][k]> : T['fields'][k] extends string ? T['store'][T['fields'][k]] : unknown);
|
||||
} : unknown;
|
||||
type StoreAction<T extends IStoreBindings<any>> = T['actions'] extends string[] ? {
|
||||
[k in T['actions'][number]]: T['store'][k];
|
||||
} : T['actions'] extends {
|
||||
[k: Action]: string;
|
||||
} ? {
|
||||
[k in keyof T['actions']]: T['store'][T['actions'][k]];
|
||||
} : unknown;
|
||||
type StoreOptions<TStoreBindings extends IStoreBindings<any>, TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}> = (Partial<WechatMiniprogram.Component.Data<TData>> & Partial<WechatMiniprogram.Component.Property<TProperty>> & Partial<WechatMiniprogram.Component.Method<TMethod>> & Partial<WechatMiniprogram.Component.OtherOption> & Partial<WechatMiniprogram.Component.Lifetimes> & {
|
||||
storeBindings: TStoreBindings;
|
||||
}) & ThisType<WechatMiniprogram.Component.Instance<TData & StoreData<TStoreBindings>, TProperty, TMethod & StoreAction<TStoreBindings>, TCustomInstanceProperty>>;
|
||||
type StoreListOptions<TStoreBindings extends IStoreBindings<any>[], TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}> = (Partial<WechatMiniprogram.Component.Data<TData>> & Partial<WechatMiniprogram.Component.Property<TProperty>> & Partial<WechatMiniprogram.Component.Method<TMethod>> & Partial<WechatMiniprogram.Component.OtherOption> & Partial<WechatMiniprogram.Component.Lifetimes> & {
|
||||
storeBindings: TStoreBindings;
|
||||
}) & ThisType<WechatMiniprogram.Component.Instance<TData & StoreData<TStoreBindings[0]> & StoreData<TStoreBindings[1]> & StoreData<TStoreBindings[2]> & StoreData<TStoreBindings[3]> & StoreData<TStoreBindings[4]> & StoreData<TStoreBindings[5]> & StoreData<TStoreBindings[6]> & StoreData<TStoreBindings[7]>, TProperty, TMethod & StoreAction<TStoreBindings[0]> & StoreAction<TStoreBindings[1]> & StoreAction<TStoreBindings[2]> & StoreAction<TStoreBindings[3]> & StoreAction<TStoreBindings[4]> & StoreAction<TStoreBindings[5]> & StoreAction<TStoreBindings[6]> & StoreAction<TStoreBindings[7]>, TCustomInstanceProperty>>;
|
||||
export declare function ComponentWithStore<TStoreBindings extends IStoreBindings<any>, TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}>(options: StoreOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export declare function ComponentWithStore<TStoreBindings extends IStoreBindings<any>[], TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}>(options: StoreListOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export declare function BehaviorWithStore<TStoreBindings extends IStoreBindings<any>, TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}>(options: StoreOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export declare function BehaviorWithStore<TStoreBindings extends IStoreBindings<any>[], TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption, TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = {}>(options: StoreListOptions<TStoreBindings, TData, TProperty, TMethod, TCustomInstanceProperty>): string;
|
||||
export declare const createStoreBindings: <TStore extends Record<string, any>>(target: any, options: IStoreBindings<TStore>) => StoreBindingsManager;
|
||||
export declare const storeBindingsBehavior: string;
|
||||
export type InitializedStoreBindings = {
|
||||
updateStoreBindings: () => void;
|
||||
};
|
||||
export declare const initStoreBindings: <TStore extends Record<string, any>>(ctx: adapter.builder.BuilderContext<any, any, any>, options: Omit<IStoreBindings<TStore>, "actions">) => InitializedStoreBindings;
|
||||
export {};
|
@ -0,0 +1 @@
|
||||
export {};
|
@ -0,0 +1 @@
|
||||
export {};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Michel Weststrate
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,16 @@
|
||||
import { Annotation } from "../internal";
|
||||
import type { ClassFieldDecorator, ClassMethodDecorator } from "../types/decorator_fills";
|
||||
export declare const ACTION = "action";
|
||||
export declare const ACTION_BOUND = "action.bound";
|
||||
export declare const AUTOACTION = "autoAction";
|
||||
export declare const AUTOACTION_BOUND = "autoAction.bound";
|
||||
export interface IActionFactory extends Annotation, PropertyDecorator, ClassMethodDecorator, ClassFieldDecorator {
|
||||
<T extends Function | undefined | null>(fn: T): T;
|
||||
<T extends Function | undefined | null>(name: string, fn: T): T;
|
||||
(customName: string): PropertyDecorator & Annotation & ClassMethodDecorator & ClassFieldDecorator;
|
||||
bound: Annotation & PropertyDecorator & ClassMethodDecorator & ClassFieldDecorator;
|
||||
}
|
||||
export declare const action: IActionFactory;
|
||||
export declare const autoAction: IActionFactory;
|
||||
export declare function runInAction<T>(fn: () => T): T;
|
||||
export declare function isAction(thing: any): boolean;
|
@ -0,0 +1,19 @@
|
||||
import { ObservableObjectAdministration } from "../internal";
|
||||
export declare const enum MakeResult {
|
||||
Cancel = 0,
|
||||
Break = 1,
|
||||
Continue = 2
|
||||
}
|
||||
export type Annotation = {
|
||||
annotationType_: string;
|
||||
make_(adm: ObservableObjectAdministration, key: PropertyKey, descriptor: PropertyDescriptor, source: object): MakeResult;
|
||||
extend_(adm: ObservableObjectAdministration, key: PropertyKey, descriptor: PropertyDescriptor, proxyTrap: boolean): boolean | null;
|
||||
decorate_20223_(value: any, context: DecoratorContext): any;
|
||||
options_?: any;
|
||||
};
|
||||
export type AnnotationMapEntry = Annotation | true | false;
|
||||
export type AnnotationsMap<T, AdditionalFields extends PropertyKey> = {
|
||||
[P in Exclude<keyof T, "toString">]?: AnnotationMapEntry;
|
||||
} & Record<AdditionalFields, AnnotationMapEntry>;
|
||||
export declare function isAnnotation(thing: any): boolean;
|
||||
export declare function isAnnotationMapEntry(thing: any): boolean;
|
@ -0,0 +1,25 @@
|
||||
import { IEqualsComparer, IReactionDisposer, IReactionPublic, GenericAbortSignal } from "../internal";
|
||||
export interface IAutorunOptions {
|
||||
delay?: number;
|
||||
name?: string;
|
||||
/**
|
||||
* Experimental.
|
||||
* Warns if the view doesn't track observables
|
||||
*/
|
||||
requiresObservable?: boolean;
|
||||
scheduler?: (callback: () => void) => any;
|
||||
onError?: (error: any) => void;
|
||||
signal?: GenericAbortSignal;
|
||||
}
|
||||
/**
|
||||
* Creates a named reactive view and keeps it alive, so that the view is always
|
||||
* updated if one of the dependencies changes, even when the view is not further used by something else.
|
||||
* @param view The reactive view
|
||||
* @returns disposer function, which can be used to stop the view from being updated in the future.
|
||||
*/
|
||||
export declare function autorun(view: (r: IReactionPublic) => any, opts?: IAutorunOptions): IReactionDisposer;
|
||||
export type IReactionOptions<T, FireImmediately extends boolean> = IAutorunOptions & {
|
||||
fireImmediately?: FireImmediately;
|
||||
equals?: IEqualsComparer<T>;
|
||||
};
|
||||
export declare function reaction<T, FireImmediately extends boolean = false>(expression: (r: IReactionPublic) => T, effect: (arg: T, prev: FireImmediately extends true ? T | undefined : T, r: IReactionPublic) => void, opts?: IReactionOptions<T, FireImmediately>): IReactionDisposer;
|
@ -0,0 +1,5 @@
|
||||
import { IComputedValue, IObservable, IObservableArray, Lambda, ObservableMap, ObservableSet, IObservableValue } from "../internal";
|
||||
export declare function onBecomeObserved(value: IObservable | IComputedValue<any> | IObservableArray<any> | ObservableMap<any, any> | ObservableSet<any> | IObservableValue<any>, listener: Lambda): Lambda;
|
||||
export declare function onBecomeObserved<K, V = any>(value: ObservableMap<K, V> | Object, property: K, listener: Lambda): Lambda;
|
||||
export declare function onBecomeUnobserved(value: IObservable | IComputedValue<any> | IObservableArray<any> | ObservableMap<any, any> | ObservableSet<any> | IObservableValue<any>, listener: Lambda): Lambda;
|
||||
export declare function onBecomeUnobserved<K, V = any>(value: ObservableMap<K, V> | Object, property: K, listener: Lambda): Lambda;
|
@ -0,0 +1,14 @@
|
||||
import { IComputedValueOptions, Annotation, IComputedValue } from "../internal";
|
||||
import type { ClassGetterDecorator } from "../types/decorator_fills";
|
||||
export declare const COMPUTED = "computed";
|
||||
export declare const COMPUTED_STRUCT = "computed.struct";
|
||||
export interface IComputedFactory extends Annotation, PropertyDecorator, ClassGetterDecorator {
|
||||
<T>(options: IComputedValueOptions<T>): Annotation & PropertyDecorator & ClassGetterDecorator;
|
||||
<T>(func: () => T, options?: IComputedValueOptions<T>): IComputedValue<T>;
|
||||
struct: Annotation & PropertyDecorator & ClassGetterDecorator;
|
||||
}
|
||||
/**
|
||||
* Decorator for class properties: @computed get value() { return expr; }.
|
||||
* For legacy purposes also invokable as ES5 observable created: `computed(() => expr)`;
|
||||
*/
|
||||
export declare const computed: IComputedFactory;
|
@ -0,0 +1,17 @@
|
||||
export declare function configure(options: {
|
||||
enforceActions?: "never" | "always" | "observed";
|
||||
computedRequiresReaction?: boolean;
|
||||
/**
|
||||
* Warn if you try to create to derivation / reactive context without accessing any observable.
|
||||
*/
|
||||
reactionRequiresObservable?: boolean;
|
||||
/**
|
||||
* Warn if observables are accessed outside a reactive context
|
||||
*/
|
||||
observableRequiresReaction?: boolean;
|
||||
isolateGlobalState?: boolean;
|
||||
disableErrorBoundaries?: boolean;
|
||||
safeDescriptors?: boolean;
|
||||
reactionScheduler?: (f: () => void) => void;
|
||||
useProxies?: "always" | "never" | "ifavailable";
|
||||
}): void;
|
@ -0,0 +1,20 @@
|
||||
import { Annotation, AnnotationsMap } from "../internal";
|
||||
import type { Decorator } from "../types/decorator_fills";
|
||||
export declare const storedAnnotationsSymbol: unique symbol;
|
||||
/**
|
||||
* Creates a function that acts as
|
||||
* - decorator
|
||||
* - annotation object
|
||||
*/
|
||||
export declare function createDecoratorAnnotation<D extends Decorator = Decorator>(annotation: Annotation): PropertyDecorator & Annotation & D;
|
||||
/**
|
||||
* Stores annotation to prototype,
|
||||
* so it can be inspected later by `makeObservable` called from constructor
|
||||
*/
|
||||
export declare function storeAnnotation(prototype: any, key: PropertyKey, annotation: Annotation): void;
|
||||
/**
|
||||
* Collects annotations from prototypes and stores them on target (instance)
|
||||
*/
|
||||
export declare function collectStoredAnnotations(target: any): AnnotationsMap<any, any>;
|
||||
export declare function is20223Decorator(context: any): context is DecoratorContext;
|
||||
export declare function assert20223DecoratorType(context: DecoratorContext, types: DecoratorContext["kind"][]): void;
|
@ -0,0 +1,2 @@
|
||||
import { CreateObservableOptions, AnnotationsMap } from "../internal";
|
||||
export declare function extendObservable<A extends Object, B extends Object>(target: A, properties: B, annotations?: AnnotationsMap<B, never>, options?: CreateObservableOptions): A & B;
|
@ -0,0 +1,10 @@
|
||||
export interface IDependencyTree {
|
||||
name: string;
|
||||
dependencies?: IDependencyTree[];
|
||||
}
|
||||
export interface IObserverTree {
|
||||
name: string;
|
||||
observers?: IObserverTree[];
|
||||
}
|
||||
export declare function getDependencyTree(thing: any, property?: string): IDependencyTree;
|
||||
export declare function getObserverTree(thing: any, property?: string): IObserverTree;
|
@ -0,0 +1,19 @@
|
||||
import { Annotation } from "../internal";
|
||||
import type { ClassMethodDecorator } from "../types/decorator_fills";
|
||||
export declare const FLOW = "flow";
|
||||
export declare function FlowCancellationError(): void;
|
||||
export declare namespace FlowCancellationError {
|
||||
var prototype: any;
|
||||
}
|
||||
export declare function isFlowCancellationError(error: Error): boolean;
|
||||
export type CancellablePromise<T> = Promise<T> & {
|
||||
cancel(): void;
|
||||
};
|
||||
interface Flow extends Annotation, PropertyDecorator, ClassMethodDecorator {
|
||||
<R, Args extends any[]>(generator: (...args: Args) => Generator<any, R, any> | AsyncGenerator<any, R, any>): (...args: Args) => CancellablePromise<R>;
|
||||
bound: Annotation & PropertyDecorator & ClassMethodDecorator;
|
||||
}
|
||||
export declare const flow: Flow;
|
||||
export declare function flowResult<T>(result: T): T extends Generator<any, infer R, any> ? CancellablePromise<R> : T extends CancellablePromise<any> ? T : never;
|
||||
export declare function isFlow(fn: any): boolean;
|
||||
export {};
|
@ -0,0 +1,8 @@
|
||||
import { IObservableArray, IObservableValue, Lambda, ObservableMap, ObservableSet } from "../internal";
|
||||
export type ReadInterceptor<T> = (value: any) => T;
|
||||
/** Experimental feature right now, tested indirectly via Mobx-State-Tree */
|
||||
export declare function interceptReads<T>(value: IObservableValue<T>, handler: ReadInterceptor<T>): Lambda;
|
||||
export declare function interceptReads<T>(observableArray: IObservableArray<T>, handler: ReadInterceptor<T>): Lambda;
|
||||
export declare function interceptReads<K, V>(observableMap: ObservableMap<K, V>, handler: ReadInterceptor<V>): Lambda;
|
||||
export declare function interceptReads<V>(observableSet: ObservableSet<V>, handler: ReadInterceptor<V>): Lambda;
|
||||
export declare function interceptReads(object: Object, property: string, handler: ReadInterceptor<any>): Lambda;
|
@ -0,0 +1,8 @@
|
||||
import { IArrayWillChange, IArrayWillSplice, IInterceptor, IMapWillChange, IObjectWillChange, IObservableArray, IObservableValue, IValueWillChange, Lambda, ObservableMap, ObservableSet, ISetWillChange } from "../internal";
|
||||
export declare function intercept<T>(value: IObservableValue<T>, handler: IInterceptor<IValueWillChange<T>>): Lambda;
|
||||
export declare function intercept<T>(observableArray: IObservableArray<T> | Array<T>, handler: IInterceptor<IArrayWillChange<T> | IArrayWillSplice<T>>): Lambda;
|
||||
export declare function intercept<K, V>(observableMap: ObservableMap<K, V> | Map<K, V>, handler: IInterceptor<IMapWillChange<K, V>>): Lambda;
|
||||
export declare function intercept<V>(observableSet: ObservableSet<V> | Set<V>, handler: IInterceptor<ISetWillChange<V>>): Lambda;
|
||||
export declare function intercept<K, V>(observableMap: ObservableMap<K, V> | Map<K, V>, property: K, handler: IInterceptor<IValueWillChange<V>>): Lambda;
|
||||
export declare function intercept(object: object, handler: IInterceptor<IObjectWillChange>): Lambda;
|
||||
export declare function intercept<T extends object, K extends keyof T>(object: T, property: K, handler: IInterceptor<IValueWillChange<T[K]>>): Lambda;
|
@ -0,0 +1,3 @@
|
||||
export declare function _isComputed(value: any, property?: PropertyKey): boolean;
|
||||
export declare function isComputed(value: any): boolean;
|
||||
export declare function isComputedProp(value: any, propName: PropertyKey): boolean;
|
@ -0,0 +1,2 @@
|
||||
export declare function isObservable(value: any): boolean;
|
||||
export declare function isObservableProp(value: any, propName: PropertyKey): boolean;
|
@ -0,0 +1,6 @@
|
||||
import { AnnotationsMap, CreateObservableOptions } from "../internal";
|
||||
type NoInfer<T> = [T][T extends any ? 0 : never];
|
||||
type MakeObservableOptions = Omit<CreateObservableOptions, "proxy">;
|
||||
export declare function makeObservable<T extends object, AdditionalKeys extends PropertyKey = never>(target: T, annotations?: AnnotationsMap<T, NoInfer<AdditionalKeys>>, options?: MakeObservableOptions): T;
|
||||
export declare function makeAutoObservable<T extends object, AdditionalKeys extends PropertyKey = never>(target: T, overrides?: AnnotationsMap<T, NoInfer<AdditionalKeys>>, options?: MakeObservableOptions): T;
|
||||
export {};
|
@ -0,0 +1,36 @@
|
||||
import { IObservableArray, ObservableMap, ObservableSet } from "../internal";
|
||||
export declare function keys<K>(map: ObservableMap<K, any>): ReadonlyArray<K>;
|
||||
export declare function keys<T>(ar: IObservableArray<T>): ReadonlyArray<number>;
|
||||
export declare function keys<T>(set: ObservableSet<T>): ReadonlyArray<T>;
|
||||
export declare function keys<T extends Object>(obj: T): ReadonlyArray<PropertyKey>;
|
||||
export declare function values<K, T>(map: ObservableMap<K, T>): ReadonlyArray<T>;
|
||||
export declare function values<T>(set: ObservableSet<T>): ReadonlyArray<T>;
|
||||
export declare function values<T>(ar: IObservableArray<T>): ReadonlyArray<T>;
|
||||
export declare function values<T = any>(obj: T): ReadonlyArray<T extends object ? T[keyof T] : any>;
|
||||
export declare function entries<K, T>(map: ObservableMap<K, T>): ReadonlyArray<[K, T]>;
|
||||
export declare function entries<T>(set: ObservableSet<T>): ReadonlyArray<[T, T]>;
|
||||
export declare function entries<T>(ar: IObservableArray<T>): ReadonlyArray<[number, T]>;
|
||||
export declare function entries<T = any>(obj: T): ReadonlyArray<[string, T extends object ? T[keyof T] : any]>;
|
||||
export declare function set<V>(obj: ObservableMap<PropertyKey, V>, values: {
|
||||
[key: string]: V;
|
||||
}): any;
|
||||
export declare function set<K, V>(obj: ObservableMap<K, V>, key: K, value: V): any;
|
||||
export declare function set<T>(obj: ObservableSet<T>, value: T): any;
|
||||
export declare function set<T>(obj: IObservableArray<T>, index: number, value: T): any;
|
||||
export declare function set<T extends Object>(obj: T, values: {
|
||||
[key: string]: any;
|
||||
}): any;
|
||||
export declare function set<T extends Object>(obj: T, key: PropertyKey, value: any): any;
|
||||
export declare function remove<K, V>(obj: ObservableMap<K, V>, key: K): any;
|
||||
export declare function remove<T>(obj: ObservableSet<T>, key: T): any;
|
||||
export declare function remove<T>(obj: IObservableArray<T>, index: number): any;
|
||||
export declare function remove<T extends Object>(obj: T, key: string): any;
|
||||
export declare function has<K>(obj: ObservableMap<K, any>, key: K): boolean;
|
||||
export declare function has<T>(obj: ObservableSet<T>, key: T): boolean;
|
||||
export declare function has<T>(obj: IObservableArray<T>, index: number): boolean;
|
||||
export declare function has<T extends Object>(obj: T, key: string): boolean;
|
||||
export declare function get<K, V>(obj: ObservableMap<K, V>, key: K): V | undefined;
|
||||
export declare function get<T>(obj: IObservableArray<T>, index: number): T | undefined;
|
||||
export declare function get<T extends Object>(obj: T, key: string): any;
|
||||
export declare function apiDefineProperty(obj: Object, key: PropertyKey, descriptor: PropertyDescriptor): boolean | null;
|
||||
export declare function apiOwnKeys(obj: Object): (string | symbol)[];
|
@ -0,0 +1,45 @@
|
||||
import { IEnhancer, IEqualsComparer, IObservableArray, IObservableMapInitialValues, IObservableSetInitialValues, IObservableValue, ObservableMap, ObservableSet, Annotation, AnnotationsMap } from "../internal";
|
||||
import type { ClassAccessorDecorator, ClassFieldDecorator } from "../types/decorator_fills";
|
||||
export declare const OBSERVABLE = "observable";
|
||||
export declare const OBSERVABLE_REF = "observable.ref";
|
||||
export declare const OBSERVABLE_SHALLOW = "observable.shallow";
|
||||
export declare const OBSERVABLE_STRUCT = "observable.struct";
|
||||
export type CreateObservableOptions = {
|
||||
name?: string;
|
||||
equals?: IEqualsComparer<any>;
|
||||
deep?: boolean;
|
||||
defaultDecorator?: Annotation;
|
||||
proxy?: boolean;
|
||||
autoBind?: boolean;
|
||||
};
|
||||
export declare const defaultCreateObservableOptions: CreateObservableOptions;
|
||||
export declare function asCreateObservableOptions(thing: any): CreateObservableOptions;
|
||||
export declare function getEnhancerFromOptions(options: CreateObservableOptions): IEnhancer<any>;
|
||||
export declare function getAnnotationFromOptions(options?: CreateObservableOptions): Annotation | undefined;
|
||||
export declare function getEnhancerFromAnnotation(annotation?: Annotation): IEnhancer<any>;
|
||||
export interface IObservableValueFactory {
|
||||
<T>(value: T, options?: CreateObservableOptions): IObservableValue<T>;
|
||||
<T>(value?: T, options?: CreateObservableOptions): IObservableValue<T | undefined>;
|
||||
}
|
||||
export interface IObservableFactory extends Annotation, PropertyDecorator, ClassAccessorDecorator, ClassFieldDecorator {
|
||||
<T = any>(value: T[], options?: CreateObservableOptions): IObservableArray<T>;
|
||||
<T = any>(value: Set<T>, options?: CreateObservableOptions): ObservableSet<T>;
|
||||
<K = any, V = any>(value: Map<K, V>, options?: CreateObservableOptions): ObservableMap<K, V>;
|
||||
<T extends object>(value: T, decorators?: AnnotationsMap<T, never>, options?: CreateObservableOptions): T;
|
||||
box: IObservableValueFactory;
|
||||
array: <T = any>(initialValues?: T[], options?: CreateObservableOptions) => IObservableArray<T>;
|
||||
set: <T = any>(initialValues?: IObservableSetInitialValues<T>, options?: CreateObservableOptions) => ObservableSet<T>;
|
||||
map: <K = any, V = any>(initialValues?: IObservableMapInitialValues<K, V>, options?: CreateObservableOptions) => ObservableMap<K, V>;
|
||||
object: <T = any>(props: T, decorators?: AnnotationsMap<T, never>, options?: CreateObservableOptions) => T;
|
||||
/**
|
||||
* Decorator that creates an observable that only observes the references, but doesn't try to turn the assigned value into an observable.ts.
|
||||
*/
|
||||
ref: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator;
|
||||
/**
|
||||
* Decorator that creates an observable converts its value (objects, maps or arrays) into a shallow observable structure
|
||||
*/
|
||||
shallow: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator;
|
||||
deep: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator;
|
||||
struct: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator;
|
||||
}
|
||||
export declare var observable: IObservableFactory;
|
@ -0,0 +1,8 @@
|
||||
import { IArrayDidChange, IComputedValue, IMapDidChange, IObjectDidChange, IObservableArray, IObservableValue, IValueDidChange, Lambda, ObservableMap, ObservableSet, ISetDidChange } from "../internal";
|
||||
export declare function observe<T>(value: IObservableValue<T> | IComputedValue<T>, listener: (change: IValueDidChange<T>) => void, fireImmediately?: boolean): Lambda;
|
||||
export declare function observe<T>(observableArray: IObservableArray<T> | Array<T>, listener: (change: IArrayDidChange<T>) => void, fireImmediately?: boolean): Lambda;
|
||||
export declare function observe<V>(observableSet: ObservableSet<V> | Set<V>, listener: (change: ISetDidChange<V>) => void, fireImmediately?: boolean): Lambda;
|
||||
export declare function observe<K, V>(observableMap: ObservableMap<K, V> | Map<K, V>, listener: (change: IMapDidChange<K, V>) => void, fireImmediately?: boolean): Lambda;
|
||||
export declare function observe<K, V>(observableMap: ObservableMap<K, V> | Map<K, V>, property: K, listener: (change: IValueDidChange<V>) => void, fireImmediately?: boolean): Lambda;
|
||||
export declare function observe(object: Object, listener: (change: IObjectDidChange) => void, fireImmediately?: boolean): Lambda;
|
||||
export declare function observe<T, K extends keyof T>(object: T, property: K, listener: (change: IValueDidChange<T[K]>) => void, fireImmediately?: boolean): Lambda;
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Recursively converts an observable to it's non-observable native counterpart.
|
||||
* It does NOT recurse into non-observables, these are left as they are, even if they contain observables.
|
||||
* Computed and other non-enumerable properties are completely ignored.
|
||||
* Complex scenarios require custom solution, eg implementing `toJSON` or using `serializr` lib.
|
||||
*/
|
||||
export declare function toJS<T>(source: T, options?: any): T;
|
@ -0,0 +1,3 @@
|
||||
export declare function trace(thing?: any, prop?: string, enterBreakPoint?: boolean): void;
|
||||
export declare function trace(thing?: any, enterBreakPoint?: boolean): void;
|
||||
export declare function trace(enterBreakPoint?: boolean): void;
|
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* During a transaction no views are updated until the end of the transaction.
|
||||
* The transaction will be run synchronously nonetheless.
|
||||
*
|
||||
* @param action a function that updates some reactive state
|
||||
* @returns any value that was returned by the 'action' parameter.
|
||||
*/
|
||||
export declare function transaction<T>(action: () => T, thisArg?: undefined): T;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue