@dxos/plugin-settings 0.8.4-main.d05673bc65 → 0.8.4-main.d9fc60f731

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 (98) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/neutral/SettingsPlugin.mjs +9 -0
  3. package/dist/lib/neutral/SettingsPlugin.mjs.map +7 -0
  4. package/dist/lib/neutral/chunk-3DJRTSII.mjs +16 -0
  5. package/dist/lib/neutral/chunk-3DJRTSII.mjs.map +7 -0
  6. package/dist/lib/{browser/chunk-DIKK4DQC.mjs → neutral/chunk-J2FJOTAW.mjs} +4 -11
  7. package/dist/lib/neutral/chunk-J2FJOTAW.mjs.map +7 -0
  8. package/dist/lib/neutral/chunk-XP4EHGJW.mjs +22 -0
  9. package/dist/lib/neutral/chunk-XP4EHGJW.mjs.map +7 -0
  10. package/dist/lib/neutral/index.mjs +18 -0
  11. package/dist/lib/neutral/index.mjs.map +7 -0
  12. package/dist/lib/neutral/meta.json +1 -0
  13. package/dist/lib/neutral/open-NRUWKEGC.mjs +28 -0
  14. package/dist/lib/neutral/open-NRUWKEGC.mjs.map +7 -0
  15. package/dist/lib/neutral/open-plugin-registry-XGFG2JWB.mjs +26 -0
  16. package/dist/lib/neutral/open-plugin-registry-XGFG2JWB.mjs.map +7 -0
  17. package/dist/lib/neutral/plugin.mjs +18 -0
  18. package/dist/lib/neutral/plugin.mjs.map +7 -0
  19. package/dist/lib/neutral/testing.mjs +7 -0
  20. package/dist/lib/neutral/testing.mjs.map +7 -0
  21. package/dist/lib/neutral/translations.mjs +15 -0
  22. package/dist/lib/neutral/translations.mjs.map +7 -0
  23. package/dist/types/src/SettingsPlugin.d.ts +1 -0
  24. package/dist/types/src/SettingsPlugin.d.ts.map +1 -1
  25. package/dist/types/src/SettingsPlugin.test.d.ts +2 -0
  26. package/dist/types/src/SettingsPlugin.test.d.ts.map +1 -0
  27. package/dist/types/src/actions.d.ts +4 -4
  28. package/dist/types/src/actions.d.ts.map +1 -1
  29. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  30. package/dist/types/src/capabilities/index.d.ts +5 -2
  31. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  32. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  33. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  34. package/dist/types/src/capabilities/{operation-resolver/operation-resolver.d.ts → react-surface.d.ts} +2 -2
  35. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  36. package/dist/types/src/index.d.ts +2 -1
  37. package/dist/types/src/index.d.ts.map +1 -1
  38. package/dist/types/src/meta.d.ts +1 -1
  39. package/dist/types/src/meta.d.ts.map +1 -1
  40. package/dist/types/src/operations/index.d.ts +3 -0
  41. package/dist/types/src/operations/index.d.ts.map +1 -0
  42. package/dist/types/src/operations/open-plugin-registry.d.ts +5 -0
  43. package/dist/types/src/operations/open-plugin-registry.d.ts.map +1 -0
  44. package/dist/types/src/operations/open.d.ts +5 -0
  45. package/dist/types/src/operations/open.d.ts.map +1 -0
  46. package/dist/types/src/plugin.d.ts +4 -0
  47. package/dist/types/src/plugin.d.ts.map +1 -0
  48. package/dist/types/src/testing.d.ts +2 -0
  49. package/dist/types/src/testing.d.ts.map +1 -0
  50. package/dist/types/src/translations.d.ts +2 -4
  51. package/dist/types/src/translations.d.ts.map +1 -1
  52. package/dist/types/src/types/index.d.ts +3 -0
  53. package/dist/types/src/types/index.d.ts.map +1 -0
  54. package/dist/types/tsconfig.tsbuildinfo +1 -1
  55. package/package.json +38 -16
  56. package/src/SettingsPlugin.test.ts +33 -0
  57. package/src/SettingsPlugin.ts +7 -4
  58. package/src/actions.ts +4 -4
  59. package/src/capabilities/{app-graph-builder/app-graph-builder.ts → app-graph-builder.ts} +27 -22
  60. package/src/capabilities/index.ts +9 -2
  61. package/src/capabilities/operation-handler.ts +16 -0
  62. package/src/capabilities/react-surface.tsx +50 -0
  63. package/src/index.ts +2 -1
  64. package/src/meta.ts +7 -4
  65. package/src/operations/index.ts +10 -0
  66. package/src/operations/open-plugin-registry.ts +28 -0
  67. package/src/operations/open.ts +30 -0
  68. package/src/plugin.ts +11 -0
  69. package/src/testing.ts +7 -0
  70. package/src/translations.ts +2 -3
  71. package/src/types/index.ts +8 -0
  72. package/dist/lib/browser/app-graph-builder-YWCB3EZC.mjs +0 -97
  73. package/dist/lib/browser/app-graph-builder-YWCB3EZC.mjs.map +0 -7
  74. package/dist/lib/browser/chunk-DIKK4DQC.mjs.map +0 -7
  75. package/dist/lib/browser/index.mjs +0 -46
  76. package/dist/lib/browser/index.mjs.map +0 -7
  77. package/dist/lib/browser/meta.json +0 -1
  78. package/dist/lib/browser/operation-resolver-7AAHDR6U.mjs +0 -54
  79. package/dist/lib/browser/operation-resolver-7AAHDR6U.mjs.map +0 -7
  80. package/dist/lib/node-esm/app-graph-builder-WSMWJBGZ.mjs +0 -98
  81. package/dist/lib/node-esm/app-graph-builder-WSMWJBGZ.mjs.map +0 -7
  82. package/dist/lib/node-esm/chunk-NAEV3LFJ.mjs +0 -37
  83. package/dist/lib/node-esm/chunk-NAEV3LFJ.mjs.map +0 -7
  84. package/dist/lib/node-esm/index.mjs +0 -47
  85. package/dist/lib/node-esm/index.mjs.map +0 -7
  86. package/dist/lib/node-esm/meta.json +0 -1
  87. package/dist/lib/node-esm/operation-resolver-QY6K6X7D.mjs +0 -55
  88. package/dist/lib/node-esm/operation-resolver-QY6K6X7D.mjs.map +0 -7
  89. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  90. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  91. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  92. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
  93. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  94. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  95. package/src/capabilities/app-graph-builder/index.ts +0 -7
  96. package/src/capabilities/operation-resolver/index.ts +0 -10
  97. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -53
  98. /package/dist/types/src/capabilities/{app-graph-builder/app-graph-builder.d.ts → app-graph-builder.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-settings",
3
- "version": "0.8.4-main.d05673bc65",
3
+ "version": "0.8.4-main.d9fc60f731",
4
4
  "description": "DXOS Settings plugin for managing application settings.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -8,40 +8,62 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/dxos/dxos"
10
10
  },
