@dxos/plugin-wnfs 0.8.4-main.70d3990 → 0.8.4-main.74a063c4e0

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 (144) hide show
  1. package/dist/lib/browser/chunk-BM3MEFES.mjs +69 -0
  2. package/dist/lib/browser/chunk-BM3MEFES.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-D6VTEQIE.mjs → chunk-N6Y4QPNF.mjs} +23 -32
  4. package/dist/lib/browser/chunk-N6Y4QPNF.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-VXUCZHVZ.mjs +69 -0
  6. package/dist/lib/browser/chunk-VXUCZHVZ.mjs.map +7 -0
  7. package/dist/lib/browser/create-NOHKWE67.mjs +24 -0
  8. package/dist/lib/browser/create-NOHKWE67.mjs.map +7 -0
  9. package/dist/lib/browser/create-file-N7ADCFOF.mjs +49 -0
  10. package/dist/lib/browser/create-file-N7ADCFOF.mjs.map +7 -0
  11. package/dist/lib/browser/index.mjs +92 -90
  12. package/dist/lib/browser/index.mjs.map +4 -4
  13. package/dist/lib/browser/meta.json +1 -1
  14. package/dist/lib/browser/operations/index.mjs +13 -0
  15. package/dist/lib/browser/operations/index.mjs.map +7 -0
  16. package/dist/lib/browser/types/index.mjs +4 -3
  17. package/dist/lib/browser/upload-DA7GBOXF.mjs +42 -0
  18. package/dist/lib/browser/upload-DA7GBOXF.mjs.map +7 -0
  19. package/dist/types/src/WnfsPlugin.d.ts +2 -1
  20. package/dist/types/src/WnfsPlugin.d.ts.map +1 -1
  21. package/dist/types/src/capabilities/blockstore.d.ts +3 -2
  22. package/dist/types/src/capabilities/blockstore.d.ts.map +1 -1
  23. package/dist/types/src/capabilities/file-uploader.d.ts +4 -2
  24. package/dist/types/src/capabilities/file-uploader.d.ts.map +1 -1
  25. package/dist/types/src/capabilities/index.d.ts +7 -6
  26. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  27. package/dist/types/src/capabilities/markdown.d.ts +3 -2
  28. package/dist/types/src/capabilities/markdown.d.ts.map +1 -1
  29. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  30. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  31. package/dist/types/src/capabilities/react-surface.d.ts +3 -2
  32. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  33. package/dist/types/src/components/FileInput/FileInput.d.ts.map +1 -0
  34. package/dist/types/src/components/FileInput/index.d.ts +2 -0
  35. package/dist/types/src/components/FileInput/index.d.ts.map +1 -0
  36. package/dist/types/src/components/FilePreview/FilePreview.d.ts +16 -0
  37. package/dist/types/src/components/FilePreview/FilePreview.d.ts.map +1 -0
  38. package/dist/types/src/components/FilePreview/index.d.ts +2 -0
  39. package/dist/types/src/components/FilePreview/index.d.ts.map +1 -0
  40. package/dist/types/src/components/index.d.ts +1 -1
  41. package/dist/types/src/components/index.d.ts.map +1 -1
  42. package/dist/types/src/containers/FileContainer/FileContainer.d.ts +7 -0
  43. package/dist/types/src/containers/FileContainer/FileContainer.d.ts.map +1 -0
  44. package/dist/types/src/containers/FileContainer/index.d.ts +2 -0
  45. package/dist/types/src/containers/FileContainer/index.d.ts.map +1 -0
  46. package/dist/types/src/containers/index.d.ts +3 -0
  47. package/dist/types/src/containers/index.d.ts.map +1 -0
  48. package/dist/types/src/extensions/image.d.ts +1 -1
  49. package/dist/types/src/extensions/image.d.ts.map +1 -1
  50. package/dist/types/src/extensions/image.stories.d.ts.map +1 -1
  51. package/dist/types/src/helpers/load.d.ts +1 -1
  52. package/dist/types/src/helpers/load.d.ts.map +1 -1
  53. package/dist/types/src/helpers/upload.d.ts +1 -1
  54. package/dist/types/src/helpers/upload.d.ts.map +1 -1
  55. package/dist/types/src/index.d.ts +1 -1
  56. package/dist/types/src/index.d.ts.map +1 -1
  57. package/dist/types/src/meta.d.ts +2 -2
  58. package/dist/types/src/meta.d.ts.map +1 -1
  59. package/dist/types/src/operations/create-file.d.ts +5 -0
  60. package/dist/types/src/operations/create-file.d.ts.map +1 -0
  61. package/dist/types/src/operations/create.d.ts +5 -0
  62. package/dist/types/src/operations/create.d.ts.map +1 -0
  63. package/dist/types/src/operations/definitions.d.ts +38 -0
  64. package/dist/types/src/operations/definitions.d.ts.map +1 -0
  65. package/dist/types/src/operations/index.d.ts +4 -0
  66. package/dist/types/src/operations/index.d.ts.map +1 -0
  67. package/dist/types/src/operations/upload.d.ts +5 -0
  68. package/dist/types/src/operations/upload.d.ts.map +1 -0
  69. package/dist/types/src/translations.d.ts +13 -9
  70. package/dist/types/src/translations.d.ts.map +1 -1
  71. package/dist/types/src/types/File.d.ts +11 -11
  72. package/dist/types/src/types/File.d.ts.map +1 -1
  73. package/dist/types/src/{capabilities → types}/capabilities.d.ts +3 -2
  74. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  75. package/dist/types/src/types/index.d.ts +1 -0
  76. package/dist/types/src/types/index.d.ts.map +1 -1
  77. package/dist/types/src/types/types.d.ts +4 -50
  78. package/dist/types/src/types/types.d.ts.map +1 -1
  79. package/dist/types/tsconfig.tsbuildinfo +1 -1
  80. package/package.json +59 -36
  81. package/src/WnfsPlugin.tsx +53 -67
  82. package/src/blockstore.ts +1 -1
  83. package/src/capabilities/blockstore.ts +15 -11
  84. package/src/capabilities/file-uploader.ts +24 -17
  85. package/src/capabilities/index.ts +10 -8
  86. package/src/capabilities/markdown.ts +22 -14
  87. package/src/capabilities/operation-handler.ts +16 -0
  88. package/src/capabilities/react-surface.tsx +40 -34
  89. package/src/components/{FileInput.tsx → FileInput/FileInput.tsx} +6 -6
  90. package/src/components/FileInput/index.ts +5 -0
  91. package/src/components/FilePreview/FilePreview.tsx +43 -0
  92. package/src/components/FilePreview/index.ts +5 -0
  93. package/src/components/index.ts +1 -4
  94. package/src/{components → containers/FileContainer}/FileContainer.tsx +13 -15
  95. package/src/containers/FileContainer/index.ts +5 -0
  96. package/src/containers/index.ts +7 -0
  97. package/src/extensions/image.stories.tsx +8 -9
  98. package/src/extensions/image.tsx +4 -3
  99. package/src/helpers/load.ts +12 -7
  100. package/src/helpers/upload.ts +5 -2
  101. package/src/index.ts +1 -1
  102. package/src/meta.ts +3 -3
  103. package/src/operations/create-file.ts +31 -0
  104. package/src/operations/create.ts +22 -0
  105. package/src/operations/definitions.ts +41 -0
  106. package/src/operations/index.ts +13 -0
  107. package/src/operations/upload.ts +29 -0
  108. package/src/translations.ts +13 -9
  109. package/src/types/File.ts +7 -3
  110. package/src/{capabilities → types}/capabilities.ts +4 -4
  111. package/src/types/index.ts +1 -0
  112. package/src/types/types.ts +3 -20
  113. package/dist/lib/browser/FileContainer-6JIJX7SN.mjs +0 -103
  114. package/dist/lib/browser/FileContainer-6JIJX7SN.mjs.map +0 -7
  115. package/dist/lib/browser/blockstore-2JFU4NBU.mjs +0 -191
  116. package/dist/lib/browser/blockstore-2JFU4NBU.mjs.map +0 -7
  117. package/dist/lib/browser/chunk-234GILVK.mjs +0 -71
  118. package/dist/lib/browser/chunk-234GILVK.mjs.map +0 -7
  119. package/dist/lib/browser/chunk-D6VTEQIE.mjs.map +0 -7
  120. package/dist/lib/browser/chunk-F4QHZWQD.mjs +0 -16
  121. package/dist/lib/browser/chunk-F4QHZWQD.mjs.map +0 -7
  122. package/dist/lib/browser/chunk-IVUX2QXX.mjs +0 -16
  123. package/dist/lib/browser/chunk-IVUX2QXX.mjs.map +0 -7
  124. package/dist/lib/browser/chunk-OGPGLJCV.mjs +0 -25
  125. package/dist/lib/browser/chunk-OGPGLJCV.mjs.map +0 -7
  126. package/dist/lib/browser/file-uploader-APZNBT66.mjs +0 -30
  127. package/dist/lib/browser/file-uploader-APZNBT66.mjs.map +0 -7
  128. package/dist/lib/browser/intent-resolver-246R4ETC.mjs +0 -48
  129. package/dist/lib/browser/intent-resolver-246R4ETC.mjs.map +0 -7
  130. package/dist/lib/browser/markdown-WYQDCVFQ.mjs +0 -198
  131. package/dist/lib/browser/markdown-WYQDCVFQ.mjs.map +0 -7
  132. package/dist/lib/browser/react-surface-CGF34KPI.mjs +0 -88
  133. package/dist/lib/browser/react-surface-CGF34KPI.mjs.map +0 -7
  134. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  135. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  136. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  137. package/dist/types/src/components/FileContainer.d.ts +0 -9
  138. package/dist/types/src/components/FileContainer.d.ts.map +0 -1
  139. package/dist/types/src/components/FileInput.d.ts.map +0 -1
  140. package/dist/types/src/components/FilePreview.d.ts +0 -11
  141. package/dist/types/src/components/FilePreview.d.ts.map +0 -1
  142. package/src/capabilities/intent-resolver.ts +0 -32
  143. package/src/components/FilePreview.tsx +0 -23
  144. /package/dist/types/src/components/{FileInput.d.ts → FileInput/FileInput.d.ts} +0 -0
