@dxos/app-framework 0.9.0 → 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.
Files changed (208) hide show
  1. package/dist/lib/browser/{capability-BOPAKKWG.mjs → capability-Z4MRP3CP.mjs} +9 -9
  2. package/dist/lib/browser/{chunk-CO3XLNUX.mjs → chunk-37PG7XJC.mjs} +18 -18
  3. package/dist/lib/browser/chunk-37PG7XJC.mjs.map +7 -0
  4. package/dist/lib/browser/{chunk-66IXTIVK.mjs → chunk-3NQLTQCP.mjs} +6 -7
  5. package/dist/lib/browser/chunk-3NQLTQCP.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-KZUDO43J.mjs → chunk-3UTDRCKX.mjs} +31 -23
  7. package/dist/lib/browser/chunk-3UTDRCKX.mjs.map +7 -0
  8. package/dist/lib/browser/chunk-53HJHMS5.mjs +7 -0
  9. package/dist/lib/browser/chunk-53HJHMS5.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-IW44C7UL.mjs → chunk-CMINFVA5.mjs} +1 -1
  11. package/dist/lib/browser/chunk-CMINFVA5.mjs.map +7 -0
  12. package/dist/lib/browser/{chunk-Y66ELD4U.mjs → chunk-DFVSOBV2.mjs} +17 -7
  13. package/dist/lib/browser/chunk-DFVSOBV2.mjs.map +7 -0
  14. package/dist/lib/browser/{chunk-DC3WRPBV.mjs → chunk-S2ZBYQPI.mjs} +45 -12
  15. package/dist/lib/browser/chunk-S2ZBYQPI.mjs.map +7 -0
  16. package/dist/lib/browser/{chunk-HFLKXMT7.mjs → chunk-SWECIICH.mjs} +57 -41
  17. package/dist/lib/browser/chunk-SWECIICH.mjs.map +7 -0
  18. package/dist/lib/browser/{chunk-5GY3YOEL.mjs → chunk-VF37YTXJ.mjs} +5 -5
  19. package/dist/lib/browser/chunk-VF37YTXJ.mjs.map +7 -0
  20. package/dist/lib/browser/{chunk-XHS5KDNX.mjs → chunk-W4BHZING.mjs} +25 -25
  21. package/dist/lib/browser/chunk-W4BHZING.mjs.map +7 -0
  22. package/dist/lib/browser/{chunk-FO3IYSLV.mjs → chunk-YUVQIOTB.mjs} +29 -37
  23. package/dist/lib/browser/chunk-YUVQIOTB.mjs.map +7 -0
  24. package/dist/lib/browser/cli/index.mjs +9 -9
  25. package/dist/lib/browser/cli/index.mjs.map +2 -2
  26. package/dist/lib/browser/common/activation-events.mjs +7 -7
  27. package/dist/lib/browser/common/capabilities.mjs +7 -7
  28. package/dist/lib/browser/config/index.mjs +8 -0
  29. package/dist/lib/browser/config/index.mjs.map +7 -0
  30. package/dist/lib/browser/core/activation-event.mjs +1 -1
  31. package/dist/lib/browser/core/capability.mjs +1 -1
  32. package/dist/lib/browser/core/plugin-manager.mjs +4 -4
  33. package/dist/lib/browser/core/plugin.mjs +12 -2
  34. package/dist/lib/browser/core/url-loader.mjs +3 -3
  35. package/dist/lib/browser/index.mjs +14 -10
  36. package/dist/lib/browser/index.mjs.map +1 -1
  37. package/dist/lib/browser/meta.json +1 -1
  38. package/dist/lib/browser/{process-manager-capability-GXNUO7AR.mjs → process-manager-capability-RDROCCQD.mjs} +9 -9
  39. package/dist/lib/browser/testing/index.mjs +15 -15
  40. package/dist/lib/browser/testing/index.mjs.map +3 -3
  41. package/dist/lib/browser/testing/react.mjs +11 -11
  42. package/dist/lib/browser/testing/react.mjs.map +3 -3
  43. package/dist/lib/browser/ui/index.mjs +16 -10
  44. package/dist/lib/node-esm/{capability-KZWRTX7R.mjs → capability-34Z6NPVR.mjs} +9 -9
  45. package/dist/lib/node-esm/chunk-2UPUZXGU.mjs +9 -0
  46. package/dist/lib/node-esm/chunk-2UPUZXGU.mjs.map +7 -0
  47. package/dist/lib/node-esm/{chunk-FSVGKTF6.mjs → chunk-A4O42ZO3.mjs} +17 -7
  48. package/dist/lib/node-esm/chunk-A4O42ZO3.mjs.map +7 -0
  49. package/dist/lib/node-esm/{chunk-CTKEZHKF.mjs → chunk-AIDZMJ3U.mjs} +1 -1
  50. package/dist/lib/node-esm/chunk-AIDZMJ3U.mjs.map +7 -0
  51. package/dist/lib/node-esm/{chunk-XOCUANHO.mjs → chunk-BMW6P6QA.mjs} +6 -7
  52. package/dist/lib/node-esm/chunk-BMW6P6QA.mjs.map +7 -0
  53. package/dist/lib/node-esm/{chunk-A5CHGAZE.mjs → chunk-H7T7XXLS.mjs} +57 -41
  54. package/dist/lib/node-esm/chunk-H7T7XXLS.mjs.map +7 -0
  55. package/dist/lib/node-esm/{chunk-NULBHQYS.mjs → chunk-LUK3FCTH.mjs} +18 -18
  56. package/dist/lib/node-esm/chunk-LUK3FCTH.mjs.map +7 -0
  57. package/dist/lib/node-esm/{chunk-XGBUKRCK.mjs → chunk-TEQSMP2O.mjs} +31 -23
  58. package/dist/lib/node-esm/chunk-TEQSMP2O.mjs.map +7 -0
  59. package/dist/lib/node-esm/{chunk-KFZEB6BV.mjs → chunk-TLKYZKPW.mjs} +5 -5
  60. package/dist/lib/node-esm/chunk-TLKYZKPW.mjs.map +7 -0
  61. package/dist/lib/node-esm/{chunk-WK7OIQKI.mjs → chunk-VCPGX7WN.mjs} +29 -37
  62. package/dist/lib/node-esm/chunk-VCPGX7WN.mjs.map +7 -0
  63. package/dist/lib/node-esm/{chunk-XIGPWXCQ.mjs → chunk-WERVO5EK.mjs} +45 -12
  64. package/dist/lib/node-esm/chunk-WERVO5EK.mjs.map +7 -0
  65. package/dist/lib/node-esm/{chunk-SX5NVETP.mjs → chunk-ZRTG4TSS.mjs} +25 -25
  66. package/dist/lib/node-esm/chunk-ZRTG4TSS.mjs.map +7 -0
  67. package/dist/lib/node-esm/cli/index.mjs +9 -9
  68. package/dist/lib/node-esm/cli/index.mjs.map +2 -2
  69. package/dist/lib/node-esm/common/activation-events.mjs +7 -7
  70. package/dist/lib/node-esm/common/capabilities.mjs +7 -7
  71. package/dist/lib/node-esm/config/index.mjs +9 -0
  72. package/dist/lib/node-esm/config/index.mjs.map +7 -0
  73. package/dist/lib/node-esm/core/activation-event.mjs +1 -1
  74. package/dist/lib/node-esm/core/capability.mjs +1 -1
  75. package/dist/lib/node-esm/core/plugin-manager.mjs +4 -4
  76. package/dist/lib/node-esm/core/plugin.mjs +12 -2
  77. package/dist/lib/node-esm/core/url-loader.mjs +3 -3
  78. package/dist/lib/node-esm/index.mjs +14 -10
  79. package/dist/lib/node-esm/index.mjs.map +1 -1
  80. package/dist/lib/node-esm/meta.json +1 -1
  81. package/dist/lib/node-esm/{process-manager-capability-TX5TA6YN.mjs → process-manager-capability-6OCXSKUW.mjs} +9 -9
  82. package/dist/lib/node-esm/testing/index.mjs +15 -15
  83. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  84. package/dist/lib/node-esm/testing/react.mjs +11 -11
  85. package/dist/lib/node-esm/testing/react.mjs.map +3 -3
  86. package/dist/lib/node-esm/ui/index.mjs +16 -10
  87. package/dist/plugin/node-esm/index.mjs +406 -71
  88. package/dist/plugin/node-esm/index.mjs.map +4 -4
  89. package/dist/plugin/node-esm/meta.json +1 -1
  90. package/dist/types/src/cli/cli.d.ts +1 -1
  91. package/dist/types/src/common/activation-events.d.ts.map +1 -1
  92. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  93. package/dist/types/src/config/index.d.ts +2 -0
  94. package/dist/types/src/config/index.d.ts.map +1 -0
  95. package/dist/types/src/core/activation-event.d.ts +9 -6
  96. package/dist/types/src/core/activation-event.d.ts.map +1 -1
  97. package/dist/types/src/core/capability.d.ts +6 -2
  98. package/dist/types/src/core/capability.d.ts.map +1 -1
  99. package/dist/types/src/core/edge-registry-plugin-provider.d.ts +6 -11
  100. package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -1
  101. package/dist/types/src/core/plugin-manager.d.ts.map +1 -1
  102. package/dist/types/src/core/plugin-manifest.d.ts +25 -7
  103. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -1
  104. package/dist/types/src/core/plugin.d.ts +81 -91
  105. package/dist/types/src/core/plugin.d.ts.map +1 -1
  106. package/dist/types/src/core/registry.d.ts +17 -57
  107. package/dist/types/src/core/registry.d.ts.map +1 -1
  108. package/dist/types/src/core/url-loader.d.ts +2 -2
  109. package/dist/types/src/core/url-loader.d.ts.map +1 -1
  110. package/dist/types/src/index.d.ts +1 -0
  111. package/dist/types/src/index.d.ts.map +1 -1
  112. package/dist/types/src/plugin-process-manager/meta.d.ts +28 -2
  113. package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -1
  114. package/dist/types/src/testing/harness.d.ts +1 -1
  115. package/dist/types/src/testing/harness.d.ts.map +1 -1
  116. package/dist/types/src/testing/react.d.ts +6 -5
  117. package/dist/types/src/testing/react.d.ts.map +1 -1
  118. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  119. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  120. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +6 -0
  121. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -1
  122. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +6 -10
  123. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -1
  124. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
  125. package/dist/types/src/ui/components/Surface/context.d.ts +6 -2
  126. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -1
  127. package/dist/types/src/ui/components/Surface/index.d.ts +10 -3
  128. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -1
  129. package/dist/types/src/ui/components/Surface/types.d.ts +50 -70
  130. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -1
  131. package/dist/types/src/ui/hooks/useApp.d.ts +1 -1
  132. package/dist/types/src/ui/hooks/useCapabilities.d.ts +11 -1
  133. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -1
  134. package/dist/types/src/vite-plugin/composer/index.d.ts +11 -4
  135. package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -1
  136. package/dist/types/src/vite-plugin/index.d.ts +1 -0
  137. package/dist/types/src/vite-plugin/index.d.ts.map +1 -1
  138. package/dist/types/src/vite-plugin/load.d.ts +16 -0
  139. package/dist/types/src/vite-plugin/load.d.ts.map +1 -0
  140. package/dist/types/src/vite-plugin/manifest.d.ts +16 -4
  141. package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -1
  142. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -1
  143. package/dist/types/tsconfig.tsbuildinfo +1 -1
  144. package/docs/registry-spec.md +331 -0
  145. package/moon.yml +1 -0
  146. package/package.json +32 -27
  147. package/src/cli/cli.ts +2 -2
  148. package/src/common/activation-events.ts +3 -3
  149. package/src/common/capabilities.ts +16 -16
  150. package/src/config/index.ts +5 -0
  151. package/src/core/activation-event.ts +15 -8
  152. package/src/core/capability.ts +15 -4
  153. package/src/core/edge-registry-plugin-provider.ts +41 -42
  154. package/src/core/plugin-manager.test.ts +133 -137
  155. package/src/core/plugin-manager.ts +25 -19
  156. package/src/core/plugin-manifest.test.ts +5 -5
  157. package/src/core/plugin-manifest.ts +13 -10
  158. package/src/core/plugin.ts +58 -114
  159. package/src/core/registry.ts +20 -60
  160. package/src/core/url-loader.test.ts +2 -2
  161. package/src/core/url-loader.ts +23 -19
  162. package/src/index.ts +1 -0
  163. package/src/testing/harness.ts +5 -3
  164. package/src/testing/react.test.tsx +4 -2
  165. package/src/testing/react.tsx +9 -8
  166. package/src/testing/service.ts +2 -2
  167. package/src/testing/withPluginManager.stories.tsx +4 -2
  168. package/src/testing/withPluginManager.tsx +3 -1
  169. package/src/ui/components/PluginManager/PluginManagerProvider.ts +7 -0
  170. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +11 -14
  171. package/src/ui/components/Surface/SurfaceComponent.tsx +84 -74
  172. package/src/ui/components/Surface/context.ts +6 -3
  173. package/src/ui/components/Surface/index.ts +12 -1
  174. package/src/ui/components/Surface/types.test.ts +39 -49
  175. package/src/ui/components/Surface/types.ts +95 -60
  176. package/src/ui/hooks/useApp.test.tsx +1 -1
  177. package/src/ui/hooks/useApp.tsx +2 -2
  178. package/src/ui/hooks/useCapabilities.ts +24 -2
  179. package/src/vite-plugin/composer/index.ts +134 -61
  180. package/src/vite-plugin/index.ts +1 -0
  181. package/src/vite-plugin/load.ts +57 -0
  182. package/src/vite-plugin/manifest.test.ts +3 -3
  183. package/src/vite-plugin/manifest.ts +21 -10
  184. package/src/vite-plugin/packages.ts +0 -1
  185. package/dist/lib/browser/chunk-5GY3YOEL.mjs.map +0 -7
  186. package/dist/lib/browser/chunk-66IXTIVK.mjs.map +0 -7
  187. package/dist/lib/browser/chunk-CO3XLNUX.mjs.map +0 -7
  188. package/dist/lib/browser/chunk-DC3WRPBV.mjs.map +0 -7
  189. package/dist/lib/browser/chunk-FO3IYSLV.mjs.map +0 -7
  190. package/dist/lib/browser/chunk-HFLKXMT7.mjs.map +0 -7
  191. package/dist/lib/browser/chunk-IW44C7UL.mjs.map +0 -7
  192. package/dist/lib/browser/chunk-KZUDO43J.mjs.map +0 -7
  193. package/dist/lib/browser/chunk-XHS5KDNX.mjs.map +0 -7
  194. package/dist/lib/browser/chunk-Y66ELD4U.mjs.map +0 -7
  195. package/dist/lib/node-esm/chunk-A5CHGAZE.mjs.map +0 -7
  196. package/dist/lib/node-esm/chunk-CTKEZHKF.mjs.map +0 -7
  197. package/dist/lib/node-esm/chunk-FSVGKTF6.mjs.map +0 -7
  198. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs.map +0 -7
  199. package/dist/lib/node-esm/chunk-NULBHQYS.mjs.map +0 -7
  200. package/dist/lib/node-esm/chunk-SX5NVETP.mjs.map +0 -7
  201. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +0 -7
  202. package/dist/lib/node-esm/chunk-XGBUKRCK.mjs.map +0 -7
  203. package/dist/lib/node-esm/chunk-XIGPWXCQ.mjs.map +0 -7
  204. package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +0 -7
  205. /package/dist/lib/browser/{capability-BOPAKKWG.mjs.map → capability-Z4MRP3CP.mjs.map} +0 -0
  206. /package/dist/lib/browser/{process-manager-capability-GXNUO7AR.mjs.map → process-manager-capability-RDROCCQD.mjs.map} +0 -0
  207. /package/dist/lib/node-esm/{capability-KZWRTX7R.mjs.map → capability-34Z6NPVR.mjs.map} +0 -0
  208. /package/dist/lib/node-esm/{process-manager-capability-TX5TA6YN.mjs.map → process-manager-capability-6OCXSKUW.mjs.map} +0 -0