11
- "license": "MIT",
11
+ "license": "FSL-1.1-Apache-2.0",
12
12
  "author": "DXOS.org",
13
13
  "sideEffects": true,
14
14
  "type": "module",
15
+ "imports": {
16
+ "#capabilities": "./src/capabilities/index.ts",
17
+ "#meta": "./src/meta.ts",
18
+ "#operations": "./src/operations/index.ts",
19
+ "#plugin": "./src/SettingsPlugin.ts",
20
+ "#translations": "./src/translations.ts",
21
+ "#types": "./src/types/index.ts"
22
+ },
15
23
  "exports": {
16
24
  ".": {
17
25
  "source": "./src/index.ts",
18
- "browser": "./dist/lib/browser/index.mjs",
19
- "node": "./dist/lib/node-esm/index.mjs",
20
- "types": "./dist/types/src/index.d.ts"
26
+ "types": "./dist/types/src/index.d.ts",
27
+ "default": "./dist/lib/neutral/index.mjs"
28
+ },
29
+ "./plugin": {
30
+ "source": "./src/plugin.ts",
31
+ "types": "./dist/types/src/plugin.d.ts",
32
+ "default": "./dist/lib/neutral/plugin.mjs"
33
+ },
34
+ "./testing": {
35
+ "source": "./src/testing.ts",
36
+ "types": "./dist/types/src/testing.d.ts",
37
+ "default": "./dist/lib/neutral/testing.mjs"
38
+ },
39
+ "./translations": {
40
+ "source": "./src/translations.ts",
41
+ "types": "./dist/types/src/translations.d.ts",
42
+ "default": "./dist/lib/neutral/translations.mjs"
21
43
  }
22
44
  },
23
45
  "types": "dist/types/src/index.d.ts",
24
- "typesVersions": {
25
- "*": {}
26
- },
27
46
  "files": [
28
47
  "dist",
29
48
  "src"
30
49
  ],
31
50
  "dependencies": {
32
- "@dxos/app-framework": "0.8.4-main.d05673bc65",
33
- "@dxos/app-graph": "0.8.4-main.d05673bc65",
34
- "@dxos/app-toolkit": "0.8.4-main.d05673bc65",
35
- "@dxos/util": "0.8.4-main.d05673bc65",
36
- "@dxos/operation": "0.8.4-main.d05673bc65"
51
+ "@dxos/app-framework": "0.8.4-main.d9fc60f731",
52
+ "@dxos/app-graph": "0.8.4-main.d9fc60f731",
53
+ "@dxos/app-toolkit": "0.8.4-main.d9fc60f731",
54
+ "@dxos/react-ui-form": "0.8.4-main.d9fc60f731",
55
+ "@dxos/compute": "0.8.4-main.d9fc60f731",
56
+ "@dxos/util": "0.8.4-main.d9fc60f731",
57
+ "@dxos/keys": "0.8.4-main.d9fc60f731"
37
58
  },