package/package.json CHANGED
@@ -1,22 +1,39 @@
1
1
  {
2
2
  "name": "@dxos/plugin-wnfs",
3
- "version": "0.8.4-main.70d3990",
3
+ "version": "0.8.4-main.74a063c4e0",
4
4
  "description": "WNFS file management plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
7
11
  "license": "MIT",
8
12
  "author": "DXOS.org",
9
13
  "type": "module",
14
+ "imports": {
15
+ "#capabilities": "./src/capabilities/index.ts",
16
+ "#components": "./src/components/index.ts",
17
+ "#containers": "./src/containers/index.ts",
18
+ "#meta": "./src/meta.ts",
19
+ "#operations": "./src/operations/index.ts",
20
+ "#types": "./src/types/index.ts"
21
+ },
10
22
  "exports": {
11
23
  ".": {
12
24
  "source": "./src/index.ts",
13
- "types": "./dist/types/src/index.d.ts",
14
- "browser": "./dist/lib/browser/index.mjs"
25
+ "browser": "./dist/lib/browser/index.mjs",
26
+ "types": "./dist/types/src/index.d.ts"
27
+ },
28
+ "./operations": {
29
+ "source": "./src/operations/index.ts",
30
+ "browser": "./dist/lib/browser/operations/index.mjs",
31
+ "types": "./dist/types/src/operations/index.d.ts"
15
32
  },
16
33
  "./types": {
17
34
  "source": "./src/types/index.ts",
18
- "types": "./dist/types/src/types/index.d.ts",
19
- "browser": "./dist/lib/browser/types/index.mjs"
35
+ "browser": "./dist/lib/browser/types/index.mjs",
36
+ "types": "./dist/types/src/types/index.d.ts"
20
37
  }
21
38
  },
22
39
  "types": "dist/types/src/index.d.ts",
@@ -24,6 +41,9 @@
24
41
  "*": {
25
42
  "types": [
26
43
  "dist/types/src/types/index.d.ts"
44
+ ],
45
+ "operations": [
46
+ "dist/types/src/operations/index.d.ts"
27
47
  ]
28
48
  }
29
49
  },
