@dxos/plugin-registry 0.8.4-staging.60fe92afc8 → 0.9.1-main.c7dcc2e112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/neutral/RegistryPlugin.node.mjs +709 -18
- package/dist/lib/neutral/RegistryPlugin.node.mjs.map +4 -4
- package/dist/lib/neutral/chunk-ZY37XLVF.mjs +46 -0
- package/dist/lib/neutral/chunk-ZY37XLVF.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +1 -1
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/{open-plugin-registry-II735N76.mjs → open-plugin-registry-ID7LV3SF.mjs} +3 -3
- package/dist/lib/neutral/open-plugin-registry-ID7LV3SF.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +2 -2
- package/dist/lib/neutral/translations.mjs +1 -1
- package/dist/lib/neutral/translations.mjs.map +3 -3
- package/dist/types/dx.config.d.ts +28 -0
- package/dist/types/dx.config.d.ts.map +1 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +4 -12
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +2 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/categories.d.ts.map +1 -1
- package/dist/types/src/commands/index.d.ts +2 -2
- package/dist/types/src/commands/index.d.ts.map +1 -1
- package/dist/types/src/commands/plugin/disable.d.ts.map +1 -0
- package/dist/types/src/commands/plugin/enable.d.ts.map +1 -0
- package/dist/types/src/commands/plugin/index.d.ts +3 -0
- package/dist/types/src/commands/plugin/index.d.ts.map +1 -0
- package/dist/types/src/commands/plugin/list.d.ts.map +1 -0
- package/dist/types/src/commands/plugin/util.d.ts.map +1 -0
- package/dist/types/src/commands/registry/index.d.ts +16 -0
- package/dist/types/src/commands/registry/index.d.ts.map +1 -0
- package/dist/types/src/commands/registry/publish-package.d.ts +29 -0
- package/dist/types/src/commands/registry/publish-package.d.ts.map +1 -0
- package/dist/types/src/commands/registry/publish-publisher.d.ts +19 -0
- package/dist/types/src/commands/registry/publish-publisher.d.ts.map +1 -0
- package/dist/types/src/commands/registry/publish.d.ts +25 -0
- package/dist/types/src/commands/registry/publish.d.ts.map +1 -0
- package/dist/types/src/commands/registry/records.d.ts +14 -0
- package/dist/types/src/commands/registry/records.d.ts.map +1 -0
- package/dist/types/src/commands/registry/unpublish.d.ts +15 -0
- package/dist/types/src/commands/registry/unpublish.d.ts.map +1 -0
- package/dist/types/src/commands/registry/util.d.ts +113 -0
- package/dist/types/src/commands/registry/util.d.ts.map +1 -0
- package/dist/types/src/commands/registry/verify.d.ts +20 -0
- package/dist/types/src/commands/registry/verify.d.ts.map +1 -0
- package/dist/types/src/components/PluginDetail/PluginDetail.d.ts +2 -2
- package/dist/types/src/components/PluginDetail/PluginDetail.d.ts.map +1 -1
- package/dist/types/src/components/PluginDetail/PluginDetail.stories.d.ts.map +1 -1
- package/dist/types/src/components/PluginList/PluginItem.d.ts.map +1 -1
- package/dist/types/src/components/PluginList/PluginList.stories.d.ts.map +1 -1
- package/dist/types/src/containers/LoadPluginDialog/LoadPluginDialog.d.ts.map +1 -1
- package/dist/types/src/containers/PluginArticle/PluginArticle.d.ts.map +1 -1
- package/dist/types/src/containers/PublicRegistryArticle/PublicRegistryArticle.d.ts.map +1 -1
- package/dist/types/src/hooks/useAutoTags.d.ts +2 -2
- package/dist/types/src/hooks/useAutoTags.d.ts.map +1 -1
- package/dist/types/src/hooks/useCatalogEntry.d.ts +4 -5
- package/dist/types/src/hooks/useCatalogEntry.d.ts.map +1 -1
- package/dist/types/src/hooks/usePluginActions.d.ts +3 -3
- package/dist/types/src/hooks/usePluginActions.d.ts.map +1 -1
- package/dist/types/src/hooks/useUpdateAvailable.d.ts +2 -2
- package/dist/types/src/hooks/useUpdateAvailable.d.ts.map +1 -1
- package/dist/types/src/hooks/useVersionPicker.d.ts +7 -8
- package/dist/types/src/hooks/useVersionPicker.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +28 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/operations/open-plugin-registry.d.ts.map +1 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +20 -0
- package/package.json +31 -24
- package/src/RegistryPlugin.node.ts +2 -2
- package/src/RegistryPlugin.test.ts +1 -1
- package/src/capabilities/app-graph-builder.ts +43 -39
- package/src/capabilities/dev-plugin-loader.ts +1 -1
- package/src/capabilities/react-surface.tsx +1 -4
- package/src/capabilities/settings.ts +2 -2
- package/src/categories.ts +5 -4
- package/src/commands/index.ts +2 -10
- package/src/commands/{disable.ts → plugin/disable.ts} +3 -3
- package/src/commands/{enable.ts → plugin/enable.ts} +3 -3
- package/src/commands/plugin/index.ts +14 -0
- package/src/commands/{list.ts → plugin/list.ts} +4 -4
- package/src/commands/registry/index.ts +30 -0
- package/src/commands/registry/publish-package.ts +119 -0
- package/src/commands/registry/publish-publisher.ts +73 -0
- package/src/commands/registry/publish.ts +278 -0
- package/src/commands/registry/records.ts +73 -0
- package/src/commands/registry/unpublish.ts +70 -0
- package/src/commands/registry/util.ts +395 -0
- package/src/commands/registry/verify.ts +76 -0
- package/src/components/DisableDependentsAlert/DisableDependentsAlert.tsx +1 -1
- package/src/components/PluginDetail/PluginDetail.stories.tsx +5 -3
- package/src/components/PluginDetail/PluginDetail.tsx +21 -23
- package/src/components/PluginFailureBadge/PluginFailureBadge.tsx +1 -1
- package/src/components/PluginList/PluginItem.tsx +5 -3
- package/src/components/PluginList/PluginList.stories.tsx +1 -2
- package/src/components/PluginList/PluginList.tsx +4 -4
- package/src/components/RegistrySettings/RegistrySettings.tsx +1 -1
- package/src/containers/BaseRegistryArticle/BaseRegistryArticle.tsx +2 -2
- package/src/containers/LoadPluginDialog/LoadPluginDialog.tsx +3 -3
- package/src/containers/PluginArticle/PluginArticle.tsx +8 -6
- package/src/containers/PublicRegistryArticle/PublicRegistryArticle.tsx +35 -28
- package/src/containers/RegistryArticle/RegistryArticle.tsx +1 -1
- package/src/containers/RegistrySettingsContainer/RegistrySettingsContainer.tsx +1 -1
- package/src/hooks/useAutoTags.ts +3 -3
- package/src/hooks/useCatalogEntry.ts +6 -7
- package/src/hooks/useDisableConfirmation.ts +1 -1
- package/src/hooks/usePluginActions.ts +13 -11
- package/src/hooks/useUpdateAvailable.ts +5 -5
- package/src/hooks/useVersionPicker.ts +22 -30
- package/src/meta.ts +6 -15
- package/src/operations/open-plugin-registry.ts +2 -2
- package/src/translations.ts +1 -1
- package/src/types.ts +3 -1
- package/dist/lib/neutral/chunk-GRQI6MLI.mjs +0 -36
- package/dist/lib/neutral/chunk-GRQI6MLI.mjs.map +0 -7
- package/dist/lib/neutral/open-plugin-registry-II735N76.mjs.map +0 -7
- package/dist/types/src/commands/disable.d.ts.map +0 -1
- package/dist/types/src/commands/enable.d.ts.map +0 -1
- package/dist/types/src/commands/list.d.ts.map +0 -1
- package/dist/types/src/commands/util.d.ts.map +0 -1
- /package/dist/types/src/commands/{disable.d.ts → plugin/disable.d.ts} +0 -0
- /package/dist/types/src/commands/{enable.d.ts → plugin/enable.d.ts} +0 -0
- /package/dist/types/src/commands/{list.d.ts → plugin/list.d.ts} +0 -0
- /package/dist/types/src/commands/{util.d.ts → plugin/util.d.ts} +0 -0
- /package/src/commands/{util.ts → plugin/util.ts} +0 -0
package/dx.config.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Config2 } from '@dxos/app-framework/config';
|
|
6
|
+
import { trim } from '@dxos/util';
|
|
7
|
+
|
|
8
|
+
export default Config2.make({
|
|
9
|
+
plugin: {
|
|
10
|
+
key: 'org.dxos.plugin.registry',
|
|
11
|
+
name: 'Plugins',
|
|
12
|
+
author: 'DXOS',
|
|
13
|
+
description: trim`
|
|
14
|
+
Plugin management system for discovering, installing, and configuring workspace extensions.
|
|
15
|
+
Browse available plugins and customize your workspace capabilities.
|
|
16
|
+
`,
|
|
17
|
+
icon: { key: 'ph--squares-four--regular' },
|
|
18
|
+
tags: ['system'],
|
|
19
|
+
},
|
|
20
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-registry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1-main.c7dcc2e112",
|
|
4
4
|
"description": "Braneframe plugin gallery",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -52,28 +52,35 @@
|
|
|
52
52
|
"types": "dist/types/src/index.d.ts",
|
|
53
53
|
"files": [
|
|
54
54
|
"dist",
|
|
55
|
+
"dx.config.ts",
|
|
55
56
|
"src"
|
|
56
57
|
],
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@effect-atom/atom-react": "^0.5.0",
|
|
59
60
|
"@effect/cli": "0.75.2",
|
|
60
61
|
"yaml": "^2.8.2",
|
|
61
|
-
"@dxos/app-
|
|
62
|
-
"@dxos/app-
|
|
63
|
-
"@dxos/
|
|
64
|
-
"@dxos/client-protocol": "0.
|
|
65
|
-
"@dxos/
|
|
66
|
-
"@dxos/
|
|
67
|
-
"@dxos/
|
|
68
|
-
"@dxos/
|
|
69
|
-
"@dxos/
|
|
70
|
-
"@dxos/keys": "0.
|
|
71
|
-
"@dxos/
|
|
72
|
-
"@dxos/
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/
|
|
75
|
-
"@dxos/
|
|
76
|
-
"@dxos/
|
|
62
|
+
"@dxos/app-framework": "0.9.1-main.c7dcc2e112",
|
|
63
|
+
"@dxos/app-toolkit": "0.9.1-main.c7dcc2e112",
|
|
64
|
+
"@dxos/client": "0.9.1-main.c7dcc2e112",
|
|
65
|
+
"@dxos/client-protocol": "0.9.1-main.c7dcc2e112",
|
|
66
|
+
"@dxos/cli-util": "0.9.1-main.c7dcc2e112",
|
|
67
|
+
"@dxos/compute": "0.9.1-main.c7dcc2e112",
|
|
68
|
+
"@dxos/edge-client": "0.9.1-main.c7dcc2e112",
|
|
69
|
+
"@dxos/invariant": "0.9.1-main.c7dcc2e112",
|
|
70
|
+
"@dxos/echo": "0.9.1-main.c7dcc2e112",
|
|
71
|
+
"@dxos/keys": "0.9.1-main.c7dcc2e112",
|
|
72
|
+
"@dxos/plugin-graph": "0.9.1-main.c7dcc2e112",
|
|
73
|
+
"@dxos/log": "0.9.1-main.c7dcc2e112",
|
|
74
|
+
"@dxos/protocols": "0.9.1-main.c7dcc2e112",
|
|
75
|
+
"@dxos/context": "0.9.1-main.c7dcc2e112",
|
|
76
|
+
"@dxos/plugin-observability": "0.9.1-main.c7dcc2e112",
|
|
77
|
+
"@dxos/react-ui-form": "0.9.1-main.c7dcc2e112",
|
|
78
|
+
"@dxos/react-ui-mosaic": "0.9.1-main.c7dcc2e112",
|
|
79
|
+
"@dxos/react-ui-stack": "0.9.1-main.c7dcc2e112",
|
|
80
|
+
"@dxos/types": "0.9.1-main.c7dcc2e112",
|
|
81
|
+
"@dxos/react-ui-markdown": "0.9.1-main.c7dcc2e112",
|
|
82
|
+
"@dxos/util": "0.9.1-main.c7dcc2e112",
|
|
83
|
+
"@dxos/effect": "0.9.1-main.c7dcc2e112"
|
|
77
84
|
},
|
|
78
85
|
"devDependencies": {
|
|
79
86
|
"@effect-atom/atom-react": "^0.5.0",
|
|
@@ -84,11 +91,11 @@
|
|
|
84
91
|
"react": "~19.2.3",
|
|
85
92
|
"react-dom": "~19.2.3",
|
|
86
93
|
"vite": "^8.0.16",
|
|
87
|
-
"@dxos/plugin-testing": "0.
|
|
88
|
-
"@dxos/
|
|
89
|
-
"@dxos/
|
|
90
|
-
"@dxos/ui-theme": "0.
|
|
91
|
-
"@dxos/
|
|
94
|
+
"@dxos/plugin-testing": "0.9.1-main.c7dcc2e112",
|
|
95
|
+
"@dxos/react-ui": "0.9.1-main.c7dcc2e112",
|
|
96
|
+
"@dxos/storybook-utils": "0.9.1-main.c7dcc2e112",
|
|
97
|
+
"@dxos/ui-theme": "0.9.1-main.c7dcc2e112",
|
|
98
|
+
"@dxos/random": "0.9.1-main.c7dcc2e112"
|
|
92
99
|
},
|
|
93
100
|
"peerDependencies": {
|
|
94
101
|
"@effect-atom/atom-react": "^0.5.0",
|
|
@@ -96,8 +103,8 @@
|
|
|
96
103
|
"effect": "3.21.3",
|
|
97
104
|
"react": "~19.2.3",
|
|
98
105
|
"react-dom": "~19.2.3",
|
|
99
|
-
"@dxos/react-ui": "0.
|
|
100
|
-
"@dxos/ui-theme": "0.
|
|
106
|
+
"@dxos/react-ui": "0.9.1-main.c7dcc2e112",
|
|
107
|
+
"@dxos/ui-theme": "0.9.1-main.c7dcc2e112"
|
|
101
108
|
},
|
|
102
109
|
"publishConfig": {
|
|
103
110
|
"access": "public"
|
|
@@ -7,11 +7,11 @@ import { AppPlugin } from '@dxos/app-toolkit';
|
|
|
7
7
|
|
|
8
8
|
import { meta } from '#meta';
|
|
9
9
|
|
|
10
|
-
import { plugin } from './commands';
|
|
10
|
+
import { plugin, registry } from './commands';
|
|
11
11
|
|
|
12
12
|
export const RegistryPlugin = Plugin.define(meta).pipe(
|
|
13
13
|
AppPlugin.addCommandModule({
|
|
14
|
-
commands: [plugin],
|
|
14
|
+
commands: [plugin, registry],
|
|
15
15
|
}),
|
|
16
16
|
Plugin.make,
|
|
17
17
|
);
|
|
@@ -10,7 +10,7 @@ import { RegistryPlugin } from '#plugin';
|
|
|
10
10
|
|
|
11
11
|
import { meta } from './meta';
|
|
12
12
|
|
|
13
|
-
const moduleId = (name: string) => `${meta.
|
|
13
|
+
const moduleId = (name: string) => `${meta.profile.key}.module.${name}`;
|
|
14
14
|
|
|
15
15
|
describe('RegistryPlugin', () => {
|
|
16
16
|
test('modules activate on the expected events', async ({ expect }) => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Effect from 'effect/Effect';
|
|
6
6
|
|
|
7
|
-
import { Capabilities, Capability,
|
|
7
|
+
import { Capabilities, Capability, Plugin } from '@dxos/app-framework';
|
|
8
8
|
import { AppCapabilities, LayoutOperation, SettingsOperation } from '@dxos/app-toolkit';
|
|
9
9
|
import { Operation } from '@dxos/compute';
|
|
10
10
|
import { DXN } from '@dxos/keys';
|
|
@@ -21,19 +21,19 @@ import { LOAD_PLUGIN_DIALOG } from '../containers';
|
|
|
21
21
|
* modules and only exists so the article surface can render details for
|
|
22
22
|
* registry plugins that haven't been installed yet.
|
|
23
23
|
*/
|
|
24
|
-
const toDisplayPlugin = (entry:
|
|
24
|
+
const toDisplayPlugin = (entry: Plugin.Meta): Plugin.Plugin =>
|
|
25
25
|
({
|
|
26
26
|
[Plugin.PluginTypeId]: Plugin.PluginTypeId,
|
|
27
27
|
meta: Plugin.makeMeta({
|
|
28
|
-
key: DXN.make(entry.
|
|
29
|
-
name: entry.name,
|
|
30
|
-
description: entry.description,
|
|
31
|
-
homePage: entry.homePage,
|
|
32
|
-
source: entry.source,
|
|
33
|
-
screenshots: entry.screenshots,
|
|
34
|
-
tags: entry.tags,
|
|
35
|
-
icon: entry.icon,
|
|
36
|
-
|
|
28
|
+
key: DXN.make(entry.profile.key),
|
|
29
|
+
name: entry.profile.name,
|
|
30
|
+
description: entry.profile.description,
|
|
31
|
+
homePage: entry.profile.homePage,
|
|
32
|
+
source: entry.profile.source,
|
|
33
|
+
screenshots: entry.profile.screenshots,
|
|
34
|
+
tags: entry.profile.tags,
|
|
35
|
+
icon: entry.profile.icon,
|
|
36
|
+
author: entry.profile.author,
|
|
37
37
|
}),
|
|
38
38
|
modules: [],
|
|
39
39
|
}) as Plugin.Plugin;
|
|
@@ -52,7 +52,7 @@ export default Capability.makeModule(
|
|
|
52
52
|
id: 'openRegistry',
|
|
53
53
|
data: () => Operation.invoke(SettingsOperation.OpenPluginRegistry),
|
|
54
54
|
properties: {
|
|
55
|
-
label: ['open-plugin-registry.label', { ns: meta.
|
|
55
|
+
label: ['open-plugin-registry.label', { ns: meta.profile.key }],
|
|
56
56
|
icon: 'ph--squares-four--regular',
|
|
57
57
|
disposition: 'menu',
|
|
58
58
|
},
|
|
@@ -77,9 +77,9 @@ export default Capability.makeModule(
|
|
|
77
77
|
return Effect.succeed([
|
|
78
78
|
Node.make({
|
|
79
79
|
id: REGISTRY_ID,
|
|
80
|
-
type: meta.
|
|
80
|
+
type: meta.profile.key,
|
|
81
81
|
properties: {
|
|
82
|
-
label: ['plugin-registry.label', { ns: meta.
|
|
82
|
+
label: ['plugin-registry.label', { ns: meta.profile.key }],
|
|
83
83
|
icon: 'ph--squares-four--regular',
|
|
84
84
|
disposition: 'pin-end',
|
|
85
85
|
position: 'first',
|
|
@@ -91,7 +91,7 @@ export default Capability.makeModule(
|
|
|
91
91
|
type: 'category',
|
|
92
92
|
data: registryCategoryId('bundled'),
|
|
93
93
|
properties: {
|
|
94
|
-
label: ['bundled-plugins.label', { ns: meta.
|
|
94
|
+
label: ['bundled-plugins.label', { ns: meta.profile.key }],
|
|
95
95
|
icon: 'ph--squares-four--regular',
|
|
96
96
|
key: REGISTRY_KEY,
|
|
97
97
|
testId: 'pluginRegistry.bundled',
|
|
@@ -103,7 +103,7 @@ export default Capability.makeModule(
|
|
|
103
103
|
type: 'category',
|
|
104
104
|
data: registryCategoryId('installed'),
|
|
105
105
|
properties: {
|
|
106
|
-
label: ['installed-plugins.label', { ns: meta.
|
|
106
|
+
label: ['installed-plugins.label', { ns: meta.profile.key }],
|
|
107
107
|
icon: 'ph--check--regular',
|
|
108
108
|
key: REGISTRY_KEY,
|
|
109
109
|
testId: 'pluginRegistry.installed',
|
|
@@ -115,7 +115,7 @@ export default Capability.makeModule(
|
|
|
115
115
|
type: 'category',
|
|
116
116
|
data: registryCategoryId('recommended'),
|
|
117
117
|
properties: {
|
|
118
|
-
label: ['recommended-plugins.label', { ns: meta.
|
|
118
|
+
label: ['recommended-plugins.label', { ns: meta.profile.key }],
|
|
119
119
|
icon: 'ph--star--regular',
|
|
120
120
|
key: REGISTRY_KEY,
|
|
121
121
|
testId: 'pluginRegistry.recommended',
|
|
@@ -127,25 +127,29 @@ export default Capability.makeModule(
|
|
|
127
127
|
type: 'category',
|
|
128
128
|
data: registryCategoryId('labs'),
|
|
129
129
|
properties: {
|
|
130
|
-
label: ['labs-plugins.label', { ns: meta.
|
|
130
|
+
label: ['labs-plugins.label', { ns: meta.profile.key }],
|
|
131
131
|
icon: 'ph--flask--regular',
|
|
132
132
|
key: REGISTRY_KEY,
|
|
133
133
|
testId: 'pluginRegistry.labs',
|
|
134
134
|
count: categoryCount(registryCategoryId('labs')),
|
|
135
135
|
},
|
|
136
136
|
}),
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
137
|
+
...(registryCount > 0
|
|
138
|
+
? [
|
|
139
|
+
Node.make({
|
|
140
|
+
id: registryCategoryId('registry'),
|
|
141
|
+
type: 'category',
|
|
142
|
+
data: registryCategoryId('registry'),
|
|
143
|
+
properties: {
|
|
144
|
+
label: ['registry-plugins.label', { ns: meta.profile.key }],
|
|
145
|
+
icon: 'ph--users-three--regular',
|
|
146
|
+
key: REGISTRY_KEY,
|
|
147
|
+
testId: 'pluginRegistry.registry',
|
|
148
|
+
count: registryCount,
|
|
149
|
+
},
|
|
150
|
+
}),
|
|
151
|
+
]
|
|
152
|
+
: []),
|
|
149
153
|
],
|
|
150
154
|
}),
|
|
151
155
|
]);
|
|
@@ -165,7 +169,7 @@ export default Capability.makeModule(
|
|
|
165
169
|
});
|
|
166
170
|
}),
|
|
167
171
|
properties: {
|
|
168
|
-
label: ['load-by-url.label', { ns: meta.
|
|
172
|
+
label: ['load-by-url.label', { ns: meta.profile.key }],
|
|
169
173
|
icon: 'ph--cloud-arrow-down--regular',
|
|
170
174
|
disposition: 'list-item-primary',
|
|
171
175
|
},
|
|
@@ -177,16 +181,16 @@ export default Capability.makeModule(
|
|
|
177
181
|
match: NodeMatcher.whenId(`root/${REGISTRY_ID}`),
|
|
178
182
|
connector: (_node, get) => {
|
|
179
183
|
const manager = capabilities.get(Capabilities.PluginManager);
|
|
180
|
-
const installedIds = new Set(manager.getPlugins().map((plugin) => plugin.meta.
|
|
184
|
+
const installedIds = new Set(manager.getPlugins().map((plugin) => plugin.meta.profile.key));
|
|
181
185
|
|
|
182
186
|
const installedNodes = manager.getPlugins().map((plugin) =>
|
|
183
187
|
Node.make({
|
|
184
|
-
id: plugin.meta.
|
|
188
|
+
id: plugin.meta.profile.key,
|
|
185
189
|
type: 'org.dxos.plugin',
|
|
186
190
|
data: plugin,
|
|
187
191
|
properties: {
|
|
188
|
-
label: plugin.meta.name ?? plugin.meta.
|
|
189
|
-
icon: plugin.meta.icon ?? 'ph--circle--regular',
|
|
192
|
+
label: plugin.meta.profile.name ?? plugin.meta.profile.key,
|
|
193
|
+
icon: plugin.meta.profile.icon?.key ?? 'ph--circle--regular',
|
|
190
194
|
disposition: 'hidden',
|
|
191
195
|
},
|
|
192
196
|
}),
|
|
@@ -194,16 +198,16 @@ export default Capability.makeModule(
|
|
|
194
198
|
|
|
195
199
|
const registryEntries = get(manager.pluginRegistry.plugins).entries;
|
|
196
200
|
const registryNodes = registryEntries
|
|
197
|
-
.filter((entry) => !installedIds.has(DXN.make(entry.
|
|
201
|
+
.filter((entry) => !installedIds.has(DXN.make(entry.profile.key)))
|
|
198
202
|
.map((entry) => {
|
|
199
203
|
const plugin = toDisplayPlugin(entry);
|
|
200
204
|
return Node.make({
|
|
201
|
-
id: plugin.meta.
|
|
205
|
+
id: plugin.meta.profile.key,
|
|
202
206
|
type: 'org.dxos.plugin',
|
|
203
207
|
data: plugin,
|
|
204
208
|
properties: {
|
|
205
|
-
label: plugin.meta.name ?? plugin.meta.
|
|
206
|
-
icon: plugin.meta.icon ?? 'ph--circle--regular',
|
|
209
|
+
label: plugin.meta.profile.name ?? plugin.meta.profile.key,
|
|
210
|
+
icon: plugin.meta.profile.icon?.key ?? 'ph--circle--regular',
|
|
207
211
|
disposition: 'hidden',
|
|
208
212
|
},
|
|
209
213
|
});
|
|
@@ -29,7 +29,7 @@ export default Capability.makeModule(
|
|
|
29
29
|
|
|
30
30
|
log.info('loading dev plugin from registry settings', { url });
|
|
31
31
|
yield* manager.add(url).pipe(
|
|
32
|
-
Effect.flatMap((plugin) => manager.enable(plugin.meta.
|
|
32
|
+
Effect.flatMap((plugin) => manager.enable(plugin.meta.profile.key)),
|
|
33
33
|
Effect.tapError((error) => Effect.sync(() => log.warn('dev plugin auto-load failed', { url, error }))),
|
|
34
34
|
Effect.ignore,
|
|
35
35
|
);
|
|
@@ -7,7 +7,6 @@ import React, { type ComponentProps, useMemo } from 'react';
|
|
|
7
7
|
|
|
8
8
|
import { Capabilities, Capability, Plugin } from '@dxos/app-framework';
|
|
9
9
|
import { Surface, usePluginManager } from '@dxos/app-framework/ui';
|
|
10
|
-
import { AppCapabilities } from '@dxos/app-toolkit';
|
|
11
10
|
import { AppSurface } from '@dxos/app-toolkit/ui';
|
|
12
11
|
|
|
13
12
|
import { DisableDependentsAlert } from '#components';
|
|
@@ -86,9 +85,7 @@ export default Capability.makeModule(() =>
|
|
|
86
85
|
}),
|
|
87
86
|
Surface.create({
|
|
88
87
|
id: 'pluginSettings',
|
|
89
|
-
|
|
90
|
-
filter: (data): data is { subject: AppCapabilities.Settings } =>
|
|
91
|
-
AppCapabilities.isSettings(data.subject) && data.subject.prefix === meta.id,
|
|
88
|
+
filter: AppSurface.settings(AppSurface.Article, meta.profile.key),
|
|
92
89
|
component: ({ data: { subject } }) => <RegistrySettingsContainer subject={subject} />,
|
|
93
90
|
}),
|
|
94
91
|
]),
|
|
@@ -17,7 +17,7 @@ const DEFAULT_DEV_PLUGIN_URL = `http://localhost:${PLUGIN_DEV_SERVER_PORT}/manif
|
|
|
17
17
|
export default Capability.makeModule(() =>
|
|
18
18
|
Effect.sync(() => {
|
|
19
19
|
const settingsAtom = createKvsStore({
|
|
20
|
-
key: meta.
|
|
20
|
+
key: meta.profile.key,
|
|
21
21
|
schema: RegistrySettingsSchema,
|
|
22
22
|
defaultValue: () => ({ devPluginUrl: DEFAULT_DEV_PLUGIN_URL }),
|
|
23
23
|
});
|
|
@@ -25,7 +25,7 @@ export default Capability.makeModule(() =>
|
|
|
25
25
|
return [
|
|
26
26
|
Capability.contributes(RegistryCapabilities.Settings, settingsAtom),
|
|
27
27
|
Capability.contributes(AppCapabilities.Settings, {
|
|
28
|
-
prefix: meta.
|
|
28
|
+
prefix: meta.profile.key,
|
|
29
29
|
schema: RegistrySettingsSchema,
|
|
30
30
|
atom: settingsAtom,
|
|
31
31
|
}),
|
package/src/categories.ts
CHANGED
|
@@ -27,13 +27,14 @@ export const getCategoryPredicate = (
|
|
|
27
27
|
): PluginPredicate => {
|
|
28
28
|
switch (category) {
|
|
29
29
|
case registryCategoryId('bundled'):
|
|
30
|
-
return ({ meta }) => !core.includes(meta.
|
|
30
|
+
return ({ meta }) => !core.includes(meta.profile.key) && !remoteIds.has(meta.profile.key);
|
|
31
31
|
case registryCategoryId('installed'):
|
|
32
|
-
return ({ meta }) => !core.includes(meta.
|
|
32
|
+
return ({ meta }) => !core.includes(meta.profile.key) && enabled.includes(meta.profile.key);
|
|
33
33
|
case registryCategoryId('recommended'):
|
|
34
|
-
return ({ meta }) =>
|
|
34
|
+
return ({ meta }) =>
|
|
35
|
+
!core.includes(meta.profile.key) && !remoteIds.has(meta.profile.key) && !meta.profile.tags?.includes('labs');
|
|
35
36
|
case registryCategoryId('labs'):
|
|
36
|
-
return ({ meta }) => meta.tags?.includes('labs') ?? false;
|
|
37
|
+
return ({ meta }) => meta.profile.tags?.includes('labs') ?? false;
|
|
37
38
|
default:
|
|
38
39
|
return () => false;
|
|
39
40
|
}
|
package/src/commands/index.ts
CHANGED
|
@@ -2,13 +2,5 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { disable } from './disable';
|
|
8
|
-
import { enable } from './enable';
|
|
9
|
-
import { list } from './list';
|
|
10
|
-
|
|
11
|
-
export const plugin: Command.Command<any, any, any, any> = Command.make('plugin').pipe(
|
|
12
|
-
Command.withDescription('Manage plugins.'),
|
|
13
|
-
Command.withSubcommands([enable, disable, list]),
|
|
14
|
-
);
|
|
5
|
+
export * from './plugin';
|
|
6
|
+
export * from './registry';
|
|
@@ -11,14 +11,14 @@ import { Plugin } from '@dxos/app-framework';
|
|
|
11
11
|
import { CommandConfig } from '@dxos/cli-util';
|
|
12
12
|
import { invariant } from '@dxos/invariant';
|
|
13
13
|
|
|
14
|
-
import { saveEnabledPlugins } from '
|
|
14
|
+
import { saveEnabledPlugins } from '../../storage';
|
|
15
15
|
|
|
16
16
|
export const handler = Effect.fn(function* ({ id }: { id: string }) {
|
|
17
17
|
const { json, profile } = yield* CommandConfig;
|
|
18
18
|
const manager = yield* Plugin.Service;
|
|
19
19
|
|
|
20
20
|
const plugins = manager.getPlugins();
|
|
21
|
-
const plugin = plugins.find((p: Plugin.Plugin) => p.meta.
|
|
21
|
+
const plugin = plugins.find((p: Plugin.Plugin) => p.meta.profile.key === id);
|
|
22
22
|
invariant(plugin, `Plugin not found: ${id}`);
|
|
23
23
|
|
|
24
24
|
const core = manager.getCore();
|
|
@@ -34,7 +34,7 @@ export const handler = Effect.fn(function* ({ id }: { id: string }) {
|
|
|
34
34
|
if (json) {
|
|
35
35
|
yield* Console.log(JSON.stringify({ id, enabled: false }, null, 2));
|
|
36
36
|
} else {
|
|
37
|
-
yield* Console.log(`Plugin "${plugin.meta.name ?? id}" disabled.`);
|
|
37
|
+
yield* Console.log(`Plugin "${plugin.meta.profile.name ?? id}" disabled.`);
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -11,14 +11,14 @@ import { Plugin } from '@dxos/app-framework';
|
|
|
11
11
|
import { CommandConfig } from '@dxos/cli-util';
|
|
12
12
|
import { invariant } from '@dxos/invariant';
|
|
13
13
|
|
|
14
|
-
import { saveEnabledPlugins } from '
|
|
14
|
+
import { saveEnabledPlugins } from '../../storage';
|
|
15
15
|
|
|
16
16
|
export const handler = Effect.fn(function* ({ id }: { id: string }) {
|
|
17
17
|
const { json, profile } = yield* CommandConfig;
|
|
18
18
|
const manager = yield* Plugin.Service;
|
|
19
19
|
|
|
20
20
|
const plugins = manager.getPlugins();
|
|
21
|
-
const plugin = plugins.find((p: Plugin.Plugin) => p.meta.
|
|
21
|
+
const plugin = plugins.find((p: Plugin.Plugin) => p.meta.profile.key === id);
|
|
22
22
|
invariant(plugin, `Plugin not found: ${id}`);
|
|
23
23
|
|
|
24
24
|
const enabled = yield* manager.enable(id);
|
|
@@ -31,7 +31,7 @@ export const handler = Effect.fn(function* ({ id }: { id: string }) {
|
|
|
31
31
|
if (json) {
|
|
32
32
|
yield* Console.log(JSON.stringify({ id, enabled: true }, null, 2));
|
|
33
33
|
} else {
|
|
34
|
-
yield* Console.log(`Plugin "${plugin.meta.name ?? id}" enabled.`);
|
|
34
|
+
yield* Console.log(`Plugin "${plugin.meta.profile.name ?? id}" enabled.`);
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Command from '@effect/cli/Command';
|
|
6
|
+
|
|
7
|
+
import { disable } from './disable';
|
|
8
|
+
import { enable } from './enable';
|
|
9
|
+
import { list } from './list';
|
|
10
|
+
|
|
11
|
+
export const plugin: Command.Command<any, any, any, any> = Command.make('plugin').pipe(
|
|
12
|
+
Command.withDescription('Manage plugins.'),
|
|
13
|
+
Command.withSubcommands([enable, disable, list]),
|
|
14
|
+
);
|
|
@@ -20,11 +20,11 @@ export const handler = Effect.fn(function* () {
|
|
|
20
20
|
const core = manager.getCore();
|
|
21
21
|
|
|
22
22
|
const formattedPlugins: FormattedPlugin[] = plugins.map((plugin: Plugin.Plugin) => {
|
|
23
|
-
const isEnabled = enabled.includes(plugin.meta.
|
|
24
|
-
const isCore = core.includes(plugin.meta.
|
|
23
|
+
const isEnabled = enabled.includes(plugin.meta.profile.key);
|
|
24
|
+
const isCore = core.includes(plugin.meta.profile.key);
|
|
25
25
|
return {
|
|
26
|
-
id: plugin.meta.
|
|
27
|
-
name: plugin.meta.name ?? plugin.meta.
|
|
26
|
+
id: plugin.meta.profile.key,
|
|
27
|
+
name: plugin.meta.profile.name ?? plugin.meta.profile.key,
|
|
28
28
|
enabled: isEnabled,
|
|
29
29
|
core: isCore,
|
|
30
30
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Command from '@effect/cli/Command';
|
|
6
|
+
|
|
7
|
+
import { publish } from './publish';
|
|
8
|
+
import { publishPackage } from './publish-package';
|
|
9
|
+
import { publishPublisher } from './publish-publisher';
|
|
10
|
+
import { records } from './records';
|
|
11
|
+
import { unpublish } from './unpublish';
|
|
12
|
+
import { verify } from './verify';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `dx registry *` — commands for publishing and inspecting records that the
|
|
16
|
+
* DXOS plugin registry indexes from AT Protocol. Auth uses an App Password
|
|
17
|
+
* (per-user secret minted at https://bsky.app/settings/app-passwords); OAuth
|
|
18
|
+
* support is a follow-up.
|
|
19
|
+
*
|
|
20
|
+
* - `publish` — config-driven: build from dx.yml, host the bundle, write records.
|
|
21
|
+
* - `publish-package` — low-level: write profile + release records from flags.
|
|
22
|
+
* - `publish-publisher` — write the publisher's own profile record.
|
|
23
|
+
* - `unpublish` — remove a package (profile + releases) from your PDS.
|
|
24
|
+
* - `verify` — write a publisher.verification record (indexed only from the configured verifier).
|
|
25
|
+
* - `records` — list everything the authenticated repo has published under `org.dxos.experimental.*`.
|
|
26
|
+
*/
|
|
27
|
+
export const registry: Command.Command<any, any, any, any> = Command.make('registry').pipe(
|
|
28
|
+
Command.withDescription('Publish to and inspect the AT Protocol-backed DXOS plugin registry.'),
|
|
29
|
+
Command.withSubcommands([publish, publishPackage, publishPublisher, unpublish, verify, records]),
|
|
30
|
+
);
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Command from '@effect/cli/Command';
|
|
6
|
+
import * as Options from '@effect/cli/Options';
|
|
7
|
+
import * as FetchHttpClient from '@effect/platform/FetchHttpClient';
|
|
8
|
+
import * as Console from 'effect/Console';
|
|
9
|
+
import * as Effect from 'effect/Effect';
|
|
10
|
+
import * as Function from 'effect/Function';
|
|
11
|
+
import * as Option from 'effect/Option';
|
|
12
|
+
|
|
13
|
+
import { ClientService } from '@dxos/client';
|
|
14
|
+
import { type PluginProfile, type PluginRelease } from '@dxos/protocols';
|
|
15
|
+
|
|
16
|
+
import { AUTH_OPTION_DESCRIPTIONS, NSID, putRecord, resolveSession } from './util';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* `dx registry publish-package` — publishes both the mutable
|
|
20
|
+
* `package.profile` (rkey = key) and a `package.release`
|
|
21
|
+
* (rkey = `<key>:<version>`) record to the authenticated user's PDS.
|
|
22
|
+
*
|
|
23
|
+
* The two writes are independent `putRecord` (upsert) calls; if the second fails the
|
|
24
|
+
* first is left in place (the indexer treats a profile with no releases as
|
|
25
|
+
* present-but-unpublishable, so a half-success is benign). Releases are conceptually
|
|
26
|
+
* single-write per version but not enforced — see docs/registry-spec.md (Integrity).
|
|
27
|
+
*/
|
|
28
|
+
export const publishPackage = Command.make(
|
|
29
|
+
'publish-package',
|
|
30
|
+
{
|
|
31
|
+
handle: Options.text('handle').pipe(Options.withDescription(AUTH_OPTION_DESCRIPTIONS.handle), Options.optional),
|
|
32
|
+
appPassword: Options.text('app-password').pipe(
|
|
33
|
+
Options.withDescription(AUTH_OPTION_DESCRIPTIONS.appPassword),
|
|
34
|
+
Options.optional,
|
|
35
|
+
),
|
|
36
|
+
key: Options.text('key').pipe(
|
|
37
|
+
Options.withDescription(
|
|
38
|
+
'Plugin key — a reverse-domain NSID (e.g. org.dxos.plugin.excalidraw); also the profile record rkey.',
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
name: Options.text('name').pipe(Options.withDescription('Human-readable package name.')),
|
|
42
|
+
description: Options.text('description').pipe(
|
|
43
|
+
Options.withDescription('Short description shown in the registry.'),
|
|
44
|
+
Options.withDefault(''),
|
|
45
|
+
),
|
|
46
|
+
version: Options.text('version').pipe(
|
|
47
|
+
Options.withDescription('Semver version (no build metadata). The release rkey is `<key>:<version>`.'),
|
|
48
|
+
),
|
|
49
|
+
moduleUrl: Options.text('module-url').pipe(
|
|
50
|
+
Options.withDescription('HTTPS URL to the bundle or manifest for this release.'),
|
|
51
|
+
),
|
|
52
|
+
homepage: Options.text('homepage').pipe(Options.withDescription('Homepage URL.'), Options.optional),
|
|
53
|
+
source: Options.text('source').pipe(Options.withDescription('Source repository URL.'), Options.optional),
|
|
54
|
+
tag: Options.text('tag').pipe(
|
|
55
|
+
Options.withDescription('Tag (repeatable). Categorizes the package for discovery.'),
|
|
56
|
+
Options.repeated,
|
|
57
|
+
),
|
|
58
|
+
iconKey: Options.text('icon-key').pipe(
|
|
59
|
+
Options.withDescription('Icon identifier (e.g. ph--sparkle--regular) resolvable by @ch-ui/icons.'),
|
|
60
|
+
Options.optional,
|
|
61
|
+
),
|
|
62
|
+
iconHue: Options.text('icon-hue').pipe(Options.withDescription('Icon palette hue (e.g. blue).'), Options.optional),
|
|
63
|
+
manifestHash: Options.text('manifest-hash').pipe(
|
|
64
|
+
Options.withDescription('Optional content hash for the bundle/manifest.'),
|
|
65
|
+
Options.optional,
|
|
66
|
+
),
|
|
67
|
+
},
|
|
68
|
+
(options) =>
|
|
69
|
+
Function.pipe(
|
|
70
|
+
Effect.gen(function* () {
|
|
71
|
+
const client = yield* ClientService;
|
|
72
|
+
const session = yield* resolveSession({
|
|
73
|
+
handle: Option.getOrUndefined(options.handle),
|
|
74
|
+
appPassword: Option.getOrUndefined(options.appPassword),
|
|
75
|
+
client,
|
|
76
|
+
});
|
|
77
|
+
const createdAt = new Date().toISOString();
|
|
78
|
+
|
|
79
|
+
const homepage = Option.getOrUndefined(options.homepage);
|
|
80
|
+
const source = Option.getOrUndefined(options.source);
|
|
81
|
+
const iconKey = Option.getOrUndefined(options.iconKey);
|
|
82
|
+
const iconHue = Option.getOrUndefined(options.iconHue);
|
|
83
|
+
const icon =
|
|
84
|
+
iconKey !== undefined ? { key: iconKey, ...(iconHue !== undefined && { hue: iconHue }) } : undefined;
|
|
85
|
+
|
|
86
|
+
const profile: PluginProfile & { createdAt: string } = {
|
|
87
|
+
key: options.key,
|
|
88
|
+
name: options.name,
|
|
89
|
+
...(options.description.length > 0 && { description: options.description }),
|
|
90
|
+
...(homepage !== undefined && { homePage: homepage }),
|
|
91
|
+
...(source !== undefined && { source }),
|
|
92
|
+
...(options.tag.length > 0 && { tags: options.tag }),
|
|
93
|
+
...(icon !== undefined && { icon }),
|
|
94
|
+
createdAt,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const profileResult = yield* putRecord(session, NSID.PackageProfile, options.key, profile);
|
|
98
|
+
yield* Console.log(`Profile ${profileResult.uri}`);
|
|
99
|
+
|
|
100
|
+
const manifestHash = Option.getOrUndefined(options.manifestHash);
|
|
101
|
+
const release: PluginRelease & { package: string; createdAt: string } = {
|
|
102
|
+
package: options.key,
|
|
103
|
+
version: options.version,
|
|
104
|
+
moduleUrl: options.moduleUrl,
|
|
105
|
+
createdAt,
|
|
106
|
+
...(manifestHash !== undefined && { manifestHash }),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const releaseResult = yield* putRecord(
|
|
110
|
+
session,
|
|
111
|
+
NSID.PackageRelease,
|
|
112
|
+
`${options.key}:${options.version}`,
|
|
113
|
+
release,
|
|
114
|
+
);
|
|
115
|
+
yield* Console.log(`Release ${releaseResult.uri}`);
|
|
116
|
+
}),
|
|
117
|
+
Effect.provide(FetchHttpClient.layer),
|
|
118
|
+
),
|
|
119
|
+
).pipe(Command.withDescription("Publish a package profile + release to the authenticated user's PDS."));
|