@dxos/app-framework 0.9.1-main.c7dcc2e112 → 0.9.1-staging.ee54ba693a

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.
Files changed (116) hide show
  1. package/dist/lib/browser/{capability-Z4MRP3CP.mjs → capability-S44TE2H7.mjs} +6 -6
  2. package/dist/lib/browser/{chunk-DFVSOBV2.mjs → chunk-KRJ4KK2W.mjs} +24 -5
  3. package/dist/lib/browser/{chunk-DFVSOBV2.mjs.map → chunk-KRJ4KK2W.mjs.map} +3 -3
  4. package/dist/lib/browser/{chunk-3UTDRCKX.mjs → chunk-LUH4Y5F2.mjs} +2 -2
  5. package/dist/lib/browser/{chunk-37PG7XJC.mjs → chunk-NKVRSMFN.mjs} +2 -2
  6. package/dist/lib/browser/{chunk-37PG7XJC.mjs.map → chunk-NKVRSMFN.mjs.map} +1 -1
  7. package/dist/lib/browser/{chunk-S2ZBYQPI.mjs → chunk-OO53M5UK.mjs} +2 -2
  8. package/dist/lib/browser/{chunk-CMINFVA5.mjs → chunk-OPTS3ZSN.mjs} +1 -1
  9. package/dist/lib/browser/{chunk-CMINFVA5.mjs.map → chunk-OPTS3ZSN.mjs.map} +2 -2
  10. package/dist/lib/browser/{chunk-SWECIICH.mjs → chunk-U5MESPM5.mjs} +6 -6
  11. package/dist/lib/browser/chunk-U5MESPM5.mjs.map +7 -0
  12. package/dist/lib/browser/{chunk-W4BHZING.mjs → chunk-UGYCLOXE.mjs} +3 -3
  13. package/dist/lib/browser/cli/index.mjs +5 -5
  14. package/dist/lib/browser/common/activation-events.mjs +4 -4
  15. package/dist/lib/browser/common/capabilities.mjs +5 -5
  16. package/dist/lib/browser/core/capability.mjs +1 -1
  17. package/dist/lib/browser/core/plugin-manager.mjs +3 -3
  18. package/dist/lib/browser/core/plugin.mjs +2 -2
  19. package/dist/lib/browser/core/url-loader.mjs +3 -3
  20. package/dist/lib/browser/index.mjs +7 -7
  21. package/dist/lib/browser/meta.json +1 -1
  22. package/dist/lib/browser/{process-manager-capability-RDROCCQD.mjs → process-manager-capability-QK4BMKMN.mjs} +6 -6
  23. package/dist/lib/browser/testing/index.mjs +7 -7
  24. package/dist/lib/browser/testing/react.mjs +6 -6
  25. package/dist/lib/browser/testing/react.mjs.map +2 -2
  26. package/dist/lib/browser/ui/index.mjs +9 -7
  27. package/dist/lib/node-esm/{capability-34Z6NPVR.mjs → capability-3YRF77LV.mjs} +6 -6
  28. package/dist/lib/node-esm/{chunk-WERVO5EK.mjs → chunk-4SE7SX7N.mjs} +2 -2
  29. package/dist/lib/node-esm/{chunk-H7T7XXLS.mjs → chunk-DRT75WGD.mjs} +6 -6
  30. package/dist/lib/node-esm/chunk-DRT75WGD.mjs.map +7 -0
  31. package/dist/lib/node-esm/{chunk-TEQSMP2O.mjs → chunk-FKMVORZN.mjs} +2 -2
  32. package/dist/lib/node-esm/{chunk-AIDZMJ3U.mjs → chunk-GLH4LGHZ.mjs} +1 -1
  33. package/dist/lib/node-esm/{chunk-AIDZMJ3U.mjs.map → chunk-GLH4LGHZ.mjs.map} +2 -2
  34. package/dist/lib/node-esm/{chunk-ZRTG4TSS.mjs → chunk-IL7O7IRX.mjs} +3 -3
  35. package/dist/lib/node-esm/{chunk-A4O42ZO3.mjs → chunk-ND2HETHD.mjs} +24 -5
  36. package/dist/lib/node-esm/{chunk-A4O42ZO3.mjs.map → chunk-ND2HETHD.mjs.map} +3 -3
  37. package/dist/lib/node-esm/{chunk-LUK3FCTH.mjs → chunk-XSZMX53L.mjs} +2 -2
  38. package/dist/lib/node-esm/{chunk-LUK3FCTH.mjs.map → chunk-XSZMX53L.mjs.map} +1 -1
  39. package/dist/lib/node-esm/cli/index.mjs +5 -5
  40. package/dist/lib/node-esm/common/activation-events.mjs +4 -4
  41. package/dist/lib/node-esm/common/capabilities.mjs +5 -5
  42. package/dist/lib/node-esm/core/capability.mjs +1 -1
  43. package/dist/lib/node-esm/core/plugin-manager.mjs +3 -3
  44. package/dist/lib/node-esm/core/plugin.mjs +2 -2
  45. package/dist/lib/node-esm/core/url-loader.mjs +3 -3
  46. package/dist/lib/node-esm/index.mjs +7 -7
  47. package/dist/lib/node-esm/meta.json +1 -1
  48. package/dist/lib/node-esm/{process-manager-capability-6OCXSKUW.mjs → process-manager-capability-5S7WZ2JR.mjs} +6 -6
  49. package/dist/lib/node-esm/testing/index.mjs +7 -7
  50. package/dist/lib/node-esm/testing/react.mjs +6 -6
  51. package/dist/lib/node-esm/testing/react.mjs.map +2 -2
  52. package/dist/lib/node-esm/ui/index.mjs +9 -7
  53. package/dist/plugin/node-esm/index.mjs +9 -11
  54. package/dist/plugin/node-esm/index.mjs.map +3 -3
  55. package/dist/plugin/node-esm/meta.json +1 -1
  56. package/dist/types/src/common/capabilities.d.ts +2 -2
  57. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  58. package/dist/types/src/core/capability.d.ts +3 -1
  59. package/dist/types/src/core/capability.d.ts.map +1 -1
  60. package/dist/types/src/core/plugin.d.ts +8 -0
  61. package/dist/types/src/core/plugin.d.ts.map +1 -1
  62. package/dist/types/src/plugin-process-manager/history/capability.d.ts +1 -3
  63. package/dist/types/src/plugin-process-manager/history/capability.d.ts.map +1 -1
  64. package/dist/types/src/plugin-process-manager/meta.d.ts +4 -0
  65. package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -1
  66. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +1 -4
  67. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -1
  68. package/dist/types/src/testing/react.d.ts.map +1 -1
  69. package/dist/types/src/ui/components/App/App.stories.d.ts +2 -2
  70. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -1
  71. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
  72. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
  73. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +1 -1
  74. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -1
  75. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -1
  76. package/dist/types/src/ui/components/Surface/index.d.ts +1 -1
  77. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
  78. package/dist/types/src/ui/components/Surface/types.d.ts +2 -2
  79. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
  80. package/dist/types/src/ui/hooks/useCapabilities.d.ts +6 -0
  81. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
  82. package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -1
  83. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -1
  84. package/dist/types/tsconfig.tsbuildinfo +1 -1
  85. package/docs/registry-spec.md +26 -26
  86. package/package.json +44 -38
  87. package/src/common/capabilities.ts +2 -2
  88. package/src/core/capability.ts +3 -2
  89. package/src/testing/react.tsx +1 -1
  90. package/src/ui/components/App/App.stories.tsx +2 -2
  91. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +11 -8
  92. package/src/ui/components/Surface/SurfaceComponent.tsx +6 -5
  93. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +1 -1
  94. package/src/ui/components/Surface/context.ts +0 -1
  95. package/src/ui/components/Surface/index.ts +2 -2
  96. package/src/ui/components/Surface/types.test.ts +4 -2
  97. package/src/ui/components/Surface/types.ts +4 -4
  98. package/src/ui/hooks/useCapabilities.ts +25 -0
  99. package/src/vite-plugin/boot-loader/BootLoader.solid-stories.tsx +11 -11
  100. package/src/vite-plugin/boot-loader/loader.ts +3 -3
  101. package/src/vite-plugin/composer/index.ts +1 -1
  102. package/src/vite-plugin/import-map/index.ts +23 -7
  103. package/src/vite-plugin/packages.ts +0 -1
  104. package/tsconfig.json +5 -2
  105. package/dist/lib/browser/chunk-SWECIICH.mjs.map +0 -7
  106. package/dist/lib/node-esm/chunk-H7T7XXLS.mjs.map +0 -7
  107. /package/dist/lib/browser/{capability-Z4MRP3CP.mjs.map → capability-S44TE2H7.mjs.map} +0 -0
  108. /package/dist/lib/browser/{chunk-3UTDRCKX.mjs.map → chunk-LUH4Y5F2.mjs.map} +0 -0
  109. /package/dist/lib/browser/{chunk-S2ZBYQPI.mjs.map → chunk-OO53M5UK.mjs.map} +0 -0
  110. /package/dist/lib/browser/{chunk-W4BHZING.mjs.map → chunk-UGYCLOXE.mjs.map} +0 -0
  111. /package/dist/lib/browser/{process-manager-capability-RDROCCQD.mjs.map → process-manager-capability-QK4BMKMN.mjs.map} +0 -0
  112. /package/dist/lib/node-esm/{capability-34Z6NPVR.mjs.map → capability-3YRF77LV.mjs.map} +0 -0
  113. /package/dist/lib/node-esm/{chunk-WERVO5EK.mjs.map → chunk-4SE7SX7N.mjs.map} +0 -0
  114. /package/dist/lib/node-esm/{chunk-TEQSMP2O.mjs.map → chunk-FKMVORZN.mjs.map} +0 -0
  115. /package/dist/lib/node-esm/{chunk-ZRTG4TSS.mjs.map → chunk-IL7O7IRX.mjs.map} +0 -0
  116. /package/dist/lib/node-esm/{process-manager-capability-6OCXSKUW.mjs.map → process-manager-capability-5S7WZ2JR.mjs.map} +0 -0
@@ -5,16 +5,16 @@ import {
5
5
  import "./chunk-Q2GLJTVV.mjs";
6
6
  import {
7
7
  capabilities_exports
8
- } from "./chunk-37PG7XJC.mjs";
8
+ } from "./chunk-NKVRSMFN.mjs";
9
9
  import "./chunk-VF37YTXJ.mjs";
10
10
  import "./chunk-YUVQIOTB.mjs";
11
- import "./chunk-3UTDRCKX.mjs";
12
- import "./chunk-W4BHZING.mjs";
11
+ import "./chunk-LUH4Y5F2.mjs";
12
+ import "./chunk-UGYCLOXE.mjs";
13
13
  import "./chunk-3NQLTQCP.mjs";
14
- import "./chunk-S2ZBYQPI.mjs";
14
+ import "./chunk-OO53M5UK.mjs";
15
15
  import {
16
16
  capability_exports
17
- } from "./chunk-CMINFVA5.mjs";
17
+ } from "./chunk-OPTS3ZSN.mjs";
18
18
  import "./chunk-J5LGTIGS.mjs";
19
19
 
20
20
  // src/plugin-process-manager/history/capability.ts
@@ -32,4 +32,4 @@ var capability_default = capability_exports.makeModule(Effect.fnUntraced(functio
32
32
  export {
33
33
  capability_default as default
34
34
  };
35
- //# sourceMappingURL=capability-Z4MRP3CP.mjs.map
35
+ //# sourceMappingURL=capability-S44TE2H7.mjs.map
@@ -3,19 +3,19 @@ import {
3
3
  topologicalSort,
4
4
  useOptionalPluginManager,
5
5
  usePluginManager
6
- } from "./chunk-SWECIICH.mjs";
6
+ } from "./chunk-U5MESPM5.mjs";
7
7
  import {
8
8
  PluginManagerContext
9
9
  } from "./chunk-FJ4765WW.mjs";
10
10
  import {
11
11
  capabilities_exports
12
- } from "./chunk-37PG7XJC.mjs";
12
+ } from "./chunk-NKVRSMFN.mjs";
13
13
  import {
14
14
  activation_events_exports
15
15
  } from "./chunk-VF37YTXJ.mjs";
16
16
  import {
17
17
  plugin_manager_exports
18
- } from "./chunk-W4BHZING.mjs";
18
+ } from "./chunk-UGYCLOXE.mjs";
19
19
 
20
20
  // src/ui/components/App/App.tsx
21
21
  import React2, { useEffect as useEffect3, useLayoutEffect } from "react";
@@ -248,13 +248,14 @@ import { useCallback as useCallback2 } from "react";
248
248
  import { invariant as invariant2 } from "@dxos/invariant";
249
249
  var __dxlog_file2 = "/__w/dxos/dxos/packages/sdk/app-framework/src/ui/hooks/useCapabilities.ts";
250
250
  var emptyCapabilities = Atom.make(() => []);
251
+ var emptyAtomValue = Atom.make(() => void 0);
251
252
  var useCapabilities = (interfaceDef) => {
252
253
  const manager = usePluginManager();
253
254
  return useAtomValue(manager.capabilities.atom(interfaceDef));
254
255
  };
255
256
  var useCapability = (interfaceDef) => {
256
257
  const capabilities = useCapabilities(interfaceDef);
257
- invariant2(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 25, S: void 0, A: ["capabilities.length > 0", "`No capability found for ${interfaceDef.identifier}`"] });
258
+ invariant2(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 26, S: void 0, A: ["capabilities.length > 0", "`No capability found for ${interfaceDef.identifier}`"] });
258
259
  return capabilities[0];
259
260
  };
260
261
  var useOptionalCapabilities = (interfaceDef) => {
@@ -281,6 +282,23 @@ var useAtomCapabilityState = (atomCapability) => {
281
282
  update
282
283
  ];
283
284
  };
285
+ var useOptionalAtomCapabilityState = (atomCapability) => {
286
+ const registry = useOptionalCapability(capabilities_exports.AtomRegistry);
287
+ const atom = useOptionalCapability(atomCapability);
288
+ const value = useAtomValue(atom ?? emptyAtomValue);
289
+ const update = useCallback2((fn) => {
290
+ if (registry && atom) {
291
+ registry.set(atom, fn(registry.get(atom)));
292
+ }
293
+ }, [
294
+ registry,
295
+ atom
296
+ ]);
297
+ return [
298
+ value,
299
+ update
300
+ ];
301
+ };
284
302
  var useOperationInvoker = () => useCapability(capabilities_exports.OperationInvoker);
285
303
 
286
304
  // src/ui/hooks/useLoading.tsx