@@ -36,11 +56,10 @@
36
56
  "@codemirror/state": "^6.5.2",
37
57
  "@codemirror/view": "^6.38.4",
38
58
  "@ipld/car": "^5.3.3",
39
- "@preact-signals/safe-react": "^0.9.0",
40
59
  "blockstore-core": "^5.0.1",
41
60
  "blockstore-idb": "^2.0.0",
42
61
  "debounce": "^2.2.0",
43
- "effect": "3.18.3",
62
+ "effect": "3.20.0",
44
63
  "idb-keyval": "^6.2.1",
45
64
  "interface-blockstore": "^5.2.10",
46
65
  "it-all": "^3.0.6",
@@ -48,39 +67,43 @@
48
67
  "react-dropzone": "^14.2.3",
49
68
  "uint8arrays": "^5.1.0",
50
69
  "wnfs": "0.2.2",
51
- "@dxos/crypto": "0.8.4-main.70d3990",
52
- "@dxos/app-framework": "0.8.4-main.70d3990",
53
- "@dxos/echo": "0.8.4-main.70d3990",
54
- "@dxos/effect": "0.8.4-main.70d3990",
55
- "@dxos/local-storage": "0.8.4-main.70d3990",
56
- "@dxos/invariant": "0.8.4-main.70d3990",
57
- "@dxos/log": "0.8.4-main.70d3990",
58
- "@dxos/plugin-client": "0.8.4-main.70d3990",
59
- "@dxos/plugin-space": "0.8.4-main.70d3990",
60
- "@dxos/plugin-markdown": "0.8.4-main.70d3990",
61
- "@dxos/react-client": "0.8.4-main.70d3990",
62
- "@dxos/react-ui": "0.8.4-main.70d3990",
63
- "@dxos/react-ui-stack": "0.8.4-main.70d3990",
64
- "@dxos/react-ui-editor": "0.8.4-main.70d3990",
65
- "@dxos/react-ui-form": "0.8.4-main.70d3990",
66
- "@dxos/util": "0.8.4-main.70d3990"
70
+ "@dxos/crypto": "0.8.4-main.74a063c4e0",
71
+ "@dxos/app-toolkit": "0.8.4-main.74a063c4e0",
72
+ "@dxos/app-framework": "0.8.4-main.74a063c4e0",
73
+ "@dxos/echo": "0.8.4-main.74a063c4e0",
74
+ "@dxos/invariant": "0.8.4-main.74a063c4e0",
75
+ "@dxos/log": "0.8.4-main.74a063c4e0",
76
+ "@dxos/operation": "0.8.4-main.74a063c4e0",
77
+ "@dxos/plugin-client": "0.8.4-main.74a063c4e0",
78
+ "@dxos/effect": "0.8.4-main.74a063c4e0",
79
+ "@dxos/react-client": "0.8.4-main.74a063c4e0",
80
+ "@dxos/plugin-space": "0.8.4-main.74a063c4e0",
81
+ "@dxos/react-ui": "0.8.4-main.74a063c4e0",
82
+ "@dxos/react-ui-mosaic": "0.8.4-main.74a063c4e0",
83
+ "@dxos/react-ui-editor": "0.8.4-main.74a063c4e0",
84
+ "@dxos/react-ui-form": "0.8.4-main.74a063c4e0",
85
+ "@dxos/react-ui-stack": "0.8.4-main.74a063c4e0",
86
+ "@dxos/ui-editor": "0.8.4-main.74a063c4e0",
87
+ "@dxos/schema": "0.8.4-main.74a063c4e0",
88
+ "@dxos/util": "0.8.4-main.74a063c4e0",
89
+ "@dxos/plugin-markdown": "0.8.4-main.74a063c4e0"
67
90
  },
