@pisell/pisellos 2.3.167 → 2.3.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ import type { CommittedProducts, ReplicatedProducts } from './types';
2
+ /** A separate committed view: failed writes must never leak into recovery snapshots. */
3
+ export declare class CommittedProductState {
4
+ private products;
5
+ private revision;
6
+ commit(change: ReplicatedProducts): CommittedProducts;
7
+ snapshot(): CommittedProducts;
8
+ }
@@ -0,0 +1,69 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
5
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
6
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
9
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
10
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
11
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
12
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
13
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
14
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
15
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
16
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
17
+ /** A separate committed view: failed writes must never leak into recovery snapshots. */
18
+ export var CommittedProductState = /*#__PURE__*/function () {
19
+ function CommittedProductState() {
20
+ _classCallCheck(this, CommittedProductState);
21
+ _defineProperty(this, "products", new Map());
22
+ _defineProperty(this, "revision", 0);
23
+ }
24
+ _createClass(CommittedProductState, [{
25
+ key: "commit",
26
+ value: function commit(change) {
27
+ var copy = structuredClone(change);
28
+ if (copy.kind === 'snapshot') this.products.clear();
29
+ var _iterator = _createForOfIteratorHelper(copy.deletedIds),
30
+ _step;
31
+ try {
32
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
33
+ var id = _step.value;
34
+ this.products.delete(id);
35
+ }
36
+ } catch (err) {
37
+ _iterator.e(err);
38
+ } finally {
39
+ _iterator.f();
40
+ }
41
+ var _iterator2 = _createForOfIteratorHelper(copy.upserts),
42
+ _step2;
43
+ try {
44
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
45
+ var product = _step2.value;
46
+ this.products.set(product.id, product);
47
+ }
48
+ } catch (err) {
49
+ _iterator2.e(err);
50
+ } finally {
51
+ _iterator2.f();
52
+ }
53
+ return _objectSpread(_objectSpread({}, copy), {}, {
54
+ revision: ++this.revision
55
+ });
56
+ }
57
+ }, {
58
+ key: "snapshot",
59
+ value: function snapshot() {
60
+ return {
61
+ kind: 'snapshot',
62
+ revision: this.revision,
63
+ upserts: structuredClone(_toConsumableArray(this.products.values())),
64
+ deletedIds: []
65
+ };
66
+ }
67
+ }]);
68
+ return CommittedProductState;
69
+ }();
@@ -32,6 +32,15 @@ export interface ProductSnapshot {
32
32
  cover?: ProductData['cover'];
33
33
  holder_config?: ProductData['holder_config'];
34
34
  }
35
+ /** Raw product data only; each screen applies its own query/pricing context. */
36
+ export interface ReplicatedProducts {
37
+ kind: 'snapshot' | 'delta';
38
+ upserts: ProductData[];
39
+ deletedIds: number[];
40
+ }
41
+ export interface CommittedProducts extends ReplicatedProducts {
42
+ revision: number;
43
+ }
35
44
  /**
36
45
  * 加载报价单商品价格参数
37
46
  */
@@ -96,7 +105,9 @@ export declare enum ProductsHooks {
96
105
  onProductSelected = "products:onProductSelected",
97
106
  onProductsPriceApplied = "products:onProductsPriceApplied",
98
107
  /** pubsub 同步批次处理完成后触发,Server 层监听此事件重新计算并推送 */
99
- onProductsSyncCompleted = "products:onProductsSyncCompleted"
108
+ onProductsSyncCompleted = "products:onProductsSyncCompleted",
109
+ onProductsCommitted = "products:onProductsCommitted",
110
+ onProductSyncDestroyed = "products:onProductSyncDestroyed"
100
111
  }
101
112
  /** pubsub 商品同步消息结构 */