@@ -474,6 +492,7 @@ export {
474
492
  useOptionalCapability,
475
493
  useAtomCapability,
476
494
  useAtomCapabilityState,
495
+ useOptionalAtomCapabilityState,
477
496
  useOperationInvoker,
478
497
  LoadingState,
479
498
  useLoading,
@@ -483,4 +502,4 @@ export {
483
502
  useSettingsState,
484
503
  App
485
504
  };
486
- //# sourceMappingURL=chunk-DFVSOBV2.mjs.map
505
+ //# sourceMappingURL=chunk-KRJ4KK2W.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/ui/components/App/App.tsx", "../../../src/ui/hooks/useApp.tsx", "../../../src/ui/hooks/useCapabilities.ts", "../../../src/ui/hooks/useLoading.tsx", "../../../src/ui/hooks/useProcessManagerRuntime.ts", "../../../src/ui/hooks/useSettingsState.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type PropsWithChildren, useEffect, useLayoutEffect } from 'react';\n\nimport { Capabilities } from '../../../common';\nimport { topologicalSort } from '../../../helpers';\nimport { LoadingState, type StartupProgress, type UseAppOptions, useCapabilities, useLoading } from '../../hooks';\n\ndeclare global {\n interface Window {\n /**\n * Driver injected by `@dxos/app-framework/vite-plugin`'s `bootLoaderPlugin`\n * (a Solid app inlined into `index.html`). Declared here — on a module that\n * is part of the `@dxos/app-framework/ui` export surface — so the React side\n * and host apps (e.g. composer-app) can drive the loader without each\n * re-declaring the type. The canonical definition lives in the plugin's\n * `loader-app/types.ts`; this mirror exists because that source compiles in a\n * separate (Solid) program that doesn't ship its globals to consumers.\n */\n __bootLoader?: {\n status: (payload: {\n event?: string;\n module?: string;\n humanized: string;\n /**\n * Optional `(index/total)` tick. When present, the loader replaces the\n * current line in place (\"Loading plugins (12/80)\") instead of appending\n * a new entry — keeps the visible log compact during long counted phases.\n */\n range?: { index: number; total: number };\n }) => void;\n progress: (fraction?: number) => void;\n ready: () => void;\n dismiss: () => void;\n };\n }\n}\n\nexport type AppProps = Pick<UseAppOptions, 'debounce'> & {\n ready: boolean;\n error: unknown;\n progress?: StartupProgress;\n};\n\nconst FIRST_INTERACTIVE_MARK = 'app-framework:first-interactive';\n\nexport const App = ({ ready, error, debounce, progress }: AppProps) => {\n const reactContexts = useCapabilities(Capabilities.ReactContext);\n const reactRoots = useCapabilities(Capabilities.ReactRoot);\n const stage = useLoading(ready, debounce);\n const placeholderDismissed = stage >= LoadingState.Done;\n\n // Relay the startup lifecycle into the boot loader injected by\n // `@dxos/app-framework/vite-plugin` (a Solid app inlined into `index.html`,\n // the only visible loading UI). Plugin activation fills the `[0.5, 1]` half\n // of the ring; the raw `event` / `module` ids ride along so the loader owns\n // how each transition is rendered and traced. No-op once the outro has\n // started (`FadeOut`), so the dismissal runs uncontended.\n useEffect(() => {\n if (stage >= LoadingState.FadeOut) {\n return;\n }\n const fraction = progress?.progress ?? 0;\n window.__bootLoader?.progress(0.5 + fraction * 0.5);\n if (progress?.humanizedName) {\n window.__bootLoader?.status({\n event: progress.event,\n module: progress.module,\n humanized: `Activating ${progress.humanizedName}`,\n });\n }\n }, [stage, progress?.progress, progress?.event, progress?.module, progress?.humanizedName]);\n\n // Hand off at fade-out: play the loader's graceful shrink-and-fade outro.\n // `useLayoutEffect` runs before the next paint so the outro begins in the\n // same frame the real shell starts rendering beneath it.\n useLayoutEffect(() => {\n if (stage >= LoadingState.FadeOut) {\n window.__bootLoader?.ready();\n }\n }, [stage]);\n\n // Emit a once-per-app `app-framework:first-interactive` mark the first time\n // the loader is dismissed and the real app shell renders. Closes the gap\n // between `Startup` activated and the first interactive paint.\n //\n // Also the framework-owned handoff-complete signal: `dismiss()` removes the\n // loader immediately on the fast-load path (where `useLoading` skips\n // `FadeOut`), and is a no-op once an outro is already in flight, so it never\n // cuts the animation short.\n useEffect(() => {\n if (!placeholderDismissed) {\n return;\n }\n if (performance.getEntriesByName(FIRST_INTERACTIVE_MARK).length === 0) {\n performance.mark(FIRST_INTERACTIVE_MARK);\n }\n window.__bootLoader?.dismiss();\n }, [placeholderDismissed]);\n\n // Used in tests to exercise the error boundary & reset dialog (see\n // composer-app's `basic.spec.ts`). Thrown into the surrounding `ErrorBoundary`.\n if (location.search === '?throw') {\n throw new Error('Test error');\n }\n\n if (error) {\n // This triggers the error boundary to provide UI feedback for the startup error.\n throw error;\n }\n\n // The boot loader owns the screen until handoff completes; render nothing\n // until then (any DOM here would sit invisibly behind the `z-index: 10`\n // loader anyway).\n // TODO(wittjosiah): Consider using Suspense instead.\n if (!placeholderDismissed) {\n return null;\n }\n\n const ComposedContext = composeContexts(reactContexts);\n return (\n <ComposedContext>\n {reactRoots.map(({ id, root: Component }) => (\n <Component key={id} />\n ))}\n </ComposedContext>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]) => {\n if (contexts.length === 0) {\n return ({ children }: PropsWithChildren) => <>{children}</>;\n }\n\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { RegistryContext } from '@effect-atom/atom-react';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Queue from 'effect/Queue';\nimport React, { type FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { EffectEx } from '@dxos/effect';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ErrorBoundary, ErrorFallback, type FallbackProps } from '@dxos/react-error-boundary';\nimport { useAsyncEffect, useDefaultValue } from '@dxos/react-hooks';\nimport { ContextProtocolProvider } from '@dxos/web-context-react';\n\nimport { ActivationEvents, Capabilities } from '../../common';\nimport { PluginManagerContext } from '../../context';\nimport { type ActivationEvent, type Plugin, PluginManager } from '../../core';\nimport { App, PluginManagerProvider } from '../components';\n\nconst ENABLED_KEY = 'org.dxos.app-framework.enabled';\n\nexport type StartupProgress = {\n /** Number of modules that have been activated. */\n activated: number;\n /** Total number of modules registered. */\n total: number;\n /** Fractional progress (0-1). */\n progress: number;\n /**\n * Raw activation event key (e.g. `org.dxos.app-framework.event.startup`).\n * Set on event-level transitions, *and* on module-level transitions where\n * it carries the parent activation event that first triggered the\n * module's load (plumbed through `_loadCapabilitiesForModules` →\n * `_loadModule`). Consumers can use this either as the primary id (when\n * {@link module} is absent) or as an extra \"context\" field alongside\n * {@link module}.\n */\n event?: string;\n /**\n * Raw module id (e.g. `org.dxos.plugin.observability.module.ReactSurface`)\n * when the in-flight activation is module-level. When present,\n * {@link event} may also be set, identifying the parent activation that\n * triggered this module's load.\n */\n module?: string;\n /**\n * Pre-humanized label for the currently surfaced transition (module\n * label if {@link module} is set, otherwise the event label), supplied\n * for consumers that want a sensible default. Hosts that prefer to\n * render their own label can read the raw {@link event}/{@link module}\n * fields and ignore this — the framework leaves the policy choice\n * (which transitions to surface, how to format them, whether to drop\n * sub-modules entirely) to the host's `Placeholder`.\n */\n humanizedName?: string;\n};\n\nexport type UseAppOptions = {\n pluginManager?: PluginManager.PluginManager;\n pluginLoader?: PluginManager.ManagerOptions['pluginLoader'];\n onPluginRemove?: PluginManager.ManagerOptions['onRemove'];\n pluginRegistryProvider?: PluginManager.ManagerOptions['pluginRegistryProvider'];\n plugins?: Plugin.Plugin[];\n defaults?: string[];\n /**\n * Additional activation events to fire before startup.\n * These are fired alongside SetupReactSurface before the Startup event.\n */\n setupEvents?: ActivationEvent.ActivationEvent[];\n cacheEnabled?: boolean;\n safeMode?: boolean;\n debounce?: number;\n timeout?: number;\n fallback?: FC<FallbackProps>;\n};\n\n/**\n * Expected usage is for this to be the entrypoint of the application.\n * Initializes plugins and renders the root components.\n *\n * @example\n * const plugins = [LayoutPlugin(), MyPlugin()];\n * const defaults = [MyPluginId];\n * const fallback = () => <div>Initializing Plugins...</div>;\n * const App = useApp({ plugins, defaults, fallback });\n * createRoot(document.getElementById('root')!).render(\n * <StrictMode>\n * <App />\n * </StrictMode>,\n * );\n *\n * @param params.pluginLoader A function which loads new plugins.\n * @param params.plugins All plugins available to the application. Plugins whose `meta.profile.tags` includes `'system'` are treated as core (force-enabled, not user-toggleable).\n * @param params.defaults Default plugins are enabled by default but can be disabled by the user.\n * @param params.cacheEnabled Whether to cache enabled plugins in localStorage.\n * @param params.safeMode Whether to enable safe mode, which disables optional plugins.\n * @param params.fallback Fallback component to render if an error occurs during startup.\n */\nexport const useApp = ({\n pluginManager,\n pluginLoader: pluginLoaderProp,\n onPluginRemove,\n pluginRegistryProvider,\n plugins: pluginsProp,\n defaults: defaultsProp,\n setupEvents: setupEventsProp,\n fallback = ErrorFallback,\n cacheEnabled = false,\n safeMode = false,\n debounce = 0,\n timeout = 30_000,\n}: UseAppOptions) => {\n const plugins = useDefaultValue(pluginsProp, () => []);\n const defaults = useDefaultValue(defaultsProp, () => []);\n const setupEvents = useDefaultValue(setupEventsProp, () => []);\n\n const pluginLoader = useMemo(\n () =>\n pluginLoaderProp ??\n ((id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n })),\n [pluginLoaderProp, plugins],\n );\n\n const readyRef = useRef(false);\n const [ready, setReady] = useState(false);\n const errorRef = useRef<unknown>(null);\n const [error, setError] = useState<unknown>(null);\n const [startupProgress, setStartupProgress] = useState<StartupProgress>({\n activated: 0,\n total: 0,\n progress: 0,\n });\n // TODO(wittjosiah): Migrate to Atom.kvs for isomorphic storage.\n const cached: string[] = useMemo(() => JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]'), []);\n const enabled = useMemo(\n () => (safeMode ? [] : cacheEnabled && cached.length > 0 ? cached : defaults),\n [safeMode, cacheEnabled, cached, defaults],\n );\n const isExternalManager = !!pluginManager;\n const manager = useMemo(() => {\n const mgr =\n pluginManager ??\n PluginManager.make({\n pluginLoader,\n plugins,\n enabled,\n onRemove: onPluginRemove,\n pluginRegistryProvider,\n });\n log('useApp: useMemo created/reused manager', { provided: !!pluginManager });\n return mgr;\n }, [pluginManager, pluginLoader, plugins, enabled, onPluginRemove, pluginRegistryProvider]);\n\n useEffect(() => {\n if (!cacheEnabled) {\n return;\n }\n return manager.registry.subscribe(manager.enabled, (value) => {\n localStorage.setItem(ENABLED_KEY, JSON.stringify(value));\n });\n }, [cacheEnabled, manager]);\n\n useEffect(() => {\n setupDevtools(manager);\n }, [manager]);\n\n useAsyncEffect(async () => {\n log('useApp: effect mount');\n\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n const fiber = Effect.gen(function* () {\n const queue = yield* PubSub.subscribe(manager.activation);\n const listener = yield* Effect.forkDaemon(\n Queue.take(queue).pipe(\n Effect.tap(({ event, state, module, error: error$ }) =>\n Effect.sync(() => {\n // Event-level Startup activated (no `module` field) fires once,\n // after every module triggered by Startup has finished. Module\n // activations now also carry their parent event id (so the trace\n // can attribute a module to its triggering event), which means\n // each module activated under Startup publishes\n // `{ event: 'startup', state: 'activated', module: <id> }`. Without\n // the `!module` guard the listener would mark the app ready on\n // the *first* such module rather than waiting for the event-level\n // completion — leaving downstream capabilities (operation-invoker,\n // app-graph, …) un-registered when the boot loader dismisses.\n if (event === ActivationEvents.Startup.id && state === 'activated' && !module) {\n clearTimeout(timeoutId);\n setReady(true);\n readyRef.current = true;\n // Trigger startup profiler dump if available.\n (globalThis as any).composer?.profiler?.dump();\n // Notify any host observability layer that startup completed.\n // A `CustomEvent` keeps this generic — app-framework doesn't\n // import a provider, and consumers can capture the startup\n // summary without us picking one.\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('app-framework:startup-activated'));\n }\n return;\n }\n // `activating` is the start-of-load signal. Surface the raw\n // `module` (or `event`) plus a pre-humanized label so the\n // boot loader can decide how to render each transition — show\n // everything, suppress noisy sub-modules, group by plugin,\n // or apply its own formatting. We intentionally do NOT touch\n // these fields on `activated`: pairing the two would cause\n // back-to-back identical updates to the host's effect, which\n // the boot loader treats as a re-trigger because\n // `progress.progress` moved. Leaving the label alone on\n // completion keeps it accurate (\"now activating X\") until\n // the next module starts.\n if (module && state === 'activating' && !readyRef.current) {\n setStartupProgress((current) => ({\n ...current,\n // `event` here is the activation event that first\n // triggered this module load (plumbed through\n // `_loadCapabilitiesForModules` → `_loadModule`).\n // Falsy/empty falls back to undefined so consumers can\n // tell \"no parent context\" from \"parent context: <X>\".\n event: event || undefined,\n module,\n humanizedName: humanizeModuleId(module),\n }));\n }\n // Update the activation count when a module commits. The\n // ring's fraction comes from this; `event`/`module`/\n // `humanizedName` were set by the matching `activating`\n // message above and are left alone so the count can advance\n // without re-firing the host's status callback.\n if (module && state === 'activated' && !readyRef.current) {\n const active = manager.getActive();\n const total = manager.getModules().length;\n setStartupProgress((current) => ({\n ...current,\n activated: active.length,\n total,\n progress: total > 0 ? active.length / total : 0,\n }));\n }\n // Event-level `activating` (no `module`) — fired at the start\n // of `_activateModulesForEvent` and recursively for each\n // before/after event. Surfaces a label during the gap before\n // the first module-level message lands; subsequent module\n // updates immediately overwrite this with a more specific\n // label.\n if (event && !module && state === 'activating' && !readyRef.current) {\n setStartupProgress((current) => ({\n ...current,\n event,\n module: undefined,\n humanizedName: humanizeEventKey(event),\n }));\n }\n if (error$ && !readyRef.current) {\n setError(error$);\n errorRef.current = error$;\n }\n }),\n ),\n Effect.forever,\n ),\n );\n\n yield* Effect.all([\n ...setupEvents.map((event) => manager.activate(event)),\n manager.activate(ActivationEvents.SetupReactSurface),\n manager.activate(ActivationEvents.Startup),\n ]);\n\n return yield* Fiber.join(listener);\n }).pipe(Effect.scoped, Effect.runFork);\n\n // Set up a timeout for startup.\n const timeoutId = setTimeout(() => {\n if (!readyRef.current && !errorRef.current) {\n log.warn('startup timeout diagnostic', {\n eventsFired: manager.getEventsFired(),\n activeModules: manager.getActive(),\n pendingReset: manager.getPendingReset(),\n });\n void EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));\n setError(new Error(`Startup timed out after ${timeout}ms`));\n }\n }, timeout);\n\n return () => {\n log('useApp: effect cleanup');\n clearTimeout(timeoutId);\n void EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));\n if (!isExternalManager) {\n void EffectEx.runAndForwardErrors(manager.shutdown());\n }\n };\n }, [manager]);\n\n const progressRef = useRef(startupProgress);\n progressRef.current = startupProgress;\n\n return useCallback(\n () => (\n <ErrorBoundary name='app' FallbackComponent={fallback}>\n <PluginManagerProvider value={manager}>\n <ContextProtocolProvider value={manager} context={PluginManagerContext}>\n <RegistryContext.Provider value={manager.registry}>\n <App ready={ready} error={error} debounce={debounce} progress={progressRef.current} />\n </RegistryContext.Provider>\n </ContextProtocolProvider>\n </PluginManagerProvider>\n </ErrorBoundary>\n ),\n [fallback, manager, ready, error],\n );\n};\n\nconst setupDevtools = (manager: PluginManager.PluginManager) => {\n (globalThis as any).composer ??= {};\n (globalThis as any).composer.manager = manager;\n};\n\n/**\n * Extracts a human-readable label from a module ID.\n *\n * Module IDs follow `org.dxos.plugin.<plugin-slug>.module.<module-name>`,\n * where `<plugin-slug>` is kebab-case and `<module-name>` is either an\n * explicit string (often kebab-case, e.g. `'observability'`, `'namespace'`)\n * or a capability tag in PascalCase from `Capability.getModuleTag(...)`\n * (e.g. `'ReactSurface'`, `'AppGraphBuilder'`). The output is\n * `\"Title Case Plugin: kebab-module\"` so the visible status names both the\n * plugin and the aspect being activated, helping disambiguate the multiple\n * modules a plugin contributes.\n *\n * Examples:\n * - \"org.dxos.plugin.markdown.module.ReactSurface\" → \"Markdown: react-surface\"\n * - \"org.dxos.plugin.observability.module.AppGraphBuilder\" → \"Observability: app-graph-builder\"\n * - \"org.dxos.plugin.observability.module.observability\" → \"Observability\"\n * (the module name matches the plugin slug — collapsed to avoid\n * \"Observability: observability\" noise.)\n */\nconst humanizeModuleId = (moduleId: string): string => {\n const match = moduleId.match(/\\.plugin\\.([^.]+)\\.module\\.(.+)$/);\n if (!match) {\n // Fallback: use the last segment.\n const parts = moduleId.split('.');\n return parts[parts.length - 1];\n }\n const [, pluginSlug, moduleName] = match;\n const pluginLabel = pluginSlug\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n // Normalise the module name to kebab-case so PascalCase capability tags\n // (\"ReactSurface\") read consistently with explicit kebab IDs\n // (\"operation-handler\"). The two-step substitution handles consecutive\n // uppercase runs (`URLLoader` → `url-loader`) without splitting them\n // mid-acronym.\n const moduleLabel = moduleName\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .toLowerCase();\n // Capability modules whose name matches the plugin slug (e.g. the\n // observability plugin's `observability` capability module) would render\n // as \"Observability: observability\" — drop the redundant suffix.\n if (moduleLabel === pluginSlug) {\n return pluginLabel;\n }\n return `${pluginLabel}: ${moduleLabel}`;\n};\n\n/**\n * Extracts a human-readable label from an activation event key.\n * E.g., \"org.dxos.app-framework.event.setup-react-surface\" → \"Setup React Surface\".\n */\nconst humanizeEventKey = (eventKey: string): string => {\n // Strip a leading specifier (composite key form: \"<id>:<specifier>\").\n const id = eventKey.split(':')[0];\n // Match the trailing segment after `.event.`.\n const match = id.match(/\\.event\\.(.+)$/);\n const slug = match ? match[1] : (id.split('.').pop() ?? id);\n return slug\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom } from '@effect-atom/atom';\nimport { useAtomValue } from '@effect-atom/atom-react';\nimport { useCallback } from 'react';\n\nimport { invariant } from '@dxos/invariant';\n\nimport { Capabilities } from '../../common';\nimport { type Capability } from '../../core';\nimport { useOptionalPluginManager, usePluginManager } from '../components';\n\n/** Stable empty result for capability lookups made outside a plugin manager. */\nconst emptyCapabilities = Atom.make(() => [] as const);\n\n/**\n * Hook to request capabilities from the plugin context.\n * @returns An array of capabilities.\n */\nexport const useCapabilities = <T>(interfaceDef: Capability.InterfaceDef<T>) => {\n const manager = usePluginManager();\n return useAtomValue(manager.capabilities.atom(interfaceDef));\n};\n\n/**\n * Hook to request a capability from the plugin context.\n * @returns The capability.\n * @throws If no capability is found.\n */\n// TODO(burdon): Option not to throw?\nexport const useCapability = <T>(interfaceDef: Capability.InterfaceDef<T>) => {\n const capabilities = useCapabilities(interfaceDef);\n invariant(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`);\n return capabilities[0];\n};\n\n/**\n * Hook to request capabilities without requiring a plugin manager.\n * @returns An array of capabilities, or an empty array when rendered outside a {@link PluginManagerProvider}.\n */\nexport const useOptionalCapabilities = <T>(interfaceDef: Capability.InterfaceDef<T>): readonly T[] => {\n const manager = useOptionalPluginManager();\n return useAtomValue(\n manager ? manager.capabilities.atom(interfaceDef) : (emptyCapabilities as Atom.Atom<readonly T[]>),\n );\n};\n\n/**\n * Hook to request a single capability without requiring a plugin manager.\n * @returns The first matching capability, or `undefined` when none is registered (or there is no plugin manager).\n */\nexport const useOptionalCapability = <T>(interfaceDef: Capability.InterfaceDef<T>): T | undefined =>\n useOptionalCapabilities(interfaceDef)[0];\n\n/**\n * Hook to get the current value of an atom capability.\n * Automatically subscribes to changes.\n * @example const settings = useAtomCapability(CommentCapabilities.Settings);\n */\nexport const useAtomCapability = <T>(atomCapability: Capability.InterfaceDef<Atom.Atom<T>>): T => {\n const atom = useCapability(atomCapability);\n return useAtomValue(atom);\n};\n\n/**\n * Hook to get value and updater for an atom capability.\n * Returns [currentValue, updateFn] similar to useState.\n * @example const [settings, updateSettings] = useAtomCapabilityState(CommentCapabilities.Settings);\n */\nexport const useAtomCapabilityState = <T>(\n atomCapability: Capability.InterfaceDef<Atom.Writable<T>>,\n): [T, (fn: (current: T) => T) => void] => {\n const registry = useCapability(Capabilities.AtomRegistry);\n const atom = useCapability(atomCapability);\n const value = useAtomValue(atom);\n const update = useCallback(\n (fn: (current: T) => T) => {\n registry.set(atom, fn(registry.get(atom)));\n },\n [registry, atom],\n );\n return [value, update];\n};\n\n/**\n * Hook to get the operation invoker capability.\n */\nexport const useOperationInvoker = (): Capabilities.OperationInvoker => useCapability(Capabilities.OperationInvoker);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useRef, useState } from 'react';\n\nexport enum LoadingState {\n Loading = 0,\n FadeIn = 1,\n FadeOut = 2,\n Done = 3,\n}\n\n/**\n * To avoid \"flashing\" the placeholder, we wait a period of time before starting the loading animation.\n * If loading completes during this time the placehoder is not shown, otherwise is it displayed for a minimum period of time.\n *\n * States:\n * 0: Loading - Wait for a period of time before starting the loading animation.\n * 1: Fade-in - Display a loading animation.\n * 2: Fade-out - Fade out the loading animation.\n * 3: Done - Remove the placeholder.\n */\nexport const useLoading = (ready: boolean, debounce = 0) => {\n const [stage, setStage] = useState<LoadingState>(LoadingState.Loading);\n // Mirror `ready` into a ref so the interval's `setStage` callback can read\n // the latest value without depending on the effect re-running. The pure\n // closure-capture pattern (with `ready` in deps) sticks the FSM at\n // `FadeIn` whenever HMR doesn't propagate the dep change end-to-end —\n // a ref sidesteps that entirely and fires the read on every tick.\n const readyRef = useRef(ready);\n readyRef.current = ready;\n\n useEffect(() => {\n if (!debounce) {\n return;\n }\n\n const i = setInterval(() => {\n setStage((stage) => {\n const isReady = readyRef.current;\n switch (stage) {\n case LoadingState.Loading: {\n if (!isReady) {\n return LoadingState.FadeIn;\n }\n clearInterval(i);\n return LoadingState.Done;\n }\n\n case LoadingState.FadeIn: {\n if (isReady) {\n return LoadingState.FadeOut;\n }\n break;\n }\n\n case LoadingState.FadeOut: {\n clearInterval(i);\n return LoadingState.Done;\n }\n }\n\n return stage;\n });\n }, debounce);\n\n return () => clearInterval(i);\n }, [debounce]);\n\n if (!debounce) {\n return ready ? LoadingState.Done : LoadingState.Loading;\n }\n\n return stage;\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport { type DependencyList, use, useCallback, useMemo } from 'react';\n\nimport { Operation, ServiceResolver } from '@dxos/compute';\nimport { EffectEx } from '@dxos/effect';\nimport type { SpaceId } from '@dxos/keys';\n\nimport { Capabilities } from '../../common';\nimport { useCapability } from './useCapabilities';\n\n/**\n * Resolve the shared {@link Capabilities.ProcessManagerRuntime} from the plugin context.\n */\nexport const useProcessManagerRuntime = (): Capabilities.ProcessManagerRuntime =>\n useCapability(Capabilities.ProcessManagerRuntime);\n\n/**\n * Build a callback that runs an effect on the {@link Capabilities.ProcessManagerRuntime}\n * with space-scoped services resolved via {@link ServiceResolver.provide}.\n *\n * The `tags` tuple must list every service the effect requires (beyond the\n * fixed {@link Capabilities.ProcessManagerRuntimeServices}); these services are\n * resolved for the given `spaceId` through the runtime's service resolver.\n *\n * Nested `Operation.invoke` / `Operation.schedule` calls within the effect\n * inherit `spaceId` as a default {@link Operation.InvokeOptions} so that\n * spawned operation processes have a space context (and therefore can resolve\n * space-scoped services like `Database.Service`) without each call site having\n * to thread the id through manually.\n */\nexport const useSpaceCallback = <const Tags extends readonly Context.Tag<any, any>[], T>(\n spaceId: SpaceId | undefined,\n tags: Tags,\n fn: () => Effect.Effect<T, any, Context.Tag.Identifier<Tags[number]> | Capabilities.ProcessManagerRuntimeServices>,\n deps?: DependencyList,\n): (() => Promise<T>) => {\n const runtime = useProcessManagerRuntime();\n return useCallback(() => {\n if (spaceId === undefined) {\n throw new TypeError('Space not provided to useSpaceCallback');\n }\n const layer = Layer.merge(\n ServiceResolver.provide({ space: spaceId }, ...tags),\n Operation.withInvocationOptions({ spaceId }),\n );\n return runtime.runPromise(fn().pipe(Effect.provide(layer)) as Effect.Effect<T, any, any>);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [runtime, spaceId, ...(deps ?? [])]);\n};\n\n/**\n * Suspensefully resolve a single space-scoped service via the\n * {@link Capabilities.ProcessManagerRuntime}'s service resolver.\n */\nexport const useSpaceService = <T extends Context.Tag<any, any>>(\n tag: T,\n spaceId: SpaceId | undefined,\n): Context.Tag.Service<T> | undefined => {\n const runtime = useProcessManagerRuntime();\n const promise = useMemo(() => {\n if (spaceId === undefined) {\n return undefined;\n }\n const layer = ServiceResolver.provide({ space: spaceId }, tag);\n const effect = Effect.flatMap(tag, (service) => Effect.succeed(service)).pipe(Effect.provide(layer));\n return runtime.runPromiseExit(effect as Effect.Effect<Context.Tag.Service<T>, any, any>);\n }, [runtime, spaceId, tag]);\n if (!promise) {\n return undefined;\n }\n return EffectEx.unwrapExit(use(promise));\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Atom, RegistryContext, useAtomValue } from '@effect-atom/atom-react';\nimport { useCallback, useContext } from 'react';\n\n/**\n * Hook to read and update a settings atom.\n * Returns the current value and an update function.\n */\nexport const useSettingsState = <T>(\n atom: Atom.Writable<T>,\n): { settings: T; updateSettings: (fn: (current: T) => T) => void } => {\n const registry = useContext(RegistryContext);\n const settings = useAtomValue(atom);\n\n const updateSettings = useCallback(\n (fn: (current: T) => T) => {\n registry.set(atom, fn(registry.get(atom)));\n },\n [registry, atom],\n );\n\n return { settings, updateSettings };\n};\n"],
5
- "mappings": "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",
6
- "names": ["React", "useEffect", "useLayoutEffect", "RegistryContext", "Effect", "Fiber", "PubSub", "Queue", "React", "useCallback", "useEffect", "useMemo", "useRef", "useState", "EffectEx", "invariant", "log", "ErrorBoundary", "ErrorFallback", "useAsyncEffect", "useDefaultValue", "ContextProtocolProvider", "ENABLED_KEY", "defaults", "useDefaultValue", "defaultsProp", "setupEvents", "setupEventsProp", "pluginLoader", "pluginLoaderProp", "plugin", "find", "meta", "invariant", "id", "plugins", "errorRef", "useRef", "error", "setError", "useState", "startupProgress", "setStartupProgress", "activated", "total", "progress", "safeMode", "cacheEnabled", "cached", "pluginManager", "enabled", "onRemove", "pluginRegistryProvider", "mgr", "onPluginRemove", "useEffect", "manager", "useAsyncEffect", "capabilities", "contribute", "interface", "Capabilities", "PluginManager", "implementation", "module", "registry", "fiber", "forkDaemon", "setReady", "readyRef", "current", "globalThis", "humanizedName", "humanizeModuleId", "length", "active", "event", "error$", "Effect", "forever", "activate", "ActivationEvents", "Startup", "join", "listener", "pipe", "timeoutId", "eventsFired", "getEventsFired", "activeModules", "pendingReset", "getPendingReset", "runAndForwardErrors", "interrupt", "Error", "timeout", "clearTimeout", "Fiber", "isExternalManager", "EffectEx", "shutdown", "progressRef", "name", "FallbackComponent", "fallback", "value", "ContextProtocolProvider", "PluginManagerContext", "App", "ready", "debounce", "composer", "match", "parts", "pluginSlug", "moduleName", "pluginLabel", "split", "map", "word", "Atom", "useAtomValue", "useCallback", "invariant", "__dxlog_file", "useAtomValue", "capabilities", "interfaceDef", "invariant", "length", "atom", "useCapability", "atomCapability", "value", "update", "fn", "registry", "set", "useCallback", "useEffect", "useRef", "useState", "LoadingState", "useLoading", "ready", "debounce", "stage", "setStage", "readyRef", "current", "i", "setInterval", "isReady", "clearInterval", "Effect", "Layer", "use", "useCallback", "useMemo", "Operation", "ServiceResolver", "EffectEx", "useProcessManagerRuntime", "useCapability", "Capabilities", "ProcessManagerRuntime", "useSpaceCallback", "spaceId", "tags", "fn", "deps", "runtime", "useCallback", "undefined", "TypeError", "layer", "merge", "ServiceResolver", "provide", "space", "Operation", "withInvocationOptions", "runPromise", "pipe", "useSpaceService", "tag", "promise", "useMemo", "effect", "flatMap", "service", "succeed", "runPromiseExit", "EffectEx", "unwrapExit", "use", "RegistryContext", "useAtomValue", "useCallback", "useContext", "useSettingsState", "atom", "registry", "settings", "updateSettings", "fn", "set", "get", "FIRST_INTERACTIVE_MARK", "App", "ready", "error", "debounce", "progress", "reactContexts", "useCapabilities", "Capabilities", "ReactContext", "reactRoots", "ReactRoot", "stage", "useLoading", "placeholderDismissed", "LoadingState", "Done", "useEffect", "FadeOut", "fraction", "window", "__bootLoader", "humanizedName", "status", "event", "module", "humanized", "useLayoutEffect", "performance", "getEntriesByName", "length", "mark", "dismiss", "location", "search", "Error", "ComposedContext", "composeContexts", "React", "map", "id", "root", "Component", "key", "contexts", "children", "topologicalSort", "context", "reduce", "Acc", "Next"]
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type PropsWithChildren, useEffect, useLayoutEffect } from 'react';\n\nimport { Capabilities } from '../../../common';\nimport { topologicalSort } from '../../../helpers';\nimport { LoadingState, type StartupProgress, type UseAppOptions, useCapabilities, useLoading } from '../../hooks';\n\ndeclare global {\n interface Window {\n /**\n * Driver injected by `@dxos/app-framework/vite-plugin`'s `bootLoaderPlugin`\n * (a Solid app inlined into `index.html`). Declared here — on a module that\n * is part of the `@dxos/app-framework/ui` export surface — so the React side\n * and host apps (e.g. composer-app) can drive the loader without each\n * re-declaring the type. The canonical definition lives in the plugin's\n * `loader-app/types.ts`; this mirror exists because that source compiles in a\n * separate (Solid) program that doesn't ship its globals to consumers.\n */\n __bootLoader?: {\n status: (payload: {\n event?: string;\n module?: string;\n humanized: string;\n /**\n * Optional `(index/total)` tick. When present, the loader replaces the\n * current line in place (\"Loading plugins (12/80)\") instead of appending\n * a new entry — keeps the visible log compact during long counted phases.\n */\n range?: { index: number; total: number };\n }) => void;\n progress: (fraction?: number) => void;\n ready: () => void;\n dismiss: () => void;\n };\n }\n}\n\nexport type AppProps = Pick<UseAppOptions, 'debounce'> & {\n ready: boolean;\n error: unknown;\n progress?: StartupProgress;\n};\n\nconst FIRST_INTERACTIVE_MARK = 'app-framework:first-interactive';\n\nexport const App = ({ ready, error, debounce, progress }: AppProps) => {\n const reactContexts = useCapabilities(Capabilities.ReactContext);\n const reactRoots = useCapabilities(Capabilities.ReactRoot);\n const stage = useLoading(ready, debounce);\n const placeholderDismissed = stage >= LoadingState.Done;\n\n // Relay the startup lifecycle into the boot loader injected by\n // `@dxos/app-framework/vite-plugin` (a Solid app inlined into `index.html`,\n // the only visible loading UI). Plugin activation fills the `[0.5, 1]` half\n // of the ring; the raw `event` / `module` ids ride along so the loader owns\n // how each transition is rendered and traced. No-op once the outro has\n // started (`FadeOut`), so the dismissal runs uncontended.\n useEffect(() => {\n if (stage >= LoadingState.FadeOut) {\n return;\n }\n const fraction = progress?.progress ?? 0;\n window.__bootLoader?.progress(0.5 + fraction * 0.5);\n if (progress?.humanizedName) {\n window.__bootLoader?.status({\n event: progress.event,\n module: progress.module,\n humanized: `Activating ${progress.humanizedName}`,\n });\n }\n }, [stage, progress?.progress, progress?.event, progress?.module, progress?.humanizedName]);\n\n // Hand off at fade-out: play the loader's graceful shrink-and-fade outro.\n // `useLayoutEffect` runs before the next paint so the outro begins in the\n // same frame the real shell starts rendering beneath it.\n useLayoutEffect(() => {\n if (stage >= LoadingState.FadeOut) {\n window.__bootLoader?.ready();\n }\n }, [stage]);\n\n // Emit a once-per-app `app-framework:first-interactive` mark the first time\n // the loader is dismissed and the real app shell renders. Closes the gap\n // between `Startup` activated and the first interactive paint.\n //\n // Also the framework-owned handoff-complete signal: `dismiss()` removes the\n // loader immediately on the fast-load path (where `useLoading` skips\n // `FadeOut`), and is a no-op once an outro is already in flight, so it never\n // cuts the animation short.\n useEffect(() => {\n if (!placeholderDismissed) {\n return;\n }\n if (performance.getEntriesByName(FIRST_INTERACTIVE_MARK).length === 0) {\n performance.mark(FIRST_INTERACTIVE_MARK);\n }\n window.__bootLoader?.dismiss();\n }, [placeholderDismissed]);\n\n // Used in tests to exercise the error boundary & reset dialog (see\n // composer-app's `basic.spec.ts`). Thrown into the surrounding `ErrorBoundary`.\n if (location.search === '?throw') {\n throw new Error('Test error');\n }\n\n if (error) {\n // This triggers the error boundary to provide UI feedback for the startup error.\n throw error;\n }\n\n // The boot loader owns the screen until handoff completes; render nothing\n // until then (any DOM here would sit invisibly behind the `z-index: 10`\n // loader anyway).\n // TODO(wittjosiah): Consider using Suspense instead.\n if (!placeholderDismissed) {\n return null;\n }\n\n const ComposedContext = composeContexts(reactContexts);\n return (\n <ComposedContext>\n {reactRoots.map(({ id, root: Component }) => (\n <Component key={id} />\n ))}\n </ComposedContext>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]) => {\n if (contexts.length === 0) {\n return ({ children }: PropsWithChildren) => <>{children}</>;\n }\n\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { RegistryContext } from '@effect-atom/atom-react';\nimport * as Effect from 'effect/Effect';\nimport * as Fiber from 'effect/Fiber';\nimport * as PubSub from 'effect/PubSub';\nimport * as Queue from 'effect/Queue';\nimport React, { type FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { EffectEx } from '@dxos/effect';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { ErrorBoundary, ErrorFallback, type FallbackProps } from '@dxos/react-error-boundary';\nimport { useAsyncEffect, useDefaultValue } from '@dxos/react-hooks';\nimport { ContextProtocolProvider } from '@dxos/web-context-react';\n\nimport { ActivationEvents, Capabilities } from '../../common';\nimport { PluginManagerContext } from '../../context';\nimport { type ActivationEvent, type Plugin, PluginManager } from '../../core';\nimport { App, PluginManagerProvider } from '../components';\n\nconst ENABLED_KEY = 'org.dxos.app-framework.enabled';\n\nexport type StartupProgress = {\n /** Number of modules that have been activated. */\n activated: number;\n /** Total number of modules registered. */\n total: number;\n /** Fractional progress (0-1). */\n progress: number;\n /**\n * Raw activation event key (e.g. `org.dxos.app-framework.event.startup`).\n * Set on event-level transitions, *and* on module-level transitions where\n * it carries the parent activation event that first triggered the\n * module's load (plumbed through `_loadCapabilitiesForModules` →\n * `_loadModule`). Consumers can use this either as the primary id (when\n * {@link module} is absent) or as an extra \"context\" field alongside\n * {@link module}.\n */\n event?: string;\n /**\n * Raw module id (e.g. `org.dxos.plugin.observability.module.ReactSurface`)\n * when the in-flight activation is module-level. When present,\n * {@link event} may also be set, identifying the parent activation that\n * triggered this module's load.\n */\n module?: string;\n /**\n * Pre-humanized label for the currently surfaced transition (module\n * label if {@link module} is set, otherwise the event label), supplied\n * for consumers that want a sensible default. Hosts that prefer to\n * render their own label can read the raw {@link event}/{@link module}\n * fields and ignore this — the framework leaves the policy choice\n * (which transitions to surface, how to format them, whether to drop\n * sub-modules entirely) to the host's `Placeholder`.\n */\n humanizedName?: string;\n};\n\nexport type UseAppOptions = {\n pluginManager?: PluginManager.PluginManager;\n pluginLoader?: PluginManager.ManagerOptions['pluginLoader'];\n onPluginRemove?: PluginManager.ManagerOptions['onRemove'];\n pluginRegistryProvider?: PluginManager.ManagerOptions['pluginRegistryProvider'];\n plugins?: Plugin.Plugin[];\n defaults?: string[];\n /**\n * Additional activation events to fire before startup.\n * These are fired alongside SetupReactSurface before the Startup event.\n */\n setupEvents?: ActivationEvent.ActivationEvent[];\n cacheEnabled?: boolean;\n safeMode?: boolean;\n debounce?: number;\n timeout?: number;\n fallback?: FC<FallbackProps>;\n};\n\n/**\n * Expected usage is for this to be the entrypoint of the application.\n * Initializes plugins and renders the root components.\n *\n * @example\n * const plugins = [LayoutPlugin(), MyPlugin()];\n * const defaults = [MyPluginId];\n * const fallback = () => <div>Initializing Plugins...</div>;\n * const App = useApp({ plugins, defaults, fallback });\n * createRoot(document.getElementById('root')!).render(\n * <StrictMode>\n * <App />\n * </StrictMode>,\n * );\n *\n * @param params.pluginLoader A function which loads new plugins.\n * @param params.plugins All plugins available to the application. Plugins whose `meta.profile.tags` includes `'system'` are treated as core (force-enabled, not user-toggleable).\n * @param params.defaults Default plugins are enabled by default but can be disabled by the user.\n * @param params.cacheEnabled Whether to cache enabled plugins in localStorage.\n * @param params.safeMode Whether to enable safe mode, which disables optional plugins.\n * @param params.fallback Fallback component to render if an error occurs during startup.\n */\nexport const useApp = ({\n pluginManager,\n pluginLoader: pluginLoaderProp,\n onPluginRemove,\n pluginRegistryProvider,\n plugins: pluginsProp,\n defaults: defaultsProp,\n setupEvents: setupEventsProp,\n fallback = ErrorFallback,\n cacheEnabled = false,\n safeMode = false,\n debounce = 0,\n timeout = 30_000,\n}: UseAppOptions) => {\n const plugins = useDefaultValue(pluginsProp, () => []);\n const defaults = useDefaultValue(defaultsProp, () => []);\n const setupEvents = useDefaultValue(setupEventsProp, () => []);\n\n const pluginLoader = useMemo(\n () =>\n pluginLoaderProp ??\n ((id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n })),\n [pluginLoaderProp, plugins],\n );\n\n const readyRef = useRef(false);\n const [ready, setReady] = useState(false);\n const errorRef = useRef<unknown>(null);\n const [error, setError] = useState<unknown>(null);\n const [startupProgress, setStartupProgress] = useState<StartupProgress>({\n activated: 0,\n total: 0,\n progress: 0,\n });\n // TODO(wittjosiah): Migrate to Atom.kvs for isomorphic storage.\n const cached: string[] = useMemo(() => JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]'), []);\n const enabled = useMemo(\n () => (safeMode ? [] : cacheEnabled && cached.length > 0 ? cached : defaults),\n [safeMode, cacheEnabled, cached, defaults],\n );\n const isExternalManager = !!pluginManager;\n const manager = useMemo(() => {\n const mgr =\n pluginManager ??\n PluginManager.make({\n pluginLoader,\n plugins,\n enabled,\n onRemove: onPluginRemove,\n pluginRegistryProvider,\n });\n log('useApp: useMemo created/reused manager', { provided: !!pluginManager });\n return mgr;\n }, [pluginManager, pluginLoader, plugins, enabled, onPluginRemove, pluginRegistryProvider]);\n\n useEffect(() => {\n if (!cacheEnabled) {\n return;\n }\n return manager.registry.subscribe(manager.enabled, (value) => {\n localStorage.setItem(ENABLED_KEY, JSON.stringify(value));\n });\n }, [cacheEnabled, manager]);\n\n useEffect(() => {\n setupDevtools(manager);\n }, [manager]);\n\n useAsyncEffect(async () => {\n log('useApp: effect mount');\n\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n const fiber = Effect.gen(function* () {\n const queue = yield* PubSub.subscribe(manager.activation);\n const listener = yield* Effect.forkDaemon(\n Queue.take(queue).pipe(\n Effect.tap(({ event, state, module, error: error$ }) =>\n Effect.sync(() => {\n // Event-level Startup activated (no `module` field) fires once,\n // after every module triggered by Startup has finished. Module\n // activations now also carry their parent event id (so the trace\n // can attribute a module to its triggering event), which means\n // each module activated under Startup publishes\n // `{ event: 'startup', state: 'activated', module: <id> }`. Without\n // the `!module` guard the listener would mark the app ready on\n // the *first* such module rather than waiting for the event-level\n // completion — leaving downstream capabilities (operation-invoker,\n // app-graph, …) un-registered when the boot loader dismisses.\n if (event === ActivationEvents.Startup.id && state === 'activated' && !module) {\n clearTimeout(timeoutId);\n setReady(true);\n readyRef.current = true;\n // Trigger startup profiler dump if available.\n (globalThis as any).composer?.profiler?.dump();\n // Notify any host observability layer that startup completed.\n // A `CustomEvent` keeps this generic — app-framework doesn't\n // import a provider, and consumers can capture the startup\n // summary without us picking one.\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('app-framework:startup-activated'));\n }\n return;\n }\n // `activating` is the start-of-load signal. Surface the raw\n // `module` (or `event`) plus a pre-humanized label so the\n // boot loader can decide how to render each transition — show\n // everything, suppress noisy sub-modules, group by plugin,\n // or apply its own formatting. We intentionally do NOT touch\n // these fields on `activated`: pairing the two would cause\n // back-to-back identical updates to the host's effect, which\n // the boot loader treats as a re-trigger because\n // `progress.progress` moved. Leaving the label alone on\n // completion keeps it accurate (\"now activating X\") until\n // the next module starts.\n if (module && state === 'activating' && !readyRef.current) {\n setStartupProgress((current) => ({\n ...current,\n // `event` here is the activation event that first\n // triggered this module load (plumbed through\n // `_loadCapabilitiesForModules` → `_loadModule`).\n // Falsy/empty falls back to undefined so consumers can\n // tell \"no parent context\" from \"parent context: <X>\".\n event: event || undefined,\n module,\n humanizedName: humanizeModuleId(module),\n }));\n }\n // Update the activation count when a module commits. The\n // ring's fraction comes from this; `event`/`module`/\n // `humanizedName` were set by the matching `activating`\n // message above and are left alone so the count can advance\n // without re-firing the host's status callback.\n if (module && state === 'activated' && !readyRef.current) {\n const active = manager.getActive();\n const total = manager.getModules().length;\n setStartupProgress((current) => ({\n ...current,\n activated: active.length,\n total,\n progress: total > 0 ? active.length / total : 0,\n }));\n }\n // Event-level `activating` (no `module`) — fired at the start\n // of `_activateModulesForEvent` and recursively for each\n // before/after event. Surfaces a label during the gap before\n // the first module-level message lands; subsequent module\n // updates immediately overwrite this with a more specific\n // label.\n if (event && !module && state === 'activating' && !readyRef.current) {\n setStartupProgress((current) => ({\n ...current,\n event,\n module: undefined,\n humanizedName: humanizeEventKey(event),\n }));\n }\n if (error$ && !readyRef.current) {\n setError(error$);\n errorRef.current = error$;\n }\n }),\n ),\n Effect.forever,\n ),\n );\n\n yield* Effect.all([\n ...setupEvents.map((event) => manager.activate(event)),\n manager.activate(ActivationEvents.SetupReactSurface),\n manager.activate(ActivationEvents.Startup),\n ]);\n\n return yield* Fiber.join(listener);\n }).pipe(Effect.scoped, Effect.runFork);\n\n // Set up a timeout for startup.\n const timeoutId = setTimeout(() => {\n if (!readyRef.current && !errorRef.current) {\n log.warn('startup timeout diagnostic', {\n eventsFired: manager.getEventsFired(),\n activeModules: manager.getActive(),\n pendingReset: manager.getPendingReset(),\n });\n void EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));\n setError(new Error(`Startup timed out after ${timeout}ms`));\n }\n }, timeout);\n\n return () => {\n log('useApp: effect cleanup');\n clearTimeout(timeoutId);\n void EffectEx.runAndForwardErrors(Fiber.interrupt(fiber));\n if (!isExternalManager) {\n void EffectEx.runAndForwardErrors(manager.shutdown());\n }\n };\n }, [manager]);\n\n const progressRef = useRef(startupProgress);\n progressRef.current = startupProgress;\n\n return useCallback(\n () => (\n <ErrorBoundary name='app' FallbackComponent={fallback}>\n <PluginManagerProvider value={manager}>\n <ContextProtocolProvider value={manager} context={PluginManagerContext}>\n <RegistryContext.Provider value={manager.registry}>\n <App ready={ready} error={error} debounce={debounce} progress={progressRef.current} />\n </RegistryContext.Provider>\n </ContextProtocolProvider>\n </PluginManagerProvider>\n </ErrorBoundary>\n ),\n [fallback, manager, ready, error],\n );\n};\n\nconst setupDevtools = (manager: PluginManager.PluginManager) => {\n (globalThis as any).composer ??= {};\n (globalThis as any).composer.manager = manager;\n};\n\n/**\n * Extracts a human-readable label from a module ID.\n *\n * Module IDs follow `org.dxos.plugin.<plugin-slug>.module.<module-name>`,\n * where `<plugin-slug>` is kebab-case and `<module-name>` is either an\n * explicit string (often kebab-case, e.g. `'observability'`, `'namespace'`)\n * or a capability tag in PascalCase from `Capability.getModuleTag(...)`\n * (e.g. `'ReactSurface'`, `'AppGraphBuilder'`). The output is\n * `\"Title Case Plugin: kebab-module\"` so the visible status names both the\n * plugin and the aspect being activated, helping disambiguate the multiple\n * modules a plugin contributes.\n *\n * Examples:\n * - \"org.dxos.plugin.markdown.module.ReactSurface\" → \"Markdown: react-surface\"\n * - \"org.dxos.plugin.observability.module.AppGraphBuilder\" → \"Observability: app-graph-builder\"\n * - \"org.dxos.plugin.observability.module.observability\" → \"Observability\"\n * (the module name matches the plugin slug — collapsed to avoid\n * \"Observability: observability\" noise.)\n */\nconst humanizeModuleId = (moduleId: string): string => {\n const match = moduleId.match(/\\.plugin\\.([^.]+)\\.module\\.(.+)$/);\n if (!match) {\n // Fallback: use the last segment.\n const parts = moduleId.split('.');\n return parts[parts.length - 1];\n }\n const [, pluginSlug, moduleName] = match;\n const pluginLabel = pluginSlug\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n // Normalise the module name to kebab-case so PascalCase capability tags\n // (\"ReactSurface\") read consistently with explicit kebab IDs\n // (\"operation-handler\"). The two-step substitution handles consecutive\n // uppercase runs (`URLLoader` → `url-loader`) without splitting them\n // mid-acronym.\n const moduleLabel = moduleName\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .toLowerCase();\n // Capability modules whose name matches the plugin slug (e.g. the\n // observability plugin's `observability` capability module) would render\n // as \"Observability: observability\" — drop the redundant suffix.\n if (moduleLabel === pluginSlug) {\n return pluginLabel;\n }\n return `${pluginLabel}: ${moduleLabel}`;\n};\n\n/**\n * Extracts a human-readable label from an activation event key.\n * E.g., \"org.dxos.app-framework.event.setup-react-surface\" → \"Setup React Surface\".\n */\nconst humanizeEventKey = (eventKey: string): string => {\n // Strip a leading specifier (composite key form: \"<id>:<specifier>\").\n const id = eventKey.split(':')[0];\n // Match the trailing segment after `.event.`.\n const match = id.match(/\\.event\\.(.+)$/);\n const slug = match ? match[1] : (id.split('.').pop() ?? id);\n return slug\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom } from '@effect-atom/atom';\nimport { useAtomValue } from '@effect-atom/atom-react';\nimport { useCallback } from 'react';\n\nimport { invariant } from '@dxos/invariant';\n\nimport { Capabilities } from '../../common';\nimport { type Capability } from '../../core';\nimport { useOptionalPluginManager, usePluginManager } from '../components';\n\n/** Stable empty result for capability lookups made outside a plugin manager. */\nconst emptyCapabilities = Atom.make(() => [] as const);\n\n/** Stable atom yielding `undefined`, used as the fallback for optional atom-capability lookups. */\nconst emptyAtomValue = Atom.make(() => undefined);\n\n/**\n * Hook to request capabilities from the plugin context.\n * @returns An array of capabilities.\n */\nexport const useCapabilities = <T>(interfaceDef: Capability.InterfaceDef<T>) => {\n const manager = usePluginManager();\n return useAtomValue(manager.capabilities.atom(interfaceDef));\n};\n\n/**\n * Hook to request a capability from the plugin context.\n * @returns The capability.\n * @throws If no capability is found.\n */\n// TODO(burdon): Option not to throw?\nexport const useCapability = <T>(interfaceDef: Capability.InterfaceDef<T>) => {\n const capabilities = useCapabilities(interfaceDef);\n invariant(capabilities.length > 0, `No capability found for ${interfaceDef.identifier}`);\n return capabilities[0];\n};\n\n/**\n * Hook to request capabilities without requiring a plugin manager.\n * @returns An array of capabilities, or an empty array when rendered outside a {@link PluginManagerProvider}.\n */\nexport const useOptionalCapabilities = <T>(interfaceDef: Capability.InterfaceDef<T>): readonly T[] => {\n const manager = useOptionalPluginManager();\n return useAtomValue(\n manager ? manager.capabilities.atom(interfaceDef) : (emptyCapabilities as Atom.Atom<readonly T[]>),\n );\n};\n\n/**\n * Hook to request a single capability without requiring a plugin manager.\n * @returns The first matching capability, or `undefined` when none is registered (or there is no plugin manager).\n */\nexport const useOptionalCapability = <T>(interfaceDef: Capability.InterfaceDef<T>): T | undefined =>\n useOptionalCapabilities(interfaceDef)[0];\n\n/**\n * Hook to get the current value of an atom capability.\n * Automatically subscribes to changes.\n * @example const settings = useAtomCapability(CommentCapabilities.Settings);\n */\nexport const useAtomCapability = <T>(atomCapability: Capability.InterfaceDef<Atom.Atom<T>>): T => {\n const atom = useCapability(atomCapability);\n return useAtomValue(atom);\n};\n\n/**\n * Hook to get value and updater for an atom capability.\n * Returns [currentValue, updateFn] similar to useState.\n * @example const [settings, updateSettings] = useAtomCapabilityState(CommentCapabilities.Settings);\n */\nexport const useAtomCapabilityState = <T>(\n atomCapability: Capability.InterfaceDef<Atom.Writable<T>>,\n): [T, (fn: (current: T) => T) => void] => {\n const registry = useCapability(Capabilities.AtomRegistry);\n const atom = useCapability(atomCapability);\n const value = useAtomValue(atom);\n const update = useCallback(\n (fn: (current: T) => T) => {\n registry.set(atom, fn(registry.get(atom)));\n },\n [registry, atom],\n );\n return [value, update];\n};\n\n/**\n * Tolerant variant of {@link useAtomCapabilityState}: returns `[undefined, noop]` when the atom\n * capability is not registered (e.g. the contributing plugin is not installed) rather than\n * throwing. The updater is a no-op while the capability is absent.\n */\nexport const useOptionalAtomCapabilityState = <T>(\n atomCapability: Capability.InterfaceDef<Atom.Writable<T>>,\n): [T | undefined, (fn: (current: T) => T) => void] => {\n const registry = useOptionalCapability(Capabilities.AtomRegistry);\n const atom = useOptionalCapability(atomCapability);\n const value = useAtomValue(atom ?? emptyAtomValue);\n const update = useCallback(\n (fn: (current: T) => T) => {\n if (registry && atom) {\n registry.set(atom, fn(registry.get(atom)));\n }\n },\n [registry, atom],\n );\n return [value, update];\n};\n\n/**\n * Hook to get the operation invoker capability.\n */\nexport const useOperationInvoker = (): Capabilities.OperationInvoker => useCapability(Capabilities.OperationInvoker);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useRef, useState } from 'react';\n\nexport enum LoadingState {\n Loading = 0,\n FadeIn = 1,\n FadeOut = 2,\n Done = 3,\n}\n\n/**\n * To avoid \"flashing\" the placeholder, we wait a period of time before starting the loading animation.\n * If loading completes during this time the placehoder is not shown, otherwise is it displayed for a minimum period of time.\n *\n * States:\n * 0: Loading - Wait for a period of time before starting the loading animation.\n * 1: Fade-in - Display a loading animation.\n * 2: Fade-out - Fade out the loading animation.\n * 3: Done - Remove the placeholder.\n */\nexport const useLoading = (ready: boolean, debounce = 0) => {\n const [stage, setStage] = useState<LoadingState>(LoadingState.Loading);\n // Mirror `ready` into a ref so the interval's `setStage` callback can read\n // the latest value without depending on the effect re-running. The pure\n // closure-capture pattern (with `ready` in deps) sticks the FSM at\n // `FadeIn` whenever HMR doesn't propagate the dep change end-to-end —\n // a ref sidesteps that entirely and fires the read on every tick.\n const readyRef = useRef(ready);\n readyRef.current = ready;\n\n useEffect(() => {\n if (!debounce) {\n return;\n }\n\n const i = setInterval(() => {\n setStage((stage) => {\n const isReady = readyRef.current;\n switch (stage) {\n case LoadingState.Loading: {\n if (!isReady) {\n return LoadingState.FadeIn;\n }\n clearInterval(i);\n return LoadingState.Done;\n }\n\n case LoadingState.FadeIn: {\n if (isReady) {\n return LoadingState.FadeOut;\n }\n break;\n }\n\n case LoadingState.FadeOut: {\n clearInterval(i);\n return LoadingState.Done;\n }\n }\n\n return stage;\n });\n }, debounce);\n\n return () => clearInterval(i);\n }, [debounce]);\n\n if (!debounce) {\n return ready ? LoadingState.Done : LoadingState.Loading;\n }\n\n return stage;\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\nimport { type DependencyList, use, useCallback, useMemo } from 'react';\n\nimport { Operation, ServiceResolver } from '@dxos/compute';\nimport { EffectEx } from '@dxos/effect';\nimport type { SpaceId } from '@dxos/keys';\n\nimport { Capabilities } from '../../common';\nimport { useCapability } from './useCapabilities';\n\n/**\n * Resolve the shared {@link Capabilities.ProcessManagerRuntime} from the plugin context.\n */\nexport const useProcessManagerRuntime = (): Capabilities.ProcessManagerRuntime =>\n useCapability(Capabilities.ProcessManagerRuntime);\n\n/**\n * Build a callback that runs an effect on the {@link Capabilities.ProcessManagerRuntime}\n * with space-scoped services resolved via {@link ServiceResolver.provide}.\n *\n * The `tags` tuple must list every service the effect requires (beyond the\n * fixed {@link Capabilities.ProcessManagerRuntimeServices}); these services are\n * resolved for the given `spaceId` through the runtime's service resolver.\n *\n * Nested `Operation.invoke` / `Operation.schedule` calls within the effect\n * inherit `spaceId` as a default {@link Operation.InvokeOptions} so that\n * spawned operation processes have a space context (and therefore can resolve\n * space-scoped services like `Database.Service`) without each call site having\n * to thread the id through manually.\n */\nexport const useSpaceCallback = <const Tags extends readonly Context.Tag<any, any>[], T>(\n spaceId: SpaceId | undefined,\n tags: Tags,\n fn: () => Effect.Effect<T, any, Context.Tag.Identifier<Tags[number]> | Capabilities.ProcessManagerRuntimeServices>,\n deps?: DependencyList,\n): (() => Promise<T>) => {\n const runtime = useProcessManagerRuntime();\n return useCallback(() => {\n if (spaceId === undefined) {\n throw new TypeError('Space not provided to useSpaceCallback');\n }\n const layer = Layer.merge(\n ServiceResolver.provide({ space: spaceId }, ...tags),\n Operation.withInvocationOptions({ spaceId }),\n );\n return runtime.runPromise(fn().pipe(Effect.provide(layer)) as Effect.Effect<T, any, any>);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [runtime, spaceId, ...(deps ?? [])]);\n};\n\n/**\n * Suspensefully resolve a single space-scoped service via the\n * {@link Capabilities.ProcessManagerRuntime}'s service resolver.\n */\nexport const useSpaceService = <T extends Context.Tag<any, any>>(\n tag: T,\n spaceId: SpaceId | undefined,\n): Context.Tag.Service<T> | undefined => {\n const runtime = useProcessManagerRuntime();\n const promise = useMemo(() => {\n if (spaceId === undefined) {\n return undefined;\n }\n const layer = ServiceResolver.provide({ space: spaceId }, tag);\n const effect = Effect.flatMap(tag, (service) => Effect.succeed(service)).pipe(Effect.provide(layer));\n return runtime.runPromiseExit(effect as Effect.Effect<Context.Tag.Service<T>, any, any>);\n }, [runtime, spaceId, tag]);\n if (!promise) {\n return undefined;\n }\n return EffectEx.unwrapExit(use(promise));\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Atom, RegistryContext, useAtomValue } from '@effect-atom/atom-react';\nimport { useCallback, useContext } from 'react';\n\n/**\n * Hook to read and update a settings atom.\n * Returns the current value and an update function.\n */\nexport const useSettingsState = <T>(\n atom: Atom.Writable<T>,\n): { settings: T; updateSettings: (fn: (current: T) => T) => void } => {\n const registry = useContext(RegistryContext);\n const settings = useAtomValue(atom);\n\n const updateSettings = useCallback(\n (fn: (current: T) => T) => {\n registry.set(atom, fn(registry.get(atom)));\n },\n [registry, atom],\n );\n\n return { settings, updateSettings };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "useEffect", "useLayoutEffect", "RegistryContext", "Effect", "Fiber", "PubSub", "Queue", "React", "useCallback", "useEffect", "useMemo", "useRef", "useState", "EffectEx", "invariant", "log", "ErrorBoundary", "ErrorFallback", "useAsyncEffect", "useDefaultValue", "ContextProtocolProvider", "ENABLED_KEY", "defaults", "useDefaultValue", "defaultsProp", "setupEvents", "setupEventsProp", "pluginLoader", "pluginLoaderProp", "plugin", "find", "meta", "invariant", "id", "plugins", "errorRef", "useRef", "error", "setError", "useState", "startupProgress", "setStartupProgress", "activated", "total", "progress", "safeMode", "cacheEnabled", "cached", "pluginManager", "enabled", "onRemove", "pluginRegistryProvider", "mgr", "onPluginRemove", "useEffect", "manager", "useAsyncEffect", "capabilities", "contribute", "interface", "Capabilities", "PluginManager", "implementation", "module", "registry", "fiber", "forkDaemon", "setReady", "readyRef", "current", "globalThis", "humanizedName", "humanizeModuleId", "length", "active", "event", "error$", "Effect", "forever", "activate", "ActivationEvents", "Startup", "join", "listener", "pipe", "timeoutId", "eventsFired", "getEventsFired", "activeModules", "pendingReset", "getPendingReset", "runAndForwardErrors", "interrupt", "Error", "timeout", "clearTimeout", "Fiber", "isExternalManager", "EffectEx", "shutdown", "progressRef", "name", "FallbackComponent", "fallback", "value", "ContextProtocolProvider", "PluginManagerContext", "App", "ready", "debounce", "composer", "match", "parts", "pluginSlug", "moduleName", "pluginLabel", "split", "map", "word", "Atom", "useAtomValue", "useCallback", "invariant", "__dxlog_file", "useAtomValue", "capabilities", "interfaceDef", "invariant", "length", "atom", "useCapability", "atomCapability", "value", "update", "fn", "registry", "set", "useCallback", "useOptionalCapability", "emptyAtomValue", "useEffect", "useRef", "useState", "LoadingState", "useLoading", "ready", "debounce", "stage", "setStage", "readyRef", "current", "i", "setInterval", "isReady", "clearInterval", "Effect", "Layer", "use", "useCallback", "useMemo", "Operation", "ServiceResolver", "EffectEx", "useProcessManagerRuntime", "useCapability", "Capabilities", "ProcessManagerRuntime", "useSpaceCallback", "spaceId", "tags", "fn", "deps", "runtime", "useCallback", "undefined", "TypeError", "layer", "merge", "ServiceResolver", "provide", "space", "Operation", "withInvocationOptions", "runPromise", "pipe", "useSpaceService", "tag", "promise", "useMemo", "effect", "flatMap", "service", "succeed", "runPromiseExit", "EffectEx", "unwrapExit", "use", "RegistryContext", "useAtomValue", "useCallback", "useContext", "useSettingsState", "atom", "registry", "settings", "updateSettings", "fn", "set", "get", "FIRST_INTERACTIVE_MARK", "App", "ready", "error", "debounce", "progress", "reactContexts", "useCapabilities", "Capabilities", "ReactContext", "reactRoots", "ReactRoot", "stage", "useLoading", "placeholderDismissed", "LoadingState", "Done", "useEffect", "FadeOut", "fraction", "window", "__bootLoader", "humanizedName", "status", "event", "module", "humanized", "useLayoutEffect", "performance", "getEntriesByName", "length", "mark", "dismiss", "location", "search", "Error", "ComposedContext", "composeContexts", "React", "map", "id", "root", "Component", "key", "contexts", "children", "topologicalSort", "context", "reduce", "Acc", "Next"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isPlugin
3
- } from "./chunk-S2ZBYQPI.mjs";
3
+ } from "./chunk-OO53M5UK.mjs";
4
4
  import {
5
5
  __export
6
6
  } from "./chunk-J5LGTIGS.mjs";
