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.mjs CHANGED
@@ -1201,11 +1201,11 @@ var observeDiff = (obj, cb) => {
1201
1201
  // src/memorize.ts
1202
1202
  var Memorize = () => {
1203
1203
  const cache = /* @__PURE__ */ new WeakMap();
1204
- const isPromiseLike = (v) => v != null && typeof v.then === "function" && typeof v.catch === "function";
1204
+ const isPromiseLike2 = (v) => v != null && typeof v.then === "function" && typeof v.catch === "function";
1205
1205
  const getOrSet = (instance, compute) => {
1206
1206
  if (cache.has(instance)) return cache.get(instance);
1207
1207
  const result = compute();
1208
- if (isPromiseLike(result)) {
1208
+ if (isPromiseLike2(result)) {
1209
1209
  const wrapped = result.catch((err) => {
1210
1210
  cache.delete(instance);
1211
1211
  throw err;
@@ -1249,6 +1249,7 @@ var getMethodDescriptor = (cls, key) => {
1249
1249
  }
1250
1250
  return void 0;
1251
1251
  };
1252
+ var isPromiseLike = (value) => !!value && typeof value.then === "function";
1252
1253
  var AppContextCore = class {
1253
1254
  constructor() {
1254
1255
  this.provideRecords = [];
@@ -1256,22 +1257,98 @@ var AppContextCore = class {
1256
1257
  this.objectSteps = [];
1257
1258
  this.started = false;
1258
1259
  this.starting = false;
1259
- this.startingEntries = null;
1260
- this.createdRecords = null;
1261
- this.createdEntries = null;
1260
+ this.settleCursor = 0;
1261
+ this.recordEntries = /* @__PURE__ */ new Map();
1262
+ this.pendingInitQueue = [];
1263
+ this.pendingInitSet = /* @__PURE__ */ new Set();
1264
+ this.initializedEntries = /* @__PURE__ */ new Set();
1262
1265
  this.loadingRecords = /* @__PURE__ */ new Set();
1266
+ this.settlementChain = Promise.resolve();
1267
+ this.settlementError = null;
1268
+ this.settling = false;
1269
+ }
1270
+ assertSettlementHealthy() {
1271
+ if (this.settlementError) {
1272
+ throw this.settlementError;
1273
+ }
1274
+ }
1275
+ enqueueInit(entry) {
1276
+ if (this.initializedEntries.has(entry) || this.pendingInitSet.has(entry)) {
1277
+ return;
1278
+ }
1279
+ this.pendingInitSet.add(entry);
1280
+ this.pendingInitQueue.push(entry);
1281
+ }
1282
+ sortInitQueueByDeclarationOrder() {
1283
+ if (this.pendingInitQueue.length <= 1) return;
1284
+ const order = /* @__PURE__ */ new Map();
1285
+ let idx = 0;
1286
+ for (const record of this.provideRecords) {
1287
+ const entry = this.recordEntries.get(record);
1288
+ if (entry) order.set(entry, idx++);
1289
+ }
1290
+ this.pendingInitQueue.sort(
1291
+ (a, b) => (order.get(a) ?? Infinity) - (order.get(b) ?? Infinity)
1292
+ );
1293
+ }
1294
+ async constructPendingRecords() {
1295
+ while (this.settleCursor < this.provideRecords.length) {
1296
+ const record = this.provideRecords[this.settleCursor];
1297
+ this.settleCursor += 1;
1298
+ await this.createEntryFromRecord(record);
1299
+ }
1300
+ this.sortInitQueueByDeclarationOrder();
1301
+ }
1302
+ async settlePending() {
1303
+ await this.constructPendingRecords();
1304
+ while (this.pendingInitQueue.length > 0) {
1305
+ const entry = this.pendingInitQueue.shift();
1306
+ this.pendingInitSet.delete(entry);
1307
+ if (this.initializedEntries.has(entry)) {
1308
+ continue;
1309
+ }
1310
+ const inst = await entry.inst;
1311
+ entry.inst = inst;
1312
+ if (inst && typeof inst.init === "function") {
1313
+ await inst.init();
1314
+ }
1315
+ this.initializedEntries.add(entry);
1316
+ const remaining = this.pendingInitQueue.splice(0);
1317
+ await this.constructPendingRecords();
1318
+ this.pendingInitQueue.push(...remaining);
1319
+ }
1320
+ }
1321
+ scheduleSettlement() {
1322
+ const run = async () => {
1323
+ this.assertSettlementHealthy();
1324
+ this.settling = true;
1325
+ try {
1326
+ await this.settlePending();
1327
+ } catch (error) {
1328
+ this.settlementError = error;
1329
+ throw error;
1330
+ } finally {
1331
+ this.settling = false;
1332
+ }
1333
+ };
1334
+ const task = this.settlementChain.then(run, run);
1335
+ this.settlementChain = task.catch(() => void 0);
1336
+ return task;
1337
+ }
1338
+ triggerSettlement() {
1339
+ void this.scheduleSettlement();
1263
1340
  }
1264
1341
  findProvideRecord(key) {
1265
1342
  for (let i = 0; i < this.provideRecords.length; i += 1) {
1266
1343
  const record = this.provideRecords[i];
1267
- if (record.classRef === key && (!this.createdRecords || !this.createdRecords.has(record))) {
1344
+ if (record.classRef === key && !this.recordEntries.has(record)) {
1268
1345
  return record;
1269
1346
  }
1270
1347
  }
1271
1348
  return void 0;
1272
1349
  }
1273
1350
  createEntryFromRecord(record) {
1274
- const existing = this.createdEntries?.get(record);
1351
+ const existing = this.recordEntries.get(record);
1275
1352
  if (existing) {
1276
1353
  return existing;
1277
1354
  }
@@ -1286,11 +1363,10 @@ var AppContextCore = class {
1286
1363
  classRef: record.classRef,
1287
1364
  inst: record.factory(this)
1288
1365
  };
1289
- this.createdRecords?.add(record);
1290
- this.createdEntries?.set(record, entry);
1366
+ this.recordEntries.set(record, entry);
1291
1367
  this.registry.set(record.classRef, entry);
1292
- this.startingEntries?.push(entry);
1293
- if (entry.inst?.then && typeof entry.inst.then === "function") {
1368
+ this.enqueueInit(entry);
1369
+ if (isPromiseLike(entry.inst)) {
1294
1370
  return entry.inst.then((resolvedInst) => {
1295
1371
  entry.inst = resolvedInst;
1296
1372
  return entry;
@@ -1302,6 +1378,7 @@ var AppContextCore = class {
1302
1378
  }
1303
1379
  }
1304
1380
  provide(cls, ...args) {
1381
+ this.assertSettlementHealthy();
1305
1382
  const last = args[args.length - 1];
1306
1383
  const hasOptions = !!last && typeof last === "object" && ("provide" in last || "merge" in last || "useValue" in last || "useFactory" in last || "useClass" in last);
1307
1384
  const options = hasOptions ? last : void 0;
@@ -1366,11 +1443,12 @@ var AppContextCore = class {
1366
1443
  return this;
1367
1444
  }
1368
1445
  get(cls) {
1446
+ this.assertSettlementHealthy();
1369
1447
  let key = cls;
1370
1448
  if (!this.registry.has(key) && typeof cls === "function" && !cls.prototype) {
1371
1449
  key = cls();
1372
1450
  }
1373
- if (!this.registry.has(key) && this.starting) {
1451
+ if (!this.registry.has(key) && (this.starting || this.settling)) {
1374
1452
  const record = this.findProvideRecord(key);
1375
1453
  if (record) {
1376
1454
  this.createEntryFromRecord(record);
@@ -1386,14 +1464,10 @@ var AppContextCore = class {
1386
1464
  return await this.get(cls);
1387
1465
  }
1388
1466
  use(...ctxes) {
1467
+ this.assertSettlementHealthy();
1389
1468
  for (const ctx of ctxes) {
1390
1469
  const other = ctx;
1391
- if (this.started && !other?.started) {
1392
- throw new Error(
1393
- "Cannot use an unstarted context into a started context."
1394
- );
1395
- }
1396
- if (Array.isArray(other?.provideRecords)) {
1470
+ if (Array.isArray(other?.provideRecords) && !other?.started) {
1397
1471
  this.provideRecords.push(...other.provideRecords);
1398
1472
  }
1399
1473
  if (Array.isArray(other?.objectSteps)) {
@@ -1413,37 +1487,23 @@ var AppContextCore = class {
1413
1487
  return this;
1414
1488
  }
1415
1489
  define() {
1490
+ this.assertSettlementHealthy();
1491
+ if (this.started && !this.starting) {
1492
+ this.triggerSettlement();
1493
+ }
1416
1494
  return this;
1417
1495
  }
1418
1496
  async start() {
1419
1497
  if (this.started) {
1420
1498
  return this;
1421
1499
  }
1422
- const startedEntries = [];
1423
- const preloadedKeys = new Set(this.registry.keys());
1500
+ this.assertSettlementHealthy();
1424
1501
  this.starting = true;
1425
- this.startingEntries = startedEntries;
1426
- this.createdRecords = /* @__PURE__ */ new Set();
1427
- this.createdEntries = /* @__PURE__ */ new Map();
1428
1502
  try {
1429
- for (const record of this.provideRecords) {
1430
- if (preloadedKeys.has(record.classRef)) {
1431
- continue;
1432
- }
1433
- await this.createEntryFromRecord(record);
1434
- }
1435
- for (const entry of startedEntries) {
1436
- const inst = entry.inst;
1437
- if (inst && typeof inst.init === "function") {
1438
- await inst.init();
1439
- }
1440
- }
1503
+ await this.scheduleSettlement();
1441
1504
  this.started = true;
1442
1505
  return this;
1443
1506
  } finally {
1444
- this.createdEntries = null;
1445
- this.createdRecords = null;
1446
- this.startingEntries = null;
1447
1507
  this.starting = false;
1448
1508
  }
1449
1509
  }