@@ -341,7 +341,9 @@ class ManagerImpl implements PluginManager {
341
341
  // Core plugins are derived from `meta.tags.includes('system')`; the set is
342
342
  // a snapshot of the initial `plugins` array (later `add()` calls do not
343
343
  // promote plugins to core).
344
- const core: string[] = plugins.filter(({ meta }) => meta.tags?.includes('system')).map(({ meta }) => meta.id);
344
+ const core: string[] = plugins
345
+ .filter(({ meta }) => meta.profile.tags?.includes('system'))
346
+ .map(({ meta }) => meta.profile.key);
345
347
  this.registry = registry ?? Registry.make();
346
348
  this.capabilities = CapabilityManager.make({
347
349
  registry: this.registry,
@@ -531,7 +533,7 @@ class ManagerImpl implements PluginManager {
531
533
  return Effect.gen(this, function* () {
532
534
  log('add plugin', { id });
533
535
  const { plugin, dev = false } = yield* this._pluginLoader(id);
534
- const pluginId = plugin.meta.id;
536
+ const pluginId = plugin.meta.profile.key;
535
537
  const existing = this._getPlugin(pluginId);
536
538
 
537
539
  if (dev && existing && existing !== plugin) {
@@ -547,7 +549,9 @@ class ManagerImpl implements PluginManager {
547
549
  yield* this.disable(pluginId);
548
550
  }
549
551
  this._markDev(pluginId, { plugin: existing, wasEnabled });
550
- this._update(this._pluginsAtom, (plugins) => plugins.map((p) => (p.meta.id === pluginId ? plugin : p)));
552
+ this._update(this._pluginsAtom, (plugins) =>
553
+ plugins.map((p) => (p.meta.profile.key === pluginId ? plugin : p)),
554
+ );
551
555
  } else {
552
556
  this._addPlugin(plugin);
553
557
  if (dev) {
@@ -721,7 +725,7 @@ class ManagerImpl implements PluginManager {
721
725
  if (!Plugin.isLazy(plugin)) {
722
726
  return plugin;
723
727
  }
724
- const id = plugin.meta.id;
728
+ const id = plugin.meta.profile.key;
725
729
 
726
730
  const existing = this._resolvingPlugins.get(id);
727
731
  if (existing) {
@@ -747,7 +751,9 @@ class ManagerImpl implements PluginManager {
747
751
  }),
748
752
  }),
749
753
  );
750
- this._update(this._pluginsAtom, (plugins) => plugins.map((p) => (p.meta.id === id ? resolvedPlugin : p)));
754
+ this._update(this._pluginsAtom, (plugins) =>
755
+ plugins.map((p) => (p.meta.profile.key === id ? resolvedPlugin : p)),
756
+ );
751
757
  yield* PubSub.publish(this.activation, { event: '', state: 'activated', module: `lazy:${id}` });
752
758
  return resolvedPlugin;
753
759
  }).pipe(
@@ -1015,17 +1021,17 @@ class ManagerImpl implements PluginManager {
1015
1021
  }
1016
1022
 
1017
1023
  private _getPlugin(id: string): Plugin.Plugin | undefined {
1018
- return this._get(this._pluginsAtom).find((plugin) => plugin.meta.id === id);
1024
+ return this._get(this._pluginsAtom).find((plugin) => plugin.meta.profile.key === id);
1019
1025
  }
1020
1026
 
1021
1027
  private _getPluginIdForModule(moduleId: string): string | undefined {
1022
1028
  return this._get(this._pluginsAtom).find((plugin) => plugin.modules.some((module) => module.id === moduleId))?.meta
1023
- .id;
1029
+ .profile.key;
1024
1030
  }
1025
1031
 
1026
1032
  /** Looks up an id in the cached registry catalog, returning the entry or `undefined`. */
1027
- private _getCatalogEntry(id: string): PluginRegistry.Plugin | undefined {
1028
- return this._get(this.pluginRegistry.plugins).entries.find((entry) => entry.id === id);
1033
+ private _getCatalogEntry(id: string): Plugin.Meta | undefined {
1034
+ return this._get(this.pluginRegistry.plugins).entries.find((entry) => entry.profile.key === id);
1029
1035
  }
1030
1036
 
1031
1037
  /**
@@ -1037,10 +1043,10 @@ class ManagerImpl implements PluginManager {
1037
1043
  private _directDependencies(id: string): string[] {
1038
1044
  const plugin = this._getPlugin(id);
1039
1045
  if (plugin) {
1040
- return [...(plugin.meta.dependsOn ?? [])];
1046
+ return [...(plugin.meta.profile.dependsOn ?? [])];
1041
1047
  }
1042
1048
  const catalog = this._getCatalogEntry(id);
1043
- return catalog?.dependsOn ? [...catalog.dependsOn] : [];
1049
+ return catalog?.profile.dependsOn ? [...catalog.profile.dependsOn] : [];
1044
1050
  }
1045
1051
 
1046
1052
  /**
@@ -1068,8 +1074,8 @@ class ManagerImpl implements PluginManager {
1068
1074
  let cycle: string[] | undefined;
1069
1075
 
1070
1076
  const knownIds = new Set<string>([
1071
- ...this._get(this._pluginsAtom).map((plugin) => plugin.meta.id),
1072
- ...this._get(this.pluginRegistry.plugins).entries.map((entry) => entry.id),
1077
+ ...this._get(this._pluginsAtom).map((plugin) => plugin.meta.profile.key),
1078
+ ...this._get(this.pluginRegistry.plugins).entries.map((entry) => entry.profile.key),
1073
1079
  ]);
1074
1080
 
1075
1081
  const visit = (currentId: string): void => {
@@ -1120,8 +1126,8 @@ class ManagerImpl implements PluginManager {
1120
1126
  */
1121
1127
  private _collectDependents(id: string, opts: { transitive: boolean; enabledOnly: boolean }): string[] {
1122
1128
  const direct = this._get(this._pluginsAtom)
1123
- .filter((plugin) => plugin.meta.dependsOn?.some((dep) => dep === id))
1124
- .map((plugin) => plugin.meta.id);
1129
+ .filter((plugin) => plugin.meta.profile.dependsOn?.some((dep) => dep === id))
1130
+ .map((plugin) => plugin.meta.profile.key);
1125
1131
 
1126
1132
  if (!opts.transitive) {
1127
1133
  return opts.enabledOnly
@@ -1137,8 +1143,8 @@ class ManagerImpl implements PluginManager {
1137
1143
  }
1138
1144
  visited.add(currentId);
1139
1145
  const parents = this._get(this._pluginsAtom)
1140
- .filter((plugin) => plugin.meta.dependsOn?.some((dep) => dep === currentId))
1141
- .map((plugin) => plugin.meta.id);
1146
+ .filter((plugin) => plugin.meta.profile.dependsOn?.some((dep) => dep === currentId))
1147
+ .map((plugin) => plugin.meta.profile.key);
1142
1148
  for (const parentId of parents) {
1143
1149
  visit(parentId);
1144
1150
  if (parentId !== id && !result.includes(parentId)) {
@@ -1281,14 +1287,14 @@ class ManagerImpl implements PluginManager {
1281
1287
  //
1282
1288
 
1283
1289
  private _addPlugin(plugin: Plugin.Plugin): void {
1284
- log('add plugin', { id: plugin.meta.id });
1290
+ log('add plugin', { id: plugin.meta.profile.key });
1285
1291
  // TODO(wittjosiah): Find a way to add a warning for duplicate plugins that doesn't cause log spam.
1286
1292
  this._update(this._pluginsAtom, (plugins) => (plugins.includes(plugin) ? plugins : [...plugins, plugin]));
1287
1293
  }
1288
1294
 
1289
1295
  private _removePlugin(id: string): void {
1290
1296
  log('remove plugin', { id });
1291
- this._update(this._pluginsAtom, (plugins) => plugins.filter((plugin) => plugin.meta.id !== id));
1297
+ this._update(this._pluginsAtom, (plugins) => plugins.filter((plugin) => plugin.meta.profile.key !== id));
1292
1298
  }
1293
1299
 
1294
1300
  private _addModule(module: Plugin.PluginModule): void {
@@ -10,12 +10,12 @@ describe('PluginManifest', () => {
10
10
  describe('parse', () => {
11
11
  test('resolves entry and assets relative to manifest URL', ({ expect }) => {
12
12
  const resolved = PluginManifest.parse('https://example.com/plugins/foo/manifest.json', {
13
- id: 'com.example.foo',
13
+ key: 'com.example.foo',
14
14
  name: 'Foo',
15
15
  version: '1.0.0',
16
16
  assets: ['index.mjs', 'style.css', 'chunks/lib-abc.js'],
17
17
  });
18
- expect(resolved.id).toBe('com.example.foo');
18
+ expect(resolved.key).toBe('com.example.foo');
19
19
  expect(resolved.dev).toBe(false);
20
20
  expect(resolved.entryUrl).toBe('https://example.com/plugins/foo/index.mjs');
21
21
  expect(resolved.assetUrls).toEqual([
@@ -28,7 +28,7 @@ describe('PluginManifest', () => {
28
28
  test('throws if the canonical entry filename is not listed in assets', ({ expect }) => {
29
29
  expect(() =>
30
30
  PluginManifest.parse('https://example.com/manifest.json', {
31
- id: 'a',
31
+ key: 'a',
32
32
  name: 'A',
33
33
  version: '0.0.1',
34
34
  assets: ['style.css'],
@@ -48,7 +48,7 @@ describe('PluginManifest', () => {
48
48
 
49
49
  test('devEntry flips dev mode and resolves the entry against the manifest URL', ({ expect }) => {
50
50
  const resolved = PluginManifest.parse('http://localhost:3967/manifest.json', {
51
- id: 'com.example.foo',
51
+ key: 'com.example.foo',
52
52
  name: 'Foo',
53
53
  version: '0.0.0-dev',
54
54
  assets: [],
@@ -63,7 +63,7 @@ describe('PluginManifest', () => {
63
63
  // No `index.mjs` in assets — would throw without devEntry.
64
64
  expect(() =>
65
65
  PluginManifest.parse('http://localhost:3967/manifest.json', {
66
- id: 'a',
66
+ key: 'a',
67
67
  name: 'A',
68
68
  version: '0.0.0-dev',
69
69
  assets: [],
@@ -10,7 +10,7 @@ import * as Effect from 'effect/Effect';
10
10
  import * as Schema from 'effect/Schema';
11
11
 
12
12
  import { BaseError } from '@dxos/errors';
13
- import { PLUGIN_ENTRY_FILENAME } from '@dxos/protocols';
13
+ import { PLUGIN_ENTRY_FILENAME, PluginManifestSchema } from '@dxos/protocols';
14
14
 
15
15
  /**
16
16
  * Default port the Vite plugin (`composerPlugin`) binds the dev server to.
@@ -48,11 +48,16 @@ export class PluginManifestError extends BaseError.extend('PluginManifestError',
48
48
  * the dev server on demand.
49
49
  */
50
50
  export const Manifest = Schema.Struct({
51
- id: Schema.String,
52
- name: Schema.String,
53
- version: Schema.String,
51
+ // Reuse the build manifest field definitions from `@dxos/protocols` (the shape `composerPlugin`
52
+ // emits), minus `assets` which we relax below, plus the dev-only `devEntry`.
53
+ ...PluginManifestSchema.omit('assets').fields,
54
+ /**
55
+ * Relative asset paths. Relaxed vs the build `PluginManifestSchema` (which requires >= 1) because
56
+ * dev-server manifests list no assets — chunks/styles flow through the dev server on demand.
57
+ */
54
58
  assets: Schema.Array(Schema.String),
55
- devEntry: Schema.String.pipe(Schema.optional),
59
+ /** Present only for dev-server manifests; points at the unbundled source entry. */
60
+ devEntry: Schema.optional(Schema.String),
56
61
  });
57
62
 
58
63
  export type Manifest = Schema.Schema.Type<typeof Manifest>;
@@ -64,10 +69,7 @@ export type Manifest = Schema.Schema.Type<typeof Manifest>;
64
69
  * on this to skip offline caching and stylesheet injection — both are no-ops (or
65
70
  * actively wrong) when the plugin is being served by a Vite dev server.
66
71
  */
67
- export type ResolvedManifest = {
68
- id: string;
69
- name: string;
70
- version: string;
72
+ export type ResolvedManifest = Pick<Manifest, 'key' | 'name' | 'version' | 'dependencies'> & {
71
73
  entryUrl: string;
72
74
  assetUrls: readonly string[];
73
75
  dev: boolean;
@@ -81,12 +83,13 @@ export type ResolvedManifest = {
81
83
  const resolve = (manifestUrl: string, manifest: Manifest): ResolvedManifest => {
82
84
  const dev = manifest.devEntry !== undefined;
83
85
  return {
84
- id: manifest.id,
86
+ key: manifest.key,
85
87
  name: manifest.name,
86
88
  version: manifest.version,
87
89
  entryUrl: new URL(dev ? manifest.devEntry! : PLUGIN_ENTRY_FILENAME, manifestUrl).toString(),
88
90
  assetUrls: manifest.assets.map((asset) => new URL(asset, manifestUrl).toString()),
89
91
  dev,
92
+ ...(manifest.dependencies !== undefined ? { dependencies: manifest.dependencies } : {}),
90
93
  };
91
94
  };
92
95
 
@@ -6,10 +6,12 @@ import * as Context from 'effect/Context';
6
6
  import * as Effect from 'effect/Effect';
7
7
  import * as Option from 'effect/Option';
8
8
  import * as Pipeable from 'effect/Pipeable';
9
+ import * as Schema from 'effect/Schema';
9
10
 
10
11
  import { BaseError } from '@dxos/errors';
11
12
  import { invariant } from '@dxos/invariant';
12
13
  import { DXN } from '@dxos/keys';
14
+ import { Config2, PluginProfileSchema, PluginReleaseSchema } from '@dxos/protocols';
13
15
 
14
16
  import type * as ActivationEvent from './activation-event';
15
17
  import * as Capability from './capability';
@@ -148,125 +150,64 @@ class PluginModuleImpl implements PluginModule {
148
150
  }
149
151
  }
150
152
 
151
- export type Meta = {
152
- /**
153
- * Bare NSID (the name portion of {@link key}, e.g. `org.dxos.plugin.example`).
154
- * Stable across versions; used for module-id namespacing, i18n namespaces,
155
- * enable/disable, and registry lookups. Derived from `key` by {@link makeMeta}
156
- * do not set directly.
157
- */
158
- id: string;
159
-
160
- /**
161
- * Canonical identity DXN, including version when published
162
- * (e.g. `dxn:org.dxos.plugin.example:0.8.3`). The validated source of truth
163
- * from which {@link id} and {@link version} are derived.
164
- *
165
- * @example DXN.make('org.dxos.plugin.example', '0.8.3')
166
- */
167
- key: DXN.DXN;
153
+ /**
154
+ * Runtime plugin metadata, derived from the `@dxos/protocols` registry schemas (protocols owns the
155
+ * config + registry schemas; the runtime projection lives here).
156
+ *
157
+ * - {@link Profile}: version-independent identity + display + provenance the wire `PluginProfileSchema`
158
+ * (which carries `key`, the display fields, `dependsOn`, `spec`) plus `author` (resolved at runtime
159
+ * from the publisher's handle/DID for registry plugins, or self-declared for bundled).
160
+ * - {@link Release}: a specific hosted release — the wire `PluginReleaseSchema` (version, moduleUrl, dependencies).
161
+ * - {@link Meta}: a resolved single-release view — `{ profile, release? }`, both nested. `release` is
162
+ * unset for bundled plugins (compiled in) and set for registry plugins.
163
+ */
164
+ export const Profile = Schema.Struct({
165
+ ...PluginProfileSchema.fields,
166
+ author: Schema.optional(Schema.String),
167
+ });
168
+ export type Profile = Schema.Schema.Type<typeof Profile>;
168
169
 
169
- /**
170
- * Human-readable name.
171
- */
172
- name: string;
170
+ export const Release = PluginReleaseSchema;
171
+ export type Release = Schema.Schema.Type<typeof Release>;
173
172
 
174
- /**
175
- * Semver version string of the plugin, typically the publishing package's
176
- * `package.json` version. Derived from the version segment of {@link key} by
177
- * {@link makeMeta} — do not set directly.
178
- */
179
- version?: string;
173
+ export const Meta = Schema.Struct({
174
+ profile: Profile,
175
+ release: Schema.optional(Release),
176
+ });
177
+ export type Meta = Schema.Schema.Type<typeof Meta>;
180
178
 
181
- /**
182
- * Short description of plugin functionality.
183
- */
179
+ /** Options for {@link makeMeta}: the {@link Profile} content fields plus the canonical DXN `key`. */
180
+ export type MakeMetaOptions = {
181
+ key: DXN.DXN;
182
+ name: string;
184
183
  description?: string;
185
-
186
- /**
187
- * Name of the author or organization that created the plugin.
188
- */
189
- // TODO(burdon): DID or domain name?
190
184
  author?: string;
191
-
192
- /**
193
- * URL of home page.
194
- */
195
185
  homePage?: string;
196
-
197
- /**
198
- * URL of source code.
199
- */
200
186
  source?: string;
201
-
202
- /**
203
- * Relative path (inside the published package) to the plugin's bundled MDL
204
- * specification file — e.g. `'PLUGIN.mdl'` or `'docs/PLUGIN.mdl'`. The file
205
- * is shipped via the package's `files` entry and resolved by registry
206
- * surfaces to render an in-app viewer and/or external link.
207
- */
187
+ tags?: readonly string[];
188
+ dependsOn?: readonly string[];
208
189
  spec?: string;
190
+ icon?: Config2.Icon;
191
+ screenshots?: ReadonlyArray<Config2.Screenshot>;
192
+ };
209
193
 
210
- /**
211
- * URL of screenshot.
212
- */
213
- screenshots?: string[];
214
-
215
- /**
216
- * Tags to help categorize the plugin.
217
- */
218
- tags?: string[];
219
-
220
- /**
221
- * A grep-able symbol string which can be resolved to an icon asset by @ch-ui/icons, via @ch-ui/vite-plugin-icons.
222
- */
223
- icon?: string;
224
-
225
- /**
226
- * Icon hue (ChromaticPalette).
227
- */
228
- iconHue?: string;
229
-
230
- /**
231
- * IDs of plugins this plugin functionally depends on.
232
- *
233
- * Treated as a convenience by the default `PluginManager` flow:
234
- * - Enabling this plugin auto-enables the transitive closure of `dependsOn`
235
- * (installing missing entries from the plugin registry when possible).
236
- * - Disabling a depended-upon plugin surfaces dependents to the caller; the
237
- * `PluginManager.disable` API supports an opt-in cascade.
238
- *
239
- * Not an invariant: low-level `PluginManager` APIs accept opt-outs
240
- * (`resolveDependencies: false`, `ignoreDependents: true`) so a caller may
241
- * substitute an alternative implementation that satisfies the dependent's
242
- * capability needs in its own way.
243
- */
244
- dependsOn?: string[];
194
+ /** Constructs a bundled-plugin {@link Meta} from a canonical DXN. `profile.key` is the bare NSID derived from `key`. */
195
+ export const makeMeta = (options: MakeMetaOptions): Meta => {
196
+ const { key, ...rest } = options;
197
+ return { profile: { ...rest, key: DXN.getName(key) } };
245
198
  };
246
199
 
247
- /**
248
- * Options for {@link makeMeta}: a {@link Meta} minus the fields derived from `key`.
249
- * Identity and version are specified solely through the `key` DXN — `id` and
250
- * `version` cannot be passed directly.
251
- */
252
- export type MakeMetaOptions = Omit<Meta, 'id' | 'version'>;
200
+ /** Returns the plugin's canonical DXN URI, constructed from `meta.profile.key` and `meta.release?.version`. */
201
+ export const getURI = (meta: Meta): DXN.DXN => DXN.make(meta.profile.key, meta.release?.version);
253
202
 
254
203
  /**
255
- * Constructs a plugin {@link Meta} from a single canonical DXN. The `key` DXN is
256
- * the one source of truth; `id` (bare NSID) and `version` (semver) are derived
257
- * from it so each datum has exactly one home and cannot drift out of sync.
258
- *
259
- * @example
260
- * export const meta = Plugin.makeMeta({
261
- * key: DXN.make('org.dxos.plugin.example', '0.8.3'),
262
- * name: 'Example',
263
- * });
204
+ * Derives a runtime {@link Meta} from a loaded `dx.config.ts` (the `@dxos/protocols` `Config2.Config`).
205
+ * Maps the flat authoring config to the nested profile; bundled plugins have no `release`.
264
206
  */
265
- export const makeMeta = (options: MakeMetaOptions): Meta => ({
266
- ...options,
267
- id: DXN.getName(options.key),
268
- version: DXN.getVersion(options.key),
269
- });
207
+ export const getMetaFromConfig = ({ plugin }: Config2.Config): Meta => {
208
+ const { key, ...rest } = plugin;
209
+ return makeMeta({ key: DXN.make(key), ...rest });
210
+ };
270
211
 
271
212
  /**
272
213
  * Identifier denoting a Plugin.
@@ -389,12 +330,12 @@ const resolveModule = (
389
330
  options?: any,
390
331
  ): PluginModuleImpl => {
391
332
  const moduleOptions = typeof module === 'function' ? module(options) : module;
392
- const pluginName = meta.id;
333
+ const pluginName = meta.profile.key;
393
334
  const id = Option.fromNullable(moduleOptions.id).pipe(
394
335
  Option.match({
395
336
  onNone: () => {
396
337
  const exportName = Capability.getModuleTag(moduleOptions.activate);
397
- invariant(exportName, `Plugin module missing name. Plugin: ${meta.id}`);
338
+ invariant(exportName, `Plugin module missing name. Plugin: ${meta.profile.key}`);
398
339
  return computeModuleId(pluginName, exportName);
399
340
  },
400
341
  onSome: (id) => computeModuleId(pluginName, id),
@@ -412,8 +353,11 @@ const resolveModule = (
412
353
  export function make<T>(builder: PluginBuilder<T>): PluginFactory<T>;
413
354
  export function make<T>(builder: PluginBuilder<T>): PluginFactory<T> {
414
355
  const meta = builder.meta;
415
- // `dependsOn` entries and `id` are both bare NSIDs, so compare directly.
416
- invariant(!meta.dependsOn?.includes(meta.id), `Plugin ${meta.id} declares itself as a dependency.`);
356
+ // `dependsOn` entries and `key` are both bare NSIDs, so compare directly.
357
+ invariant(
358
+ !meta.profile.dependsOn?.includes(meta.profile.key),
359
+ `Plugin ${meta.profile.key} declares itself as a dependency.`,
360
+ );
417
361
 
418
362
  const factory = (options: T) => {
419
363
  const modules = builder.modules.map((module) => resolveModule(meta, module, options));
@@ -448,7 +392,7 @@ type LazyPayload = { loader: LazyLoader<any>; options: unknown };
448
392
  * Defines a lazy plugin whose body is loaded on first enable.
449
393
  *
450
394
  * The returned factory produces a stub `Plugin` that exposes `meta`
451
- * synchronously (so callers can read `Plugin.meta.id` for free) but defers
395
+ * synchronously (so callers can read `Plugin.meta.profile.key` for free) but defers
452
396
  * loading the real plugin's modules until the manager calls
453
397
  * `Plugin.resolveLazy`. This lets the plugin's main entry point ship as a
454
398
  * tiny meta-only chunk — the heavy capabilities, schema, React surfaces,
@@ -487,7 +431,7 @@ export const isLazy = (plugin: Plugin): boolean => LazyTag in plugin;
487
431
 
488
432
  /**
489
433
  * Tagged error for failures during lazy plugin resolution. `context.id` is
490
- * the lazy plugin's `meta.id`; `context.reason` discriminates the failure
434
+ * the lazy plugin's `meta.profile.key`; `context.reason` discriminates the failure
491
435
  * mode (`'load-failed' | 'missing-default' | 'invalid-plugin' |
492
436
  * 'meta-mismatch'`) so callers can route on it.
493
437
  */
@@ -522,7 +466,7 @@ export const resolveLazy = (plugin: Plugin): Effect.Effect<Plugin, LazyPluginErr
522
466
  if (!isLazy(plugin)) {
523
467
  return plugin;
524
468
  }
525
- const id = plugin.meta.id;
469
+ const id = plugin.meta.profile.key;
526
470
  const { loader, options } = (plugin as unknown as { [LazyTag]: LazyPayload })[LazyTag];
527
471
  const mod = yield* Effect.tryPromise({
528
472
  try: loader,
@@ -535,9 +479,9 @@ export const resolveLazy = (plugin: Plugin): Effect.Effect<Plugin, LazyPluginErr
535
479
  if (!isPlugin(result)) {
536
480
  return yield* Effect.fail(new LazyPluginError({ context: { id, reason: 'invalid-plugin' } }));
537
481
  }
538
- if (result.meta.id !== id) {
482
+ if (result.meta.profile.key !== id) {
539
483
  return yield* Effect.fail(
540
- new LazyPluginError({ context: { id, reason: 'meta-mismatch', returnedId: result.meta.id } }),
484
+ new LazyPluginError({ context: { id, reason: 'meta-mismatch', returnedId: result.meta.profile.key } }),
541
485
  );
542
486
  }
543
487
  return result;
@@ -8,53 +8,14 @@ import * as Effect from 'effect/Effect';
8
8
  import { EffectEx } from '@dxos/effect';
9
9
  import { log } from '@dxos/log';
10
10
 
11
- /**
12
- * A registry plugin entry as seen by the plugin manager layer.
13
- * Populated from the registry catalog; represents the latest available version of a plugin.
14
- *
15
- * Independently defined from @dxos/protocols PluginEntry — similar shape but not the same type.
16
- * Implementations of {@link PluginProvider} (e.g. {@link EdgeRegistryPluginProvider})
17
- * are responsible for mapping their wire-format entries to this shape.
18
- */
19
- export type Plugin = {
20
- id: string;
21
- name: string;
22
- description?: string;
23
- homePage?: string;
24
- source?: string;
25
- screenshots?: string[];
26
- tags?: string[];
27
- icon?: string;
28
- iconHue?: string;
29
- /**
30
- * IDs of plugins this entry declares as runtime dependencies. Mirrors
31
- * {@link Plugin.Meta.dependsOn}. Surfaced in the catalog so the manager can
32
- * resolve and auto-install transitive deps before they are first loaded.
33
- */
34
- dependsOn?: string[];
35
- /** URL to dynamic-import the latest version of this plugin module. */
36
- moduleUrl: string;
37
- /** GitHub repository slug, e.g. `owner/name`. Used to fetch version history. */
38
- repo: string;
39
- /**
40
- * Latest known version string, e.g. `v1.2.0`.
41
- * Corresponds to releaseTag in the wire-format PluginEntry; named `version` here
42
- * because the plugin manager layer speaks versions, not release tags.
43
- */
44
- version: string;
45
- };
11
+ import type * as Plugin from './plugin';
46
12
 
47
13
  /**
48
- * A single installable version of a registry plugin.
14
+ * A registry catalog entry is a {@link Plugin.Meta} (profile + the latest release), the same
15
+ * runtime type bundled plugins use. {@link PluginProvider} implementations (e.g.
16
+ * {@link EdgeRegistryPluginProvider}) map their wire-format entries (`PluginView`) to this shape.
17
+ * A single installable version is a {@link Plugin.Release}.
49
18
  */
50
- export type PluginVersion = {
51
- /** Version string, e.g. `v1.2.0`. */
52
- tag: string;
53
- /** URL to dynamic-import this specific version of the plugin module. */
54
- moduleUrl: string;
55
- /** Unix ms of when this version was published (optional; omitted when unknown). */
56
- releasedAt?: number;
57
- };
58
19
 
59
20
  /**
60
21
  * Abstraction over the plugin registry catalog backend.
@@ -67,23 +28,22 @@ export type PluginVersion = {
67
28
  */
68
29
  export interface PluginProvider {
69
30
  /**
70
- * Returns all healthy registry plugins (latest version of each).
31
+ * Returns all registry plugins (latest version of each).
71
32
  */
72
- listPlugins(): Effect.Effect<readonly Plugin[], Error>;
33
+ listPlugins(): Effect.Effect<readonly Plugin.Meta[], Error>;
73
34
 
74
35
  /**
75
- * Returns all known versions of a plugin identified by its GitHub repo slug.
76
- * Until the backend implements a versions endpoint, implementations MUST
77
- * return at least one entry representing the current/latest release.
36
+ * Returns all known versions of a plugin, identified by its composer plugin id (NSID).
37
+ * Ordered newest-first. Must return at least one entry.
78
38
  */
79
- listVersions(repo: string): Effect.Effect<readonly PluginVersion[], Error>;
39
+ listVersions(id: string): Effect.Effect<readonly Plugin.Release[], Error>;
80
40
 
81
41
  /**
82
- * Returns a single plugin entry for the given repo.
42
+ * Returns a single plugin entry for the given id.
83
43
  * If `version` is omitted, returns the latest.
84
- * Fails if the specified version is not found.
44
+ * Fails if the plugin or version is not found.
85
45
  */
86
- getPlugin(repo: string, version?: string): Effect.Effect<Plugin, Error>;
46
+ getPlugin(id: string, version?: string): Effect.Effect<Plugin.Meta, Error>;
87
47
  }
88
48
 
89
49
  /**
@@ -92,7 +52,7 @@ export interface PluginProvider {
92
52
  * (loading state, list contents, last error).
93
53
  */
94
54
  export type PluginsState = {
95
- entries: readonly Plugin[];
55
+ entries: readonly Plugin.Meta[];
96
56
  loading: boolean;
97
57
  error: Error | null;
98
58
  };
@@ -106,7 +66,7 @@ export type PluginsState = {
106
66
  * callers know they need to configure a real provider.
107
67
  */
108
68
  const NULL_PROVIDER: PluginProvider = {
109
- listPlugins: () => Effect.succeed([] as readonly Plugin[]),
69
+ listPlugins: () => Effect.succeed([] as readonly Plugin.Meta[]),
110
70
  listVersions: () => Effect.fail(new Error('No plugin registry provider configured')),
111
71
  getPlugin: () => Effect.fail(new Error('No plugin registry provider configured')),
112
72
  };
@@ -147,17 +107,17 @@ export class Manager {
147
107
  }
148
108
 
149
109
  /** Forwards to the underlying provider. */
150
- listPlugins(): Effect.Effect<readonly Plugin[], Error> {
110
+ listPlugins(): Effect.Effect<readonly Plugin.Meta[], Error> {
151
111
  return this.#provider.listPlugins();
152
112
  }
153
113
 
154
114
  /** Forwards to the underlying provider. */
155
- listVersions(repo: string): Effect.Effect<readonly PluginVersion[], Error> {
156
- return this.#provider.listVersions(repo);
115
+ listVersions(id: string): Effect.Effect<readonly Plugin.Release[], Error> {
116
+ return this.#provider.listVersions(id);
157
117
  }
158
118
 
159
119
  /** Forwards to the underlying provider. */
160
- getPlugin(repo: string, version?: string): Effect.Effect<Plugin, Error> {
161
- return this.#provider.getPlugin(repo, version);
120
+ getPlugin(id: string, version?: string): Effect.Effect<Plugin.Meta, Error> {
121
+ return this.#provider.getPlugin(id, version);
162
122
  }
163
123
  }
@@ -129,8 +129,8 @@ describe('UrlLoader', () => {
129
129
  Effect.gen(function* () {
130
130
  const testPlugin = Plugin.make(Plugin.define(testMeta))();
131
131
  const loader = UrlLoader.make([testPlugin]);
132
- const result = yield* loader(testMeta.id);
133
- assert.strictEqual(result.plugin.meta.id, testMeta.id);
132
+ const result = yield* loader(testMeta.profile.key);
133
+ assert.strictEqual(result.plugin.meta.profile.key, testMeta.profile.key);
134
134
  // Builtins are not dev plugins.
135
135
  assert.notOk(result.dev);
136
136
  }),