@@ -427,4 +427,4 @@ export {
427
427
  uninstall,
428
428
  url_loader_exports
429
429
  };
430
- //# sourceMappingURL=chunk-3UTDRCKX.mjs.map
430
+ //# sourceMappingURL=chunk-LUH4Y5F2.mjs.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  capability_exports
3
- } from "./chunk-CMINFVA5.mjs";
3
+ } from "./chunk-OPTS3ZSN.mjs";
4
4
  import {
5
5
  __export
6
6
  } from "./chunk-J5LGTIGS.mjs";
@@ -92,4 +92,4 @@ export {
92
92
  subscribeAtom,
93
93
  capabilities_exports
94
94
  };
95
- //# sourceMappingURL=chunk-37PG7XJC.mjs.map
95
+ //# sourceMappingURL=chunk-NKVRSMFN.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/common/capabilities.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Atom, type Registry } from '@effect-atom/atom-react';\nimport type * as Command$ from '@effect/cli/Command';\nimport * as Effect from 'effect/Effect';\nimport type * as Exit$ from 'effect/Exit';\nimport type * as Fiber$ from 'effect/Fiber';\nimport type * as Layer$ from 'effect/Layer';\nimport type * as ManagedRuntime$ from 'effect/ManagedRuntime';\nimport type * as Runtime$ from 'effect/Runtime';\nimport type { FC, PropsWithChildren } from 'react';\n\nimport type {\n LayerSpec as LayerSpec$,\n Operation as Operation$,\n OperationHandlerSet,\n Process as Process$,\n ServiceResolver as ServiceResolver$,\n Trace as Trace$,\n} from '@dxos/compute';\nimport type { ProcessManager as ProcessManager$ } from '@dxos/compute-runtime';\nimport { OperationInvoker as OperationInvoker$ } from '@dxos/operation';\n\nimport { Capability as Capability$, Plugin as Plugin$, type PluginManager as PluginManager$ } from '../core';\nimport type {\n HistoryTracker as HistoryTracker$,\n UndoMapping as UndoMapping$,\n UndoRegistry as UndoRegistry$,\n} from '../plugin-process-manager';\nimport type { Surface } from '../ui';\n\n/**\n * Null capability.\n * @category Capability\n */\nexport const Null = Capability$.make<null>('org.dxos.app-framework.capability.null');\n\n/**\n * @category Capability\n */\nexport const PluginManager = Capability$.make<PluginManager$.PluginManager>(\n 'org.dxos.app-framework.capability.pluginManager',\n);\n\n/**\n * @category Capability\n */\nexport const AtomRegistry = Capability$.make<Registry.Registry>('org.dxos.app-framework.capability.atomRegistry');\n\nexport type ReactContext = Readonly<{\n id: string;\n dependsOn?: string[];\n context: FC<PropsWithChildren>;\n}>;\n\n/**\n * @category Capability\n */\nexport const ReactContext = Capability$.make<ReactContext>('org.dxos.app-framework.capability.reactContext');\n\nexport type ReactRoot = Readonly<{ id: string; root: FC<PropsWithChildren> }>;\n\n/**\n * @category Capability\n */\nexport const ReactRoot = Capability$.make<ReactRoot>('org.dxos.app-framework.capability.reactRoot');\n\n/**\n * Surface definitions that can be either React components or Web Components.\n */\nexport type ReactSurface = Surface.Definition | readonly Surface.Definition[];\n\n/**\n * @category Capability\n */\nexport const ReactSurface = Capability$.make<ReactSurface>('org.dxos.app-framework.capability.reactSurface');\n\nexport type AnyCommand = Command$.Command<any, any, any, any>;\n\n/**\n * @category Capability\n */\nexport const Command = Capability$.make<AnyCommand>('org.dxos.app-framework.capability.command');\n\n/**\n * @category Capability\n */\nexport const Layer = Capability$.make<Layer$.Layer<any, any, any>>('org.dxos.app-framework.capability.layer');\n\n/**\n * Layer specification contributed by plugins.\n *\n * Plugins contribute {@link LayerSpec.LayerSpec} entries that are collected by the\n * process-manager module and composed into a {@link LayerStack} which backs the\n * {@link ProcessManagerRuntime}'s service resolver.\n *\n * @category Capability\n */\nexport const LayerSpec = Capability$.make<LayerSpec$.LayerSpec>('org.dxos.app-framework.capability.layerSpec');\n\n/**\n * Context passed to {@link TraceSinkFactory} implementations when the\n * process-manager capability materialises contributed sinks.\n */\nexport interface TraceSinkFactoryContext {\n /**\n * Service resolver backing the shared {@link ProcessManagerRuntime}. Use it\n * to resolve per-space (or per-process) services like `FeedTraceSink` when\n * building a routing sink.\n */\n readonly resolver: ServiceResolver$.ServiceResolver;\n}\n\n/**\n * Factory that builds a {@link Trace$.Sink} when the process-manager\n * capability is ready. Plugins that only need a static sink can ignore the\n * context (e.g. `() => myConsoleSink`); plugins that need per-space routing\n * can use {@link TraceSinkFactoryContext.resolver} to look up services.\n */\nexport type TraceSinkFactory = (ctx: TraceSinkFactoryContext) => Trace$.Sink;\n\n/**\n * Trace sink contribution.\n *\n * Plugins contribute {@link TraceSinkFactory} functions; the process-manager\n * capability invokes each factory with the runtime's\n * {@link ServiceResolver$.ServiceResolver}, collects the resulting\n * {@link Trace$.Sink}s, merges them via {@link Trace$.mergeSinks}, and\n * installs the merged sink as {@link Trace$.TraceSink} in the runtime layer\n * so every process writes to every contributed sink.\n *\n * @category Capability\n */\nexport const TraceSink = Capability$.make<TraceSinkFactory>('org.dxos.app-framework.capability.traceSink');\n\n/**\n * Service resolver backing the shared {@link ProcessManagerRuntime}.\n *\n * Contributed by the process-manager capability module. Consumers can combine\n * it with {@link ServiceResolver$.provide} to build space-scoped layers without\n * having to go through the process-manager runtime:\n *\n * @example\n * ```ts\n * const resolver = yield* Capability.get(Capabilities.ServiceResolver);\n * yield* effect.pipe(\n * Effect.provide(\n * ServiceResolver.provide({ space }, Database.Service, Feed.FeedService).pipe(\n * Layer.provide(Layer.succeed(ServiceResolver.ServiceResolver, resolver)),\n * ),\n * ),\n * );\n * ```\n *\n * @category Capability\n */\nexport const ServiceResolver = Capability$.make<ServiceResolver$.ServiceResolver>(\n 'org.dxos.app-framework.capability.serviceResolver',\n);\n\n/**\n * Process monitor backing the shared {@link ProcessManagerRuntime}. Exposes the\n * live process tree (including inactive/terminated entries) via\n * {@link Process$.Monitor#processTreeAtom}.\n *\n * @category Capability\n */\nexport const ProcessMonitor = Capability$.make<Process$.Monitor>('org.dxos.app-framework.capability.processMonitor');\n\n/**\n * Services that are always available when running effects through a {@link ProcessManagerRuntime}.\n */\nexport type ProcessManagerRuntimeServices =\n | Capability$.Service\n | Plugin$.Service\n | ProcessManager$.ProcessManagerService\n | Operation$.Service\n | ProcessManager$.ProcessOperationInvoker.Service\n | ServiceResolver$.ServiceResolver;\n\n/**\n * Runtime that runs effects requiring a fixed set of capability-manager and\n * process-manager services.\n *\n * The shape mirrors {@link ManagedRuntime$.ManagedRuntime} but deliberately does\n * not expose `dispose` – lifecycle is driven by the host plugin manager.\n */\nexport interface ProcessManagerRuntime {\n runPromise<A, E>(\n effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>,\n options?: { readonly signal?: AbortSignal },\n ): Promise<A>;\n runPromiseExit<A, E>(\n effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>,\n options?: { readonly signal?: AbortSignal },\n ): Promise<Exit$.Exit<A, E>>;\n runFork<A, E>(\n effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>,\n options?: Runtime$.RunForkOptions,\n ): Fiber$.RuntimeFiber<A, E>;\n runSync<A, E>(effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>): A;\n}\n\n/**\n * @category Capability\n */\nexport const ProcessManagerRuntime = Capability$.make<ProcessManagerRuntime>(\n 'org.dxos.app-framework.capability.processManagerRuntime',\n);\n\nexport type ManagedRuntime = ManagedRuntime$.ManagedRuntime<any, any>;\n\n/**\n * @category Capability\n */\nexport const ManagedRuntime = Capability$.make<ManagedRuntime>('org.dxos.app-framework.capability.managedRuntime');\n\n//\n// Operation System Capabilities\n//\n\nexport const OperationHandler = Capability$.make<OperationHandlerSet.OperationHandlerSet>(\n 'org.dxos.app-framework.capability.operationHandler',\n);\n\nexport type UndoMapping = UndoMapping$.UndoMapping;\n\n/**\n * Undo mapping registration - contributed by plugins.\n * @category Capability\n */\nexport const UndoMapping = Capability$.make<UndoMapping[]>('org.dxos.app-framework.capability.undoMapping');\n\n/**\n * Operation invoker backed by the process manager. Spawns a process per\n * operation invocation; see {@link ProcessManager$.ProcessOperationInvoker}.\n */\nexport type OperationInvoker = OperationInvoker$.OperationInvoker;\n\n/**\n * Operation invoker - provided by the process-manager capability.\n * @category Capability\n */\nexport const OperationInvoker = Capability$.make<OperationInvoker>(\n 'org.dxos.app-framework.capability.operationInvoker',\n);\n\nexport type UndoRegistry = UndoRegistry$.UndoRegistry;\n\n/**\n * Undo registry - provided by ProcessManagerPlugin.\n * @category Capability\n */\nexport const UndoRegistry = Capability$.make<UndoRegistry>('org.dxos.app-framework.capability.undoRegistry');\n\nexport type HistoryTracker = HistoryTracker$.HistoryTracker;\n\n/**\n * History tracker - provided by ProcessManagerPlugin.\n * @category Capability\n */\nexport const HistoryTracker = Capability$.make<HistoryTracker>('org.dxos.app-framework.capability.historyTracker');\n\n//\n// Atom Capability Helpers\n//\n\n/**\n * Get the current value of an atom capability.\n * @example const settings = yield* Capabilities.getAtomValue(CommentCapabilities.Settings);\n */\nexport const getAtomValue = <T>(\n atomCapability: Capability$.InterfaceDef<Atom.Atom<T>>,\n): Effect.Effect<T, Error, Capability$.Service> =>\n Effect.gen(function* () {\n const registry = yield* Capability$.get(AtomRegistry);\n const atom = yield* Capability$.get(atomCapability);\n return registry.get(atom);\n });\n\n/**\n * Update an atom capability value (requires writable atom).\n * @example yield* Capabilities.updateAtomValue(CommentCapabilities.Settings, (s) => ({ ...s, foo: true }));\n */\nexport const updateAtomValue = <T>(\n atomCapability: Capability$.InterfaceDef<Atom.Writable<T>>,\n fn: (current: T) => T,\n): Effect.Effect<void, Error, Capability$.Service> =>\n Effect.gen(function* () {\n const registry = yield* Capability$.get(AtomRegistry);\n const atom = yield* Capability$.get(atomCapability);\n registry.set(atom, fn(registry.get(atom)));\n });\n\n/**\n * Subscribe to an atom capability.\n * @example const unsubscribe = yield* Capabilities.subscribeAtom(CommentCapabilities.Settings, (value) => ...);\n */\nexport const subscribeAtom = <T>(\n atomCapability: Capability$.InterfaceDef<Atom.Atom<T>>,\n callback: (value: T) => void,\n): Effect.Effect<() => void, Error, Capability$.Service> =>\n Effect.gen(function* () {\n const registry = yield* Capability$.get(AtomRegistry);\n const atom = yield* Capability$.get(atomCapability);\n return registry.subscribe(atom, () => callback(registry.get(atom)));\n });\n"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Atom, type Registry } from '@effect-atom/atom-react';\nimport type * as Command$ from '@effect/cli/Command';\nimport * as Effect from 'effect/Effect';\nimport type * as Exit$ from 'effect/Exit';\nimport type * as Fiber$ from 'effect/Fiber';\nimport type * as Layer$ from 'effect/Layer';\nimport type * as ManagedRuntime$ from 'effect/ManagedRuntime';\nimport type * as Runtime$ from 'effect/Runtime';\nimport type { FC, PropsWithChildren } from 'react';\n\nimport type {\n OperationHandlerSet,\n LayerSpec as LayerSpec$,\n Operation as Operation$,\n Process as Process$,\n ServiceResolver as ServiceResolver$,\n Trace as Trace$,\n} from '@dxos/compute';\nimport type { ProcessManager as ProcessManager$ } from '@dxos/compute-runtime';\nimport { OperationInvoker as OperationInvoker$ } from '@dxos/operation';\n\nimport { Capability as Capability$, Plugin as Plugin$, type PluginManager as PluginManager$ } from '../core';\nimport type {\n HistoryTracker as HistoryTracker$,\n UndoMapping as UndoMapping$,\n UndoRegistry as UndoRegistry$,\n} from '../plugin-process-manager';\nimport type { Surface } from '../ui';\n\n/**\n * Null capability.\n * @category Capability\n */\nexport const Null = Capability$.make<null>('org.dxos.app-framework.capability.null');\n\n/**\n * @category Capability\n */\nexport const PluginManager = Capability$.make<PluginManager$.PluginManager>(\n 'org.dxos.app-framework.capability.pluginManager',\n);\n\n/**\n * @category Capability\n */\nexport const AtomRegistry = Capability$.make<Registry.Registry>('org.dxos.app-framework.capability.atomRegistry');\n\nexport type ReactContext = Readonly<{\n id: string;\n dependsOn?: string[];\n context: FC<PropsWithChildren>;\n}>;\n\n/**\n * @category Capability\n */\nexport const ReactContext = Capability$.make<ReactContext>('org.dxos.app-framework.capability.reactContext');\n\nexport type ReactRoot = Readonly<{ id: string; root: FC<PropsWithChildren> }>;\n\n/**\n * @category Capability\n */\nexport const ReactRoot = Capability$.make<ReactRoot>('org.dxos.app-framework.capability.reactRoot');\n\n/**\n * Surface definitions that can be either React components or Web Components.\n */\nexport type ReactSurface = Surface.Definition | readonly Surface.Definition[];\n\n/**\n * @category Capability\n */\nexport const ReactSurface = Capability$.make<ReactSurface>('org.dxos.app-framework.capability.reactSurface');\n\nexport type AnyCommand = Command$.Command<any, any, any, any>;\n\n/**\n * @category Capability\n */\nexport const Command = Capability$.make<AnyCommand>('org.dxos.app-framework.capability.command');\n\n/**\n * @category Capability\n */\nexport const Layer = Capability$.make<Layer$.Layer<any, any, any>>('org.dxos.app-framework.capability.layer');\n\n/**\n * Layer specification contributed by plugins.\n *\n * Plugins contribute {@link LayerSpec.LayerSpec} entries that are collected by the\n * process-manager module and composed into a {@link LayerStack} which backs the\n * {@link ProcessManagerRuntime}'s service resolver.\n *\n * @category Capability\n */\nexport const LayerSpec = Capability$.make<LayerSpec$.LayerSpec>('org.dxos.app-framework.capability.layerSpec');\n\n/**\n * Context passed to {@link TraceSinkFactory} implementations when the\n * process-manager capability materialises contributed sinks.\n */\nexport interface TraceSinkFactoryContext {\n /**\n * Service resolver backing the shared {@link ProcessManagerRuntime}. Use it\n * to resolve per-space (or per-process) services like `FeedTraceSink` when\n * building a routing sink.\n */\n readonly resolver: ServiceResolver$.ServiceResolver;\n}\n\n/**\n * Factory that builds a {@link Trace$.Sink} when the process-manager\n * capability is ready. Plugins that only need a static sink can ignore the\n * context (e.g. `() => myConsoleSink`); plugins that need per-space routing\n * can use {@link TraceSinkFactoryContext.resolver} to look up services.\n */\nexport type TraceSinkFactory = (ctx: TraceSinkFactoryContext) => Trace$.Sink;\n\n/**\n * Trace sink contribution.\n *\n * Plugins contribute {@link TraceSinkFactory} functions; the process-manager\n * capability invokes each factory with the runtime's\n * {@link ServiceResolver$.ServiceResolver}, collects the resulting\n * {@link Trace$.Sink}s, merges them via {@link Trace$.mergeSinks}, and\n * installs the merged sink as {@link Trace$.TraceSink} in the runtime layer\n * so every process writes to every contributed sink.\n *\n * @category Capability\n */\nexport const TraceSink = Capability$.make<TraceSinkFactory>('org.dxos.app-framework.capability.traceSink');\n\n/**\n * Service resolver backing the shared {@link ProcessManagerRuntime}.\n *\n * Contributed by the process-manager capability module. Consumers can combine\n * it with {@link ServiceResolver$.provide} to build space-scoped layers without\n * having to go through the process-manager runtime:\n *\n * @example\n * ```ts\n * const resolver = yield* Capability.get(Capabilities.ServiceResolver);\n * yield* effect.pipe(\n * Effect.provide(\n * ServiceResolver.provide({ space }, Database.Service).pipe(\n * Layer.provide(Layer.succeed(ServiceResolver.ServiceResolver, resolver)),\n * ),\n * ),\n * );\n * ```\n *\n * @category Capability\n */\nexport const ServiceResolver = Capability$.make<ServiceResolver$.ServiceResolver>(\n 'org.dxos.app-framework.capability.serviceResolver',\n);\n\n/**\n * Process monitor backing the shared {@link ProcessManagerRuntime}. Exposes the\n * live process tree (including inactive/terminated entries) via\n * {@link Process$.Monitor#processTreeAtom}.\n *\n * @category Capability\n */\nexport const ProcessMonitor = Capability$.make<Process$.Monitor>('org.dxos.app-framework.capability.processMonitor');\n\n/**\n * Services that are always available when running effects through a {@link ProcessManagerRuntime}.\n */\nexport type ProcessManagerRuntimeServices =\n | Capability$.Service\n | Plugin$.Service\n | ProcessManager$.ProcessManagerService\n | Operation$.Service\n | ProcessManager$.ProcessOperationInvoker.Service\n | ServiceResolver$.ServiceResolver;\n\n/**\n * Runtime that runs effects requiring a fixed set of capability-manager and\n * process-manager services.\n *\n * The shape mirrors {@link ManagedRuntime$.ManagedRuntime} but deliberately does\n * not expose `dispose` – lifecycle is driven by the host plugin manager.\n */\nexport interface ProcessManagerRuntime {\n runPromise<A, E>(\n effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>,\n options?: { readonly signal?: AbortSignal },\n ): Promise<A>;\n runPromiseExit<A, E>(\n effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>,\n options?: { readonly signal?: AbortSignal },\n ): Promise<Exit$.Exit<A, E>>;\n runFork<A, E>(\n effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>,\n options?: Runtime$.RunForkOptions,\n ): Fiber$.RuntimeFiber<A, E>;\n runSync<A, E>(effect: Effect.Effect<A, E, ProcessManagerRuntimeServices>): A;\n}\n\n/**\n * @category Capability\n */\nexport const ProcessManagerRuntime = Capability$.make<ProcessManagerRuntime>(\n 'org.dxos.app-framework.capability.processManagerRuntime',\n);\n\nexport type ManagedRuntime = ManagedRuntime$.ManagedRuntime<any, any>;\n\n/**\n * @category Capability\n */\nexport const ManagedRuntime = Capability$.make<ManagedRuntime>('org.dxos.app-framework.capability.managedRuntime');\n\n//\n// Operation System Capabilities\n//\n\nexport const OperationHandler = Capability$.make<OperationHandlerSet.OperationHandlerSet>(\n 'org.dxos.app-framework.capability.operationHandler',\n);\n\nexport type UndoMapping = UndoMapping$.UndoMapping;\n\n/**\n * Undo mapping registration - contributed by plugins.\n * @category Capability\n */\nexport const UndoMapping = Capability$.make<UndoMapping[]>('org.dxos.app-framework.capability.undoMapping');\n\n/**\n * Operation invoker backed by the process manager. Spawns a process per\n * operation invocation; see {@link ProcessManager$.ProcessOperationInvoker}.\n */\nexport type OperationInvoker = OperationInvoker$.OperationInvoker;\n\n/**\n * Operation invoker - provided by the process-manager capability.\n * @category Capability\n */\nexport const OperationInvoker = Capability$.make<OperationInvoker>(\n 'org.dxos.app-framework.capability.operationInvoker',\n);\n\nexport type UndoRegistry = UndoRegistry$.UndoRegistry;\n\n/**\n * Undo registry - provided by ProcessManagerPlugin.\n * @category Capability\n */\nexport const UndoRegistry = Capability$.make<UndoRegistry>('org.dxos.app-framework.capability.undoRegistry');\n\nexport type HistoryTracker = HistoryTracker$.HistoryTracker;\n\n/**\n * History tracker - provided by ProcessManagerPlugin.\n * @category Capability\n */\nexport const HistoryTracker = Capability$.make<HistoryTracker>('org.dxos.app-framework.capability.historyTracker');\n\n//\n// Atom Capability Helpers\n//\n\n/**\n * Get the current value of an atom capability.\n * @example const settings = yield* Capabilities.getAtomValue(CommentCapabilities.Settings);\n */\nexport const getAtomValue = <T>(\n atomCapability: Capability$.InterfaceDef<Atom.Atom<T>>,\n): Effect.Effect<T, Error, Capability$.Service> =>\n Effect.gen(function* () {\n const registry = yield* Capability$.get(AtomRegistry);\n const atom = yield* Capability$.get(atomCapability);\n return registry.get(atom);\n });\n\n/**\n * Update an atom capability value (requires writable atom).\n * @example yield* Capabilities.updateAtomValue(CommentCapabilities.Settings, (s) => ({ ...s, foo: true }));\n */\nexport const updateAtomValue = <T>(\n atomCapability: Capability$.InterfaceDef<Atom.Writable<T>>,\n fn: (current: T) => T,\n): Effect.Effect<void, Error, Capability$.Service> =>\n Effect.gen(function* () {\n const registry = yield* Capability$.get(AtomRegistry);\n const atom = yield* Capability$.get(atomCapability);\n registry.set(atom, fn(registry.get(atom)));\n });\n\n/**\n * Subscribe to an atom capability.\n * @example const unsubscribe = yield* Capabilities.subscribeAtom(CommentCapabilities.Settings, (value) => ...);\n */\nexport const subscribeAtom = <T>(\n atomCapability: Capability$.InterfaceDef<Atom.Atom<T>>,\n callback: (value: T) => void,\n): Effect.Effect<() => void, Error, Capability$.Service> =>\n Effect.gen(function* () {\n const registry = yield* Capability$.get(AtomRegistry);\n const atom = yield* Capability$.get(atomCapability);\n return registry.subscribe(atom, () => callback(registry.get(atom)));\n });\n"],
5
5
  "mappings": ";;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,YAAYA,YAAY;AA+BjB,IAAMC,OAAOC,mBAAYC,KAAW,wCAAA;AAKpC,IAAMC,gBAAgBF,mBAAYC,KACvC,iDAAA;AAMK,IAAME,eAAeH,mBAAYC,KAAwB,gDAAA;AAWzD,IAAMG,eAAeJ,mBAAYC,KAAmB,gDAAA;AAOpD,IAAMI,YAAYL,mBAAYC,KAAgB,6CAAA;AAU9C,IAAMK,eAAeN,mBAAYC,KAAmB,gDAAA;AAOpD,IAAMM,UAAUP,mBAAYC,KAAiB,2CAAA;AAK7C,IAAMO,QAAQR,mBAAYC,KAAkC,yCAAA;AAW5D,IAAMQ,YAAYT,mBAAYC,KAA2B,6CAAA;AAmCzD,IAAMS,YAAYV,mBAAYC,KAAuB,6CAAA;AAuBrD,IAAMU,kBAAkBX,mBAAYC,KACzC,mDAAA;AAUK,IAAMW,iBAAiBZ,mBAAYC,KAAuB,kDAAA;AAuC1D,IAAMY,wBAAwBb,mBAAYC,KAC/C,yDAAA;AAQK,IAAMa,iBAAiBd,mBAAYC,KAAqB,kDAAA;AAMxD,IAAMc,mBAAmBf,mBAAYC,KAC1C,oDAAA;AASK,IAAMe,cAAchB,mBAAYC,KAAoB,+CAAA;AAYpD,IAAMgB,mBAAmBjB,mBAAYC,KAC1C,oDAAA;AASK,IAAMiB,eAAelB,mBAAYC,KAAmB,gDAAA;AAQpD,IAAMkB,iBAAiBnB,mBAAYC,KAAqB,kDAAA;AAUxD,IAAMmB,eAAe,CAC1BC,mBAEOC,WAAI,aAAA;AACT,QAAMC,WAAW,OAAOvB,mBAAYwB,IAAIrB,YAAAA;AACxC,QAAMsB,OAAO,OAAOzB,mBAAYwB,IAAIH,cAAAA;AACpC,SAAOE,SAASC,IAAIC,IAAAA;AACtB,CAAA;AAMK,IAAMC,kBAAkB,CAC7BL,gBACAM,OAEOL,WAAI,aAAA;AACT,QAAMC,WAAW,OAAOvB,mBAAYwB,IAAIrB,YAAAA;AACxC,QAAMsB,OAAO,OAAOzB,mBAAYwB,IAAIH,cAAAA;AACpCE,WAASK,IAAIH,MAAME,GAAGJ,SAASC,IAAIC,IAAAA,CAAAA,CAAAA;AACrC,CAAA;AAMK,IAAMI,gBAAgB,CAC3BR,gBACAS,aAEOR,WAAI,aAAA;AACT,QAAMC,WAAW,OAAOvB,mBAAYwB,IAAIrB,YAAAA;AACxC,QAAMsB,OAAO,OAAOzB,mBAAYwB,IAAIH,cAAAA;AACpC,SAAOE,SAASQ,UAAUN,MAAM,MAAMK,SAASP,SAASC,IAAIC,IAAAA,CAAAA,CAAAA;AAC9D,CAAA;",