102
113
  export interface ProductSyncMessage {
@@ -10,6 +10,8 @@
10
10
  * 商品轻量查询范围
11
11
  */
12
12
 
13
+ /** Raw product data only; each screen applies its own query/pricing context. */
14
+
13
15
  /**
14
16
  * 加载报价单商品价格参数
15
17
  */
@@ -35,6 +37,8 @@ export var ProductsHooks = /*#__PURE__*/function (ProductsHooks) {
35
37
  ProductsHooks["onProductSelected"] = "products:onProductSelected";
36
38
  ProductsHooks["onProductsPriceApplied"] = "products:onProductsPriceApplied";
37
39
  ProductsHooks["onProductsSyncCompleted"] = "products:onProductsSyncCompleted";
40
+ ProductsHooks["onProductsCommitted"] = "products:onProductsCommitted";
41
+ ProductsHooks["onProductSyncDestroyed"] = "products:onProductSyncDestroyed";
38
42
  return ProductsHooks;
39
43
  }({});
40
44
 
@@ -1 +1,46 @@
1
- "use strict";
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "BUY_X_GET_Y_FREE_STRATEGY", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _examples.BUY_X_GET_Y_FREE_STRATEGY;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "ITEM_REWARD_STRATEGY", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _examples.ITEM_REWARD_STRATEGY;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "PromotionAdapter", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _adapter.PromotionAdapter;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "PromotionEvaluator", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _evaluator.PromotionEvaluator;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "X_ITEMS_FOR_Y_PRICE_STRATEGY", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _examples.X_ITEMS_FOR_Y_PRICE_STRATEGY;
34
+ }
35
+ });
36
+ Object.defineProperty(exports, "default", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _adapter.default;
40
+ }
41
+ });
42
+ var _evaluator = require("./evaluator");
43
+ var _adapter = _interopRequireWildcard(require("./adapter"));
44
+ var _examples = require("./examples");
45
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
46
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -540,7 +540,7 @@ class Server {
540
540
 
541
541
  // 监听 ProductsModule 同步完成事件,重新计算并推送查询结果
542
542
  this.core.effects.on(_types2.ProductsHooks.onProductsSyncCompleted, payload => {
543
- this.recomputeAndNotifyProductQuery({
543
+ return this.recomputeAndNotifyProductQuery({
544
544
  changedIds: payload?.changedIds
545
545
  });
546
546
  });
@@ -6247,7 +6247,7 @@ class Server {
6247
6247
  const result = await this.computeProductQueryResult(subscriber.context, {
6248
6248
  changedIds: options?.changedIds
6249
6249
  });
6250
- subscriber.callback(result);
6250
+ await subscriber.callback(result);
6251
6251
  this.logInfo('recomputeAndNotifyProductQuery: 已推送', {
6252
6252
  subscriberId
6253
6253
  });
@@ -3,6 +3,7 @@ import { BaseModule } from '../../../modules/BaseModule';
3
3
  import { ProductData } from '../../../modules/Product/types';
4
4
  import type { RouteDefinition } from '../../types';
5
5
  import { ProductIdScope, type ProductSnapshot, ProductFormatter, ProductFormatterContext } from './types';
6
+ import type { CommittedProducts, ReplicatedProducts } from './types';
6
7
  /**
7
8
  * Products 模块 - 用于获取和管理完整的商品详细数据
8
9
  * 相比 ProductList 模块,Products 会获取所有详细信息并缓存
@@ -40,6 +41,26 @@ export declare class ProductsModule extends BaseModule implements Module {
40
41
  private productIndexDBSaveQueue;
41
42
  /** 最近一次智能定价评估提取的 schedule 变价时间点(HH:mm),供 Server 订阅定时刷新使用 */
42
43
  private lastScheduleTimePoints;
44
+ private committedProductState?;
45
+ private productReplicationSourceGeneration;
46
+ private productPersistenceFailed;
47
+ private runtimeSyncMode;
48
+ private runtimeSyncGeneration;
49
+ private requestReplicaRefresh?;
50
+ private replicaApplyQueue;
51
+ private productSyncQueue;
52
+ private replicaPriceDirtyIds;
53
+ /** Installed after initial preload; initial cache/network loading stays unchanged. */
54
+ setRuntimeSyncMode(mode: 'normal' | 'memoryReplica', requestRefresh?: (trigger: string) => Promise<void>): Promise<void>;
55
+ isMemoryReplica(): boolean;
56
+ /** Read persisted data once on the main screen to establish a committed baseline. */
57
+ enableProductReplicationSource(): Promise<void>;
58
+ /** Release the extra catalog without changing the normal product store or persistence. */
59
+ disableProductReplicationSource(): void;
60
+ getCommittedProductSnapshot(): CommittedProducts | null;
61
+ private recordProductCommit;
62
+ applyReplicatedProducts(change: ReplicatedProducts): Promise<void>;
63
+ private refreshFromReplica;
43
64
  constructor(name?: string, version?: string);
44
65
  initialize(core: PisellCore, options: any): Promise<void>;
45
66
  /**
@@ -230,7 +251,10 @@ export declare class ProductsModule extends BaseModule implements Module {
230
251
  * 根据 ID 列表删除商品(用于 pubsub 同步删除场景)
231
252
  * 同时更新 store.list、store.map、IndexDB 和价格缓存
232
253
  */
233
- removeProductsByIds(ids: number[]): Promise<void>;
254
+ removeProductsByIds(ids: number[], options?: {
255
+ skipIndexDB?: boolean;
256
+ skipEmit?: boolean;
257
+ }): Promise<void>;
234
258
  /**
235
259
  * 重新从服务器加载全量商品列表并更新本地 store
236
260
  * 用于 pubsub 同步 create / update / batch_update 场景
@@ -261,13 +285,8 @@ export declare class ProductsModule extends BaseModule implements Module {
261
285
  * await this.replaceProductsSnapshotInIndexDB(list, 'loadProductsByServer')
262
286
  */
263
287
  private replaceProductsSnapshotInIndexDB;
264
- /**
265
- * 增量 upsert 商品到 IndexDB,不清空表;用于 pubsub 批次合并后的变更商品。
266
- *
267
- * @example
268
- * await this.patchProductsInIndexDB(changedProducts, 'pubsub.processProductSyncMessages', mergeActions)
269
- */
270
288
  private patchProductsInIndexDB;
289
+ private persistProductDelta;
271
290
  /**
272
291
  * 同步更新商品 Map 缓存
273
292
  * 将 list 中的商品同步到 map,以 id 为 key
@@ -309,6 +328,7 @@ export declare class ProductsModule extends BaseModule implements Module {
309
328
  * Server 层监听该事件后对变更商品增量执行 prepareProductsWithPrice 并更新缓存
310
329
  */
311
330
  private processProductSyncMessages;
331
+ private processProductSyncBatch;
312
332
  /**
313
333
  * 通过 SSE 按 ids 增量拉取商品数据
314
334
  * 请求 GET /shop/core/stream?type=product&ids={ids}
@@ -342,6 +362,7 @@ export declare class ProductsModule extends BaseModule implements Module {
342
362
  * 销毁同步资源(取消 pubsub 订阅、清除定时器)
343
363
  */
344
364
  destroyProductSync(): void;
365
+ destroy(): void;
345
366
  /**
346
367
  * 获取模块的路由定义
347
368
  * Products 模块暂不提供路由,由 Server 层统一处理