@logixjs/react 0.1.1 → 1.0.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.
@@ -1,13 +1,14 @@
1
1
  import {
2
2
  useModule,
3
3
  useRuntime
4
- } from "./chunk-G2LX7WWQ.js";
4
+ } from "./chunk-E3ZXST5F.js";
5
5
  import {
6
6
  RuntimeProvider
7
- } from "./chunk-2M6MDNVT.js";
7
+ } from "./chunk-XSGDBJXD.js";
8
8
 
9
9
  // src/ModuleScope.ts
10
10
  import React from "react";
11
+ import { Effect } from "effect";
11
12
  import * as Logix from "@logixjs/core";
12
13
  var makeModuleScope = (handle, defaults) => {
13
14
  const Context = React.createContext(null);
@@ -17,7 +18,9 @@ var makeModuleScope = (handle, defaults) => {
17
18
  };
18
19
  const getRegistryOrThrow = (runtime, where) => {
19
20
  try {
20
- const registry = runtime.runSync(Logix.ScopeRegistry.ScopeRegistryTag);
21
+ const registry = runtime.runSync(
22
+ Effect.service(Logix.ScopeRegistry.ScopeRegistryTag).pipe(Effect.orDie)
23
+ );
21
24
  if (!registry) {
22
25
  throw new Error("ScopeRegistry service is undefined");
23
26
  }
@@ -4,16 +4,16 @@ import {
4
4
  getModuleCache,
5
5
  isDevEnv,
6
6
  useLayerBinding
7
- } from "./chunk-2WFULYPJ.js";
7
+ } from "./chunk-L7KTYBXN.js";
8
8
 
9
9
  // src/internal/provider/RuntimeProvider.tsx
10
10
  import React2, { useContext, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
11
- import { Layer as Layer2, Effect as Effect2, Cause, FiberRef, Context as Context2, Scope } from "effect";
11
+ import { Cause, Effect as Effect2, Layer as Layer2, Scope, ServiceMap as ServiceMap2 } from "effect";
12
12
  import * as Logix2 from "@logixjs/core";
13
13
 
14
14
  // src/internal/provider/config.ts
15
- import { Config, Context, Effect, Layer, Option } from "effect";
16
- var ReactRuntimeConfigTag = class extends Context.Tag("@logixjs/react/RuntimeConfig")() {
15
+ import { Config, Effect, Layer, Option, ServiceMap } from "effect";
16
+ var ReactRuntimeConfigTag = class extends ServiceMap.Service()("@logixjs/react/RuntimeConfig") {
17
17
  };
18
18
  var DEFAULT_CONFIG = {
19
19
  gcTime: 500,
@@ -394,6 +394,9 @@ var RuntimeProvider = ({
394
394
  }) => {
395
395
  const parent = useContext(RuntimeContext);
396
396
  const baseRuntime = useRuntimeResolution(runtime, parent);
397
+ const providerStartedAtRef = React2.useRef(performance.now());
398
+ const providerReadyAtRef = React2.useRef(void 0);
399
+ const didReportProviderGatingRef = React2.useRef(false);
397
400
  const resolvedPolicy = useMemo(
398
401
  () => resolveRuntimeProviderPolicy({
399
402
  policy,
@@ -433,7 +436,7 @@ var RuntimeProvider = ({
433
436
  moduleId: event.moduleId,
434
437
  instanceId: event.instanceId,
435
438
  runtimeLabel: event.runtimeLabel
436
- }).pipe(Effect2.catchAllCause(() => Effect2.void));
439
+ }).pipe(Effect2.catchCause(() => Effect2.void));
437
440
  }
438
441
  if (event.type === "diagnostic" && event.severity === "error") {
439
442
  return handler(
@@ -452,7 +455,7 @@ var RuntimeProvider = ({
452
455
  instanceId: event.instanceId,
453
456
  runtimeLabel: event.runtimeLabel
454
457
  }
455
- ).pipe(Effect2.catchAllCause(() => Effect2.void));
458
+ ).pipe(Effect2.catchCause(() => Effect2.void));
456
459
  }
457
460
  return Effect2.void;
458
461
  }
@@ -467,9 +470,7 @@ var RuntimeProvider = ({
467
470
  return layerBinding.debugSinks;
468
471
  }
469
472
  try {
470
- return baseRuntime.runSync(
471
- FiberRef.get(Logix2.Debug.internal.currentDebugSinks)
472
- );
473
+ return baseRuntime.runSync(Effect2.service(Logix2.Debug.internal.currentDebugSinks).pipe(Effect2.orDie));
473
474
  } catch {
474
475
  return [];
475
476
  }
@@ -596,6 +597,41 @@ var RuntimeProvider = ({
596
597
  const resolveFallback = (phase) => {
597
598
  return resolveRuntimeProviderFallback({ fallback, phase, policyMode: resolvedPolicy.mode });
598
599
  };
600
+ const preloadCache = useMemo(
601
+ () => getModuleCache(runtimeWithBindings, configState.snapshot, configState.version),
602
+ [runtimeWithBindings, configState.snapshot, configState.version]
603
+ );
604
+ const syncWarmPreloadReady = useMemo(() => {
605
+ if (resolvedPolicy.mode !== "defer") return false;
606
+ if (!resolvedPolicy.preload) return true;
607
+ if (!isLayerReady || !isConfigReady) return false;
608
+ const handles = resolvedPolicy.preload.handles;
609
+ if (handles.length === 0) return true;
610
+ for (const handle of handles) {
611
+ if (handle?._tag === "ModuleImpl") {
612
+ const moduleId = handle.module?.id ?? "ModuleImpl";
613
+ const key2 = resolvedPolicy.preload.keysByModuleId.get(moduleId) ?? getPreloadKeyForModuleId(moduleId);
614
+ const factory2 = (scope) => Layer2.buildWithScope(handle.layer, scope).pipe(
615
+ Effect2.map((context) => ServiceMap2.get(context, handle.module))
616
+ );
617
+ const value2 = preloadCache.warmSync(key2, factory2, configState.snapshot.gcTime, moduleId, {
618
+ entrypoint: "react.runtime.preload.sync-warm",
619
+ policyMode: "defer"
620
+ });
621
+ if (!value2) return false;
622
+ continue;
623
+ }
624
+ const tagId = handle.id ?? "ModuleTag";
625
+ const key = resolvedPolicy.preload.keysByTagId.get(tagId) ?? getPreloadKeyForTagId(tagId);
626
+ const factory = (scope) => Scope.provide(scope)(Effect2.service(handle).pipe(Effect2.orDie));
627
+ const value = preloadCache.warmSync(key, factory, configState.snapshot.gcTime, tagId, {
628
+ entrypoint: "react.runtime.preload.sync-warm",
629
+ policyMode: "defer"
630
+ });
631
+ if (!value) return false;
632
+ }
633
+ return true;
634
+ }, [resolvedPolicy, isLayerReady, isConfigReady, preloadCache, configState.snapshot.gcTime]);
599
635
  const [deferReady, setDeferReady] = useState2(false);
600
636
  useEffect2(() => {
601
637
  if (resolvedPolicy.mode !== "defer") {
@@ -609,6 +645,10 @@ var RuntimeProvider = ({
609
645
  if (resolvedPolicy.mode !== "defer") {
610
646
  return;
611
647
  }
648
+ if (syncWarmPreloadReady) {
649
+ setDeferReady(true);
650
+ return;
651
+ }
612
652
  setDeferReady(false);
613
653
  if (!resolvedPolicy.preload) {
614
654
  setDeferReady(true);
@@ -618,7 +658,7 @@ var RuntimeProvider = ({
618
658
  return;
619
659
  }
620
660
  let cancelled = false;
621
- const cache = getModuleCache(runtimeWithBindings, configState.snapshot, configState.version);
661
+ const cache = preloadCache;
622
662
  const preloadHandles = resolvedPolicy.preload.handles;
623
663
  if (preloadHandles.length === 0) {
624
664
  setDeferReady(true);
@@ -636,13 +676,14 @@ var RuntimeProvider = ({
636
676
  const moduleId = handle.module?.id ?? "ModuleImpl";
637
677
  const key2 = resolvedPolicy.preload.keysByModuleId.get(moduleId) ?? getPreloadKeyForModuleId(moduleId);
638
678
  const factory2 = (scope) => Layer2.buildWithScope(handle.layer, scope).pipe(
639
- Effect2.map((context) => Context2.get(context, handle.module))
679
+ Effect2.map((context) => ServiceMap2.get(context, handle.module))
640
680
  );
641
681
  const op2 = cache.preload(key2, factory2, {
642
682
  ownerId: moduleId,
643
683
  yield: resolvedPolicy.preload.yield,
644
684
  entrypoint: "react.runtime.preload",
645
- policyMode: "defer"
685
+ policyMode: "defer",
686
+ optimisticSyncBudgetMs: resolvedPolicy.syncBudgetMs
646
687
  });
647
688
  allCancels.add(op2.cancel);
648
689
  await op2.promise;
@@ -667,14 +708,13 @@ var RuntimeProvider = ({
667
708
  }
668
709
  const tagId = handle.id ?? "ModuleTag";
669
710
  const key = resolvedPolicy.preload.keysByTagId.get(tagId) ?? getPreloadKeyForTagId(tagId);
670
- const factory = (scope) => handle.pipe(
671
- Scope.extend(scope)
672
- );
711
+ const factory = (scope) => Scope.provide(scope)(Effect2.service(handle).pipe(Effect2.orDie));
673
712
  const op = cache.preload(key, factory, {
674
713
  ownerId: tagId,
675
714
  yield: resolvedPolicy.preload.yield,
676
715
  entrypoint: "react.runtime.preload",
677
- policyMode: "defer"
716
+ policyMode: "defer",
717
+ optimisticSyncBudgetMs: resolvedPolicy.syncBudgetMs
678
718
  });
679
719
  allCancels.add(op.cancel);
680
720
  await op.promise;
@@ -712,7 +752,7 @@ var RuntimeProvider = ({
712
752
  if (cancelled) return;
713
753
  if (onErrorRef.current) {
714
754
  runtimeWithBindings.runFork(
715
- onErrorRef.current(Cause.die(error), { source: "provider", phase: "provider.layer.build" }).pipe(Effect2.catchAllCause(() => Effect2.void))
755
+ onErrorRef.current(Cause.die(error), { source: "provider", phase: "provider.layer.build" }).pipe(Effect2.catchCause(() => Effect2.void))
716
756
  );
717
757
  }
718
758
  setDeferReady(true);
@@ -745,13 +785,54 @@ var RuntimeProvider = ({
745
785
  release();
746
786
  };
747
787
  }, [resolvedPolicy.mode, deferReady]);
748
- const isReady = isTickServicesReady && isLayerReady && isConfigReady && (resolvedPolicy.mode !== "defer" || deferReady);
788
+ const isReady = isTickServicesReady && isLayerReady && isConfigReady && (resolvedPolicy.mode !== "defer" || deferReady || syncWarmPreloadReady);
789
+ if (isReady && providerReadyAtRef.current === void 0) {
790
+ providerReadyAtRef.current = performance.now();
791
+ }
792
+ useEffect2(() => {
793
+ if (!isReady) {
794
+ return;
795
+ }
796
+ if (didReportProviderGatingRef.current) {
797
+ return;
798
+ }
799
+ let diagnosticsLevel = "off";
800
+ try {
801
+ diagnosticsLevel = runtimeWithBindings.runSync(
802
+ Effect2.service(Logix2.Debug.internal.currentDiagnosticsLevel).pipe(Effect2.orDie)
803
+ );
804
+ } catch {
805
+ diagnosticsLevel = isDevEnv() ? "light" : "off";
806
+ }
807
+ if (diagnosticsLevel === "off") {
808
+ return;
809
+ }
810
+ didReportProviderGatingRef.current = true;
811
+ const readyAt = providerReadyAtRef.current ?? performance.now();
812
+ const durationMs = Math.round((readyAt - providerStartedAtRef.current) * 100) / 100;
813
+ const effectDelayMs = Math.round((performance.now() - readyAt) * 100) / 100;
814
+ void runtimeWithBindings.runPromise(
815
+ Logix2.Debug.record({
816
+ type: "trace:react.provider.gating",
817
+ data: {
818
+ event: "ready",
819
+ policyMode: resolvedPolicy.mode,
820
+ durationMs,
821
+ effectDelayMs,
822
+ configLoadMode: configState.loadMode,
823
+ syncOverBudget: Boolean(configState.syncOverBudget),
824
+ syncDurationMs: configState.syncDurationMs !== void 0 ? Math.round(configState.syncDurationMs * 100) / 100 : void 0
825
+ }
826
+ })
827
+ ).catch(() => {
828
+ });
829
+ }, [configState.loadMode, configState.syncDurationMs, configState.syncOverBudget, isReady, resolvedPolicy.mode, runtimeWithBindings]);
749
830
  if (!isReady) {
750
831
  const blockersList = [
751
832
  isTickServicesReady ? null : "tick",
752
833
  isLayerReady ? null : "layer",
753
834
  isConfigReady ? null : "config",
754
- resolvedPolicy.mode !== "defer" || deferReady ? null : "preload"
835
+ resolvedPolicy.mode !== "defer" || deferReady || syncWarmPreloadReady ? null : "preload"
755
836
  ].filter((x) => x !== null);
756
837
  const blockers = blockersList.length > 0 ? blockersList.join("+") : void 0;
757
838
  return /* @__PURE__ */ jsx2(