6
6
  "names": ["Effect", "Null", "Capability$", "make", "PluginManager", "AtomRegistry", "ReactContext", "ReactRoot", "ReactSurface", "Command", "Layer", "LayerSpec", "TraceSink", "ServiceResolver", "ProcessMonitor", "ProcessManagerRuntime", "ManagedRuntime", "OperationHandler", "UndoMapping", "OperationInvoker", "UndoRegistry", "HistoryTracker", "getAtomValue", "atomCapability", "gen", "registry", "get", "atom", "updateAtomValue", "fn", "set", "subscribeAtom", "callback", "subscribe"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getModuleTag
3
- } from "./chunk-CMINFVA5.mjs";
3
+ } from "./chunk-OPTS3ZSN.mjs";
4
4
  import {
5
5
  __export
6
6
  } from "./chunk-J5LGTIGS.mjs";
@@ -257,4 +257,4 @@ export {
257
257
  resolveLazy,
258
258
  plugin_exports
259
259
  };
260
- //# sourceMappingURL=chunk-S2ZBYQPI.mjs.map
260
+ //# sourceMappingURL=chunk-OO53M5UK.mjs.map
@@ -80,4 +80,4 @@ export {
80
80
  makeModule,
81
81
  capability_exports
82
82
  };
83
- //# sourceMappingURL=chunk-CMINFVA5.mjs.map
83
+ //# sourceMappingURL=chunk-OPTS3ZSN.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/capability.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Atom } from '@effect-atom/atom-react';\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport type { DXN } from '@dxos/keys';\n\nimport type * as CapabilityManager from './capability-manager';\nimport type * as Plugin from './plugin';\n\n//\n// Capability Service Layer\n//\n\n/**\n * Effect Context.Tag for accessing CapabilityManager via the Effect layer system.\n * This allows capability modules to access the capability manager without having it passed as an argument.\n */\nexport class Service extends Context.Tag('@dxos/app-framework/CapabilityManager')<\n Service,\n CapabilityManager.CapabilityManager\n>() {}\n\n/**\n * Get a single capability from the capability manager.\n * @param interfaceDef The interface definition of the capability.\n * @returns The capability implementation.\n * @throws If no capability is found.\n */\n// TODO(wittjosiah): Add custom tagged errors (Data.TaggedError) for app-framework to enable\n// type-safe error handling with Effect. Consider CapabilityNotFoundError, ModuleActivationError, etc.\nexport const get = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T, Error, Service> =>\n Effect.flatMap(Service, (manager) =>\n Effect.try({\n try: () => manager.get(interfaceDef),\n catch: (error) => (error instanceof Error ? error : new Error(String(error))),\n }),\n );\n\n/**\n * Get all capabilities from the capability manager for a given interface.\n * @param interfaceDef The interface definition of the capability.\n * @returns An array of capability implementations.\n */\nexport const getAll = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T[], never, Service> =>\n Effect.map(Service, (manager) => manager.getAll(interfaceDef));\n\n/**\n * Wait for a capability to be available.\n * @param interfaceDef The interface definition of the capability.\n * @returns The capability implementation once available.\n */\nexport const waitFor = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.waitFor(interfaceDef));\n\n/**\n * Get the Atom reference to capabilities for reactive access.\n * @param interfaceDef The interface definition of the capability.\n * @returns An Atom containing the array of capability implementations.\n */\nexport const atom = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<Atom.Atom<T[]>, never, Service> =>\n Effect.map(Service, (manager) => manager.atom(interfaceDef));\n\n/**\n * Get capabilities grouped by the module that contributed them.\n * @param interfaceDef The interface definition of the capability.\n * @returns An Atom containing a record from module ID to capability implementations.\n */\nexport const atomByModule = <T>(\n interfaceDef: InterfaceDef<T>,\n): Effect.Effect<Atom.Atom<Record<string, T[]>>, never, Service> =>\n Effect.map(Service, (manager) => manager.atomByModule(interfaceDef));\n\n/**\n * Constructs a layer that will request its interface implementation from the capability manager.\n */\nexport const asLayer = <T, I>(interfaceDef: InterfaceDef<T>, tag: Context.Tag<I, T>): Layer.Layer<I, never, Service> =>\n Layer.effect(tag, get(interfaceDef).pipe(Effect.orDie));\n\nconst InterfaceDefTypeId: unique symbol = Symbol.for('InterfaceDefTypeId');\n\n/**\n * Symbol used to tag lazy capability functions with their module ID.\n */\nexport const ModuleTag: unique symbol = Symbol.for('@dxos/app-framework/ModuleTag');\n\n/**\n * The interface definition of a capability.\n */\nexport type InterfaceDef<T> = {\n [InterfaceDefTypeId]: T;\n identifier: string;\n};\n\nexport namespace InterfaceDef {\n export type Implementation<I extends InterfaceDef<any>> = I extends InterfaceDef<infer T> ? T : never;\n}\n\n/**\n * Helper to define the interface of a capability.\n * Static NSID strings are validated at compile time via {@link DXN.Name}.\n */\nexport const make: {\n <T, S extends string = string>(\n identifier: [DXN.Name<S>] extends [never] ? `Invalid NSID \"${S}\": final segment must be camelCase (no hyphens)` : S,\n ): InterfaceDef<T>;\n} = <T>(identifier: string): InterfaceDef<T> => {\n return { identifier } as InterfaceDef<T>;\n};\n\n/**\n * A unique string identifier with a Typescript type associated with it.\n * When a capability is contributed to the application an implementation of the interface is provided.\n */\nexport type Capability<T> = {\n /**\n * The interface definition of the capability.\n */\n readonly interface: InterfaceDef<T>;\n\n /**\n * The implementation of the capability.\n */\n readonly implementation: T;\n\n /**\n * Called when the capability is deactivated.\n */\n readonly deactivate?: () => Effect.Effect<void, Error>;\n};\n\nexport type Any = Capability<any>;\n\n/**\n * Union type representing all valid return types for a capability module.\n * Supports single capabilities, arrays, and tuples of different capability types.\n */\nexport type ModuleReturn = void | Any | Any[] | readonly Any[] | [Any, ...Any[]] | readonly [Any, ...Any[]];\n\n/**\n * Helper to define the implementation of a capability.\n */\n// TODO(dmaretskyi): Make the return type non-generic so capabilities are non-discernable.\nexport const contributes = <I extends InterfaceDef<any>>(\n interfaceDef: I,\n implementation: Capability<InterfaceDef.Implementation<I>>['implementation'],\n deactivate?: Capability<InterfaceDef.Implementation<I>>['deactivate'],\n): Capability<I> => {\n return {\n interface: interfaceDef,\n implementation,\n deactivate,\n } satisfies Capability<I>;\n};\n\ntype LoadCapability<Props, Capabilities extends ModuleReturn = ModuleReturn> = () => Promise<{\n default: (props: Props) => Effect.Effect<Capabilities, Error, Service | Plugin.Service | never>;\n}>;\ntype LoadCapabilities<Props, Capabilities extends ModuleReturn = ModuleReturn> = () => Promise<{\n default: (props: Props) => Effect.Effect<Capabilities, Error, Service | Plugin.Service | never>;\n}>;\n\ntype NormalizeReturn<R> = R extends readonly (infer A)[]\n ? A[]\n : R extends (infer A)[]\n ? A[]\n : R extends Any\n ? [R]\n : Any[];\n\nexport type LazyCapability<Props = void, Capabilities extends ModuleReturn = ModuleReturn, E extends Error = Error> = (\n props: Props,\n) => Effect.Effect<NormalizeReturn<Capabilities>, E, Service | Plugin.Service | never>;\n\n/**\n * Helper to define a lazily loaded implementation of a capability.\n * Supports single capabilities, arrays, and tuples of different capability types.\n * @param name The export name (e.g., 'AppGraphBuilder') - used to auto-compute module IDs.\n * @param loader The lazy loader function.\n * @returns A lazy capability function with ModuleTag symbol attached.\n */\nexport const lazy = <T = void, R extends ModuleReturn = ModuleReturn>(\n name: string,\n c: LoadCapability<T, R> | LoadCapabilities<T, R>,\n): LazyCapability<T> => {\n const lazyFn = (props: T) =>\n Effect.gen(function* () {\n const { default: getCapability } = yield* Effect.promise(() => c());\n const result = yield* getCapability(props);\n const normalized = result == null ? [] : Array.isArray(result) ? Array.from(result) : [result];\n return normalized as NormalizeReturn<R>;\n });\n\n // Props (T) are preserved so callers pass correctly-typed options, but the contributed\n // Capabilities type is widened to the opaque base. The concrete capability type often traces to a\n // module-internal source path that TypeScript cannot name in declaration files (TS2883); the base\n // type is portable. The contributed type is checked at Capability.contributes regardless.\n return Object.assign(lazyFn, { [ModuleTag]: name }) as LazyCapability<T>;\n};\n\n/**\n * Gets the module tag (export name) from a lazy capability function.\n * @param capability The lazy capability function.\n * @returns The module tag if present, undefined otherwise.\n */\n// TODO(wittjosiah): Stricter type for capability.\nexport const getModuleTag = (capability: unknown): string | undefined => {\n return capability && typeof capability === 'function' && ModuleTag in capability\n ? String(capability[ModuleTag])\n : undefined;\n};\n\n/**\n * Helper to define a capability module with explicit typing.\n * Wraps the default export function to provide better type inference and make the pattern explicit.\n *\n * This helper provides explicit typing for the module activation function,\n * making it clear that the function should:\n * - Access CapabilityManager via the Effect layer system (Capability.get, Capability.getAll, etc.)\n * - Return a capability, array of capabilities, or tuple of different capability types (sync or async)\n *\n * Supports returning multiple capabilities of different types as a tuple, which will be normalized\n * to an array at runtime for compatibility with the plugin system.\n *\n * @example\n * ```ts\n * // Module without options - single capability\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* () {\n * const client = yield* Capability.get(ClientCapabilities.Client);\n * return contributes(Capabilities.SettingsStore, store);\n * })\n * );\n *\n * // Module with multiple capabilities\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* () {\n * return [\n * contributes(Capabilities.SettingsStore, store),\n * contributes(Capabilities.Translations, translations),\n * ];\n * })\n * );\n *\n * // Module with required options (context accessed via layer)\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* (props: { observability: boolean }) {\n * const invoker = yield* Capability.get(Capabilities.OperationInvoker);\n * return contributes(Capabilities.OperationHandler, ...);\n * })\n * );\n * ```\n */\nexport const makeModule = <\n TProps = void,\n TReturn extends ModuleReturn = ModuleReturn,\n E extends Error = Error,\n R extends Service | Plugin.Service | never = Service,\n>(\n fn: (props: TProps) => Effect.Effect<TReturn, E, R>,\n): ((props: TProps) => Effect.Effect<TReturn, E, R>) => fn;\n"],
5
- "mappings": ";;;;;AAAA;;;;;;;;;;;;;;;;AAKA,YAAYA,aAAa;AACzB,YAAYC,YAAY;AACxB,YAAYC,WAAW;AAehB,IAAMC,UAAN,cAA8BC,YAAI,uCAAA,EAAA,EAAA;AAGpC;AAUE,IAAMC,MAAM,CAAIC,iBACdC,eAAQJ,SAAS,CAACK,YAChBC,WAAI;EACTA,KAAK,MAAMD,QAAQH,IAAIC,YAAAA;EACvBI,OAAO,CAACC,UAAWA,iBAAiBC,QAAQD,QAAQ,IAAIC,MAAMC,OAAOF,KAAAA,CAAAA;AACvE,CAAA,CAAA;AAQG,IAAMG,SAAS,CAAIR,iBACjBS,WAAIZ,SAAS,CAACK,YAAYA,QAAQM,OAAOR,YAAAA,CAAAA;AAO3C,IAAMU,UAAU,CAAIV,iBAClBC,eAAQJ,SAAS,CAACK,YAAYA,QAAQQ,QAAQV,YAAAA,CAAAA;AAOhD,IAAMW,OAAO,CAAIX,iBACfS,WAAIZ,SAAS,CAACK,YAAYA,QAAQS,KAAKX,YAAAA,CAAAA;AAOzC,IAAMY,eAAe,CAC1BZ,iBAEOS,WAAIZ,SAAS,CAACK,YAAYA,QAAQU,aAAaZ,YAAAA,CAAAA;AAKjD,IAAMa,UAAU,CAAOb,cAA+Bc,QACrDC,aAAOD,KAAKf,IAAIC,YAAAA,EAAcgB,KAAYC,YAAK,CAAA;AAOhD,IAAMC,YAA2BC,uBAAOC,IAAI,+BAAA;AAkB5C,IAAMC,OAIT,CAAIC,eAAAA;AACN,SAAO;IAAEA;EAAW;AACtB;AAmCO,IAAMC,cAAc,CACzBC,cACAC,gBACAC,eAAAA;AAEA,SAAO;IACLC,WAAWH;IACXC;IACAC;EACF;AACF;AA4BO,IAAME,OAAO,CAClBC,MACAC,MAAAA;AAEA,QAAMC,SAAS,CAACC,UACPC,WAAI,aAAA;AACT,UAAM,EAAEC,SAASC,cAAa,IAAK,OAAcC,eAAQ,MAAMN,EAAAA,CAAAA;AAC/D,UAAMO,SAAS,OAAOF,cAAcH,KAAAA;AACpC,UAAMM,aAAaD,UAAU,OAAO,CAAA,IAAKE,MAAMC,QAAQH,MAAAA,IAAUE,MAAME,KAAKJ,MAAAA,IAAU;MAACA;;AACvF,WAAOC;EACT,CAAA;AAMF,SAAOI,OAAOC,OAAOZ,QAAQ;IAAE,CAACb,SAAAA,GAAYW;EAAK,CAAA;AACnD;AAQO,IAAMe,eAAe,CAACC,eAAAA;AAC3B,SAAOA,cAAc,OAAOA,eAAe,cAAc3B,aAAa2B,aAClEC,OAAOD,WAAW3B,SAAAA,CAAU,IAC5B6B;AACN;AA2CO,IAAMC,aAAa,CAMxBC,OACsDA;",
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Atom } from '@effect-atom/atom-react';\nimport * as Context from 'effect/Context';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport type { DXN } from '@dxos/keys';\n\nimport type * as CapabilityManager from './capability-manager';\nimport type * as Plugin from './plugin';\n\n//\n// Capability Service Layer\n//\n\n/**\n * Effect Context.Tag for accessing CapabilityManager via the Effect layer system.\n * This allows capability modules to access the capability manager without having it passed as an argument.\n */\nexport class Service extends Context.Tag('@dxos/app-framework/CapabilityManager')<\n Service,\n CapabilityManager.CapabilityManager\n>() {}\n\n/**\n * Get a single capability from the capability manager.\n * @param interfaceDef The interface definition of the capability.\n * @returns The capability implementation.\n * @throws If no capability is found.\n */\n// TODO(wittjosiah): Add custom tagged errors (Data.TaggedError) for app-framework to enable\n// type-safe error handling with Effect. Consider CapabilityNotFoundError, ModuleActivationError, etc.\nexport const get = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T, Error, Service> =>\n Effect.flatMap(Service, (manager) =>\n Effect.try({\n try: () => manager.get(interfaceDef),\n catch: (error) => (error instanceof Error ? error : new Error(String(error))),\n }),\n );\n\n/**\n * Get all capabilities from the capability manager for a given interface.\n * @param interfaceDef The interface definition of the capability.\n * @returns An array of capability implementations.\n */\nexport const getAll = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T[], never, Service> =>\n Effect.map(Service, (manager) => manager.getAll(interfaceDef));\n\n/**\n * Wait for a capability to be available.\n * @param interfaceDef The interface definition of the capability.\n * @returns The capability implementation once available.\n */\nexport const waitFor = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<T, Error, Service> =>\n Effect.flatMap(Service, (manager) => manager.waitFor(interfaceDef));\n\n/**\n * Get the Atom reference to capabilities for reactive access.\n * @param interfaceDef The interface definition of the capability.\n * @returns An Atom containing the array of capability implementations.\n */\nexport const atom = <T>(interfaceDef: InterfaceDef<T>): Effect.Effect<Atom.Atom<T[]>, never, Service> =>\n Effect.map(Service, (manager) => manager.atom(interfaceDef));\n\n/**\n * Get capabilities grouped by the module that contributed them.\n * @param interfaceDef The interface definition of the capability.\n * @returns An Atom containing a record from module ID to capability implementations.\n */\nexport const atomByModule = <T>(\n interfaceDef: InterfaceDef<T>,\n): Effect.Effect<Atom.Atom<Record<string, T[]>>, never, Service> =>\n Effect.map(Service, (manager) => manager.atomByModule(interfaceDef));\n\n/**\n * Constructs a layer that will request its interface implementation from the capability manager.\n */\nexport const asLayer = <T, I>(interfaceDef: InterfaceDef<T>, tag: Context.Tag<I, T>): Layer.Layer<I, never, Service> =>\n Layer.effect(tag, get(interfaceDef).pipe(Effect.orDie));\n\nconst InterfaceDefTypeId: unique symbol = Symbol.for('InterfaceDefTypeId');\n\n/**\n * Symbol used to tag lazy capability functions with their module ID.\n */\nexport const ModuleTag: unique symbol = Symbol.for('@dxos/app-framework/ModuleTag');\n\n/**\n * The interface definition of a capability.\n */\nexport type InterfaceDef<T> = {\n [InterfaceDefTypeId]: T;\n identifier: string;\n};\n\nexport namespace InterfaceDef {\n export type Implementation<I extends InterfaceDef<any>> = I extends InterfaceDef<infer T> ? T : never;\n}\n\n/**\n * Helper to define the interface of a capability.\n * Static NSID strings are validated at compile time via {@link DXN.Name}.\n */\nexport const make: {\n <T, S extends string = string>(\n identifier: [DXN.Name<S>] extends [never] ? `Invalid NSID \"${S}\": final segment must be camelCase (no hyphens)` : S,\n ): InterfaceDef<T>;\n} = <T>(identifier: string): InterfaceDef<T> => {\n return { identifier } as InterfaceDef<T>;\n};\n\n/**\n * A unique string identifier with a Typescript type associated with it.\n * When a capability is contributed to the application an implementation of the interface is provided.\n */\nexport type Capability<T> = {\n /**\n * The interface definition of the capability.\n */\n readonly interface: InterfaceDef<T>;\n\n /**\n * The implementation of the capability.\n */\n readonly implementation: T;\n\n /**\n * Called when the capability is deactivated.\n */\n readonly deactivate?: () => Effect.Effect<void, Error>;\n};\n\nexport type Any = Capability<any>;\n\n/**\n * Union type representing all valid return types for a capability module.\n * Supports single capabilities, arrays, and tuples of different capability types.\n */\nexport type ModuleReturn = void | Any | Any[] | readonly Any[] | [Any, ...Any[]] | readonly [Any, ...Any[]];\n\n/**\n * Helper to define the implementation of a capability.\n * Returns the opaque base type so callers cannot discriminate on capability kind,\n * keeping d.ts emit portable across packages.\n */\nexport const contributes = <I extends InterfaceDef<any>>(\n interfaceDef: I,\n implementation: Capability<InterfaceDef.Implementation<I>>['implementation'],\n deactivate?: Capability<InterfaceDef.Implementation<I>>['deactivate'],\n): Any => {\n return {\n interface: interfaceDef,\n implementation,\n deactivate,\n } satisfies Capability<I>;\n};\n\ntype LoadCapability<Props, Capabilities extends ModuleReturn = ModuleReturn> = () => Promise<{\n default: (props: Props) => Effect.Effect<Capabilities, Error, Service | Plugin.Service | never>;\n}>;\ntype LoadCapabilities<Props, Capabilities extends ModuleReturn = ModuleReturn> = () => Promise<{\n default: (props: Props) => Effect.Effect<Capabilities, Error, Service | Plugin.Service | never>;\n}>;\n\ntype NormalizeReturn<R> = R extends readonly (infer A)[]\n ? A[]\n : R extends (infer A)[]\n ? A[]\n : R extends Any\n ? [R]\n : Any[];\n\nexport type LazyCapability<Props = void, Capabilities extends ModuleReturn = ModuleReturn, E extends Error = Error> = (\n props: Props,\n) => Effect.Effect<NormalizeReturn<Capabilities>, E, Service | Plugin.Service | never>;\n\n/**\n * Helper to define a lazily loaded implementation of a capability.\n * Supports single capabilities, arrays, and tuples of different capability types.\n * @param name The export name (e.g., 'AppGraphBuilder') - used to auto-compute module IDs.\n * @param loader The lazy loader function.\n * @returns A lazy capability function with ModuleTag symbol attached.\n */\nexport const lazy = <T = void, R extends ModuleReturn = ModuleReturn>(\n name: string,\n c: LoadCapability<T, R> | LoadCapabilities<T, R>,\n): LazyCapability<T> => {\n const lazyFn = (props: T) =>\n Effect.gen(function* () {\n const { default: getCapability } = yield* Effect.promise(() => c());\n const result = yield* getCapability(props);\n const normalized = result == null ? [] : Array.isArray(result) ? Array.from(result) : [result];\n return normalized as NormalizeReturn<R>;\n });\n\n // Props (T) are preserved so callers pass correctly-typed options, but the contributed\n // Capabilities type is widened to the opaque base. The concrete capability type often traces to a\n // module-internal source path that TypeScript cannot name in declaration files (TS2883); the base\n // type is portable. The contributed type is checked at Capability.contributes regardless.\n return Object.assign(lazyFn, { [ModuleTag]: name }) as LazyCapability<T>;\n};\n\n/**\n * Gets the module tag (export name) from a lazy capability function.\n * @param capability The lazy capability function.\n * @returns The module tag if present, undefined otherwise.\n */\n// TODO(wittjosiah): Stricter type for capability.\nexport const getModuleTag = (capability: unknown): string | undefined => {\n return capability && typeof capability === 'function' && ModuleTag in capability\n ? String(capability[ModuleTag])\n : undefined;\n};\n\n/**\n * Helper to define a capability module with explicit typing.\n * Wraps the default export function to provide better type inference and make the pattern explicit.\n *\n * This helper provides explicit typing for the module activation function,\n * making it clear that the function should:\n * - Access CapabilityManager via the Effect layer system (Capability.get, Capability.getAll, etc.)\n * - Return a capability, array of capabilities, or tuple of different capability types (sync or async)\n *\n * Supports returning multiple capabilities of different types as a tuple, which will be normalized\n * to an array at runtime for compatibility with the plugin system.\n *\n * @example\n * ```ts\n * // Module without options - single capability\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* () {\n * const client = yield* Capability.get(ClientCapabilities.Client);\n * return contributes(Capabilities.SettingsStore, store);\n * })\n * );\n *\n * // Module with multiple capabilities\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* () {\n * return [\n * contributes(Capabilities.SettingsStore, store),\n * contributes(Capabilities.Translations, translations),\n * ];\n * })\n * );\n *\n * // Module with required options (context accessed via layer)\n * export default Capability.makeModule(\n * Effect.fnUntraced(function* (props: { observability: boolean }) {\n * const invoker = yield* Capability.get(Capabilities.OperationInvoker);\n * return contributes(Capabilities.OperationHandler, ...);\n * })\n * );\n * ```\n */\nexport const makeModule = <\n TProps = void,\n TReturn extends ModuleReturn = ModuleReturn,\n E extends Error = Error,\n R extends Service | Plugin.Service | never = Service,\n>(\n fn: (props: TProps) => Effect.Effect<TReturn, E, R>,\n): ((props: TProps) => Effect.Effect<TReturn, E, R>) => fn;\n"],
5
+ "mappings": ";;;;;AAAA;;;;;;;;;;;;;;;;AAKA,YAAYA,aAAa;AACzB,YAAYC,YAAY;AACxB,YAAYC,WAAW;AAehB,IAAMC,UAAN,cAA8BC,YAAI,uCAAA,EAAA,EAAA;AAGpC;AAUE,IAAMC,MAAM,CAAIC,iBACdC,eAAQJ,SAAS,CAACK,YAChBC,WAAI;EACTA,KAAK,MAAMD,QAAQH,IAAIC,YAAAA;EACvBI,OAAO,CAACC,UAAWA,iBAAiBC,QAAQD,QAAQ,IAAIC,MAAMC,OAAOF,KAAAA,CAAAA;AACvE,CAAA,CAAA;AAQG,IAAMG,SAAS,CAAIR,iBACjBS,WAAIZ,SAAS,CAACK,YAAYA,QAAQM,OAAOR,YAAAA,CAAAA;AAO3C,IAAMU,UAAU,CAAIV,iBAClBC,eAAQJ,SAAS,CAACK,YAAYA,QAAQQ,QAAQV,YAAAA,CAAAA;AAOhD,IAAMW,OAAO,CAAIX,iBACfS,WAAIZ,SAAS,CAACK,YAAYA,QAAQS,KAAKX,YAAAA,CAAAA;AAOzC,IAAMY,eAAe,CAC1BZ,iBAEOS,WAAIZ,SAAS,CAACK,YAAYA,QAAQU,aAAaZ,YAAAA,CAAAA;AAKjD,IAAMa,UAAU,CAAOb,cAA+Bc,QACrDC,aAAOD,KAAKf,IAAIC,YAAAA,EAAcgB,KAAYC,YAAK,CAAA;AAOhD,IAAMC,YAA2BC,uBAAOC,IAAI,+BAAA;AAkB5C,IAAMC,OAIT,CAAIC,eAAAA;AACN,SAAO;IAAEA;EAAW;AACtB;AAoCO,IAAMC,cAAc,CACzBC,cACAC,gBACAC,eAAAA;AAEA,SAAO;IACLC,WAAWH;IACXC;IACAC;EACF;AACF;AA4BO,IAAME,OAAO,CAClBC,MACAC,MAAAA;AAEA,QAAMC,SAAS,CAACC,UACPC,WAAI,aAAA;AACT,UAAM,EAAEC,SAASC,cAAa,IAAK,OAAcC,eAAQ,MAAMN,EAAAA,CAAAA;AAC/D,UAAMO,SAAS,OAAOF,cAAcH,KAAAA;AACpC,UAAMM,aAAaD,UAAU,OAAO,CAAA,IAAKE,MAAMC,QAAQH,MAAAA,IAAUE,MAAME,KAAKJ,MAAAA,IAAU;MAACA;;AACvF,WAAOC;EACT,CAAA;AAMF,SAAOI,OAAOC,OAAOZ,QAAQ;IAAE,CAACb,SAAAA,GAAYW;EAAK,CAAA;AACnD;AAQO,IAAMe,eAAe,CAACC,eAAAA;AAC3B,SAAOA,cAAc,OAAOA,eAAe,cAAc3B,aAAa2B,aAClEC,OAAOD,WAAW3B,SAAAA,CAAU,IAC5B6B;AACN;AA2CO,IAAMC,aAAa,CAMxBC,OACsDA;",
6
6
  "names": ["Context", "Effect", "Layer", "Service", "Tag", "get", "interfaceDef", "flatMap", "manager", "try", "catch", "error", "Error", "String", "getAll", "map", "waitFor", "atom", "atomByModule", "asLayer", "tag", "effect", "pipe", "orDie", "ModuleTag", "Symbol", "for", "make", "identifier", "contributes", "interfaceDef", "implementation", "deactivate", "interface", "lazy", "name", "c", "lazyFn", "props", "gen", "default", "getCapability", "promise", "result", "normalized", "Array", "isArray", "from", "Object", "assign", "getModuleTag", "capability", "String", "undefined", "makeModule", "fn"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  capabilities_exports
3
- } from "./chunk-37PG7XJC.mjs";
3
+ } from "./chunk-NKVRSMFN.mjs";
4
4
 