38
59
  "devDependencies": {
39
60
  "@types/react": "~19.2.7",
40
- "effect": "3.19.16",
41
- "react": "~19.2.3"
61
+ "effect": "3.21.2",
62
+ "react": "~19.2.3",
63
+ "@dxos/plugin-graph": "0.8.4-main.d9fc60f731"
42
64
  },
43
65
  "peerDependencies": {
44
- "effect": "3.19.16",
66
+ "effect": "3.21.2",
45
67
  "react": "~19.2.3"
46
68
  },
47
69
  "publishConfig": {
@@ -0,0 +1,33 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { describe, test } from 'vitest';
6
+
7
+ import { ProcessManagerPlugin } from '@dxos/app-framework';
8
+ import { createTestApp } from '@dxos/app-framework/testing';
9
+ import { GraphPlugin } from '@dxos/plugin-graph/plugin';
10
+
11
+ import { SettingsPlugin } from '#plugin';
12
+
13
+ import { meta } from './meta';
14
+
15
+ const moduleId = (name: string) => `${meta.id}.module.${name}`;
16
+
17
+ describe('SettingsPlugin', () => {
18
+ test('modules activate on the expected events', async ({ expect }) => {
19
+ // Use createTestApp directly to avoid a circular dep with plugin-testing.
20
+ // GraphPlugin fires SetupAppGraph (via firesBeforeActivation) during Startup,
21
+ // activating SettingsAppGraphBuilder. ProcessManagerPlugin fires SetupProcessManager
22
+ // during Startup, activating OperationHandler.
23
+ await using harness = await createTestApp({
24
+ plugins: [GraphPlugin(), ProcessManagerPlugin(), SettingsPlugin()],
25
+ });
26
+
27
+ // SettingsAppGraphBuilder activates on SetupAppGraph (fired by GraphPlugin during Startup).
28
+ // OperationHandler activates on SetupProcessManager (fired by ProcessManagerPlugin during Startup).
29
+ expect(harness.manager.getActive()).toEqual(
30
+ expect.arrayContaining([moduleId('SettingsAppGraphBuilder'), moduleId('OperationHandler')]),
31
+ );
32
+ });
33
+ });
@@ -5,13 +5,16 @@
5
5
  import { Plugin } from '@dxos/app-framework';
6
6
  import { AppPlugin } from '@dxos/app-toolkit';
7
7
 
8
- import { SettingsAppGraphBuilder, SettingsOperationResolver } from './capabilities';
9
- import { meta } from './meta';
10
- import { translations } from './translations';
8
+ import { OperationHandler, ReactSurface, SettingsAppGraphBuilder } from '#capabilities';
9
+ import { meta } from '#meta';
10
+ import { translations } from '#translations';
11
11
 
12
12
  export const SettingsPlugin = Plugin.define(meta).pipe(
13
13
  AppPlugin.addAppGraphModule({ activate: SettingsAppGraphBuilder }),
14
- AppPlugin.addOperationResolverModule({ activate: SettingsOperationResolver }),
14
+ AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),
15
+ AppPlugin.addSurfaceModule({ activate: ReactSurface }),
15
16
  AppPlugin.addTranslationsModule({ translations }),
16
17
  Plugin.make,
17
18
  );
19
+
20
+ export default SettingsPlugin;
package/src/actions.ts CHANGED
@@ -4,10 +4,10 @@
4
4
 
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
- import { meta } from './meta';
7
+ import { meta } from '#meta';
8
+ import { SETTINGS_ID, SETTINGS_KEY } from '#types';
8
9
 
9
- export const SETTINGS_ID = '!dxos:settings';
10
- export const SETTINGS_KEY = 'settings';
10
+ export { SETTINGS_ID, SETTINGS_KEY };
11
11
 
