@dxos/plugin-registry 0.9.0 → 0.9.1-staging.ee54ba693a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/lib/neutral/RegistryPlugin.node.mjs +709 -18
  2. package/dist/lib/neutral/RegistryPlugin.node.mjs.map +4 -4
  3. package/dist/lib/neutral/chunk-ZY37XLVF.mjs +46 -0
  4. package/dist/lib/neutral/chunk-ZY37XLVF.mjs.map +7 -0
  5. package/dist/lib/neutral/index.mjs +1 -1
  6. package/dist/lib/neutral/meta.json +1 -1
  7. package/dist/lib/neutral/{open-plugin-registry-II735N76.mjs → open-plugin-registry-ID7LV3SF.mjs} +3 -3
  8. package/dist/lib/neutral/open-plugin-registry-ID7LV3SF.mjs.map +7 -0
  9. package/dist/lib/neutral/plugin.mjs +2 -2
  10. package/dist/lib/neutral/translations.mjs +6 -6
  11. package/dist/lib/neutral/translations.mjs.map +3 -3
  12. package/dist/types/dx.config.d.ts +28 -0
  13. package/dist/types/dx.config.d.ts.map +1 -0
  14. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -2
  15. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  16. package/dist/types/src/capabilities/index.d.ts +4 -12
  17. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  18. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  19. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  20. package/dist/types/src/capabilities/settings.d.ts +1 -10
  21. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  22. package/dist/types/src/categories.d.ts.map +1 -1
  23. package/dist/types/src/commands/index.d.ts +2 -2
  24. package/dist/types/src/commands/index.d.ts.map +1 -1
  25. package/dist/types/src/commands/plugin/disable.d.ts.map +1 -0
  26. package/dist/types/src/commands/plugin/enable.d.ts.map +1 -0
  27. package/dist/types/src/commands/plugin/index.d.ts +3 -0
  28. package/dist/types/src/commands/plugin/index.d.ts.map +1 -0
  29. package/dist/types/src/commands/plugin/list.d.ts.map +1 -0
  30. package/dist/types/src/commands/plugin/util.d.ts.map +1 -0
  31. package/dist/types/src/commands/registry/index.d.ts +16 -0
  32. package/dist/types/src/commands/registry/index.d.ts.map +1 -0
  33. package/dist/types/src/commands/registry/publish-package.d.ts +29 -0
  34. package/dist/types/src/commands/registry/publish-package.d.ts.map +1 -0
  35. package/dist/types/src/commands/registry/publish-publisher.d.ts +19 -0
  36. package/dist/types/src/commands/registry/publish-publisher.d.ts.map +1 -0
  37. package/dist/types/src/commands/registry/publish.d.ts +25 -0
  38. package/dist/types/src/commands/registry/publish.d.ts.map +1 -0
  39. package/dist/types/src/commands/registry/records.d.ts +14 -0
  40. package/dist/types/src/commands/registry/records.d.ts.map +1 -0
  41. package/dist/types/src/commands/registry/unpublish.d.ts +15 -0
  42. package/dist/types/src/commands/registry/unpublish.d.ts.map +1 -0
  43. package/dist/types/src/commands/registry/util.d.ts +113 -0
  44. package/dist/types/src/commands/registry/util.d.ts.map +1 -0
  45. package/dist/types/src/commands/registry/verify.d.ts +20 -0
  46. package/dist/types/src/commands/registry/verify.d.ts.map +1 -0
  47. package/dist/types/src/components/PluginDetail/PluginDetail.d.ts +2 -2
  48. package/dist/types/src/components/PluginDetail/PluginDetail.d.ts.map +1 -1
  49. package/dist/types/src/components/PluginDetail/PluginDetail.stories.d.ts +6 -5
  50. package/dist/types/src/components/PluginDetail/PluginDetail.stories.d.ts.map +1 -1
  51. package/dist/types/src/components/PluginFailureBadge/PluginFailureBadge.d.ts +1 -3
  52. package/dist/types/src/components/PluginFailureBadge/PluginFailureBadge.d.ts.map +1 -1
  53. package/dist/types/src/components/PluginList/PluginItem.d.ts.map +1 -1
  54. package/dist/types/src/components/PluginList/PluginList.d.ts.map +1 -1
  55. package/dist/types/src/components/PluginList/PluginList.stories.d.ts +5 -5
  56. package/dist/types/src/components/PluginList/PluginList.stories.d.ts.map +1 -1
  57. package/dist/types/src/components/RegistrySettings/RegistrySettings.d.ts +5 -1
  58. package/dist/types/src/components/RegistrySettings/RegistrySettings.d.ts.map +1 -1
  59. package/dist/types/src/components/RegistrySettings/RegistrySettings.stories.d.ts +78 -0
  60. package/dist/types/src/components/RegistrySettings/RegistrySettings.stories.d.ts.map +1 -0
  61. package/dist/types/src/containers/LoadPluginDialog/LoadPluginDialog.d.ts.map +1 -1
  62. package/dist/types/src/containers/PluginArticle/PluginArticle.d.ts.map +1 -1
  63. package/dist/types/src/containers/PublicRegistryArticle/PublicRegistryArticle.d.ts.map +1 -1
  64. package/dist/types/src/containers/PublicRegistryArticle/index.d.ts +1 -1
  65. package/dist/types/src/containers/PublicRegistryArticle/index.d.ts.map +1 -1
  66. package/dist/types/src/containers/RegistryArticle/index.d.ts +1 -1
  67. package/dist/types/src/containers/RegistryArticle/index.d.ts.map +1 -1
  68. package/dist/types/src/hooks/useAutoTags.d.ts +2 -2
  69. package/dist/types/src/hooks/useAutoTags.d.ts.map +1 -1
  70. package/dist/types/src/hooks/useCatalogEntry.d.ts +4 -5
  71. package/dist/types/src/hooks/useCatalogEntry.d.ts.map +1 -1
  72. package/dist/types/src/hooks/usePluginActions.d.ts +3 -3
  73. package/dist/types/src/hooks/usePluginActions.d.ts.map +1 -1
  74. package/dist/types/src/hooks/useUpdateAvailable.d.ts +2 -2
  75. package/dist/types/src/hooks/useUpdateAvailable.d.ts.map +1 -1
  76. package/dist/types/src/hooks/useVersionPicker.d.ts +7 -8
  77. package/dist/types/src/hooks/useVersionPicker.d.ts.map +1 -1
  78. package/dist/types/src/meta.d.ts +32 -2
  79. package/dist/types/src/meta.d.ts.map +1 -1
  80. package/dist/types/src/operations/open-plugin-registry.d.ts.map +1 -1
  81. package/dist/types/src/translations.d.ts +5 -5
  82. package/dist/types/src/translations.d.ts.map +1 -1
  83. package/dist/types/src/types.d.ts.map +1 -1
  84. package/dist/types/tsconfig.tsbuildinfo +1 -1
  85. package/dx.config.ts +20 -0
  86. package/package.json +40 -33
  87. package/src/RegistryPlugin.node.ts +2 -2
  88. package/src/RegistryPlugin.test.ts +1 -1
  89. package/src/capabilities/app-graph-builder.ts +46 -41
  90. package/src/capabilities/dev-plugin-loader.ts +1 -1
  91. package/src/capabilities/react-surface.tsx +1 -4
  92. package/src/capabilities/settings.ts +2 -2
  93. package/src/categories.ts +5 -4
  94. package/src/commands/index.ts +2 -10
  95. package/src/commands/{disable.ts → plugin/disable.ts} +3 -3
  96. package/src/commands/{enable.ts → plugin/enable.ts} +3 -3
  97. package/src/commands/plugin/index.ts +14 -0
  98. package/src/commands/{list.ts → plugin/list.ts} +4 -4
  99. package/src/commands/registry/index.ts +30 -0
  100. package/src/commands/registry/publish-package.ts +119 -0
  101. package/src/commands/registry/publish-publisher.ts +73 -0
  102. package/src/commands/registry/publish.ts +278 -0
  103. package/src/commands/registry/records.ts +73 -0
  104. package/src/commands/registry/unpublish.ts +70 -0
  105. package/src/commands/registry/util.ts +395 -0
  106. package/src/commands/registry/verify.ts +76 -0
  107. package/src/components/DisableDependentsAlert/DisableDependentsAlert.tsx +1 -1
  108. package/src/components/PluginDetail/PluginDetail.stories.tsx +31 -15
  109. package/src/components/PluginDetail/PluginDetail.tsx +21 -23
  110. package/src/components/PluginFailureBadge/PluginFailureBadge.tsx +21 -24
  111. package/src/components/PluginList/PluginItem.tsx +16 -11
  112. package/src/components/PluginList/PluginList.stories.tsx +1 -2
  113. package/src/components/PluginList/PluginList.tsx +18 -13
  114. package/src/components/RegistrySettings/RegistrySettings.stories.tsx +45 -0
  115. package/src/components/RegistrySettings/RegistrySettings.tsx +44 -33
  116. package/src/containers/BaseRegistryArticle/BaseRegistryArticle.tsx +2 -2
  117. package/src/containers/LoadPluginDialog/LoadPluginDialog.tsx +3 -3
  118. package/src/containers/PluginArticle/PluginArticle.tsx +8 -6
  119. package/src/containers/PublicRegistryArticle/PublicRegistryArticle.tsx +35 -28
  120. package/src/containers/PublicRegistryArticle/index.ts +1 -1
  121. package/src/containers/RegistryArticle/RegistryArticle.tsx +1 -1
  122. package/src/containers/RegistryArticle/index.ts +1 -1
  123. package/src/containers/RegistrySettingsContainer/RegistrySettingsContainer.tsx +2 -2
  124. package/src/hooks/useAutoTags.ts +3 -3
  125. package/src/hooks/useCatalogEntry.ts +6 -7
  126. package/src/hooks/useDisableConfirmation.ts +1 -1
  127. package/src/hooks/usePluginActions.ts +13 -11
  128. package/src/hooks/useUpdateAvailable.ts +5 -5
  129. package/src/hooks/useVersionPicker.ts +22 -30
  130. package/src/meta.ts +6 -15
  131. package/src/operations/open-plugin-registry.ts +2 -2
  132. package/src/translations.ts +6 -6
  133. package/src/types.ts +3 -1
  134. package/dist/lib/neutral/chunk-GRQI6MLI.mjs +0 -36
  135. package/dist/lib/neutral/chunk-GRQI6MLI.mjs.map +0 -7
  136. package/dist/lib/neutral/open-plugin-registry-II735N76.mjs.map +0 -7
  137. package/dist/types/src/commands/disable.d.ts.map +0 -1
  138. package/dist/types/src/commands/enable.d.ts.map +0 -1
  139. package/dist/types/src/commands/list.d.ts.map +0 -1
  140. package/dist/types/src/commands/util.d.ts.map +0 -1
  141. /package/dist/types/src/commands/{disable.d.ts → plugin/disable.d.ts} +0 -0
  142. /package/dist/types/src/commands/{enable.d.ts → plugin/enable.d.ts} +0 -0
  143. /package/dist/types/src/commands/{list.d.ts → plugin/list.d.ts} +0 -0
  144. /package/dist/types/src/commands/{util.d.ts → plugin/util.d.ts} +0 -0
  145. /package/src/commands/{util.ts → plugin/util.ts} +0 -0
