nfkit 1.0.25 → 1.0.26

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
@@ -1247,11 +1247,11 @@ var observeDiff = (obj, cb) => {
1247
1247
  // src/memorize.ts
1248
1248
  var Memorize = () => {
1249
1249
  const cache = /* @__PURE__ */ new WeakMap();
1250
- const isPromiseLike2 = (v) => v != null && typeof v.then === "function" && typeof v.catch === "function";
1250
+ const isPromiseLike = (v) => v != null && typeof v.then === "function" && typeof v.catch === "function";
1251
1251
  const getOrSet = (instance, compute) => {
1252
1252
  if (cache.has(instance)) return cache.get(instance);
1253
1253
  const result = compute();
1254
- if (isPromiseLike2(result)) {
1254
+ if (isPromiseLike(result)) {
1255
1255
  const wrapped = result.catch((err) => {
1256
1256
  cache.delete(instance);
1257
1257
  throw err;
@@ -1285,54 +1285,6 @@ var makeArray = (value) => {
1285
1285
  return Array.isArray(value) ? value : [value];
1286
1286
  };
1287
1287
 
1288
- // src/app-context/promise-utils.ts
1289
- var promiseStates = /* @__PURE__ */ new WeakMap();
1290
- var isPromiseLike = (value) => !!value && typeof value.then === "function";
1291
- var trackPromise = (promise) => {
1292
- const existing = promiseStates.get(promise);
1293
- if (existing) return existing;
1294
- const state = { status: "pending" };
1295
- promiseStates.set(promise, state);
1296
- promise.then(
1297
- (value) => {
1298
- state.status = "fulfilled";
1299
- state.value = value;
1300
- },
1301
- (error) => {
1302
- state.status = "rejected";
1303
- state.error = error;
1304
- }
1305
- );
1306
- return state;
1307
- };
1308
- var wrapMaybePromise = (value, options) => {
1309
- if (!isPromiseLike(value)) return value;
1310
- const promise = Promise.resolve(value);
1311
- const state = trackPromise(promise);
1312
- if (state.status === "fulfilled") return state.value;
1313
- if (state.status === "rejected") throw state.error;
1314
- return dualizeAny(
1315
- () => {
1316
- const current = trackPromise(promise);
1317
- if (current.status === "fulfilled") return current.value;
1318
- if (current.status === "rejected") throw current.error;
1319
- throwDualPending();
1320
- },
1321
- () => promise,
1322
- {
1323
- // Intentionally hide strict method return type here.
1324
- asyncMethods: Array.from(options?.methodKeys ?? [])
1325
- }
1326
- );
1327
- };
1328
- var createAsyncMethod = (inst, key) => (...args) => Promise.resolve(inst).then((resolved) => {
1329
- const fn = resolved?.[key];
1330
- if (typeof fn !== "function") {
1331
- throw new TypeError("Target method is not a function");
1332
- }
1333
- return fn.apply(resolved, args);
1334
- });
1335
-
1336
1288
  // src/app-context/app-context.ts
1337
1289
  var ProvidePrefix = "provide:";
1338
1290
  var getMethodDescriptor = (cls, key) => {
@@ -1344,52 +1296,27 @@ var getMethodDescriptor = (cls, key) => {
1344
1296
  }
1345
1297
  return void 0;
1346
1298
  };
1347
- var flushPendingSets = (entry) => {
1348
- if (isPromiseLike(entry.inst)) return;
1349
- if (!entry.pendingSets.length) return;
1350
- for (const item of entry.pendingSets) {
1351
- entry.inst[item.key] = item.value;
1352
- }
1353
- entry.pendingSets.length = 0;
1354
- };
1355
- var resolveEntryIfNeeded = async (entry) => {
1356
- if (isPromiseLike(entry.inst)) {
1357
- entry.inst = await entry.inst;
1358
- }
1359
- flushPendingSets(entry);
1360
- return entry.inst;
1361
- };
1362
1299
  var AppContextCore = class {
1363
1300
  constructor() {
1301
+ this.provideRecords = [];
1364
1302
  this.registry = /* @__PURE__ */ new Map();
1365
1303
  this.loadSeq = [];
1366
1304
  this.objectSteps = [];
1305
+ this.started = false;
1367
1306
  }
1368
1307
  provide(cls, ...args) {
1369
1308
  const last = args[args.length - 1];
1370
1309
  const hasOptions = !!last && typeof last === "object" && ("provide" in last || "merge" in last || "useValue" in last || "useFactory" in last || "useClass" in last);
1371
1310
  const options = hasOptions ? last : void 0;
1372
1311
  const _args = hasOptions ? args.slice(0, -1) : args;
1373
- const inst = options?.useValue ?? (options?.useFactory ? options.useFactory(this, ..._args) : new (options?.useClass ?? cls)(this, ..._args));
1374
1312
  const classRef = cls;
1375
1313
  const provideKey = options?.provide ? ProvidePrefix + String(options.provide) : void 0;
1376
- const methodKeys = /* @__PURE__ */ new Set();
1377
- for (const name of Object.getOwnPropertyNames(cls.prototype)) {
1378
- if (name === "constructor") continue;
1379
- const desc = Object.getOwnPropertyDescriptor(cls.prototype, name);
1380
- if (desc && typeof desc.value === "function") {
1381
- methodKeys.add(name);
1382
- }
1383
- }
1384
- const entry = {
1314
+ const factory = () => options?.useValue ?? (options?.useFactory ? options.useFactory(this, ..._args) : new (options?.useClass ?? cls)(this, ..._args));
1315
+ this.provideRecords.push({
1385
1316
  classRef,
1386
- inst,
1387
- methodKeys,
1388
- pendingSets: []
1389
- };
1390
- this.registry.set(classRef, entry);
1391
- if (provideKey) this.registry.set(provideKey, entry);
1392
- this.loadSeq.push(entry);
1317
+ factory,
1318
+ provideKey
1319
+ });
1393
1320
  if (options?.provide) {
1394
1321
  const prop = options.provide;
1395
1322
  const step = (ctx) => {
@@ -1398,7 +1325,7 @@ var AppContextCore = class {
1398
1325
  configurable: true,
1399
1326
  get: () => {
1400
1327
  const currentEntry = ctx.registry.get(classRef);
1401
- return wrapMaybePromise(currentEntry?.inst, { methodKeys });
1328
+ return currentEntry?.inst;
1402
1329
  }
1403
1330
  });
1404
1331
  };
@@ -1417,8 +1344,6 @@ var AppContextCore = class {
1417
1344
  get: () => {
1418
1345
  const currentEntry = ctx.registry.get(classRef);
1419
1346
  const currentInst = currentEntry?.inst;
1420
- if (isPromiseLike(currentInst))
1421
- return createAsyncMethod(currentInst, key);
1422
1347
  const fn = currentInst?.[key];
1423
1348
  return typeof fn === "function" ? fn.bind(currentInst) : fn;
1424
1349
  }
@@ -1430,25 +1355,12 @@ var AppContextCore = class {
1430
1355
  configurable: true,
1431
1356
  get: () => {
1432
1357
  const currentEntry = ctx.registry.get(classRef);
1433
- const target = wrapMaybePromise(currentEntry?.inst);
1434
- return target?.[key];
1358
+ return currentEntry?.inst?.[key];
1435
1359
  },
1436
1360
  set: (value) => {
1437
1361
  const currentEntry = ctx.registry.get(classRef);
1438
1362
  if (!currentEntry) return;
1439
- if (!isPromiseLike(currentEntry.inst)) {
1440
- currentEntry.inst[key] = value;
1441
- return;
1442
- }
1443
- const state = trackPromise(currentEntry.inst);
1444
- if (state.status === "fulfilled") {
1445
- currentEntry.inst = state.value;
1446
- flushPendingSets(currentEntry);
1447
- currentEntry.inst[key] = value;
1448
- return;
1449
- }
1450
- if (state.status === "rejected") throw state.error;
1451
- currentEntry.pendingSets.push({ key, value });
1363
+ currentEntry.inst[key] = value;
1452
1364
  }
1453
1365
  });
1454
1366
  };
@@ -1467,53 +1379,19 @@ var AppContextCore = class {
1467
1379
  throw new Error(`Service not provided: ${key?.name ?? cls.name}`);
1468
1380
  }
1469
1381
  const entry = this.registry.get(key);
1470
- const inst = entry.inst;
1471
- if (isPromiseLike(inst)) {
1472
- const state = trackPromise(inst);
1473
- if (state.status === "fulfilled") {
1474
- entry.inst = state.value;
1475
- flushPendingSets(entry);
1476
- return state.value;
1477
- }
1478
- if (state.status === "rejected") throw state.error;
1479
- return wrapMaybePromise(inst, {
1480
- methodKeys: entry.methodKeys
1481
- });
1482
- }
1483
- flushPendingSets(entry);
1484
- return inst;
1382
+ return entry.inst;
1485
1383
  }
1384
+ /**
1385
+ * @deprecated Use get() instead. getAsync() is no longer needed as all services are loaded synchronously during start().
1386
+ */
1486
1387
  async getAsync(cls) {
1487
- let key = cls;
1488
- if (!this.registry.has(key) && typeof cls === "function" && !cls.prototype) {
1489
- key = cls();
1490
- }
1491
- if (!this.registry.has(key)) {
1492
- throw new Error(`Service not provided: ${cls.name}`);
1493
- }
1494
- const entry = this.registry.get(key);
1495
- const resolved = await resolveEntryIfNeeded(entry);
1496
- return resolved;
1388
+ return this.get(cls);
1497
1389
  }
1498
1390
  use(...ctxes) {
1499
1391
  for (const ctx of ctxes) {
1500
1392
  const other = ctx;
1501
- const entryMap = /* @__PURE__ */ new Map();
1502
- if (Array.isArray(other?.loadSeq)) {
1503
- const copiedSeq = other.loadSeq.map((item) => ({
1504
- ...item,
1505
- methodKeys: new Set(item.methodKeys ?? []),
1506
- pendingSets: [...item.pendingSets ?? []]
1507
- }));
1508
- other.loadSeq.forEach((item, index) => {
1509
- entryMap.set(item, copiedSeq[index]);
1510
- });
1511
- this.loadSeq.push(...copiedSeq);
1512
- }
1513
- if (other?.registry instanceof Map) {
1514
- for (const [key, value] of other.registry.entries()) {
1515
- this.registry.set(key, entryMap.get(value) ?? value);
1516
- }
1393
+ if (Array.isArray(other?.provideRecords)) {
1394
+ this.provideRecords.push(...other.provideRecords);
1517
1395
  }
1518
1396
  if (Array.isArray(other?.objectSteps)) {
1519
1397
  this.objectSteps.push(...other.objectSteps);
@@ -1521,6 +1399,16 @@ var AppContextCore = class {
1521
1399
  step(this);
1522
1400
  }
1523
1401
  }
1402
+ if (other?.started) {
1403
+ if (Array.isArray(other?.loadSeq)) {
1404
+ this.loadSeq.push(...other.loadSeq);
1405
+ }
1406
+ if (other?.registry instanceof Map) {
1407
+ for (const [key, value] of other.registry.entries()) {
1408
+ this.registry.set(key, value);
1409
+ }
1410
+ }
1411
+ }
1524
1412
  }
1525
1413
  return this;
1526
1414
  }
@@ -1528,8 +1416,25 @@ var AppContextCore = class {
1528
1416
  return this;
1529
1417
  }
1530
1418
  async start() {
1419
+ if (this.started) {
1420
+ return this;
1421
+ }
1422
+ for (const record of this.provideRecords) {
1423
+ const inst = record.factory();
1424
+ const entry = {
1425
+ classRef: record.classRef,
1426
+ inst
1427
+ };
1428
+ this.registry.set(record.classRef, entry);
1429
+ if (record.provideKey) {
1430
+ this.registry.set(record.provideKey, entry);
1431
+ }
1432
+ this.loadSeq.push(entry);
1433
+ }
1531
1434
  for (const entry of this.loadSeq) {
1532
- await resolveEntryIfNeeded(entry);
1435
+ if (entry.inst && typeof entry.inst.then === "function") {
1436
+ entry.inst = await entry.inst;
1437
+ }
1533
1438
  }
1534
1439
  for (const entry of this.loadSeq) {
1535
1440
  const inst = entry.inst;
@@ -1537,6 +1442,7 @@ var AppContextCore = class {
1537
1442
  await inst.init();
1538
1443
  }
1539
1444
  }
1445
+ this.started = true;
1540
1446
  return this;
1541
1447
  }
1542
1448
  };