nfkit 1.0.35 → 1.0.37

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
@@ -1249,11 +1249,11 @@ var observeDiff = (obj, cb) => {
1249
1249
  // src/memorize.ts
1250
1250
  var Memorize = () => {
1251
1251
  const cache = /* @__PURE__ */ new WeakMap();
1252
- const isPromiseLike = (v) => v != null && typeof v.then === "function" && typeof v.catch === "function";
1252
+ const isPromiseLike2 = (v) => v != null && typeof v.then === "function" && typeof v.catch === "function";
1253
1253
  const getOrSet = (instance, compute) => {
1254
1254
  if (cache.has(instance)) return cache.get(instance);
1255
1255
  const result = compute();
1256
- if (isPromiseLike(result)) {
1256
+ if (isPromiseLike2(result)) {
1257
1257
  const wrapped = result.catch((err) => {
1258
1258
  cache.delete(instance);
1259
1259
  throw err;
@@ -1297,6 +1297,7 @@ var getMethodDescriptor = (cls, key) => {
1297
1297
  }
1298
1298
  return void 0;
1299
1299
  };
1300
+ var isPromiseLike = (value) => !!value && typeof value.then === "function";
1300
1301
  var AppContextCore = class {
1301
1302
  constructor() {
1302
1303
  this.provideRecords = [];
@@ -1304,22 +1305,98 @@ var AppContextCore = class {
1304
1305
  this.objectSteps = [];
1305
1306
  this.started = false;
1306
1307
  this.starting = false;
1307
- this.startingEntries = null;
1308
- this.createdRecords = null;
1309
- this.createdEntries = null;
1308
+ this.settleCursor = 0;
1309
+ this.recordEntries = /* @__PURE__ */ new Map();
1310
+ this.pendingInitQueue = [];
1311
+ this.pendingInitSet = /* @__PURE__ */ new Set();
1312
+ this.initializedEntries = /* @__PURE__ */ new Set();
1310
1313
  this.loadingRecords = /* @__PURE__ */ new Set();
1314
+ this.settlementChain = Promise.resolve();
1315
+ this.settlementError = null;
1316
+ this.settling = false;
1317
+ }
1318
+ assertSettlementHealthy() {
1319
+ if (this.settlementError) {
1320
+ throw this.settlementError;
1321
+ }
1322
+ }
1323
+ enqueueInit(entry) {
1324
+ if (this.initializedEntries.has(entry) || this.pendingInitSet.has(entry)) {
1325
+ return;
1326
+ }
1327
+ this.pendingInitSet.add(entry);
1328
+ this.pendingInitQueue.push(entry);
1329
+ }
1330
+ sortInitQueueByDeclarationOrder() {
1331
+ if (this.pendingInitQueue.length <= 1) return;
1332
+ const order = /* @__PURE__ */ new Map();
1333
+ let idx = 0;
1334
+ for (const record of this.provideRecords) {
1335
+ const entry = this.recordEntries.get(record);
1336
+ if (entry) order.set(entry, idx++);
1337
+ }
1338
+ this.pendingInitQueue.sort(
1339
+ (a, b) => (order.get(a) ?? Infinity) - (order.get(b) ?? Infinity)
1340
+ );
1341
+ }
1342
+ async constructPendingRecords() {
1343
+ while (this.settleCursor < this.provideRecords.length) {
1344
+ const record = this.provideRecords[this.settleCursor];
1345
+ this.settleCursor += 1;
1346
+ await this.createEntryFromRecord(record);
1347
+ }
1348
+ this.sortInitQueueByDeclarationOrder();
1349
+ }
1350
+ async settlePending() {
1351
+ await this.constructPendingRecords();
1352
+ while (this.pendingInitQueue.length > 0) {
1353
+ const entry = this.pendingInitQueue.shift();
1354
+ this.pendingInitSet.delete(entry);
1355
+ if (this.initializedEntries.has(entry)) {
1356
+ continue;
1357
+ }
1358
+ const inst = await entry.inst;
1359
+ entry.inst = inst;
1360
+ if (inst && typeof inst.init === "function") {
1361
+ await inst.init();
1362
+ }
1363
+ this.initializedEntries.add(entry);
1364
+ const remaining = this.pendingInitQueue.splice(0);
1365
+ await this.constructPendingRecords();
1366
+ this.pendingInitQueue.push(...remaining);
1367
+ }
1368
+ }
1369
+ scheduleSettlement() {
1370
+ const run = async () => {
1371
+ this.assertSettlementHealthy();
1372
+ this.settling = true;
1373
+ try {
1374
+ await this.settlePending();
1375
+ } catch (error) {
1376
+ this.settlementError = error;
1377
+ throw error;
1378
+ } finally {
1379
+ this.settling = false;
1380
+ }
1381
+ };
1382
+ const task = this.settlementChain.then(run, run);
1383
+ this.settlementChain = task.catch(() => void 0);
1384
+ return task;
1385
+ }
1386
+ triggerSettlement() {
1387
+ void this.scheduleSettlement();
1311
1388
  }
1312
1389
  findProvideRecord(key) {
1313
1390
  for (let i = 0; i < this.provideRecords.length; i += 1) {
1314
1391
  const record = this.provideRecords[i];
1315
- if (record.classRef === key && (!this.createdRecords || !this.createdRecords.has(record))) {
1392
+ if (record.classRef === key && !this.recordEntries.has(record)) {
1316
1393
  return record;
1317
1394
  }
1318
1395
  }
1319
1396
  return void 0;
1320
1397
  }
1321
1398
  createEntryFromRecord(record) {
1322
- const existing = this.createdEntries?.get(record);
1399
+ const existing = this.recordEntries.get(record);
1323
1400
  if (existing) {
1324
1401
  return existing;
1325
1402
  }
@@ -1334,11 +1411,10 @@ var AppContextCore = class {
1334
1411
  classRef: record.classRef,
1335
1412
  inst: record.factory(this)
1336
1413
  };
1337
- this.createdRecords?.add(record);
1338
- this.createdEntries?.set(record, entry);
1414
+ this.recordEntries.set(record, entry);
1339
1415
  this.registry.set(record.classRef, entry);
1340
- this.startingEntries?.push(entry);
1341
- if (entry.inst?.then && typeof entry.inst.then === "function") {
1416
+ this.enqueueInit(entry);
1417
+ if (isPromiseLike(entry.inst)) {
1342
1418
  return entry.inst.then((resolvedInst) => {
1343
1419
  entry.inst = resolvedInst;
1344
1420
  return entry;
@@ -1350,6 +1426,7 @@ var AppContextCore = class {
1350
1426
  }
1351
1427
  }
1352
1428
  provide(cls, ...args) {
1429
+ this.assertSettlementHealthy();
1353
1430
  const last = args[args.length - 1];
1354
1431
  const hasOptions = !!last && typeof last === "object" && ("provide" in last || "merge" in last || "useValue" in last || "useFactory" in last || "useClass" in last);
1355
1432
  const options = hasOptions ? last : void 0;
@@ -1414,11 +1491,12 @@ var AppContextCore = class {
1414
1491
  return this;
1415
1492
  }
1416
1493
  get(cls) {
1494
+ this.assertSettlementHealthy();
1417
1495
  let key = cls;
1418
1496
  if (!this.registry.has(key) && typeof cls === "function" && !cls.prototype) {
1419
1497
  key = cls();
1420
1498
  }
1421
- if (!this.registry.has(key) && this.starting) {
1499
+ if (!this.registry.has(key) && (this.starting || this.settling)) {
1422
1500
  const record = this.findProvideRecord(key);
1423
1501
  if (record) {
1424
1502
  this.createEntryFromRecord(record);
@@ -1434,14 +1512,10 @@ var AppContextCore = class {
1434
1512
  return await this.get(cls);
1435
1513
  }
1436
1514
  use(...ctxes) {
1515
+ this.assertSettlementHealthy();
1437
1516
  for (const ctx of ctxes) {
1438
1517
  const other = ctx;
1439
- if (this.started && !other?.started) {
1440
- throw new Error(
1441
- "Cannot use an unstarted context into a started context."
1442
- );
1443
- }
1444
- if (Array.isArray(other?.provideRecords)) {
1518
+ if (Array.isArray(other?.provideRecords) && !other?.started) {
1445
1519
  this.provideRecords.push(...other.provideRecords);
1446
1520
  }
1447
1521
  if (Array.isArray(other?.objectSteps)) {
@@ -1461,37 +1535,23 @@ var AppContextCore = class {
1461
1535
  return this;
1462
1536
  }
1463
1537
  define() {
1538
+ this.assertSettlementHealthy();
1539
+ if (this.started && !this.starting) {
1540
+ this.triggerSettlement();
1541
+ }
1464
1542
  return this;
1465
1543
  }
1466
1544
  async start() {
1467
1545
  if (this.started) {
1468
1546
  return this;
1469
1547
  }
1470
- const startedEntries = [];
1471
- const preloadedKeys = new Set(this.registry.keys());
1548
+ this.assertSettlementHealthy();
1472
1549
  this.starting = true;
1473
- this.startingEntries = startedEntries;
1474
- this.createdRecords = /* @__PURE__ */ new Set();
1475
- this.createdEntries = /* @__PURE__ */ new Map();
1476
1550
  try {
1477
- for (const record of this.provideRecords) {
1478
- if (preloadedKeys.has(record.classRef)) {
1479
- continue;
1480
- }
1481
- await this.createEntryFromRecord(record);
1482
- }
1483
- for (const entry of startedEntries) {
1484
- const inst = entry.inst;
1485
- if (inst && typeof inst.init === "function") {
1486
- await inst.init();
1487
- }
1488
- }
1551
+ await this.scheduleSettlement();
1489
1552
  this.started = true;
1490
1553
  return this;
1491
1554
  } finally {
1492
- this.createdEntries = null;
1493
- this.createdRecords = null;
1494
- this.startingEntries = null;
1495
1555
  this.starting = false;
1496
1556
  }
1497
1557
  }