@@ -7,10 +7,10 @@ import { Plugin as Plugin4 } from "@dxos/app-framework";
7
7
  import { AppPlugin } from "@dxos/app-toolkit";
8
8
  import { meta } from "#meta";
9
9
 
10
- // src/commands/index.ts
10
+ // src/commands/plugin/index.ts
11
11
  import * as Command4 from "@effect/cli/Command";
12
12
 
13
- // src/commands/disable.ts
13
+ // src/commands/plugin/disable.ts
14
14
  import * as Args from "@effect/cli/Args";
15
15
  import * as Command from "@effect/cli/Command";
16
16
  import * as Console from "effect/Console";
@@ -18,12 +18,12 @@ import * as Effect from "effect/Effect";
18
18
  import { Plugin } from "@dxos/app-framework";
19
19
  import { CommandConfig } from "@dxos/cli-util";
20
20
  import { invariant } from "@dxos/invariant";
21
- var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-registry/src/commands/disable.ts";
21
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-registry/src/commands/plugin/disable.ts";
22
22
  var handler = Effect.fn(function* ({ id }) {
23
23
  const { json, profile } = yield* CommandConfig;
24
24
  const manager = yield* Plugin.Service;
25
25
  const plugins = manager.getPlugins();
26
- const plugin2 = plugins.find((p) => p.meta.id === id);
26
+ const plugin2 = plugins.find((p) => p.meta.profile.key === id);
27
27
  invariant(plugin2, `Plugin not found: ${id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 17, S: this, A: ["plugin", "`Plugin not found: ${id}`"] });
28
28
  const core = manager.getCore();
29
29
  invariant(!core.includes(id), `Cannot disable core plugin: ${id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 19, S: this, A: ["!core.includes(id)", "`Cannot disable core plugin: ${id}`"] });
@@ -42,7 +42,7 @@ var handler = Effect.fn(function* ({ id }) {
42
42
  enabled: false
43
43
  }, null, 2));
44
44
  } else {
45
- yield* Console.log(`Plugin "${plugin2.meta.name ?? id}" disabled.`);
45
+ yield* Console.log(`Plugin "${plugin2.meta.profile.name ?? id}" disabled.`);
46
46
  }
47
47
  });
48
48
  var disable = Command.make("disable", {
@@ -51,7 +51,7 @@ var disable = Command.make("disable", {
51
51
  }).pipe(Args.withDescription("The ID of the plugin to disable."))
52
52
  }, handler).pipe(Command.withDescription("Disable a plugin."));
53
53
 
54
- // src/commands/enable.ts
54
+ // src/commands/plugin/enable.ts
55
55
  import * as Args2 from "@effect/cli/Args";
56
56
  import * as Command2 from "@effect/cli/Command";
57
57
  import * as Console2 from "effect/Console";
