@rei-standard/amsg-sw 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -46,6 +46,7 @@ var DEFAULT_MULTIPART_OPTIONS = Object.freeze({
46
46
  var memoryMultipartPending = /* @__PURE__ */ new Map();
47
47
  var memoryMultipartDone = /* @__PURE__ */ new Map();
48
48
  var memoryMultipartChunks = /* @__PURE__ */ new Map();
49
+ var multipartLocks = /* @__PURE__ */ new Map();
49
50
  var REI_AMSG_POSTMESSAGE_TYPE = "REI_AMSG_PUSH";
50
51
  var REI_SW_EVENT = Object.freeze({
51
52
  CONTENT_RECEIVED: "rei-amsg-content-received",
@@ -146,8 +147,8 @@ async function dispatchBusinessPayload(sw, payload, defaults) {
146
147
  if (typeof defaults.onBusinessPayload === "function") {
147
148
  try {
148
149
  const result = defaults.onBusinessPayload(payload);
149
- if (result instanceof Promise) {
150
- work.push(result.catch((error) => {
150
+ if (result && typeof result.then === "function") {
151
+ work.push(Promise.resolve(result).catch((error) => {
151
152
  console.error("[rei-standard-amsg-sw] onBusinessPayload promise rejected:", error);
152
153
  }));
153
154
  }
@@ -222,7 +223,7 @@ function createNotificationFromPayload(payload, defaults) {
222
223
  };
223
224
  }
224
225
  const pushNotification = payload.notification && typeof payload.notification === "object" ? payload.notification : {};
225
- const title = pushNotification.title || payload.title || payload.contactName || "New notification";
226
+ const title = pushNotification.title || payload.title || payload.contactName && `\u6765\u81EA ${payload.contactName}` || "New notification";
226
227
  const body = pushNotification.body || payload.body || payload.message || "";
227
228
  const data = pushNotification.data && typeof pushNotification.data === "object" ? { ...pushNotification.data } : payload.data && typeof payload.data === "object" ? { ...payload.data } : {};
228
229
  if (data.payload == null) data.payload = payload;
@@ -266,6 +267,18 @@ function isMultipartPush(payload) {
266
267
  async function acceptMultipartChunk(sw, payload, options) {
267
268
  const normalized = normalizeMultipartChunk(payload, options);
268
269
  if (!normalized) return null;
270
+ const previous = multipartLocks.get(normalized.id) || Promise.resolve();
271
+ const current = previous.catch(() => void 0).then(() => acceptMultipartChunkInternal(sw, normalized, options));
272
+ multipartLocks.set(normalized.id, current);
273
+ try {
274
+ return await current;
275
+ } finally {
276
+ if (multipartLocks.get(normalized.id) === current) {
277
+ multipartLocks.delete(normalized.id);
278
+ }
279
+ }
280
+ }
281
+ async function acceptMultipartChunkInternal(sw, normalized, options) {
269
282
  if (normalized.expiresAt <= Date.now()) {
270
283
  await dispatchMultipartExpired(sw, {
271
284
  id: normalized.id,
package/dist/index.d.cts CHANGED
@@ -66,6 +66,7 @@ const DEFAULT_MULTIPART_OPTIONS = Object.freeze({
66
66
  const memoryMultipartPending = new Map();
67
67
  const memoryMultipartDone = new Map();
68
68
  const memoryMultipartChunks = new Map();
69
+ const multipartLocks = new Map();
69
70
 
70
71
  /**
71
72
  * Wire-level message type for SW → client postMessage envelopes.
@@ -220,8 +221,8 @@ async function dispatchBusinessPayload(sw, payload, defaults) {
220
221
  if (typeof defaults.onBusinessPayload === 'function') {
221
222
  try {
222
223
  const result = defaults.onBusinessPayload(payload);
223
- if (result instanceof Promise) {
224
- work.push(result.catch(error => {
224
+ if (result && typeof result.then === 'function') {
225
+ work.push(Promise.resolve(result).catch(error => {
225
226
  console.error('[rei-standard-amsg-sw] onBusinessPayload promise rejected:', error);
226
227
  }));
227
228
  }
@@ -345,7 +346,7 @@ function createNotificationFromPayload(payload, defaults) {
345
346
  const title =
346
347
  pushNotification.title ||
347
348
  payload.title ||
348
- payload.contactName ||
349
+ (payload.contactName && `来自 ${payload.contactName}`) ||
349
350
  'New notification';
350
351
  const body = pushNotification.body || payload.body || payload.message || '';
351
352
  const data = pushNotification.data && typeof pushNotification.data === 'object'
@@ -404,14 +405,31 @@ function isMultipartPush(payload) {
404
405
  }
405
406
 
406
407
  async function acceptMultipartChunk(sw, payload, options) {
408
+ const normalized = normalizeMultipartChunk(payload, options);
409
+ if (!normalized) return null;
410
+
411
+ const previous = multipartLocks.get(normalized.id) || Promise.resolve();
412
+ const current = previous
413
+ .catch(() => undefined)
414
+ .then(() => acceptMultipartChunkInternal(sw, normalized, options));
415
+
416
+ multipartLocks.set(normalized.id, current);
417
+ try {
418
+ return await current;
419
+ } finally {
420
+ if (multipartLocks.get(normalized.id) === current) {
421
+ multipartLocks.delete(normalized.id);
422
+ }
423
+ }
424
+ }
425
+
426
+ async function acceptMultipartChunkInternal(sw, normalized, options) {
407
427
  // State machine:
408
428
  // 1. Validate the transport envelope and reject expired chunks before storage.
409
429
  // 2. Drop already-completed multipart ids using the short-lived done marker.
410
430
  // 3. Expire any stale pending record for this id before accepting a new one.
411
431
  // 4. Store only new chunk indexes, track total received bytes, and wait.
412
432
  // 5. Once all indexes are present, restore original JSON and mark done.
413
- const normalized = normalizeMultipartChunk(payload, options);
414
- if (!normalized) return null;
415
433
  if (normalized.expiresAt <= Date.now()) {
416
434
  await dispatchMultipartExpired(sw, {
417
435
  id: normalized.id,
package/dist/index.d.ts CHANGED
@@ -66,6 +66,7 @@ const DEFAULT_MULTIPART_OPTIONS = Object.freeze({
66
66
  const memoryMultipartPending = new Map();
67
67
  const memoryMultipartDone = new Map();
68
68
  const memoryMultipartChunks = new Map();
69
+ const multipartLocks = new Map();
69
70
 
70
71
  /**
71
72
  * Wire-level message type for SW → client postMessage envelopes.
@@ -220,8 +221,8 @@ async function dispatchBusinessPayload(sw, payload, defaults) {
220
221
  if (typeof defaults.onBusinessPayload === 'function') {
221
222
  try {
222
223
  const result = defaults.onBusinessPayload(payload);
223
- if (result instanceof Promise) {
224
- work.push(result.catch(error => {
224
+ if (result && typeof result.then === 'function') {
225
+ work.push(Promise.resolve(result).catch(error => {
225
226
  console.error('[rei-standard-amsg-sw] onBusinessPayload promise rejected:', error);
226
227
  }));
227
228
  }
@@ -345,7 +346,7 @@ function createNotificationFromPayload(payload, defaults) {
345
346
  const title =
346
347
  pushNotification.title ||
347
348
  payload.title ||
348
- payload.contactName ||
349
+ (payload.contactName && `来自 ${payload.contactName}`) ||
349
350
  'New notification';
350
351
  const body = pushNotification.body || payload.body || payload.message || '';
351
352
  const data = pushNotification.data && typeof pushNotification.data === 'object'
@@ -404,14 +405,31 @@ function isMultipartPush(payload) {
404
405
  }
405
406
 
406
407
  async function acceptMultipartChunk(sw, payload, options) {
408
+ const normalized = normalizeMultipartChunk(payload, options);
409
+ if (!normalized) return null;
410
+
411
+ const previous = multipartLocks.get(normalized.id) || Promise.resolve();
412
+ const current = previous
413
+ .catch(() => undefined)
414
+ .then(() => acceptMultipartChunkInternal(sw, normalized, options));
415
+
416
+ multipartLocks.set(normalized.id, current);
417
+ try {
418
+ return await current;
419
+ } finally {
420
+ if (multipartLocks.get(normalized.id) === current) {
421
+ multipartLocks.delete(normalized.id);
422
+ }
423
+ }
424
+ }
425
+
426
+ async function acceptMultipartChunkInternal(sw, normalized, options) {
407
427
  // State machine:
408
428
  // 1. Validate the transport envelope and reject expired chunks before storage.
409
429
  // 2. Drop already-completed multipart ids using the short-lived done marker.
410
430
  // 3. Expire any stale pending record for this id before accepting a new one.
411
431
  // 4. Store only new chunk indexes, track total received bytes, and wait.
412
432
  // 5. Once all indexes are present, restore original JSON and mark done.
413
- const normalized = normalizeMultipartChunk(payload, options);
414
- if (!normalized) return null;
415
433
  if (normalized.expiresAt <= Date.now()) {
416
434
  await dispatchMultipartExpired(sw, {
417
435
  id: normalized.id,
package/dist/index.mjs CHANGED
@@ -20,6 +20,7 @@ var DEFAULT_MULTIPART_OPTIONS = Object.freeze({
20
20
  var memoryMultipartPending = /* @__PURE__ */ new Map();
21
21
  var memoryMultipartDone = /* @__PURE__ */ new Map();
22
22
  var memoryMultipartChunks = /* @__PURE__ */ new Map();
23
+ var multipartLocks = /* @__PURE__ */ new Map();
23
24
  var REI_AMSG_POSTMESSAGE_TYPE = "REI_AMSG_PUSH";
24
25
  var REI_SW_EVENT = Object.freeze({
25
26
  CONTENT_RECEIVED: "rei-amsg-content-received",
@@ -120,8 +121,8 @@ async function dispatchBusinessPayload(sw, payload, defaults) {
120
121
  if (typeof defaults.onBusinessPayload === "function") {
121
122
  try {
122
123
  const result = defaults.onBusinessPayload(payload);
123
- if (result instanceof Promise) {
124
- work.push(result.catch((error) => {
124
+ if (result && typeof result.then === "function") {
125
+ work.push(Promise.resolve(result).catch((error) => {
125
126
  console.error("[rei-standard-amsg-sw] onBusinessPayload promise rejected:", error);
126
127
  }));
127
128
  }
@@ -196,7 +197,7 @@ function createNotificationFromPayload(payload, defaults) {
196
197
  };
197
198
  }
198
199
  const pushNotification = payload.notification && typeof payload.notification === "object" ? payload.notification : {};
199
- const title = pushNotification.title || payload.title || payload.contactName || "New notification";
200
+ const title = pushNotification.title || payload.title || payload.contactName && `\u6765\u81EA ${payload.contactName}` || "New notification";
200
201
  const body = pushNotification.body || payload.body || payload.message || "";
201
202
  const data = pushNotification.data && typeof pushNotification.data === "object" ? { ...pushNotification.data } : payload.data && typeof payload.data === "object" ? { ...payload.data } : {};
202
203
  if (data.payload == null) data.payload = payload;
@@ -240,6 +241,18 @@ function isMultipartPush(payload) {
240
241
  async function acceptMultipartChunk(sw, payload, options) {
241
242
  const normalized = normalizeMultipartChunk(payload, options);
242
243
  if (!normalized) return null;
244
+ const previous = multipartLocks.get(normalized.id) || Promise.resolve();
245
+ const current = previous.catch(() => void 0).then(() => acceptMultipartChunkInternal(sw, normalized, options));
246
+ multipartLocks.set(normalized.id, current);
247
+ try {
248
+ return await current;
249
+ } finally {
250
+ if (multipartLocks.get(normalized.id) === current) {
251
+ multipartLocks.delete(normalized.id);
252
+ }
253
+ }
254
+ }
255
+ async function acceptMultipartChunkInternal(sw, normalized, options) {
243
256
  if (normalized.expiresAt <= Date.now()) {
244
257
  await dispatchMultipartExpired(sw, {
245
258
  id: normalized.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rei-standard/amsg-sw",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "ReiStandard Active Messaging service worker SDK — three-axis push schema (content / reasoning / tool_request / error) with per-kind client postMessage events",
5
5
  "repository": {
6
6
  "type": "git",