5
5
  // src/helpers.ts
6
6
  var topologicalSort = (nodes) => {
@@ -55,7 +55,7 @@ import React3, { Fragment, Profiler, Suspense, forwardRef as forwardRef2, memo,
55
55
  import { log } from "@dxos/log";
56
56
  import { ErrorBoundary } from "@dxos/react-error-boundary";
57
57
  import { useDefaultValue } from "@dxos/react-hooks";
58
- import { byPosition } from "@dxos/util";
58
+ import { Position } from "@dxos/util";
59
59
 
60
60
  // src/ui/components/Surface/SurfaceInfo.tsx
61
61
  import React, { cloneElement, forwardRef, useCallback, useLayoutEffect, useState } from "react";
@@ -264,7 +264,7 @@ var emptySnapshot = () => EMPTY_SNAPSHOT;
264
264
 
265
265
  // src/ui/components/Surface/SurfaceComponent.tsx
266
266
  var __dxlog_file = "/__w/dxos/dxos/packages/sdk/app-framework/src/ui/components/Surface/SurfaceComponent.tsx";
267
- var DEBUG = import.meta.env.VITE_DEBUG;
267
+ var DEBUG = import.meta.env?.VITE_DEBUG;
268
268
  var DEFAULT_PLACEHOLDER = /* @__PURE__ */ React3.createElement(Fragment, null);
269
269
  var WebComponentWrapper = /* @__PURE__ */ memo(/* @__PURE__ */ forwardRef2(({ id, role, data, limit, definition, ...rest }, forwardedRef) => {
270
270
  const containerRef = useRef2(null);
@@ -460,14 +460,14 @@ var ErrorFallback = ({ error }) => {
460
460
  }, message));
461
461
  };
462
462
  var findCandidates = (surfaces, { role, data }) => {
463
- return Object.values(surfaces).filter((definition) => Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role).filter(({ filter }) => filter ? filter(data ?? {}, role) : true).toSorted(byPosition);
463
+ return Object.values(surfaces).filter((definition) => Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role).filter(({ filter }) => filter ? filter(data ?? {}, role) : true).toSorted(Position.compare);
464
464
  };
465
465
  var useSurfaces = () => {
466
466
  const manager = usePluginManager();
467
467
  const surfacesByModule = useAtomValue(manager.capabilities.atomByModule(capabilities_exports.ReactSurface));
468
468
  return useMemo2(() => {
469
469
  const result = [];
470
- for (const [moduleId, surfaces] of Object.entries(surfacesByModule)) {
470
+ for (const [_moduleId, surfaces] of Object.entries(surfacesByModule)) {
471
471
  for (const def of surfaces.flat()) {
472
472
  result.push(def);
473
473
  }
@@ -600,4 +600,4 @@ export {
600
600
  SurfaceComponent,
601
601
  Surface
602
602
  };
603
- //# sourceMappingURL=chunk-SWECIICH.mjs.map
603
+ //# sourceMappingURL=chunk-U5MESPM5.mjs.map