@@ -59,12 +59,12 @@ import * as Effect2 from "effect/Effect";
59
59
  import { Plugin as Plugin2 } from "@dxos/app-framework";
60
60
  import { CommandConfig as CommandConfig2 } from "@dxos/cli-util";
61
61
  import { invariant as invariant2 } from "@dxos/invariant";
62
- var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-registry/src/commands/enable.ts";
62
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-registry/src/commands/plugin/enable.ts";
63
63
  var handler2 = Effect2.fn(function* ({ id }) {
64
64
  const { json, profile } = yield* CommandConfig2;
65
65
  const manager = yield* Plugin2.Service;
66
66
  const plugins = manager.getPlugins();
67
- const plugin2 = plugins.find((p) => p.meta.id === id);
67
+ const plugin2 = plugins.find((p) => p.meta.profile.key === id);
68
68
  invariant2(plugin2, `Plugin not found: ${id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 17, S: this, A: ["plugin", "`Plugin not found: ${id}`"] });
69
69
  const enabled = yield* manager.enable(id);
70
70
  invariant2(enabled, `Failed to enable plugin: ${id}`, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 19, S: this, A: ["enabled", "`Failed to enable plugin: ${id}`"] });
@@ -81,7 +81,7 @@ var handler2 = Effect2.fn(function* ({ id }) {
81
81
  enabled: true
82
82
  }, null, 2));
83
83
  } else {
84
- yield* Console2.log(`Plugin "${plugin2.meta.name ?? id}" enabled.`);
84
+ yield* Console2.log(`Plugin "${plugin2.meta.profile.name ?? id}" enabled.`);
85
85
  }
86
86
  });
87
87
  var enable = Command2.make("enable", {
@@ -90,14 +90,14 @@ var enable = Command2.make("enable", {
90
90
  }).pipe(Args2.withDescription("The ID of the plugin to enable."))
91
91
  }, handler2).pipe(Command2.withDescription("Enable a plugin."));
92
92
 
93
- // src/commands/list.ts
93
+ // src/commands/plugin/list.ts
94
94
  import * as Command3 from "@effect/cli/Command";
95
95
  import * as Console3 from "effect/Console";
96
96
  import * as Effect3 from "effect/Effect";
97
97
  import { Plugin as Plugin3 } from "@dxos/app-framework";
98
98
  import { CommandConfig as CommandConfig3, printList } from "@dxos/cli-util";
99
99
 
100
- // src/commands/util.ts
100
+ // src/commands/plugin/util.ts
101
101
  import { FormBuilder } from "@dxos/cli-util";
102
102
  var printPlugin = (plugin2) => {
103
103
  const status = plugin2.core ? "core" : plugin2.enabled ? "enabled" : "disabled";
@@ -106,7 +106,7 @@ var printPlugin = (plugin2) => {
106
106
  }).pipe(FormBuilder.set("id", plugin2.id), FormBuilder.set("status", status), FormBuilder.build);
107
107
  };
108
108
 
109
- // src/commands/list.ts
109
+ // src/commands/plugin/list.ts
110
110
  var handler3 = Effect3.fn(function* () {
111
111
  const { json } = yield* CommandConfig3;
112
112
  const manager = yield* Plugin3.Service;
@@ -114,11 +114,11 @@ var handler3 = Effect3.fn(function* () {
114
114
  const enabled = manager.getEnabled();
115
115
  const core = manager.getCore();
116
116
  const formattedPlugins = plugins.map((plugin2) => {
117
- const isEnabled = enabled.includes(plugin2.meta.id);
118
- const isCore = core.includes(plugin2.meta.id);
117
+ const isEnabled = enabled.includes(plugin2.meta.profile.key);
118
+ const isCore = core.includes(plugin2.meta.profile.key);
119
119
  return {
120
- id: plugin2.meta.id,
121
- name: plugin2.meta.name ?? plugin2.meta.id,
120
+ id: plugin2.meta.profile.key,
121
+ name: plugin2.meta.profile.name ?? plugin2.meta.profile.key,
122
122
  enabled: isEnabled,
123
123
  core: isCore
124
124
  };
@@ -132,17 +132,708 @@ var handler3 = Effect3.fn(function* () {
132
132
  });
133
133
  var list = Command3.make("list", {}, handler3).pipe(Command3.withDescription("List all available plugins."));
134
134
 
135
- // src/commands/index.ts
135
+ // src/commands/plugin/index.ts
136
136
  var plugin = Command4.make("plugin").pipe(Command4.withDescription("Manage plugins."), Command4.withSubcommands([
137
137
  enable,
138
138
  disable,
139
139
  list
140
140
  ]));
141
141
 
142
+ // src/commands/registry/index.ts
143
+ import * as Command11 from "@effect/cli/Command";
144
+
145
+ // src/commands/registry/publish.ts
146
+ import * as Command5 from "@effect/cli/Command";
147
+ import * as Options from "@effect/cli/Options";
148
+ import * as PlatformCommand from "@effect/platform/Command";
149
+ import * as FetchHttpClient from "@effect/platform/FetchHttpClient";
150
+ import * as FileSystem from "@effect/platform/FileSystem";
151
+ import * as Path from "@effect/platform/Path";
152
+ import * as Console4 from "effect/Console";
153
+ import * as Effect5 from "effect/Effect";
154
+ import * as Function from "effect/Function";
155
+ import * as Option2 from "effect/Option";
156
+ import * as Schema2 from "effect/Schema";
157
+ import { findDxConfigFile, loadDxConfig } from "@dxos/app-framework/vite-plugin";
158
+ import { ClientService } from "@dxos/client";
159
+ import { Context } from "@dxos/context";
160
+ import { EdgeHttpClient } from "@dxos/edge-client";
161
+ import { Config2 } from "@dxos/protocols";
162
+
163
+ // src/commands/registry/util.ts
164
+ import * as HttpClient from "@effect/platform/HttpClient";
165
+ import * as HttpClientRequest from "@effect/platform/HttpClientRequest";
166
+ import * as Config from "effect/Config";
167
+ import * as Effect4 from "effect/Effect";
168
+ import * as Option from "effect/Option";
169
+ import * as Schema from "effect/Schema";
170
+ import { AppSpace } from "@dxos/app-toolkit";
171
+ import { Filter } from "@dxos/echo";
172
+ import { ALL_NSIDS, NSID } from "@dxos/protocols";
173
+ import { AccessToken } from "@dxos/types";
174
+ var ATMOSPHERE_SOURCE = "atproto.local";
175
+ var BSKY_PUBLIC_API = "https://public.api.bsky.app/xrpc";
176
+ var PLC_DIRECTORY = "https://plc.directory";
177
+ var CreateSessionResponseSchema = Schema.Struct({
178
+ did: Schema.String,
179
+ handle: Schema.String,
180
+ accessJwt: Schema.String,
181
+ refreshJwt: Schema.String
182
+ });
183
+ var ResolveHandleResponseSchema = Schema.Struct({
184
+ did: Schema.String
185
+ });
186
+ var DidServiceSchema = Schema.Struct({
187
+ id: Schema.String,
188
+ type: Schema.optional(Schema.String),
189
+ serviceEndpoint: Schema.Unknown
190
+ });
191
+ var DidDocumentSchema = Schema.Struct({
192
+ service: Schema.optional(Schema.Array(DidServiceSchema))
193
+ });
194
+ var PutRecordResponseSchema = Schema.Struct({
195
+ uri: Schema.String,
196
+ cid: Schema.String
197
+ });
198
+ var ListRecordsEntrySchema = Schema.Struct({
199
+ uri: Schema.String,
200
+ cid: Schema.String,
201
+ value: Schema.Unknown
202
+ });
203
+ var ListRecordsResponseSchema = Schema.Struct({
204
+ cursor: Schema.optional(Schema.String),
205
+ records: Schema.Array(ListRecordsEntrySchema)
206
+ });
207
+ var decodeJson = (schema) => (response) => Effect4.flatMap(response.json, Schema.decodeUnknown(schema));
208
+ var xrpcGet = (url, query, schema) => Effect4.gen(function* () {
209
+ const client = yield* HttpClient.HttpClient;
210
+ return yield* HttpClientRequest.get(url).pipe(HttpClientRequest.setUrlParams(query), client.execute, Effect4.flatMap(decodeJson(schema)), Effect4.scoped);
211
+ });
212
+ var xrpcPost = (url, body, schema, headers = {}) => Effect4.gen(function* () {
213
+ const client = yield* HttpClient.HttpClient;
214
+ const response = yield* HttpClientRequest.post(url).pipe(HttpClientRequest.setHeaders(headers), HttpClientRequest.bodyJson(body), Effect4.flatMap((req) => client.execute(req)), Effect4.scoped);
215
+ if (schema === void 0) {
216
+ return void 0;
217
+ }
218
+ return yield* decodeJson(schema)(response);
219
+ });
220
+ var resolveHandle = (handle) => xrpcGet(`${BSKY_PUBLIC_API}/com.atproto.identity.resolveHandle`, {
221
+ handle
222
+ }, ResolveHandleResponseSchema).pipe(Effect4.map((response) => response.did));
223
+ var resolvePds = (did) => Effect4.gen(function* () {
224
+ let doc;
225
+ if (did.startsWith("did:plc:")) {
226
+ doc = yield* xrpcGet(`${PLC_DIRECTORY}/${did}`, {}, DidDocumentSchema);
227
+ } else if (did.startsWith("did:web:")) {
228
+ const rest = did.slice("did:web:".length);
229
+ const [host, ...segments] = rest.split(":").map((part) => decodeURIComponent(part));
230
+ const path = segments.length > 0 ? `/${segments.join("/")}/did.json` : "/.well-known/did.json";
231
+ doc = yield* xrpcGet(`https://${host}${path}`, {}, DidDocumentSchema);
232
+ } else {
233
+ return yield* Effect4.fail(new Error(`Unsupported DID method: ${did}`));
234
+ }
235
+ const service = doc.service?.find((entry) => entry.id === "#atproto_pds" || entry.type === "AtprotoPersonalDataServer");
236
+ const endpoint = service?.serviceEndpoint;
237
+ if (typeof endpoint !== "string" || endpoint.length === 0) {
238
+ return yield* Effect4.fail(new Error(`PDS endpoint missing in DID document for ${did}`));
239
+ }
240
+ return endpoint;
241
+ });
242
+ var resolveRepo = (handleOrDid) => Effect4.gen(function* () {
243
+ const did = handleOrDid.startsWith("did:") ? handleOrDid : yield* resolveHandle(handleOrDid);
244
+ const pdsBaseUrl = yield* resolvePds(did);
245
+ return {
246
+ did,
247
+ pdsBaseUrl
248
+ };
249
+ });
250
+ var createSession = (handle, appPassword) => Effect4.gen(function* () {
251
+ const { did, pdsBaseUrl } = yield* resolveRepo(handle);
252
+ const response = yield* xrpcPost(`${pdsBaseUrl}/xrpc/com.atproto.server.createSession`, {
253
+ identifier: handle,
254
+ password: appPassword
255
+ }, CreateSessionResponseSchema);
256
+ return {
257
+ mode: "app-password",
258
+ did: response.did,
259
+ handle: response.handle,
260
+ accessJwt: response.accessJwt,
261
+ pdsBaseUrl
262
+ };
263
+ });
264
+ var resolveSession = (options) => Effect4.gen(function* () {
265
+ const handle = options.handle ?? Option.getOrUndefined(yield* Config.option(Config.string("ATPROTO_HANDLE")));
266
+ const appPassword = options.appPassword ?? Option.getOrUndefined(yield* Config.option(Config.string("ATPROTO_APP_PASSWORD")));
267
+ if (handle && appPassword) {
268
+ return yield* createSession(handle, appPassword);
269
+ }
270
+ const fromPersonalSpace = yield* resolvePersonalSpaceSession(options.client);
271
+ if (fromPersonalSpace) {
272
+ return fromPersonalSpace;
273
+ }
274
+ if (options.client.halo.identity.get()) {
275
+ return yield* Effect4.fail(new Error("No atproto integration connected. Connect one with `dx integration add`, or pass --handle/--app-password. (`dx account login` cannot add an integration to an existing identity.)"));
276
+ }
277
+ return yield* Effect4.fail(new Error("No DXOS identity. Run `dx account login` first, or pass --handle/--app-password."));
278
+ });
279
+ var resolvePersonalSpaceSession = (client) => Effect4.gen(function* () {
280
+ const space = AppSpace.getPersonalSpace(client);
281
+ if (!space) {
282
+ return void 0;
283
+ }
284
+ const tokens = yield* Effect4.promise(() => space.db.query(Filter.type(AccessToken.AccessToken)).run());
285
+ const token = tokens.find((object) => object.source === ATMOSPHERE_SOURCE && !!object.account && !!object.token);
286
+ if (!token?.account) {
287
+ return void 0;
288
+ }
289
+ const { did, pdsBaseUrl } = yield* resolveRepo(token.account);
290
+ return {
291
+ mode: "dpop-proxy",
292
+ did,
293
+ handle: token.account,
294
+ pdsBaseUrl,
295
+ edgeBaseUrl: client.edge.http.baseUrl,
296
+ spaceId: space.id,
297
+ accessTokenId: token.id,
298
+ token: token.token,
299
+ // Best-effort VP auth header for the proxy. The `/atproto/proxy` route currently skips auth
300
+ // in dev; production reads the caller's verifiable presentation when present.
301
+ authHeader: client.edge.http._authHeader
302
+ };
303
+ });
304
+ var proxyCall = (session, params, schema) => {
305
+ const query = params.query ? `?${new URLSearchParams(params.query).toString()}` : "";
306
+ const innerHeaders = {
307
+ Accept: "application/json",
308
+ Authorization: `DPoP ${session.token}`
309
+ };
310
+ if (params.jsonBody) {
311
+ innerHeaders["Content-Type"] = "application/json";
312
+ }
313
+ const outerHeaders = {};
314
+ if (session.authHeader) {
315
+ outerHeaders.Authorization = session.authHeader;
316
+ }
317
+ return xrpcPost(`${session.edgeBaseUrl.replace(/\/$/, "")}/atproto/proxy`, {
318
+ spaceId: session.spaceId,
319
+ accessTokenId: session.accessTokenId,
320
+ request: {
321
+ endpoint: `${session.pdsBaseUrl}/xrpc/${params.xrpcMethod}${query}`,
322
+ method: params.method,
323
+ headers: innerHeaders,
324
+ // Edge's proxy forwards the body to `fetch` as-is, so it must be a pre-serialized string.
325
+ body: params.jsonBody ? JSON.stringify(params.jsonBody) : null
326
+ }
327
+ }, schema, outerHeaders);
328
+ };
329
+ var putRecord = (session, collection, rkey, record) => {
330
+ const body = {
331
+ repo: session.did,
332
+ collection,
333
+ rkey,
334
+ record: {
335
+ $type: collection,
336
+ ...record
337
+ }
338
+ };
339
+ return session.mode === "app-password" ? xrpcPost(`${session.pdsBaseUrl}/xrpc/com.atproto.repo.putRecord`, body, PutRecordResponseSchema, {
340
+ Authorization: `Bearer ${session.accessJwt}`
341
+ }) : proxyCall(session, {
342
+ xrpcMethod: "com.atproto.repo.putRecord",
343
+ method: "POST",
344
+ jsonBody: body
345
+ }, PutRecordResponseSchema);
346
+ };
347
+ var deleteRecord = (session, collection, rkey) => {
348
+ const body = {
349
+ repo: session.did,
350
+ collection,
351
+ rkey
352
+ };
353
+ return session.mode === "app-password" ? xrpcPost(`${session.pdsBaseUrl}/xrpc/com.atproto.repo.deleteRecord`, body, void 0, {
354
+ Authorization: `Bearer ${session.accessJwt}`
355
+ }) : proxyCall(session, {
356
+ xrpcMethod: "com.atproto.repo.deleteRecord",
357
+ method: "POST",
358
+ jsonBody: body
359
+ }, void 0);
360
+ };
361
+ var listRecords = (session, collection, options = {}) => {
362
+ const query = {
363
+ repo: session.did,
364
+ collection,
365
+ ...options.limit !== void 0 ? {
366
+ limit: String(options.limit)
367
+ } : {},
368
+ ...options.cursor !== void 0 ? {
369
+ cursor: options.cursor
370
+ } : {}
371
+ };
372
+ return session.mode === "app-password" ? xrpcGet(`${session.pdsBaseUrl}/xrpc/com.atproto.repo.listRecords`, query, ListRecordsResponseSchema) : proxyCall(session, {
373
+ xrpcMethod: "com.atproto.repo.listRecords",
374
+ method: "GET",
375
+ query
376
+ }, ListRecordsResponseSchema);
377
+ };
378
+ var AUTH_OPTION_DESCRIPTIONS = {
379
+ handle: "AT Protocol handle (e.g. alice.bsky.social). Defaults to the logged-in identity; falls back to $ATPROTO_HANDLE.",
380
+ appPassword: "AT Protocol app password (https://bsky.app/settings/app-passwords). Falls back to $ATPROTO_APP_PASSWORD. Not needed when logged in via `dx account login`."
381
+ };
382
+
383
+ // src/commands/registry/publish.ts
384
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/plugins/plugin-registry/src/commands/registry/publish.ts";
385
+ var ManifestSchema = Schema2.Struct({
386
+ ...Config2.Plugin.fields,
387
+ version: Schema2.String.pipe(Schema2.nonEmptyString()),
388
+ dependencies: Schema2.optional(Schema2.Record({
389
+ key: Schema2.String,
390
+ value: Schema2.String
391
+ }))
392
+ });
393
+ var ensureTrailingSlash = (url) => url.endsWith("/") ? url : `${url}/`;
394
+ var sha256Base64 = async (bytes) => {
395
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
396
+ return Buffer.from(new Uint8Array(digest)).toString("base64");
397
+ };
398
+ var publish = Command5.make("publish", {
399
+ handle: Options.text("handle").pipe(Options.withDescription(AUTH_OPTION_DESCRIPTIONS.handle), Options.optional),
400
+ appPassword: Options.text("app-password").pipe(Options.withDescription(AUTH_OPTION_DESCRIPTIONS.appPassword), Options.optional),
401
+ dir: Options.text("dir").pipe(Options.withDescription("Project directory containing dx.config.ts. Defaults to the current directory."), Options.withDefault(".")),
402
+ noBuild: Options.boolean("no-build").pipe(Options.withDescription("Skip running the build command (publish a pre-built dist).")),
403
+ assetBaseUrl: Options.text("asset-base-url").pipe(Options.withDescription("Skip upload and point the release at an already-hosted bundle directory."), Options.optional),
404
+ edgeUrl: Options.text("edge-url").pipe(Options.withDescription("Edge base URL for bundle upload (e.g. http://localhost:8787). Bypasses profile config; auth is skipped (requires WORKER_ENV=dev on the server)."), Options.optional)
405
+ }, (options) => Function.pipe(Effect5.gen(function* () {
406
+ const fs = yield* FileSystem.FileSystem;
407
+ const path = yield* Path.Path;
408
+ const dir = path.resolve(options.dir);
409
+ const configFile = findDxConfigFile(dir);
410
+ if (!configFile) {
411
+ return yield* Effect5.fail(new Error(`No dx.config.ts found in ${dir}.`));
412
+ }
413
+ const config = yield* Effect5.tryPromise({
414
+ try: () => loadDxConfig(configFile),
415
+ catch: (error) => new Error(`Failed to load dx.config.ts in ${dir}: ${error}`)
416
+ });
417
+ const buildCommand = config.publish?.buildCommand;
418
+ if (!options.noBuild && buildCommand) {
419
+ yield* Console4.log(`Building: ${buildCommand}`);
420
+ const binDir = path.join(dir, "node_modules", ".bin");
421
+ const exitCode2 = yield* PlatformCommand.make("sh", "-c", `export PATH="${binDir}:$PATH"; ${buildCommand}`).pipe(PlatformCommand.workingDirectory(dir), PlatformCommand.stdout("inherit"), PlatformCommand.stderr("inherit"), PlatformCommand.exitCode);
422
+ if (exitCode2 !== 0) {
423
+ return yield* Effect5.fail(new Error(`Build failed (exit ${exitCode2}): ${buildCommand}`));
424
+ }
425
+ }
426
+ const outdir = path.join(dir, config.publish?.outputDirectory ?? "dist");
427
+ const manifestPath = path.join(outdir, "manifest.json");
428
+ if (!(yield* fs.exists(manifestPath))) {
429
+ return yield* Effect5.fail(new Error(`manifest.json not found in ${outdir}. Did the build run?`));
430
+ }
431
+ const manifestRaw = yield* fs.readFileString(manifestPath);
432
+ const manifest = yield* Schema2.decodeUnknown(ManifestSchema)(JSON.parse(manifestRaw));
433
+ const key = manifest.key;
434
+ const version = manifest.version;
435
+ const manifestHash = `sha256-${yield* Effect5.promise(() => sha256Base64(new TextEncoder().encode(manifestRaw)))}`;
436
+ const assetBaseUrl = Option2.getOrUndefined(options.assetBaseUrl) ?? config.publish?.assetBaseUrl;
437
+ let moduleUrl;
438
+ if (assetBaseUrl) {
439
+ moduleUrl = new URL("manifest.json", ensureTrailingSlash(assetBaseUrl)).toString();
440
+ yield* Console4.log(`Self-hosted: ${moduleUrl}`);
441
+ } else {
442
+ const explicitEdgeUrl = Option2.getOrUndefined(options.edgeUrl);
443
+ if (explicitEdgeUrl) {
444
+ const http = new EdgeHttpClient(explicitEdgeUrl);
445
+ moduleUrl = yield* uploadBundleDirect({
446
+ http,
447
+ key,
448
+ version,
449
+ outdir
450
+ });
451
+ } else {
452
+ const client2 = yield* ClientService;
453
+ const hasIdentity = !!client2.halo.identity.get();
454
+ moduleUrl = yield* uploadBundle({
455
+ client: client2,
456
+ key,
457
+ version,
458
+ outdir,
459
+ auth: hasIdentity
460
+ });
461
+ }
462
+ yield* Console4.log(`Uploaded: ${moduleUrl}`);
463
+ }
464
+ const client = yield* ClientService;
465
+ const session = yield* resolveSession({
466
+ handle: Option2.getOrUndefined(options.handle),
467
+ appPassword: Option2.getOrUndefined(options.appPassword),
468
+ client
469
+ });
470
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
471
+ const profile = {
472
+ key,
473
+ name: manifest.name,
474
+ createdAt
475
+ };
476
+ if (manifest.description !== void 0) {
477
+ profile.description = manifest.description;
478
+ }
479
+ if (manifest.homePage !== void 0) {
480
+ profile.homePage = manifest.homePage;
481
+ }
482
+ if (manifest.source !== void 0) {
483
+ profile.source = manifest.source;
484
+ }
485
+ if (manifest.icon !== void 0) {
486
+ profile.icon = manifest.icon;
487
+ }
488
+ if (manifest.tags && manifest.tags.length > 0) {
489
+ profile.tags = manifest.tags;
490
+ }
491
+ if (manifest.screenshots && manifest.screenshots.length > 0) {
492
+ profile.screenshots = manifest.screenshots;
493
+ }
494
+ if (manifest.dependsOn?.length) {
495
+ profile.dependsOn = manifest.dependsOn;
496
+ }
497
+ if (manifest.spec !== void 0) {
498
+ profile.spec = manifest.spec;
499
+ }
500
+ const profileResult = yield* putRecord(session, NSID.PluginProfile, key, profile);
501
+ yield* Console4.log(`Profile ${profileResult.uri}`);
502
+ const releaseResult = yield* putRecord(session, NSID.PluginRelease, `${key}:${version}`, {
503
+ pluginKey: key,
504
+ version,
505
+ moduleUrl,
506
+ manifestHash,
507
+ createdAt,
508
+ ...manifest.dependencies ? {
509
+ dependencies: manifest.dependencies
510
+ } : {}
511
+ });
512
+ yield* Console4.log(`Release ${releaseResult.uri}`);
513
+ }), Effect5.provide(FetchHttpClient.layer))).pipe(Command5.withDescription("Build, host, and publish the plugin in the current directory to the registry."));
514
+ var uploadBundle = ({ client, key, version, outdir, auth = true }) => Effect5.gen(function* () {
515
+ const fs = yield* FileSystem.FileSystem;
516
+ const path = yield* Path.Path;
517
+ const entries = yield* fs.readDirectory(outdir, {
518
+ recursive: true
519
+ });
520
+ const files = [];
521
+ for (const entry of entries) {
522
+ const full = path.join(outdir, entry);
523
+ const info = yield* fs.stat(full);
524
+ if (info.type !== "File") {
525
+ continue;
526
+ }
527
+ const bytes = yield* fs.readFile(full);
528
+ files.push({
529
+ path: entry.split(path.sep).join("/"),
530
+ content: Buffer.from(bytes).toString("base64")
531
+ });
532
+ }
533
+ const { moduleUrl } = yield* Effect5.tryPromise(() => client.edge.http.uploadPluginBundle(Context.default(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 194 }), {
534
+ slug: key,
535
+ version,
536
+ files
537
+ }, {
538
+ auth
539
+ }));
540
+ return moduleUrl;
541
+ });
542
+ var uploadBundleDirect = ({ http, key, version, outdir }) => Effect5.gen(function* () {
543
+ const fs = yield* FileSystem.FileSystem;
544
+ const path = yield* Path.Path;
545
+ const entries = yield* fs.readDirectory(outdir, {
546
+ recursive: true
547
+ });
548
+ const files = [];
549
+ for (const entry of entries) {
550
+ const full = path.join(outdir, entry);
551
+ const info = yield* fs.stat(full);
552
+ if (info.type !== "File") {
553
+ continue;
554
+ }
555
+ const bytes = yield* fs.readFile(full);
556
+ files.push({
557
+ path: entry.split(path.sep).join("/"),
558
+ content: Buffer.from(bytes).toString("base64")
559
+ });
560
+ }
561
+ const { moduleUrl } = yield* Effect5.tryPromise(() => http.uploadPluginBundle(Context.default(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 225 }), {
562
+ slug: key,
563
+ version,
564
+ files
565
+ }, {
566
+ auth: false
567
+ }));
568
+ return moduleUrl;
569
+ });
570
+
571
+ // src/commands/registry/publish-package.ts
572
+ import * as Command6 from "@effect/cli/Command";
573
+ import * as Options2 from "@effect/cli/Options";
574
+ import * as FetchHttpClient2 from "@effect/platform/FetchHttpClient";
575
+ import * as Console5 from "effect/Console";
576
+ import * as Effect6 from "effect/Effect";
577
+ import * as Function2 from "effect/Function";
578
+ import * as Option3 from "effect/Option";
579
+ import { ClientService as ClientService2 } from "@dxos/client";
580
+ var publishPackage = Command6.make("publish-package", {
581
+ handle: Options2.text("handle").pipe(Options2.withDescription(AUTH_OPTION_DESCRIPTIONS.handle), Options2.optional),
582
+ appPassword: Options2.text("app-password").pipe(Options2.withDescription(AUTH_OPTION_DESCRIPTIONS.appPassword), Options2.optional),
583
+ key: Options2.text("key").pipe(Options2.withDescription("Plugin key \u2014 a reverse-domain NSID (e.g. org.dxos.plugin.excalidraw); also the profile record rkey.")),
584
+ name: Options2.text("name").pipe(Options2.withDescription("Human-readable package name.")),
585
+ description: Options2.text("description").pipe(Options2.withDescription("Short description shown in the registry."), Options2.withDefault("")),
586
+ version: Options2.text("version").pipe(Options2.withDescription("Semver version (no build metadata). The release rkey is `<key>:<version>`.")),
587
+ moduleUrl: Options2.text("module-url").pipe(Options2.withDescription("HTTPS URL to the bundle or manifest for this release.")),
588
+ homepage: Options2.text("homepage").pipe(Options2.withDescription("Homepage URL."), Options2.optional),
589
+ source: Options2.text("source").pipe(Options2.withDescription("Source repository URL."), Options2.optional),
590
+ tag: Options2.text("tag").pipe(Options2.withDescription("Tag (repeatable). Categorizes the package for discovery."), Options2.repeated),
591
+ iconKey: Options2.text("icon-key").pipe(Options2.withDescription("Icon identifier (e.g. ph--sparkle--regular) resolvable by @ch-ui/icons."), Options2.optional),
592
+ iconHue: Options2.text("icon-hue").pipe(Options2.withDescription("Icon palette hue (e.g. blue)."), Options2.optional),
593
+ manifestHash: Options2.text("manifest-hash").pipe(Options2.withDescription("Optional content hash for the bundle/manifest."), Options2.optional)
594
+ }, (options) => Function2.pipe(Effect6.gen(function* () {
595
+ const client = yield* ClientService2;
596
+ const session = yield* resolveSession({
597
+ handle: Option3.getOrUndefined(options.handle),
598
+ appPassword: Option3.getOrUndefined(options.appPassword),
599
+ client
600
+ });
601
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
602
+ const homepage = Option3.getOrUndefined(options.homepage);
603
+ const source = Option3.getOrUndefined(options.source);
604
+ const iconKey = Option3.getOrUndefined(options.iconKey);
605
+ const iconHue = Option3.getOrUndefined(options.iconHue);
606
+ const icon = iconKey !== void 0 ? {
607
+ key: iconKey,
608
+ ...iconHue !== void 0 && {
609
+ hue: iconHue
610
+ }
611
+ } : void 0;
612
+ const profile = {
613
+ key: options.key,
614
+ name: options.name,
615
+ ...options.description.length > 0 && {
616
+ description: options.description
617
+ },
618
+ ...homepage !== void 0 && {
619
+ homePage: homepage
620
+ },
621
+ ...source !== void 0 && {
622
+ source
623
+ },
624
+ ...options.tag.length > 0 && {
625
+ tags: options.tag
626
+ },
627
+ ...icon !== void 0 && {
628
+ icon
629
+ },
630
+ createdAt
631
+ };
632
+ const profileResult = yield* putRecord(session, NSID.PluginProfile, options.key, profile);
633
+ yield* Console5.log(`Profile ${profileResult.uri}`);
634
+ const manifestHash = Option3.getOrUndefined(options.manifestHash);
635
+ const release = {
636
+ pluginKey: options.key,
637
+ version: options.version,
638
+ moduleUrl: options.moduleUrl,
639
+ createdAt,
640
+ ...manifestHash !== void 0 && {
641
+ manifestHash
642
+ }
643
+ };
644
+ const releaseResult = yield* putRecord(session, NSID.PluginRelease, `${options.key}:${options.version}`, release);
645
+ yield* Console5.log(`Release ${releaseResult.uri}`);
646
+ }), Effect6.provide(FetchHttpClient2.layer))).pipe(Command6.withDescription("Publish a package profile + release to the authenticated user's PDS."));
647
+
648
+ // src/commands/registry/publish-publisher.ts
649
+ import * as Command7 from "@effect/cli/Command";
650
+ import * as Options3 from "@effect/cli/Options";
651
+ import * as FetchHttpClient3 from "@effect/platform/FetchHttpClient";
652
+ import * as Console6 from "effect/Console";
653
+ import * as Effect7 from "effect/Effect";
654
+ import * as Function3 from "effect/Function";
655
+ import * as Option4 from "effect/Option";
656
+ import { ClientService as ClientService3 } from "@dxos/client";
657
+ var publishPublisher = Command7.make("publish-publisher", {
658
+ handle: Options3.text("handle").pipe(Options3.withDescription(AUTH_OPTION_DESCRIPTIONS.handle), Options3.optional),
659
+ appPassword: Options3.text("app-password").pipe(Options3.withDescription(AUTH_OPTION_DESCRIPTIONS.appPassword), Options3.optional),
660
+ displayName: Options3.text("display-name").pipe(Options3.withDescription("Publisher display name (the human/org name shown in UIs).")),
661
+ bio: Options3.text("bio").pipe(Options3.withDescription("Short bio."), Options3.optional),
662
+ homepageUrl: Options3.text("homepage-url").pipe(Options3.withDescription("Publisher homepage URL."), Options3.optional),
663
+ contact: Options3.text("contact").pipe(Options3.withDescription("Contact (email, handle, etc.)."), Options3.optional)
664
+ }, (options) => Function3.pipe(Effect7.gen(function* () {
665
+ const client = yield* ClientService3;
666
+ const session = yield* resolveSession({
667
+ handle: Option4.getOrUndefined(options.handle),
668
+ appPassword: Option4.getOrUndefined(options.appPassword),
669
+ client
670
+ });
671
+ const record = {
672
+ displayName: options.displayName
673
+ };
674
+ const bio = Option4.getOrUndefined(options.bio);
675
+ if (bio !== void 0) {
676
+ record.bio = bio;
677
+ }
678
+ const homepageUrl = Option4.getOrUndefined(options.homepageUrl);
679
+ if (homepageUrl !== void 0) {
680
+ record.homepageUrl = homepageUrl;
681
+ }
682
+ const contact = Option4.getOrUndefined(options.contact);
683
+ if (contact !== void 0) {
684
+ record.contact = contact;
685
+ }
686
+ const result = yield* putRecord(session, NSID.PublisherProfile, "self", record);
687
+ yield* Console6.log(`Publisher ${result.uri}`);
688
+ }), Effect7.provide(FetchHttpClient3.layer))).pipe(Command7.withDescription("Publish the authenticated user's publisher.profile record (rkey = self)."));
689
+
690
+ // src/commands/registry/records.ts
691
+ import * as Command8 from "@effect/cli/Command";
692
+ import * as Options4 from "@effect/cli/Options";
693
+ import * as FetchHttpClient4 from "@effect/platform/FetchHttpClient";
694
+ import * as Console7 from "effect/Console";
695
+ import * as Effect8 from "effect/Effect";
696
+ import * as Function4 from "effect/Function";
697
+ import * as Option5 from "effect/Option";
698
+ import { CommandConfig as CommandConfig4 } from "@dxos/cli-util";
699
+ import { ClientService as ClientService4 } from "@dxos/client";
700
+ var records = Command8.make("records", {
701
+ handle: Options4.text("handle").pipe(Options4.withDescription(AUTH_OPTION_DESCRIPTIONS.handle), Options4.optional),
702
+ appPassword: Options4.text("app-password").pipe(Options4.withDescription(AUTH_OPTION_DESCRIPTIONS.appPassword), Options4.optional)
703
+ }, (options) => Function4.pipe(Effect8.gen(function* () {
704
+ const { json } = yield* CommandConfig4;
705
+ const client = yield* ClientService4;
706
+ const session = yield* resolveSession({
707
+ handle: Option5.getOrUndefined(options.handle),
708
+ appPassword: Option5.getOrUndefined(options.appPassword),
709
+ client
710
+ });
711
+ const results = yield* Effect8.all(ALL_NSIDS.map((collection) => listRecords(session, collection).pipe(
712
+ Effect8.map(({ records: entries }) => ({
713
+ collection,
714
+ records: entries
715
+ })),
716
+ // Empty collections come back as a 200 with `records: []`; if the
717
+ // PDS responds 400 because we've never written that collection we
718
+ // still want the others to render.
719
+ Effect8.catchAll(() => Effect8.succeed({
720
+ collection,
721
+ records: []
722
+ }))
723
+ )), {
724
+ concurrency: "unbounded"
725
+ });
726
+ if (json) {
727
+ yield* Console7.log(JSON.stringify({
728
+ did: session.did,
729
+ results
730
+ }, null, 2));
731
+ return;
732
+ }
733
+ yield* Console7.log(`Repo: ${session.did} (${session.handle})`);
734
+ for (const { collection, records: entries } of results) {
735
+ yield* Console7.log(`
736
+ ${collection} (${entries.length})`);
737
+ for (const entry of entries) {
738
+ yield* Console7.log(` ${entry.uri}`);
739
+ }
740
+ }
741
+ }), Effect8.provide(FetchHttpClient4.layer))).pipe(Command8.withDescription("List org.dxos.experimental.* records on the authenticated user's repo."));
742
+
743
+ // src/commands/registry/unpublish.ts
744
+ import * as Command9 from "@effect/cli/Command";
745
+ import * as Options5 from "@effect/cli/Options";
746
+ import * as FetchHttpClient5 from "@effect/platform/FetchHttpClient";
747
+ import * as Console8 from "effect/Console";
748
+ import * as Effect9 from "effect/Effect";
749
+ import * as Function5 from "effect/Function";
750
+ import * as Option6 from "effect/Option";
751
+ import { ClientService as ClientService5 } from "@dxos/client";
752
+ var rkeyOf = (uri) => uri.split("/").pop() ?? "";
753
+ var unpublish = Command9.make("unpublish", {
754
+ handle: Options5.text("handle").pipe(Options5.withDescription(AUTH_OPTION_DESCRIPTIONS.handle), Options5.optional),
755
+ appPassword: Options5.text("app-password").pipe(Options5.withDescription(AUTH_OPTION_DESCRIPTIONS.appPassword), Options5.optional),
756
+ key: Options5.text("key").pipe(Options5.withDescription("Plugin key (the profile rkey). Removes its profile and all releases."))
757
+ }, (options) => Function5.pipe(Effect9.gen(function* () {
758
+ const client = yield* ClientService5;
759
+ const session = yield* resolveSession({
760
+ handle: Option6.getOrUndefined(options.handle),
761
+ appPassword: Option6.getOrUndefined(options.appPassword),
762
+ client
763
+ });
764
+ const key = options.key;
765
+ let cursor;
766
+ let deletedReleases = 0;
767
+ do {
768
+ const releases = yield* listRecords(session, NSID.PluginRelease, {
769
+ limit: 100,
770
+ cursor
771
+ });
772
+ cursor = releases.cursor;
773
+ for (const record of releases.records) {
774
+ const rkey = rkeyOf(record.uri);
775
+ if (rkey.startsWith(`${key}:`)) {
776
+ yield* deleteRecord(session, NSID.PluginRelease, rkey);
777
+ yield* Console8.log(`Deleted release ${rkey}`);
778
+ deletedReleases += 1;
779
+ }
780
+ }
781
+ } while (cursor !== void 0);
782
+ yield* deleteRecord(session, NSID.PluginProfile, key);
783
+ yield* Console8.log(`Deleted profile ${key} (${deletedReleases} release(s) removed)`);
784
+ }), Effect9.provide(FetchHttpClient5.layer))).pipe(Command9.withDescription("Remove a package (profile + releases) from the authenticated user's PDS."));
785
+
786
+ // src/commands/registry/verify.ts
787
+ import * as Command10 from "@effect/cli/Command";
788
+ import * as Options6 from "@effect/cli/Options";
789
+ import * as FetchHttpClient6 from "@effect/platform/FetchHttpClient";
790
+ import * as Console9 from "effect/Console";
791
+ import * as Effect10 from "effect/Effect";
792
+ import * as Function6 from "effect/Function";
793
+ import * as Option7 from "effect/Option";
794
+ import { ClientService as ClientService6 } from "@dxos/client";
795
+ var verify = Command10.make("verify", {
796
+ handle: Options6.text("handle").pipe(Options6.withDescription(AUTH_OPTION_DESCRIPTIONS.handle), Options6.optional),
797
+ appPassword: Options6.text("app-password").pipe(Options6.withDescription(AUTH_OPTION_DESCRIPTIONS.appPassword), Options6.optional),
798
+ subject: Options6.text("subject").pipe(Options6.withDescription("Handle or DID of the publisher being verified.")),
799
+ subjectHandle: Options6.text("subject-handle").pipe(Options6.withDescription("Optional human-readable handle to record for the verified subject (defaults to --subject if it is a handle)."), Options6.optional),
800
+ displayName: Options6.text("display-name").pipe(Options6.withDescription("Display name to record for the verified subject."))
801
+ }, (options) => Function6.pipe(Effect10.gen(function* () {
802
+ const client = yield* ClientService6;
803
+ const session = yield* resolveSession({
804
+ handle: Option7.getOrUndefined(options.handle),
805
+ appPassword: Option7.getOrUndefined(options.appPassword),
806
+ client
807
+ });
808
+ const subjectDid = options.subject.startsWith("did:") ? options.subject : yield* resolveHandle(options.subject);
809
+ const subjectHandle = Option7.getOrUndefined(options.subjectHandle) ?? (options.subject.startsWith("did:") ? "" : options.subject);
810
+ const record = {
811
+ subject: subjectDid,
812
+ ...subjectHandle ? {
813
+ handle: subjectHandle
814
+ } : {},
815
+ displayName: options.displayName,
816
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
817
+ };
818
+ const result = yield* putRecord(session, NSID.PublisherVerification, subjectDid, record);
819
+ yield* Console9.log(`Verified ${subjectDid} -> ${result.uri}`);
820
+ }), Effect10.provide(FetchHttpClient6.layer))).pipe(Command10.withDescription("Write a publisher.verification record (indexed only if authored by the configured verifier, REGISTRY_CURATOR_DID)."));
821
+
822
+ // src/commands/registry/index.ts
823
+ var registry = Command11.make("registry").pipe(Command11.withDescription("Publish to and inspect the AT Protocol-backed DXOS plugin registry."), Command11.withSubcommands([
824
+ publish,
825
+ publishPackage,
826
+ publishPublisher,
827
+ unpublish,
828
+ verify,
829
+ records
830
+ ]));
831
+
142
832
  // src/RegistryPlugin.node.ts
143
833
  var RegistryPlugin = Plugin4.define(meta).pipe(AppPlugin.addCommandModule({
144
834
  commands: [
145
- plugin
835
+ plugin,
836
+ registry
146
837
  ]
147
838
  }), Plugin4.make);
148
839
  var RegistryPlugin_node_default = RegistryPlugin;