@async/framework 0.11.3 → 0.11.5

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/browser.ts CHANGED
@@ -1219,10 +1219,16 @@ const __signalsModule = (() => {
1219
1219
  let subscriptionCounter = 0;
1220
1220
  let effectCounter = 0;
1221
1221
 
1222
+ for (const id of entries.keys()) {
1223
+ if (asyncDescriptors.has(id)) {
1224
+ throw new Error(`Signal "${id}" is already registered.`);
1225
+ }
1226
+ }
1227
+
1222
1228
  const registry = attachRegistryInspection({
1223
1229
  register(id, signalLike) {
1224
1230
  assertId(id);
1225
- if (entries.has(id)) {
1231
+ if (entries.has(id) || asyncDescriptors.has(id)) {
1226
1232
  throw new Error(`Signal "${id}" is already registered.`);
1227
1233
  }
1228
1234
  const entry = normalizeSignal(signalLike);
@@ -1240,14 +1246,19 @@ const __signalsModule = (() => {
1240
1246
 
1241
1247
  unregister(id) {
1242
1248
  assertId(id);
1243
- if (!entries.has(id)) {
1249
+ const hadEntry = entries.has(id);
1250
+ const hadDescriptor = asyncDescriptors.has(id);
1251
+ if (!hadEntry && !hadDescriptor) {
1244
1252
  return false;
1245
1253
  }
1246
- registryCleanups.get(id)?.();
1247
- registryCleanups.delete(id);
1248
- entries.get(id)?._dispose?.();
1249
- entries.delete(id);
1250
- boundEntries.delete(id);
1254
+ if (hadEntry) {
1255
+ registryCleanups.get(id)?.();
1256
+ registryCleanups.delete(id);
1257
+ entries.get(id)?._dispose?.();
1258
+ entries.delete(id);
1259
+ boundEntries.delete(id);
1260
+ }
1261
+ asyncDescriptors.delete(id);
1251
1262
  return true;
1252
1263
  },
1253
1264
 
@@ -1409,6 +1420,24 @@ const __signalsModule = (() => {
1409
1420
  return requireEntry(entries, id);
1410
1421
  },
1411
1422
 
1423
+ _setPath(path, value) {
1424
+ const parsed = parseRootPath(path);
1425
+ if (!entries.has(parsed.id)) {
1426
+ if (asyncDescriptors.has(parsed.id)) {
1427
+ materializeAsyncSignal(parsed.id);
1428
+ } else {
1429
+ registry.register(parsed.id, createSignal(parsed.parts.length === 0 ? value : {}));
1430
+ }
1431
+ }
1432
+ const entry = requireEntry(entries, parsed.id);
1433
+ if (parsed.parts.length === 0) {
1434
+ return entry.set(value);
1435
+ }
1436
+ const nextValue = setPath(entry.value, parsed.parts, value);
1437
+ entry.set(nextValue);
1438
+ return value;
1439
+ },
1440
+
1412
1441
  _setContext(context = {}) {
1413
1442
  Object.assign(runtimeContext, context);
1414
1443
  return registry;
@@ -1421,6 +1450,9 @@ const __signalsModule = (() => {
1421
1450
  _adoptMany(map = {}) {
1422
1451
  for (const [id, signalLike] of Object.entries(map ?? {})) {
1423
1452
  if (!entries.has(id)) {
1453
+ if (asyncDescriptors.has(id)) {
1454
+ throw new Error(`Signal "${id}" is already registered.`);
1455
+ }
1424
1456
  const entry = cloneSignalDeclaration(signalLike);
1425
1457
  entries.set(id, entry);
1426
1458
  bindEntry(id, entry);
@@ -1465,6 +1497,14 @@ const __signalsModule = (() => {
1465
1497
  return { id, parts, path };
1466
1498
  }
1467
1499
 
1500
+ function parseRootPath(path) {
1501
+ if (typeof path !== "string" || path.length === 0) {
1502
+ throw new TypeError("Signal path must be a non-empty string.");
1503
+ }
1504
+ const [id, ...parts] = path.split(".");
1505
+ return { id, parts, path };
1506
+ }
1507
+
1468
1508
  function materializeAsyncSignal(id) {
1469
1509
  if (entries.has(id) || !asyncDescriptors.has(id)) {
1470
1510
  return;
@@ -5005,7 +5045,7 @@ const __appModule = (() => {
5005
5045
 
5006
5046
  if (result.signals) {
5007
5047
  for (const [path, value] of Object.entries(result.signals)) {
5008
- setOrRegisterSignal(signals, path, value);
5048
+ applySignalPatch(signals, path, value);
5009
5049
  }
5010
5050
  }
5011
5051
  if (result.cache?.browser) {
@@ -5283,8 +5323,9 @@ const __appModule = (() => {
5283
5323
 
5284
5324
  function applySnapshotToRuntime(runtime, snapshot = {}, options = {}) {
5285
5325
  const normalized = normalizeSnapshot(snapshot);
5286
- for (const [path, value] of Object.entries(normalized.signal)) {
5287
- setOrRegisterSignal(runtime.signals, path, value);
5326
+ mergeRegistryEntries(runtime, "asyncSignal", normalized.asyncSignal, null, options);
5327
+ for (const [id, value] of Object.entries(normalized.signal)) {
5328
+ restoreSignalEntry(runtime.signals, id, value);
5288
5329
  }
5289
5330
  runtime.browser.cache.restore(normalized.cache.browser);
5290
5331
  mergeRegistryEntries(runtime, "handler", normalized.handler, runtime.handlers, options);
@@ -5292,7 +5333,6 @@ const __appModule = (() => {
5292
5333
  mergeRegistryEntries(runtime, "partial", normalized.partial, runtime.partials, options);
5293
5334
  mergeRegistryEntries(runtime, "route", normalized.route, runtime.routes, options);
5294
5335
  mergeRegistryEntries(runtime, "component", normalized.component, runtime.components, options);
5295
- mergeRegistryEntries(runtime, "asyncSignal", normalized.asyncSignal, null, options);
5296
5336
  return runtime;
5297
5337
  }
5298
5338
 
@@ -5313,6 +5353,9 @@ const __appModule = (() => {
5313
5353
  return;
5314
5354
  }
5315
5355
  for (const [id, value] of Object.entries(entries)) {
5356
+ if (type === "asyncSignal" && runtime.signals?.has?.(id) && !runtime.registry.has(type, id)) {
5357
+ throw new Error(`Signal "${id}" is already registered.`);
5358
+ }
5316
5359
  registerSnapshotEntry(runtime.registry, type, id, value, options);
5317
5360
  }
5318
5361
  concreteRegistry?._adoptMany?.(entries);
@@ -5398,16 +5441,26 @@ const __appModule = (() => {
5398
5441
  }
5399
5442
  }
5400
5443
 
5401
- function setOrRegisterSignal(signals, path, value) {
5402
- const id = String(path).split(".")[0];
5444
+ function restoreSignalEntry(signals, id, value) {
5403
5445
  if (signals.has?.(id)) {
5404
- if (path === id) {
5405
- const entry = signals._entry?.(id);
5406
- if (typeof entry?._restore === "function" && isAsyncSignalSnapshot(value)) {
5407
- entry._restore(value);
5408
- return;
5409
- }
5446
+ const entry = signals._entry?.(id);
5447
+ if (typeof entry?._restore === "function" && isAsyncSignalSnapshot(value)) {
5448
+ entry._restore(value);
5449
+ return;
5410
5450
  }
5451
+ signals.set(id, value);
5452
+ return;
5453
+ }
5454
+ signals.register(id, createSignal(value));
5455
+ }
5456
+
5457
+ function applySignalPatch(signals, path, value) {
5458
+ if (typeof signals._setPath === "function") {
5459
+ signals._setPath(path, value);
5460
+ return;
5461
+ }
5462
+ const id = String(path).split(".")[0];
5463
+ if (signals.has?.(id)) {
5411
5464
  signals.set(path, value);
5412
5465
  return;
5413
5466
  }
package/browser.umd.js CHANGED
@@ -1229,10 +1229,16 @@
1229
1229
  let subscriptionCounter = 0;
1230
1230
  let effectCounter = 0;
1231
1231
 
1232
+ for (const id of entries.keys()) {
1233
+ if (asyncDescriptors.has(id)) {
1234
+ throw new Error(`Signal "${id}" is already registered.`);
1235
+ }
1236
+ }
1237
+
1232
1238
  const registry = attachRegistryInspection({
1233
1239
  register(id, signalLike) {
1234
1240
  assertId(id);
1235
- if (entries.has(id)) {
1241
+ if (entries.has(id) || asyncDescriptors.has(id)) {
1236
1242
  throw new Error(`Signal "${id}" is already registered.`);
1237
1243
  }
1238
1244
  const entry = normalizeSignal(signalLike);
@@ -1250,14 +1256,19 @@
1250
1256
 
1251
1257
  unregister(id) {
1252
1258
  assertId(id);
1253
- if (!entries.has(id)) {
1259
+ const hadEntry = entries.has(id);
1260
+ const hadDescriptor = asyncDescriptors.has(id);
1261
+ if (!hadEntry && !hadDescriptor) {
1254
1262
  return false;
1255
1263
  }
1256
- registryCleanups.get(id)?.();
1257
- registryCleanups.delete(id);
1258
- entries.get(id)?._dispose?.();
1259
- entries.delete(id);
1260
- boundEntries.delete(id);
1264
+ if (hadEntry) {
1265
+ registryCleanups.get(id)?.();
1266
+ registryCleanups.delete(id);
1267
+ entries.get(id)?._dispose?.();
1268
+ entries.delete(id);
1269
+ boundEntries.delete(id);
1270
+ }
1271
+ asyncDescriptors.delete(id);
1261
1272
  return true;
1262
1273
  },
1263
1274
 
@@ -1419,6 +1430,24 @@
1419
1430
  return requireEntry(entries, id);
1420
1431
  },
1421
1432
 
1433
+ _setPath(path, value) {
1434
+ const parsed = parseRootPath(path);
1435
+ if (!entries.has(parsed.id)) {
1436
+ if (asyncDescriptors.has(parsed.id)) {
1437
+ materializeAsyncSignal(parsed.id);
1438
+ } else {
1439
+ registry.register(parsed.id, createSignal(parsed.parts.length === 0 ? value : {}));
1440
+ }
1441
+ }
1442
+ const entry = requireEntry(entries, parsed.id);
1443
+ if (parsed.parts.length === 0) {
1444
+ return entry.set(value);
1445
+ }
1446
+ const nextValue = setPath(entry.value, parsed.parts, value);
1447
+ entry.set(nextValue);
1448
+ return value;
1449
+ },
1450
+
1422
1451
  _setContext(context = {}) {
1423
1452
  Object.assign(runtimeContext, context);
1424
1453
  return registry;
@@ -1431,6 +1460,9 @@
1431
1460
  _adoptMany(map = {}) {
1432
1461
  for (const [id, signalLike] of Object.entries(map ?? {})) {
1433
1462
  if (!entries.has(id)) {
1463
+ if (asyncDescriptors.has(id)) {
1464
+ throw new Error(`Signal "${id}" is already registered.`);
1465
+ }
1434
1466
  const entry = cloneSignalDeclaration(signalLike);
1435
1467
  entries.set(id, entry);
1436
1468
  bindEntry(id, entry);
@@ -1475,6 +1507,14 @@
1475
1507
  return { id, parts, path };
1476
1508
  }
1477
1509
 
1510
+ function parseRootPath(path) {
1511
+ if (typeof path !== "string" || path.length === 0) {
1512
+ throw new TypeError("Signal path must be a non-empty string.");
1513
+ }
1514
+ const [id, ...parts] = path.split(".");
1515
+ return { id, parts, path };
1516
+ }
1517
+
1478
1518
  function materializeAsyncSignal(id) {
1479
1519
  if (entries.has(id) || !asyncDescriptors.has(id)) {
1480
1520
  return;
@@ -5015,7 +5055,7 @@
5015
5055
 
5016
5056
  if (result.signals) {
5017
5057
  for (const [path, value] of Object.entries(result.signals)) {
5018
- setOrRegisterSignal(signals, path, value);
5058
+ applySignalPatch(signals, path, value);
5019
5059
  }
5020
5060
  }
5021
5061
  if (result.cache?.browser) {
@@ -5293,8 +5333,9 @@
5293
5333
 
5294
5334
  function applySnapshotToRuntime(runtime, snapshot = {}, options = {}) {
5295
5335
  const normalized = normalizeSnapshot(snapshot);
5296
- for (const [path, value] of Object.entries(normalized.signal)) {
5297
- setOrRegisterSignal(runtime.signals, path, value);
5336
+ mergeRegistryEntries(runtime, "asyncSignal", normalized.asyncSignal, null, options);
5337
+ for (const [id, value] of Object.entries(normalized.signal)) {
5338
+ restoreSignalEntry(runtime.signals, id, value);
5298
5339
  }
5299
5340
  runtime.browser.cache.restore(normalized.cache.browser);
5300
5341
  mergeRegistryEntries(runtime, "handler", normalized.handler, runtime.handlers, options);
@@ -5302,7 +5343,6 @@
5302
5343
  mergeRegistryEntries(runtime, "partial", normalized.partial, runtime.partials, options);
5303
5344
  mergeRegistryEntries(runtime, "route", normalized.route, runtime.routes, options);
5304
5345
  mergeRegistryEntries(runtime, "component", normalized.component, runtime.components, options);
5305
- mergeRegistryEntries(runtime, "asyncSignal", normalized.asyncSignal, null, options);
5306
5346
  return runtime;
5307
5347
  }
5308
5348
 
@@ -5323,6 +5363,9 @@
5323
5363
  return;
5324
5364
  }
5325
5365
  for (const [id, value] of Object.entries(entries)) {
5366
+ if (type === "asyncSignal" && runtime.signals?.has?.(id) && !runtime.registry.has(type, id)) {
5367
+ throw new Error(`Signal "${id}" is already registered.`);
5368
+ }
5326
5369
  registerSnapshotEntry(runtime.registry, type, id, value, options);
5327
5370
  }
5328
5371
  concreteRegistry?._adoptMany?.(entries);
@@ -5408,16 +5451,26 @@
5408
5451
  }
5409
5452
  }
5410
5453
 
5411
- function setOrRegisterSignal(signals, path, value) {
5412
- const id = String(path).split(".")[0];
5454
+ function restoreSignalEntry(signals, id, value) {
5413
5455
  if (signals.has?.(id)) {
5414
- if (path === id) {
5415
- const entry = signals._entry?.(id);
5416
- if (typeof entry?._restore === "function" && isAsyncSignalSnapshot(value)) {
5417
- entry._restore(value);
5418
- return;
5419
- }
5456
+ const entry = signals._entry?.(id);
5457
+ if (typeof entry?._restore === "function" && isAsyncSignalSnapshot(value)) {
5458
+ entry._restore(value);
5459
+ return;
5420
5460
  }
5461
+ signals.set(id, value);
5462
+ return;
5463
+ }
5464
+ signals.register(id, createSignal(value));
5465
+ }
5466
+
5467
+ function applySignalPatch(signals, path, value) {
5468
+ if (typeof signals._setPath === "function") {
5469
+ signals._setPath(path, value);
5470
+ return;
5471
+ }
5472
+ const id = String(path).split(".")[0];
5473
+ if (signals.has?.(id)) {
5421
5474
  signals.set(path, value);
5422
5475
  return;
5423
5476
  }