68
91
  "devDependencies": {
69
- "@types/react": "~19.2.2",
70
- "@types/react-dom": "~19.2.2",
71
- "react": "~19.2.0",
72
- "react-dom": "~19.2.0",
73
- "vite": "7.1.9",
74
- "@dxos/random": "0.8.4-main.70d3990",
75
- "@dxos/react-ui-theme": "0.8.4-main.70d3990",
76
- "@dxos/storybook-utils": "0.8.4-main.70d3990"
92
+ "@types/react": "~19.2.7",
93
+ "@types/react-dom": "~19.2.3",
94
+ "react": "~19.2.3",
95
+ "react-dom": "~19.2.3",
96
+ "vite": "^7.1.11",
97
+ "@dxos/storybook-utils": "0.8.4-main.74a063c4e0",
98
+ "@dxos/ui-theme": "0.8.4-main.74a063c4e0",
99
+ "@dxos/random": "0.8.4-main.74a063c4e0"
77
100
  },
78
101
  "peerDependencies": {
79
- "effect": "^3.13.3",
80
- "react": "^19.0.0",
81
- "react-dom": "^19.0.0",
82
- "@dxos/react-ui": "0.8.4-main.70d3990",
83
- "@dxos/react-ui-theme": "0.8.4-main.70d3990"
102
+ "effect": "3.20.0",
103
+ "react": "~19.2.3",
104
+ "react-dom": "~19.2.3",
105
+ "@dxos/react-ui": "0.8.4-main.74a063c4e0",
106
+ "@dxos/ui-theme": "0.8.4-main.74a063c4e0"
84
107
  },