12
12
  export namespace SettingsAction {
13
13
  export class Open extends Schema.TaggedClass<Open>()(`${meta.id}.open`, {
@@ -17,7 +17,7 @@ export namespace SettingsAction {
17
17
  output: Schema.Void,
18
18
  }) {}
19
19
 
20
- export class OpenPluginRegistry extends Schema.TaggedClass<OpenPluginRegistry>()(`${meta.id}.open-plugin-registry`, {
20
+ export class OpenPluginRegistry extends Schema.TaggedClass<OpenPluginRegistry>()(`${meta.id}.openPluginRegistry`, {
21
21
  input: Schema.Void,
22
22
  output: Schema.Void,
23
23
  }) {}
@@ -5,13 +5,14 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability, type Plugin as Plugin$ } from '@dxos/app-framework';
8
- import { GraphBuilder, NodeMatcher } from '@dxos/app-graph';
8
+ import { GraphBuilder, Node, NodeMatcher } from '@dxos/app-graph';
9
9
  import { AppCapabilities, SettingsOperation, getSpacePath } from '@dxos/app-toolkit';
10
- import { Operation } from '@dxos/operation';
10
+ import { Operation } from '@dxos/compute';
11
11
  import { isNonNullable } from '@dxos/util';
12
12
 
13
- import { SETTINGS_ID, SETTINGS_KEY } from '../../actions';
14
- import { meta } from '../../meta';
13
+ import { meta } from '#meta';
14
+
15
+ import { SETTINGS_ID, SETTINGS_KEY } from '../actions';
15
16
 
16
17
  export default Capability.makeModule(
17
18
  Effect.fnUntraced(function* () {
@@ -22,15 +23,15 @@ export default Capability.makeModule(
22
23
 
23
24
  const extensions = yield* Effect.all([
24
25
  GraphBuilder.createExtension({
25
- id: `${meta.id}.action`,
26
+ id: 'action',
26
27
  match: NodeMatcher.whenRoot,
27
28
  actions: () =>
28
29
  Effect.succeed([
29
30
  {
30
- id: meta.id,
31
+ id: 'root',
31
32
  data: () => Operation.invoke(SettingsOperation.Open, {}),
32
33
  properties: {
33
- label: ['open settings label', { ns: meta.id }],
34
+ label: ['plugin-settings.label', { ns: meta.id }],
34
35
  icon: 'ph--gear--regular',
35
36
  disposition: 'menu',
36
37
  keyBinding: {
@@ -42,25 +43,25 @@ export default Capability.makeModule(
42
43
  ]),
43
44
  }),
44
45
  GraphBuilder.createExtension({
45
- id: `${meta.id}.core`,
46
+ id: 'core',
46
47
  match: NodeMatcher.whenRoot,
47
48
  connector: () =>
48
49
  Effect.succeed([
49
- {
50
+ Node.make({
50
51
  id: SETTINGS_ID,
51
52
  type: meta.id,
52
53
  properties: {
53
- label: ['app settings label', { ns: meta.id }],
54
+ label: ['plugin-settings.label', { ns: meta.id }],
54
55
  icon: 'ph--gear--regular',
55
56
  disposition: 'pin-end',
56
- position: 'hoist',
57
+ position: 'first',
57
58
  testId: 'treeView.appSettings',
58
59
  },
59
- },
60
+ }),
60
61
  ]),
61
62
  }),
62
63
  GraphBuilder.createExtension({
63
- id: `${meta.id}.plugins`,
64
+ id: 'plugins',
64
65
  match: NodeMatcher.whenId(getSpacePath(SETTINGS_ID)),
65
66
  connector: (node, get) => {
66
67
  const [manager] = get(managerAtom);
@@ -77,15 +78,19 @@ export default Capability.makeModule(
77
78
  return [plugin.meta, settings];
78
79
  })
79
80
  .filter(isNonNullable)
80
- .map(([meta, settings]: [Plugin$.Meta, AppCapabilities.Settings]) => ({
81
- id: `${SETTINGS_KEY}:${meta.id.replaceAll('/', ':')}`,
82
- type: 'category',
83
- data: settings,
84
- properties: {
85
- label: meta.name ?? meta.id,
86
- icon: meta.icon ?? 'ph--circle--regular',
87
- },
88
- })),
81
+ .sort(([a], [b]) => (a.name ?? a.id).localeCompare(b.name ?? b.id, undefined, { sensitivity: 'base' }))
82
+ .map(([meta, settings]: [Plugin$.Meta, AppCapabilities.Settings]) =>
83
+ Node.make({
84
+ id: `${SETTINGS_KEY}:${meta.id.replaceAll('/', ':')}`,
85
+ type: 'category',
86
+ data: settings,
87
+ properties: {
88
+ label: meta.name ?? meta.id,
89
+ icon: meta.icon ?? 'ph--circle--regular',
90
+ iconHue: meta.iconHue,
91
+ },
92
+ }),
93
+ ),
89
94
  );
90
95
  },
91
96
  }),
@@ -2,5 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './app-graph-builder';
6
- export * from './operation-resolver';
5
+ import { Capability } from '@dxos/app-framework';
6
+ import { OperationHandlerSet } from '@dxos/compute';
7
+
8
+ export const SettingsAppGraphBuilder = Capability.lazy('SettingsAppGraphBuilder', () => import('./app-graph-builder'));
9
+ export const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(
10
+ 'OperationHandler',
11
+ () => import('./operation-handler'),
12
+ );
13
+ export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
@@ -0,0 +1,16 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capabilities, Capability } from '@dxos/app-framework';
8
+ import type { OperationHandlerSet } from '@dxos/compute';
9
+
10
+ import { SettingsOperationHandlerSet } from '#operations';
11
+
12
+ export default Capability.makeModule<OperationHandlerSet.OperationHandlerSet>(
13
+ Effect.fnUntraced(function* () {
14
+ return Capability.contributes(Capabilities.OperationHandler, SettingsOperationHandlerSet);
15
+ }),
16
+ );
@@ -0,0 +1,50 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import React from 'react';
7
+
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
+ import { Surface, useSettingsState } from '@dxos/app-framework/ui';
10
+ import { type AppCapabilities } from '@dxos/app-toolkit';
11
+ import { AppSurface } from '@dxos/app-toolkit/ui';
12
+ import { Settings as SettingsForm } from '@dxos/react-ui-form';
13
+
14
+ /**
15
+ * Generic settings surface rendered for any plugin that contributes an
16
+ * `AppCapabilities.Settings` entry. It drives a schema-based form from the
17
+ * contributed `schema`/`atom`, so plugins whose settings are plain editable
18
+ * fields need not register a bespoke settings surface.
19
+ *
20
+ * No section title is rendered: the settings plank heading already names the
21
+ * plugin. Registered with `position: 'last'` so a plugin-specific surface
22
+ * (matching by prefix) always wins under the settings article's `limit={1}`
23
+ * dispatch.
24
+ */
25
+ const DefaultSettings = ({ subject }: { subject: AppCapabilities.Settings }) => {
26
+ const { settings, updateSettings } = useSettingsState<Record<string, any>>(subject.atom);
27
+
28
+ return (
29
+ <SettingsForm.Viewport>
30
+ <SettingsForm.FieldSet
31
+ schema={subject.schema}
32
+ values={settings}
33
+ onValuesChanged={(values) => updateSettings(() => values)}
34
+ />
35
+ </SettingsForm.Viewport>
36
+ );
37
+ };
38
+
39
+ export default Capability.makeModule(() =>
40
+ Effect.succeed(
41
+ Capability.contributes(Capabilities.ReactSurface, [
42
+ Surface.create({
43
+ id: 'defaultPluginSettings',
44
+ position: 'last',
45
+ filter: AppSurface.settings(AppSurface.Article),
46
+ component: ({ data: { subject } }) => <DefaultSettings subject={subject} />,
47
+ }),
48
+ ]),
49
+ ),
50
+ );
package/src/index.ts CHANGED
@@ -3,4 +3,5 @@
3
3
  //
4
4
 
5
5
  export * from './actions';
6
- export * from './SettingsPlugin';
6
+ export * from './meta';
7
+ export { SETTINGS_ID, SETTINGS_KEY } from './types';
package/src/meta.ts CHANGED
@@ -2,9 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Plugin } from '@dxos/app-framework';
5
+ import { Plugin } from '@dxos/app-framework';
6
+ import { DXN } from '@dxos/keys';
6
7
 
7
- export const meta: Plugin.Meta = {
8
- id: 'org.dxos.plugin.settings',
8
+ export const meta = Plugin.makeMeta({
9
+ key: DXN.make('org.dxos.plugin.settings'),
9
10
  name: 'Settings',
10
- };
11
+ author: 'DXOS',
12
+ tags: ['system'],
13
+ });
@@ -0,0 +1,10 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { OperationHandlerSet } from '@dxos/compute';
6
+
7
+ export const SettingsOperationHandlerSet = OperationHandlerSet.lazy(
8
+ () => import('./open'),
9
+ () => import('./open-plugin-registry'),
10
+ );
@@ -0,0 +1,28 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capabilities, Capability } from '@dxos/app-framework';
8
+ import { LayoutOperation, SettingsOperation, getSpacePath } from '@dxos/app-toolkit';
9
+ import { Operation } from '@dxos/compute';
10
+
11
+ import { SETTINGS_ID, SETTINGS_KEY } from '../actions';
12
+
13
+ const handler: Operation.WithHandler<typeof SettingsOperation.OpenPluginRegistry> =
14
+ SettingsOperation.OpenPluginRegistry.pipe(
15
+ Operation.withHandler(() =>
16
+ Effect.gen(function* () {
17
+ const { invoke } = yield* Capability.get(Capabilities.OperationInvoker);
18
+ yield* invoke(LayoutOperation.SwitchWorkspace, { subject: getSpacePath(SETTINGS_ID) });
19
+ // Await (don't fork): SwitchWorkspace selects the workspace's first child, so a forked Open
20
+ // races/drops before its deck update applies. Awaiting guarantees the registry is selected.
21
+ yield* invoke(LayoutOperation.Open, {
22
+ subject: [`${getSpacePath(SETTINGS_ID)}/${SETTINGS_KEY}:plugins`],
23
+ });
24
+ }),
25
+ ),
26
+ );
27
+
28
+ export default handler;
@@ -0,0 +1,30 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capabilities, Capability } from '@dxos/app-framework';
8
+ import { LayoutOperation, SettingsOperation, getSpacePath } from '@dxos/app-toolkit';
9
+ import { Operation } from '@dxos/compute';
10
+
11
+ import { SETTINGS_ID, SETTINGS_KEY } from '../actions';
12
+
13
+ const handler: Operation.WithHandler<typeof SettingsOperation.Open> = SettingsOperation.Open.pipe(
14
+ Operation.withHandler((input) =>
15
+ Effect.gen(function* () {
16
+ const { invoke } = yield* Capability.get(Capabilities.OperationInvoker);
17
+ yield* invoke(LayoutOperation.SwitchWorkspace, { subject: getSpacePath(SETTINGS_ID) });
18
+ if (input.plugin) {
19
+ // Await (don't fork): SwitchWorkspace already selects the workspace's first child, so a
20
+ // forked Open for the requested plugin races/drops before its deck update applies, leaving
21
+ // the wrong plugin selected. Awaiting guarantees the requested plugin becomes the selection.
22
+ yield* invoke(LayoutOperation.Open, {
23
+ subject: [`${getSpacePath(SETTINGS_ID)}/${SETTINGS_KEY}:${input.plugin.replaceAll('/', ':')}`],
24
+ });
25
+ }
26
+ }),
27
+ ),
28
+ );
29
+
30
+ export default handler;
package/src/plugin.ts ADDED
@@ -0,0 +1,11 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { Plugin } from '@dxos/app-framework';
6
+
7
+ import { meta } from './meta';
8
+
9
+ export const SettingsPlugin = Plugin.lazy(meta, () => import('#plugin'));
10
+
11
+ export { SettingsOperationHandlerSet } from './operations';
package/src/testing.ts ADDED
@@ -0,0 +1,7 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ // Eager re-export of `SettingsPlugin`. See `@dxos/plugin-testing/src/core.ts`
6
+ // for the rationale.
7
+ export * from './SettingsPlugin';
@@ -4,14 +4,13 @@
4
4
 
5
5
  import { type Resource } from '@dxos/app-toolkit';
6
6
 
7
- import { meta } from './meta';
7
+ import { meta } from '#meta';
8
8
 
9
9
  export const translations = [
10
10
  {
11
11
  'en-US': {
12
12
  [meta.id]: {
13
- 'open settings label': 'Open settings',
14
- 'app settings label': 'Settings',
13
+ 'plugin-settings.label': 'Plugin Settings',
15
14
  },
16
15
  },
17
16
  },
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { pinnedWorkspaceId } from '@dxos/app-toolkit';
6
+
7
+ export const SETTINGS_ID = pinnedWorkspaceId('dxos:settings');
8
+ export const SETTINGS_KEY = 'settings';
@@ -1,97 +0,0 @@
1
- import {
2
- SETTINGS_ID,
3
- SETTINGS_KEY,
4
- meta
5
- } from "./chunk-DIKK4DQC.mjs";
6
-
7
- // src/capabilities/app-graph-builder/app-graph-builder.ts
8
- import * as Effect from "effect/Effect";
9
- import { Capabilities, Capability } from "@dxos/app-framework";
10
- import { GraphBuilder, NodeMatcher } from "@dxos/app-graph";
11
- import { AppCapabilities, SettingsOperation, getSpacePath } from "@dxos/app-toolkit";
12
- import { Operation } from "@dxos/operation";
13
- import { isNonNullable } from "@dxos/util";
14
- var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
15
- const capabilities = yield* Capability.Service;
16
- const managerAtom = capabilities.atom(Capabilities.PluginManager);
17
- const settingsAtom = capabilities.atom(AppCapabilities.Settings);
18
- const extensions = yield* Effect.all([
19
- GraphBuilder.createExtension({
20
- id: `${meta.id}.action`,
21
- match: NodeMatcher.whenRoot,
22
- actions: () => Effect.succeed([
23
- {
24
- id: meta.id,
25
- data: () => Operation.invoke(SettingsOperation.Open, {}),
26
- properties: {
27
- label: [
28
- "open settings label",
29
- {
30
- ns: meta.id
31
- }
32
- ],
33
- icon: "ph--gear--regular",
34
- disposition: "menu",
35
- keyBinding: {
36
- macos: "meta+,",
37
- windows: "alt+,"
38
- }
39
- }
40
- }
41
- ])
42
- }),
43
- GraphBuilder.createExtension({
44
- id: `${meta.id}.core`,
45
- match: NodeMatcher.whenRoot,
46
- connector: () => Effect.succeed([
47
- {
48
- id: SETTINGS_ID,
49
- type: meta.id,
50
- properties: {
51
- label: [
52
- "app settings label",
53
- {
54
- ns: meta.id
55
- }
56
- ],
57
- icon: "ph--gear--regular",
58
- disposition: "pin-end",
59
- position: "hoist",
60
- testId: "treeView.appSettings"
61
- }
62
- }
63
- ])
64
- }),
65
- GraphBuilder.createExtension({
66
- id: `${meta.id}.plugins`,
67
- match: NodeMatcher.whenId(getSpacePath(SETTINGS_ID)),
68
- connector: (node, get) => {
69
- const [manager] = get(managerAtom);
70
- const allSettings = get(settingsAtom);
71
- return Effect.succeed(manager.getPlugins().map((plugin) => {
72
- const settings = allSettings.find((s) => s.prefix === plugin.meta.id);
73
- if (!settings) {
74
- return null;
75
- }
76
- return [
77
- plugin.meta,
78
- settings
79
- ];
80
- }).filter(isNonNullable).map(([meta2, settings]) => ({
81
- id: `${SETTINGS_KEY}:${meta2.id.replaceAll("/", ":")}`,
82
- type: "category",
83
- data: settings,
84
- properties: {
85
- label: meta2.name ?? meta2.id,
86
- icon: meta2.icon ?? "ph--circle--regular"
87
- }
88
- })));
89
- }
90
- })
91
- ]);
92
- return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
93
- }));
94
- export {
95
- app_graph_builder_default as default
96
- };
97
- //# sourceMappingURL=app-graph-builder-YWCB3EZC.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/capabilities/app-graph-builder/app-graph-builder.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { Capabilities, Capability, type Plugin as Plugin$ } from '@dxos/app-framework';\nimport { GraphBuilder, NodeMatcher } from '@dxos/app-graph';\nimport { AppCapabilities, SettingsOperation, getSpacePath } from '@dxos/app-toolkit';\nimport { Operation } from '@dxos/operation';\nimport { isNonNullable } from '@dxos/util';\n\nimport { SETTINGS_ID, SETTINGS_KEY } from '../../actions';\nimport { meta } from '../../meta';\n\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n // Get context for lazy capability access in callbacks.\n const capabilities = yield* Capability.Service;\n const managerAtom = capabilities.atom(Capabilities.PluginManager);\n const settingsAtom = capabilities.atom(AppCapabilities.Settings);\n\n const extensions = yield* Effect.all([\n GraphBuilder.createExtension({\n id: `${meta.id}.action`,\n match: NodeMatcher.whenRoot,\n actions: () =>\n Effect.succeed([\n {\n id: meta.id,\n data: () => Operation.invoke(SettingsOperation.Open, {}),\n properties: {\n label: ['open settings label', { ns: meta.id }],\n icon: 'ph--gear--regular',\n disposition: 'menu',\n keyBinding: {\n macos: 'meta+,',\n windows: 'alt+,',\n },\n },\n },\n ]),\n }),\n GraphBuilder.createExtension({\n id: `${meta.id}.core`,\n match: NodeMatcher.whenRoot,\n connector: () =>\n Effect.succeed([\n {\n id: SETTINGS_ID,\n type: meta.id,\n properties: {\n label: ['app settings label', { ns: meta.id }],\n icon: 'ph--gear--regular',\n disposition: 'pin-end',\n position: 'hoist',\n testId: 'treeView.appSettings',\n },\n },\n ]),\n }),\n GraphBuilder.createExtension({\n id: `${meta.id}.plugins`,\n match: NodeMatcher.whenId(getSpacePath(SETTINGS_ID)),\n connector: (node, get) => {\n const [manager] = get(managerAtom);\n const allSettings = get(settingsAtom);\n return Effect.succeed(\n manager\n .getPlugins()\n .map((plugin: Plugin$.Plugin): [Plugin$.Meta, AppCapabilities.Settings] | null => {\n const settings = allSettings.find((s) => s.prefix === plugin.meta.id);\n if (!settings) {\n return null;\n }\n\n return [plugin.meta, settings];\n })\n .filter(isNonNullable)\n .map(([meta, settings]: [Plugin$.Meta, AppCapabilities.Settings]) => ({\n id: `${SETTINGS_KEY}:${meta.id.replaceAll('/', ':')}`,\n type: 'category',\n data: settings,\n properties: {\n label: meta.name ?? meta.id,\n icon: meta.icon ?? 'ph--circle--regular',\n },\n })),\n );\n },\n }),\n ]);\n\n return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],
5
- "mappings": ";;;;;;;AAIA,YAAYA,YAAY;AAExB,SAASC,cAAcC,kBAA0C;AACjE,SAASC,cAAcC,mBAAmB;AAC1C,SAASC,iBAAiBC,mBAAmBC,oBAAoB;AACjE,SAASC,iBAAiB;AAC1B,SAASC,qBAAqB;AAK9B,IAAA,4BAAeC,WAAWC,WACjBC,kBAAW,aAAA;AAEhB,QAAMC,eAAe,OAAOH,WAAWI;AACvC,QAAMC,cAAcF,aAAaG,KAAKC,aAAaC,aAAa;AAChE,QAAMC,eAAeN,aAAaG,KAAKI,gBAAgBC,QAAQ;AAE/D,QAAMC,aAAa,OAAcC,WAAI;IACnCC,aAAaC,gBAAgB;MAC3BC,IAAI,GAAGC,KAAKD,EAAE;MACdE,OAAOC,YAAYC;MACnBC,SAAS,MACAC,eAAQ;QACb;UACEN,IAAIC,KAAKD;UACTO,MAAM,MAAMC,UAAUC,OAAOC,kBAAkBC,MAAM,CAAC,CAAA;UACtDC,YAAY;YACVC,OAAO;cAAC;cAAuB;gBAAEC,IAAIb,KAAKD;cAAG;;YAC7Ce,MAAM;YACNC,aAAa;YACbC,YAAY;cACVC,OAAO;cACPC,SAAS;YACX;UACF;QACF;OACD;IACL,CAAA;IACArB,aAAaC,gBAAgB;MAC3BC,IAAI,GAAGC,KAAKD,EAAE;MACdE,OAAOC,YAAYC;MACnBgB,WAAW,MACFd,eAAQ;QACb;UACEN,IAAIqB;UACJC,MAAMrB,KAAKD;UACXY,YAAY;YACVC,OAAO;cAAC;cAAsB;gBAAEC,IAAIb,KAAKD;cAAG;;YAC5Ce,MAAM;YACNC,aAAa;YACbO,UAAU;YACVC,QAAQ;UACV;QACF;OACD;IACL,CAAA;IACA1B,aAAaC,gBAAgB;MAC3BC,IAAI,GAAGC,KAAKD,EAAE;MACdE,OAAOC,YAAYsB,OAAOC,aAAaL,WAAAA,CAAAA;MACvCD,WAAW,CAACO,MAAMC,QAAAA;AAChB,cAAM,CAACC,OAAAA,IAAWD,IAAIvC,WAAAA;AACtB,cAAMyC,cAAcF,IAAInC,YAAAA;AACxB,eAAca,eACZuB,QACGE,WAAU,EACVC,IAAI,CAACC,WAAAA;AACJ,gBAAMC,WAAWJ,YAAYK,KAAK,CAACC,MAAMA,EAAEC,WAAWJ,OAAOhC,KAAKD,EAAE;AACpE,cAAI,CAACkC,UAAU;AACb,mBAAO;UACT;AAEA,iBAAO;YAACD,OAAOhC;YAAMiC;;QACvB,CAAA,EACCI,OAAOC,aAAAA,EACPP,IAAI,CAAC,CAAC/B,OAAMiC,QAAAA,OAAyD;UACpElC,IAAI,GAAGwC,YAAAA,IAAgBvC,MAAKD,GAAGyC,WAAW,KAAK,GAAA,CAAA;UAC/CnB,MAAM;UACNf,MAAM2B;UACNtB,YAAY;YACVC,OAAOZ,MAAKyC,QAAQzC,MAAKD;YACzBe,MAAMd,MAAKc,QAAQ;UACrB;QACF,EAAA,CAAA;MAEN;IACF,CAAA;GACD;AAED,SAAO/B,WAAW2D,YAAYjD,gBAAgBkD,iBAAiBhD,UAAAA;AACjE,CAAA,CAAA;",
6
- "names": ["Effect", "Capabilities", "Capability", "GraphBuilder", "NodeMatcher", "AppCapabilities", "SettingsOperation", "getSpacePath", "Operation", "isNonNullable", "Capability", "makeModule", "fnUntraced", "capabilities", "Service", "managerAtom", "atom", "Capabilities", "PluginManager", "settingsAtom", "AppCapabilities", "Settings", "extensions", "all", "GraphBuilder", "createExtension", "id", "meta", "match", "NodeMatcher", "whenRoot", "actions", "succeed", "data", "Operation", "invoke", "SettingsOperation", "Open", "properties", "label", "ns", "icon", "disposition", "keyBinding", "macos", "windows", "connector", "SETTINGS_ID", "type", "position", "testId", "whenId", "getSpacePath", "node", "get", "manager", "allSettings", "getPlugins", "map", "plugin", "settings", "find", "s", "prefix", "filter", "isNonNullable", "SETTINGS_KEY", "replaceAll", "name", "contributes", "AppGraphBuilder"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/meta.ts", "../../../src/actions.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Plugin } from '@dxos/app-framework';\n\nexport const meta: Plugin.Meta = {\n id: 'org.dxos.plugin.settings',\n name: 'Settings',\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { meta } from './meta';\n\nexport const SETTINGS_ID = '!dxos:settings';\nexport const SETTINGS_KEY = 'settings';\n\nexport namespace SettingsAction {\n export class Open extends Schema.TaggedClass<Open>()(`${meta.id}.open`, {\n input: Schema.Struct({\n plugin: Schema.optional(Schema.String),\n }),\n output: Schema.Void,\n }) {}\n\n export class OpenPluginRegistry extends Schema.TaggedClass<OpenPluginRegistry>()(`${meta.id}.open-plugin-registry`, {\n input: Schema.Void,\n output: Schema.Void,\n }) {}\n}\n"],
5
- "mappings": ";AAMO,IAAMA,OAAoB;EAC/BC,IAAI;EACJC,MAAM;AACR;;;ACLA,YAAYC,YAAY;AAIjB,IAAMC,cAAc;AACpB,IAAMC,eAAe;UAEXC,iBAAAA;EACR,MAAMC,aAAoBC,mBAAW,EAAS,GAAGC,KAAKC,EAAE,SAAS;IACtEC,OAAcC,cAAO;MACnBC,QAAeC,gBAAgBC,aAAM;IACvC,CAAA;IACAC,QAAeC;EACjB,CAAA,EAAA;EAAI;kBALSV,OAAAA;EAON,MAAMW,2BAAkCV,mBAAW,EAAuB,GAAGC,KAAKC,EAAE,yBAAyB;IAClHC,OAAcM;IACdD,QAAeC;EACjB,CAAA,EAAA;EAAI;kBAHSC,qBAAAA;AAIf,GAZiBZ,mBAAAA,iBAAAA,CAAAA,EAAAA;;",
6
- "names": ["meta", "id", "name", "Schema", "SETTINGS_ID", "SETTINGS_KEY", "SettingsAction", "Open", "TaggedClass", "meta", "id", "input", "Struct", "plugin", "optional", "String", "output", "Void", "OpenPluginRegistry"]
7
- }