85
108
  "publishConfig": {
86
109
  "access": "public"
@@ -2,88 +2,74 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as Function from 'effect/Function';
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Option from 'effect/Option';
6
7
 
7
- import {
8
- Capabilities,
9
- Events,
10
- chain,
11
- contributes,
12
- createIntent,
13
- defineModule,
14
- definePlugin,
15
- } from '@dxos/app-framework';
16
- import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
8
+ import { Capability, Plugin } from '@dxos/app-framework';
9
+ import { AppPlugin } from '@dxos/app-toolkit';
10
+ import { Annotation } from '@dxos/echo';
11
+ import { Operation } from '@dxos/operation';
12
+ import { ClientEvents } from '@dxos/plugin-client/types';
17
13
  import { MarkdownEvents } from '@dxos/plugin-markdown';
18
- import { type CreateObjectIntent } from '@dxos/plugin-space/types';
14
+ import { SpaceOperation } from '@dxos/plugin-space/operations';
15
+ import { type CreateObject } from '@dxos/plugin-space/types';
16
+
17
+ import { Blockstore, FileUploader, Markdown, OperationHandler, ReactSurface } from '#capabilities';
18
+ import { meta } from '#meta';
19
+ import { WnfsOperation } from '#operations';
20
+ import { WnfsAction, WnfsCapabilities, WnfsFile } from '#types';
19
21
 
20
- import { Blockstore, FileUploader, IntentResolver, Markdown, ReactSurface, WnfsCapabilities } from './capabilities';
21
- import { meta } from './meta';
22
22
  import { translations } from './translations';
23
- import { WnfsAction, WnfsFile } from './types';
24
23
 
25
- export const WnfsPlugin = definePlugin(meta, () => [
26
- defineModule({
27
- id: `${meta.id}/module/blockstore`,
24
+ export const WnfsPlugin = Plugin.define(meta).pipe(
25
+ AppPlugin.addMetadataModule({
26
+ metadata: {
27
+ id: WnfsFile.File.typename,
28
+ metadata: {
29
+ // TODO(wittjosiah): Would be nice if icon could change based on the type of the file.
30
+ icon: Annotation.IconAnnotation.get(WnfsFile.File).pipe(Option.getOrThrow).icon,
31
+ iconHue: Annotation.IconAnnotation.get(WnfsFile.File).pipe(Option.getOrThrow).hue ?? 'white',
32
+ inputSchema: WnfsAction.UploadFileSchema,
33
+ createObject: ((props, options) =>
34
+ Effect.gen(function* () {
35
+ const { object } = yield* Operation.invoke(WnfsOperation.CreateFile, { ...props, db: options.db });
36
+ return yield* Operation.invoke(SpaceOperation.AddObject, {
37
+ object,
38
+ target: options.target,
39
+ hidden: true,
40
+ targetNodeId: options.targetNodeId,
41
+ });
42
+ })) satisfies CreateObject,
43
+ },
44
+ },
45
+ }),
46
+ AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),
47
+ AppPlugin.addSchemaModule({ schema: [WnfsFile.File] }),
48
+ AppPlugin.addSurfaceModule({ activate: ReactSurface }),
49
+ AppPlugin.addTranslationsModule({ translations }),
50
+ Plugin.addModule({
51
+ id: 'blockstore',
28
52
  activatesOn: ClientEvents.ClientReady,
29
53
  activate: Blockstore,
30
54
  }),
31
- defineModule({
32
- id: `${meta.id}/module/instances`,
55
+ Plugin.addModule({
56
+ id: 'instances',
33
57
  activatesOn: ClientEvents.ClientReady,
34
- activate: () => {
35
- const instances: WnfsCapabilities.Instances = {};
36
- return contributes(WnfsCapabilities.Instances, instances);
37
- },
38
- }),
39
- defineModule({
40
- id: `${meta.id}/module/translations`,
41
- activatesOn: Events.SetupTranslations,
42
- activate: () => contributes(Capabilities.Translations, translations),
43
- }),
44
- defineModule({
45
- id: `${meta.id}/module/metadata`,
46
- activatesOn: Events.SetupMetadata,
47
58
  activate: () =>
48
- contributes(Capabilities.Metadata, {
49
- id: WnfsFile.File.typename,
50
- metadata: {
51
- // TODO(wittjosiah): Would be nice if icon could change based on the type of the file.
52
- icon: 'ph--file--regular',
53
- iconHue: 'teal',
54
- inputSchema: WnfsAction.UploadFileSchema,
55
- createObjectIntent: ((props, options) =>
56
- Function.pipe(
57
- createIntent(WnfsAction.Upload, { ...props, space: options.space }),
58
- chain(WnfsAction.Create, {}),
59
- )) satisfies CreateObjectIntent,
60
- addToCollectionOnCreate: true,
61
- },
59
+ Effect.sync(() => {
60
+ const instances: WnfsCapabilities.Instances = {};
61
+ return Capability.contributes(WnfsCapabilities.Instances, instances);
62
62
  }),
63
63
  }),
64
- defineModule({
65
- id: `${meta.id}/module/schema`,
66
- activatesOn: ClientEvents.SetupSchema,
67
- activate: () => contributes(ClientCapabilities.Schema, [WnfsFile.File]),
68
- }),
69
- defineModule({
70
- id: `${meta.id}/module/file-uploader`,
64
+ Plugin.addModule({
65
+ id: 'file-uploader',
71
66
  activatesOn: ClientEvents.ClientReady,
72
67
  activate: FileUploader,
73
68
  }),
74
- defineModule({
75
- id: `${meta.id}/module/markdown`,
69
+ Plugin.addModule({
70
+ id: 'markdown',
76
71
  activatesOn: MarkdownEvents.SetupExtensions,
77
72
  activate: Markdown,
78
73
  }),
79
- defineModule({
80
- id: `${meta.id}/module/react-surface`,
81
- activatesOn: Events.SetupReactSurface,
82
- activate: ReactSurface,
83
- }),
84
- defineModule({
85
- id: `${meta.id}/module/intent-resolver`,
86
- activatesOn: Events.SetupIntentResolver,
87
- activate: IntentResolver,
88
- }),
89
- ]);
74
+ Plugin.make,
75
+ );
package/src/blockstore.ts CHANGED
@@ -145,7 +145,7 @@ export class MixedBlockstore extends BaseBlockstore {
145
145
 
146
146
  // QUEUE
147
147
 
148
- readonly queueCacheName = `${storeName()}/state/queue`;
148
+ readonly queueCacheName = `${storeName()}.state.queue`;
149
149
 
150
150
  async #addToQueue(key: CID): Promise<void> {
151
151
  await this.#saveQueue([...this.#queue, key.toString()]);
@@ -2,18 +2,22 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type PluginContext, contributes } from '@dxos/app-framework';
6
- import { ClientCapabilities } from '@dxos/plugin-client';
5
+ import * as Effect from 'effect/Effect';
7
6
 
8
- import * as Blockstore from '../blockstore';
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { ClientCapabilities } from '@dxos/plugin-client/types';
9
+
10
+ import { WnfsCapabilities } from '#types';
9
11
 
10
- import { WnfsCapabilities } from './capabilities';
12
+ import * as Blockstore from '../blockstore';
11
13
 
12
- export default async (context: PluginContext) => {
13
- const client = context.getCapability(ClientCapabilities.Client);
14
- const apiHost = client.config.values.runtime?.services?.edge?.url || 'http://localhost:8787';
15
- const blockstore = Blockstore.create(apiHost);
16
- await blockstore.open();
14
+ export default Capability.makeModule(
15
+ Effect.fnUntraced(function* () {
16
+ const client = yield* Capability.get(ClientCapabilities.Client);
17
+ const apiHost = client.config.values.runtime?.services?.edge?.url || 'http://localhost:8787';
18
+ const blockstore = Blockstore.create(apiHost);
19
+ yield* Effect.tryPromise(() => blockstore.open());
17
20
 
18
- return contributes(WnfsCapabilities.Blockstore, blockstore);
19
- };
21
+ return Capability.contributes(WnfsCapabilities.Blockstore, blockstore);
22
+ }),
23
+ );
@@ -3,25 +3,32 @@
3
3
  //
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
- import * as Function from 'effect/Function';
7
6
 
8
- import { Capabilities, type PluginContext, chain, contributes, createIntent } from '@dxos/app-framework';
9
- import { SpaceAction } from '@dxos/plugin-space/types';
7
+ import { Capabilities, Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities } from '@dxos/app-toolkit';
9
+ import { runAndForwardErrors } from '@dxos/effect';
10
+ import { SpaceOperation } from '@dxos/plugin-space/operations';
10
11
 
11
- import { WnfsAction } from '../types';
12
+ import { WnfsOperation } from '#operations';
12
13
 
13
- export default (context: PluginContext) => {
14
- return contributes(Capabilities.FileUploader, (space, file) => {
15
- const { dispatch } = context.getCapability(Capabilities.IntentDispatcher);
16
- const program = Effect.gen(function* () {
17
- const fileInfo = yield* dispatch(createIntent(WnfsAction.Upload, { space, file }));
18
- yield* dispatch(
19
- Function.pipe(createIntent(WnfsAction.Create, fileInfo), chain(SpaceAction.AddObject, { target: space })),
20
- );
14
+ export default Capability.makeModule(
15
+ Effect.fnUntraced(function* () {
16
+ // Get context for lazy capability access in callbacks.
17
+ const capabilities = yield* Capability.Service;
21
18
 
22
- return fileInfo;
23
- });
19
+ return Capability.contributes(AppCapabilities.FileUploader, (db, file) => {
20
+ const { invoke } = capabilities.get(Capabilities.OperationInvoker);
21
+ const program = Effect.gen(function* () {
22
+ const fileInfo = yield* invoke(WnfsOperation.Upload, { db, file });
23
+ const createResult = yield* invoke(WnfsOperation.Create, fileInfo);
24
+ if (createResult?.object) {
25
+ yield* invoke(SpaceOperation.AddObject, { target: db, object: createResult.object });
26
+ }
27
+
28
+ return fileInfo;
29
+ });
24
30
 
25
- return Effect.runPromise(program);
26
- });
27
- };
31
+ return runAndForwardErrors(program);
32
+ });
33
+ }),
34
+ );
@@ -2,12 +2,14 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { lazy } from '@dxos/app-framework';
5
+ import { Capability } from '@dxos/app-framework';
6
+ import { OperationHandlerSet } from '@dxos/operation';
6
7
 
7
- export const Blockstore = lazy(() => import('./blockstore'));
8
- export const FileUploader = lazy(() => import('./file-uploader'));
9
- export const IntentResolver = lazy(() => import('./intent-resolver'));
10
- export const Markdown = lazy(() => import('./markdown'));
11
- export const ReactSurface = lazy(() => import('./react-surface'));
12
-
13
- export * from './capabilities';
8
+ export const Blockstore = Capability.lazy('Blockstore', () => import('./blockstore'));
9
+ export const FileUploader = Capability.lazy('FileUploader', () => import('./file-uploader'));
10
+ export const Markdown = Capability.lazy('Markdown', () => import('./markdown'));
11
+ export const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(
12
+ 'OperationHandler',
13
+ () => import('./operation-handler'),
14
+ );
15
+ export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
@@ -2,25 +2,33 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type PluginContext, contributes } from '@dxos/app-framework';
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
6
8
  import { MarkdownCapabilities } from '@dxos/plugin-markdown';
7
9
  import { getSpace } from '@dxos/react-client/echo';
8
10
 
11
+ import { WnfsCapabilities } from '#types';
12
+
9
13
  import { image } from '../extensions';
10
14
 
11
- import { WnfsCapabilities } from './capabilities';
15
+ export default Capability.makeModule(
16
+ Effect.fnUntraced(function* () {
17
+ // Get context for lazy capability access in callbacks.
18
+ const capabilities = yield* Capability.Service;
12
19
 
13
- export default (context: PluginContext) =>
14
- contributes(MarkdownCapabilities.Extensions, [
15
- ({ document }) => {
16
- const blockstore = context.getCapability(WnfsCapabilities.Blockstore);
17
- const instances = context.getCapability(WnfsCapabilities.Instances);
20
+ return Capability.contributes(MarkdownCapabilities.Extensions, [
21
+ ({ document }: { document?: any }) => {
22
+ const blockstore = capabilities.get(WnfsCapabilities.Blockstore);
23
+ const instances = capabilities.get(WnfsCapabilities.Instances);
18
24
 
19
- if (document) {
20
- const space = getSpace(document);
21
- return space ? [image({ blockstore, instances, space })] : [];
22
- }
25
+ if (document) {
26
+ const space = getSpace(document);
27
+ return space ? [image({ blockstore, instances, space })] : [];
28
+ }
23
29
 
24
- return [];
25
- },
26
- ]);
30
+ return [];
31
+ },
32
+ ]);
33
+ }),
34
+ );
@@ -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/operation';
9
+
10
+ import { WnfsOperationHandlerSet } from '#operations';
11
+
12
+ export default Capability.makeModule<OperationHandlerSet.OperationHandlerSet>(
13
+ Effect.fnUntraced(function* () {
14
+ return Capability.contributes(Capabilities.OperationHandler, WnfsOperationHandlerSet);
15
+ }),
16
+ );
@@ -2,44 +2,50 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import * as Effect from 'effect/Effect';
5
6
  import type * as Schema from 'effect/Schema';
6
7
  import React, { useCallback } from 'react';
7
8
 
8
- import { Capabilities, contributes, createSurface } from '@dxos/app-framework';
9
- import { Obj } from '@dxos/echo';
9
+ import { Capabilities, Capability } from '@dxos/app-framework';
10
+ import { Surface } from '@dxos/app-framework/ui';
11
+ import { AppSurface } from '@dxos/app-toolkit/ui';
10
12
  import { findAnnotation } from '@dxos/effect';
11
- import { type InputProps } from '@dxos/react-ui-form';
13
+ import { type FormFieldComponentProps } from '@dxos/react-ui-form';
12
14
 
13
- import { FileContainer, FileInput } from '../components';
14
- import { meta } from '../meta';
15
- import { WnfsAction, WnfsFile } from '../types';
15
+ import { FileInput } from '#components';
16
+ import { FileContainer } from '#containers';
17
+ import { WnfsAction, WnfsFile } from '#types';
16
18
 
17
- export default () =>
18
- contributes(Capabilities.ReactSurface, [
19
- createSurface({
20
- id: `${meta.id}/article`,
21
- role: ['article', 'section', 'slide'],
22
- filter: (data): data is { subject: WnfsFile.File } => Obj.instanceOf(WnfsFile.File, data.subject),
23
- component: ({ data, role }) => <FileContainer role={role} file={data.subject} />,
24
- }),
25
- createSurface({
26
- id: `${meta.id}/create-form`,
27
- role: 'form-input',
28
- filter: (data): data is { prop: string; schema: Schema.Schema.Any } => {
29
- const annotation = findAnnotation<boolean>(
30
- (data.schema as Schema.Schema.All).ast,
31
- WnfsAction.UploadAnnotationId,
32
- );
33
- return !!annotation;
34
- },
35
- component: ({ data: { prop, schema }, ...props }) => {
36
- const inputProps = props as unknown as InputProps;
37
- const handleChange = useCallback(
38
- (file: File) => inputProps.onValueChange?.('object', file),
39
- [prop, inputProps.onValueChange],
40
- );
19
+ export default Capability.makeModule(() =>
20
+ Effect.succeed(
21
+ Capability.contributes(Capabilities.ReactSurface, [
22
+ Surface.create({
23
+ id: 'article',
24
+ // TODO(wittjosiah): Split into multiple surfaces if this filter proves too strict for non-article roles.
25
+ role: ['article', 'section', 'slide'],
26
+ filter: AppSurface.objectArticle(WnfsFile.File),
27
+ component: ({ data, role }) => <FileContainer role={role} subject={data.subject} />,
28
+ }),
29
+ Surface.create({
30
+ id: 'create-form',
31
+ role: 'form-input',
32
+ filter: (data): data is { prop: string; schema: Schema.Schema.Any } => {
33
+ const annotation = findAnnotation<boolean>(
34
+ (data.schema as Schema.Schema.All).ast,
35
+ WnfsAction.UploadAnnotationId,
36
+ );
37
+ return !!annotation;
38
+ },
39
+ component: ({ data: { schema }, ...props }) => {
40
+ const inputProps = props as unknown as FormFieldComponentProps;
41
+ const handleChange = useCallback(
42
+ (file: File) => inputProps.onValueChange?.(inputProps.type, file),
43
+ [inputProps.type, inputProps.onValueChange],
44
+ );
41
45
 
42
- return <FileInput schema={schema} onChange={handleChange} />;
43
- },
44
- }),
45
- ]);
46
+ return <FileInput schema={schema} onChange={handleChange} />;
47
+ },
48
+ }),
49
+ ]),
50
+ ),
51
+ );
@@ -8,10 +8,10 @@ import { useDropzone } from 'react-dropzone';
8
8
 
9
9
  import { findAnnotation } from '@dxos/effect';
10
10
  import { useTranslation } from '@dxos/react-ui';
11
- import { mx } from '@dxos/react-ui-theme';
11
+ import { mx } from '@dxos/ui-theme';
12
12
 
13
- import { meta } from '../meta';
14
- import { WnfsAction } from '../types';
13
+ import { meta } from '#meta';
14
+ import { WnfsAction } from '#types';
15
15
 
16
16
  export type FileInputProps = {
17
17
  schema: Schema.Schema.Any;
@@ -36,12 +36,12 @@ export const FileInput = ({ schema, onChange }: FileInputProps) => {
36
36
  className={mx(
37
37
  'flex flex-col items-center p-8 border border-separator',
38
38
  isFocused && 'focus-ring',
39
- isDragAccept && 'bg-attention',
40
- isDragReject && 'border-roseFill',
39
+ isDragAccept && 'bg-attention-surface',
40
+ isDragReject && 'border-rose-fill',
41
41
  )}
42
42
  >
43
43
  <input {...getInputProps()} />
44
- {acceptedFiles[0] ? <p>{acceptedFiles[0].name}</p> : <p>{t('file input placeholder')}</p>}
44
+ {acceptedFiles[0] ? <p>{acceptedFiles[0].name}</p> : <p>{t('file-input.placeholder')}</p>}
45
45
  </div>
46
46
  );
47
47
  };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './FileInput';
@@ -0,0 +1,43 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import React, { ForwardedRef } from 'react';
6
+
7
+ import { composable, composableProps } from '@dxos/ui-theme';
8
+
9
+ export type FilePreviewProps = { type: string; url: string };
10
+
11
+ /**
12
+ * File/content preview iframe.
13
+ */
14
+ export const FilePreview = composable<HTMLElement, FilePreviewProps>(
15
+ ({ type, url, children, ...props }, forwardedRef) => {
16
+ if (type.startsWith('image/')) {
17
+ return (
18
+ <img
19
+ {...composableProps(props, { classNames: 'h-full w-full object-contain' })}
20
+ src={url}
21
+ ref={forwardedRef as ForwardedRef<HTMLImageElement>}
22
+ />
23
+ );
24
+ } else if (type.startsWith('video/')) {
25
+ return (
26
+ <video
27
+ {...composableProps(props, { classNames: 'h-full w-full object-contain' })}
28
+ src={url}
29
+ controls
30
+ ref={forwardedRef as ForwardedRef<HTMLVideoElement>}
31
+ />
32
+ );
33
+ } else {
34
+ return (
35
+ <iframe
36
+ {...composableProps(props, { classNames: 'h-full w-full overflow-auto' })}
37
+ src={url}
38
+ ref={forwardedRef as ForwardedRef<HTMLIFrameElement>}
39
+ />
40
+ );
41
+ }
42
+ },
43
+ );
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export * from './FilePreview';