@anvilkit/plugin-asset-manager 0.1.5 → 0.1.7

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 (224) hide show
  1. package/README.md +27 -19
  2. package/dist/adapters/data-url.cjs +9 -5
  3. package/dist/adapters/extract-image-dimensions.cjs +12 -8
  4. package/dist/adapters/in-memory.cjs +9 -5
  5. package/dist/adapters/s3-presigned.cjs +9 -5
  6. package/dist/index.cjs +16 -5
  7. package/dist/index.d.cts +11 -3
  8. package/dist/index.d.cts.map +1 -1
  9. package/dist/index.d.ts +11 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -1
  12. package/dist/plugin.cjs +76 -9
  13. package/dist/plugin.d.cts +3 -2
  14. package/dist/plugin.d.cts.map +1 -1
  15. package/dist/plugin.d.ts +3 -2
  16. package/dist/plugin.d.ts.map +1 -1
  17. package/dist/plugin.js +67 -4
  18. package/dist/sources/composite-source.cjs +137 -0
  19. package/dist/sources/composite-source.d.cts +39 -0
  20. package/dist/sources/composite-source.d.cts.map +1 -0
  21. package/dist/sources/composite-source.d.ts +39 -0
  22. package/dist/sources/composite-source.d.ts.map +1 -0
  23. package/dist/sources/composite-source.js +99 -0
  24. package/dist/sources/federated-search.cjs +163 -0
  25. package/dist/sources/federated-search.d.cts +33 -0
  26. package/dist/sources/federated-search.d.cts.map +1 -0
  27. package/dist/sources/federated-search.d.ts +33 -0
  28. package/dist/sources/federated-search.d.ts.map +1 -0
  29. package/dist/sources/federated-search.js +113 -0
  30. package/dist/sources/provider.cjs +18 -0
  31. package/dist/sources/provider.d.cts +51 -0
  32. package/dist/sources/provider.d.cts.map +1 -0
  33. package/dist/sources/provider.d.ts +51 -0
  34. package/dist/sources/provider.d.ts.map +1 -0
  35. package/dist/sources/provider.js +1 -0
  36. package/dist/sources/unsplash/client.cjs +189 -0
  37. package/dist/sources/unsplash/client.d.cts +87 -0
  38. package/dist/sources/unsplash/client.d.cts.map +1 -0
  39. package/dist/sources/unsplash/client.d.ts +87 -0
  40. package/dist/sources/unsplash/client.d.ts.map +1 -0
  41. package/dist/sources/unsplash/client.js +151 -0
  42. package/dist/sources/unsplash/index.cjs +192 -0
  43. package/dist/sources/unsplash/index.d.cts +16 -0
  44. package/dist/sources/unsplash/index.d.cts.map +1 -0
  45. package/dist/sources/unsplash/index.d.ts +16 -0
  46. package/dist/sources/unsplash/index.d.ts.map +1 -0
  47. package/dist/sources/unsplash/index.js +148 -0
  48. package/dist/sources/unsplash/themes.cjs +141 -0
  49. package/dist/sources/unsplash/themes.d.cts +18 -0
  50. package/dist/sources/unsplash/themes.d.cts.map +1 -0
  51. package/dist/sources/unsplash/themes.d.ts +18 -0
  52. package/dist/sources/unsplash/themes.d.ts.map +1 -0
  53. package/dist/sources/unsplash/themes.js +93 -0
  54. package/dist/sources/unsplash/throttle-cache.cjs +86 -0
  55. package/dist/sources/unsplash/throttle-cache.d.cts +25 -0
  56. package/dist/sources/unsplash/throttle-cache.d.cts.map +1 -0
  57. package/dist/sources/unsplash/throttle-cache.d.ts +25 -0
  58. package/dist/sources/unsplash/throttle-cache.d.ts.map +1 -0
  59. package/dist/sources/unsplash/throttle-cache.js +45 -0
  60. package/dist/testing/index.cjs +9 -5
  61. package/dist/types/categories.cjs +18 -0
  62. package/dist/types/categories.d.cts +48 -0
  63. package/dist/types/categories.d.cts.map +1 -0
  64. package/dist/types/categories.d.ts +48 -0
  65. package/dist/types/categories.d.ts.map +1 -0
  66. package/dist/types/categories.js +1 -0
  67. package/dist/types/data-source.cjs +18 -0
  68. package/dist/types/data-source.d.cts +59 -0
  69. package/dist/types/data-source.d.cts.map +1 -0
  70. package/dist/types/data-source.d.ts +59 -0
  71. package/dist/types/data-source.d.ts.map +1 -0
  72. package/dist/types/data-source.js +1 -0
  73. package/dist/types/filter.cjs +18 -0
  74. package/dist/types/filter.d.cts +55 -0
  75. package/dist/types/filter.d.cts.map +1 -0
  76. package/dist/types/filter.d.ts +55 -0
  77. package/dist/types/filter.d.ts.map +1 -0
  78. package/dist/types/filter.js +1 -0
  79. package/dist/types/folders.cjs +42 -0
  80. package/dist/types/folders.d.cts +46 -0
  81. package/dist/types/folders.d.cts.map +1 -0
  82. package/dist/types/folders.d.ts +46 -0
  83. package/dist/types/folders.d.ts.map +1 -0
  84. package/dist/types/folders.js +4 -0
  85. package/dist/types/options.cjs +18 -0
  86. package/dist/types/options.d.cts +68 -0
  87. package/dist/types/options.d.cts.map +1 -0
  88. package/dist/types/options.d.ts +68 -0
  89. package/dist/types/options.d.ts.map +1 -0
  90. package/dist/types/options.js +1 -0
  91. package/dist/types/types.d.cts +15 -27
  92. package/dist/types/types.d.cts.map +1 -1
  93. package/dist/types/types.d.ts +15 -27
  94. package/dist/types/types.d.ts.map +1 -1
  95. package/dist/types/unsplash.cjs +18 -0
  96. package/dist/types/unsplash.d.cts +60 -0
  97. package/dist/types/unsplash.d.cts.map +1 -0
  98. package/dist/types/unsplash.d.ts +60 -0
  99. package/dist/types/unsplash.d.ts.map +1 -0
  100. package/dist/types/unsplash.js +1 -0
  101. package/dist/ui/AssetBrowser.cjs +69 -104
  102. package/dist/ui/AssetBrowser.d.cts +17 -7
  103. package/dist/ui/AssetBrowser.d.cts.map +1 -1
  104. package/dist/ui/AssetBrowser.d.ts +17 -7
  105. package/dist/ui/AssetBrowser.d.ts.map +1 -1
  106. package/dist/ui/AssetBrowser.js +60 -99
  107. package/dist/ui/AssetCommandPalette.cjs +9 -5
  108. package/dist/ui/AssetManagerUI.cjs +17 -7
  109. package/dist/ui/AssetManagerUI.d.cts +19 -3
  110. package/dist/ui/AssetManagerUI.d.cts.map +1 -1
  111. package/dist/ui/AssetManagerUI.d.ts +19 -3
  112. package/dist/ui/AssetManagerUI.d.ts.map +1 -1
  113. package/dist/ui/AssetManagerUI.js +8 -2
  114. package/dist/ui/DeleteAssetDialog.cjs +9 -5
  115. package/dist/ui/DeleteFolderDialog.cjs +78 -0
  116. package/dist/ui/DeleteFolderDialog.d.cts +11 -0
  117. package/dist/ui/DeleteFolderDialog.d.cts.map +1 -0
  118. package/dist/ui/DeleteFolderDialog.d.ts +11 -0
  119. package/dist/ui/DeleteFolderDialog.d.ts.map +1 -0
  120. package/dist/ui/DeleteFolderDialog.js +40 -0
  121. package/dist/ui/EmptyFolderState.cjs +53 -0
  122. package/dist/ui/EmptyFolderState.d.cts +6 -0
  123. package/dist/ui/EmptyFolderState.d.cts.map +1 -0
  124. package/dist/ui/EmptyFolderState.d.ts +6 -0
  125. package/dist/ui/EmptyFolderState.d.ts.map +1 -0
  126. package/dist/ui/EmptyFolderState.js +15 -0
  127. package/dist/ui/FolderBreadcrumb.cjs +73 -0
  128. package/dist/ui/FolderBreadcrumb.d.cts +9 -0
  129. package/dist/ui/FolderBreadcrumb.d.cts.map +1 -0
  130. package/dist/ui/FolderBreadcrumb.d.ts +9 -0
  131. package/dist/ui/FolderBreadcrumb.d.ts.map +1 -0
  132. package/dist/ui/FolderBreadcrumb.js +35 -0
  133. package/dist/ui/FolderNameDialog.cjs +98 -0
  134. package/dist/ui/FolderNameDialog.d.cts +14 -0
  135. package/dist/ui/FolderNameDialog.d.cts.map +1 -0
  136. package/dist/ui/FolderNameDialog.d.ts +14 -0
  137. package/dist/ui/FolderNameDialog.d.ts.map +1 -0
  138. package/dist/ui/FolderNameDialog.js +60 -0
  139. package/dist/ui/FolderTree.cjs +83 -0
  140. package/dist/ui/FolderTree.d.cts +13 -0
  141. package/dist/ui/FolderTree.d.cts.map +1 -0
  142. package/dist/ui/FolderTree.d.ts +13 -0
  143. package/dist/ui/FolderTree.d.ts.map +1 -0
  144. package/dist/ui/FolderTree.js +42 -0
  145. package/dist/ui/MetadataPanel.cjs +16 -9
  146. package/dist/ui/MetadataPanel.d.cts.map +1 -1
  147. package/dist/ui/MetadataPanel.d.ts.map +1 -1
  148. package/dist/ui/MetadataPanel.js +7 -4
  149. package/dist/ui/MoveTargetPicker.cjs +84 -0
  150. package/dist/ui/MoveTargetPicker.d.cts +16 -0
  151. package/dist/ui/MoveTargetPicker.d.cts.map +1 -0
  152. package/dist/ui/MoveTargetPicker.d.ts +16 -0
  153. package/dist/ui/MoveTargetPicker.d.ts.map +1 -0
  154. package/dist/ui/MoveTargetPicker.js +46 -0
  155. package/dist/ui/ReplaceAssetDialog.cjs +9 -5
  156. package/dist/ui/ReplaceAssetDialog.d.cts +2 -1
  157. package/dist/ui/ReplaceAssetDialog.d.cts.map +1 -1
  158. package/dist/ui/ReplaceAssetDialog.d.ts +2 -1
  159. package/dist/ui/ReplaceAssetDialog.d.ts.map +1 -1
  160. package/dist/ui/UnsplashPanel.cjs +134 -0
  161. package/dist/ui/UnsplashPanel.d.cts +28 -0
  162. package/dist/ui/UnsplashPanel.d.cts.map +1 -0
  163. package/dist/ui/UnsplashPanel.d.ts +28 -0
  164. package/dist/ui/UnsplashPanel.d.ts.map +1 -0
  165. package/dist/ui/UnsplashPanel.js +96 -0
  166. package/dist/ui/UploadButton.cjs +10 -10
  167. package/dist/ui/UploadButton.d.cts +9 -2
  168. package/dist/ui/UploadButton.d.cts.map +1 -1
  169. package/dist/ui/UploadButton.d.ts +9 -2
  170. package/dist/ui/UploadButton.d.ts.map +1 -1
  171. package/dist/ui/UploadButton.js +1 -5
  172. package/dist/ui/index.cjs +46 -5
  173. package/dist/ui/index.d.cts +14 -0
  174. package/dist/ui/index.d.cts.map +1 -1
  175. package/dist/ui/index.d.ts +14 -0
  176. package/dist/ui/index.d.ts.map +1 -1
  177. package/dist/ui/index.js +7 -0
  178. package/dist/utils/asset-reference.cjs +12 -8
  179. package/dist/utils/csp.cjs +12 -8
  180. package/dist/utils/data-source.cjs +177 -0
  181. package/dist/utils/data-source.d.cts +63 -0
  182. package/dist/utils/data-source.d.cts.map +1 -0
  183. package/dist/utils/data-source.d.ts +63 -0
  184. package/dist/utils/data-source.d.ts.map +1 -0
  185. package/dist/utils/data-source.js +136 -0
  186. package/dist/utils/errors.cjs +31 -9
  187. package/dist/utils/errors.d.cts +27 -0
  188. package/dist/utils/errors.d.cts.map +1 -1
  189. package/dist/utils/errors.d.ts +27 -0
  190. package/dist/utils/errors.d.ts.map +1 -1
  191. package/dist/utils/errors.js +16 -1
  192. package/dist/utils/folders.cjs +261 -0
  193. package/dist/utils/folders.d.cts +49 -0
  194. package/dist/utils/folders.d.cts.map +1 -0
  195. package/dist/utils/folders.d.ts +49 -0
  196. package/dist/utils/folders.d.ts.map +1 -0
  197. package/dist/utils/folders.js +223 -0
  198. package/dist/utils/header-action.cjs +12 -8
  199. package/dist/utils/infer-kind.cjs +12 -8
  200. package/dist/utils/registry.cjs +36 -17
  201. package/dist/utils/registry.d.cts +21 -1
  202. package/dist/utils/registry.d.cts.map +1 -1
  203. package/dist/utils/registry.d.ts +21 -1
  204. package/dist/utils/registry.d.ts.map +1 -1
  205. package/dist/utils/registry.js +20 -11
  206. package/dist/utils/resolver.cjs +9 -5
  207. package/dist/utils/retry.cjs +13 -9
  208. package/dist/utils/studio-asset-source.cjs +14 -7
  209. package/dist/utils/studio-asset-source.d.cts +6 -1
  210. package/dist/utils/studio-asset-source.d.cts.map +1 -1
  211. package/dist/utils/studio-asset-source.d.ts +6 -1
  212. package/dist/utils/studio-asset-source.d.ts.map +1 -1
  213. package/dist/utils/studio-asset-source.js +1 -1
  214. package/dist/utils/validate-upload-result.cjs +9 -5
  215. package/dist/utils/validate-upload-result.d.cts +2 -1
  216. package/dist/utils/validate-upload-result.d.cts.map +1 -1
  217. package/dist/utils/validate-upload-result.d.ts +2 -1
  218. package/dist/utils/validate-upload-result.d.ts.map +1 -1
  219. package/dist/version.cjs +12 -8
  220. package/dist/version.d.cts +1 -1
  221. package/dist/version.d.ts +1 -1
  222. package/dist/version.js +1 -1
  223. package/meta/config.json +1 -1
  224. package/package.json +19 -9
package/dist/plugin.js CHANGED
@@ -3,6 +3,7 @@ import { createElement } from "react";
3
3
  import config from "../meta/config.json" with {
4
4
  type: "json"
5
5
  };
6
+ import { inMemoryUploader } from "./adapters/in-memory.js";
6
7
  import { createAssetReference } from "./utils/asset-reference.js";
7
8
  import { AssetValidationError } from "./utils/errors.js";
8
9
  import { uploadAssetAction } from "./utils/header-action.js";
@@ -19,7 +20,7 @@ const META = {
19
20
  };
20
21
  const stateByToken = new WeakMap();
21
22
  const tokenByContext = new WeakMap();
22
- function createAssetManagerPlugin(options) {
23
+ function createAssetManagerPlugin(options = {}) {
23
24
  const token = {};
24
25
  const registry = createAssetRegistry();
25
26
  const normalizedOptions = normalizeOptions(options);
@@ -46,15 +47,34 @@ function createAssetManagerPlugin(options) {
46
47
  });
47
48
  tokenByContext.set(initCtx, token);
48
49
  initCtx.registerAssetResolver(assetResolver);
50
+ const upload = (file, opts)=>uploadAsset(initCtx, file, opts?.signal);
49
51
  const studioAssetSource = createStudioAssetSource({
50
52
  registry,
51
- upload: (file, opts)=>uploadAsset(initCtx, file, opts?.signal),
53
+ upload,
52
54
  ...normalizedOptions.getThumbnail ? {
53
55
  getThumbnail: normalizedOptions.getThumbnail
54
56
  } : {}
55
57
  });
56
- const unregisterAssetSource = initCtx.registerAssetSource?.(studioAssetSource);
57
- if (void 0 !== unregisterAssetSource) cleanups.push(unregisterAssetSource);
58
+ let unregisterAssetSource = initCtx.registerAssetSource?.(studioAssetSource);
59
+ cleanups.push(()=>unregisterAssetSource?.());
60
+ if (needsRichSource(normalizedOptions)) {
61
+ let disposed = false;
62
+ cleanups.push(()=>{
63
+ disposed = true;
64
+ });
65
+ loadRichSource(initCtx, registry, upload, normalizedOptions).then((composite)=>{
66
+ if (disposed) return;
67
+ unregisterAssetSource?.();
68
+ unregisterAssetSource = void 0;
69
+ const unregisterComposite = initCtx.registerAssetSource?.(composite);
70
+ if (disposed) return void unregisterComposite?.();
71
+ cleanups.push(()=>unregisterComposite?.());
72
+ }).catch((error)=>{
73
+ initCtx.log("error", "asset-manager: failed to load the data source.", {
74
+ error
75
+ });
76
+ });
77
+ }
58
78
  },
59
79
  onDestroy (destroyCtx) {
60
80
  const state = stateByToken.get(token);
@@ -118,9 +138,52 @@ function getRuntimeState(ctx) {
118
138
  if (!state) throw new Error("createAssetManagerPlugin: uploadAsset called before the plugin runtime was initialized.");
119
139
  return state;
120
140
  }
141
+ function needsRichSource(options) {
142
+ return false !== options.folders || void 0 !== options.dataSource || void 0 !== options.providers && options.providers.length > 0 || void 0 !== options.unsplash;
143
+ }
144
+ async function loadRichSource(ctx, registry, upload, options) {
145
+ const [{ resolveDataSource }, { createCompositeAssetSource }] = await Promise.all([
146
+ import("./utils/data-source.js"),
147
+ import("./sources/composite-source.js")
148
+ ]);
149
+ const maxDepth = "object" == typeof options.folders ? options.folders.maxDepth : void 0;
150
+ const resolved = resolveDataSource({
151
+ registry,
152
+ upload,
153
+ ...options.dataSource ? {
154
+ hostDataSource: options.dataSource
155
+ } : {},
156
+ ...void 0 !== maxDepth ? {
157
+ maxDepth
158
+ } : {},
159
+ warn: (message)=>ctx.log("warn", message)
160
+ });
161
+ const providers = [
162
+ ...options.providers ?? []
163
+ ];
164
+ if (void 0 !== options.unsplash) {
165
+ const { createUnsplashProvider, unsplashEnabled } = await import("./sources/unsplash/index.js");
166
+ if (unsplashEnabled(options.unsplash)) {
167
+ if (void 0 !== options.unsplash.accessKey && void 0 === options.unsplash.proxyEndpoint) ctx.log("warn", "asset-manager: the Unsplash accessKey is public in the browser — use a server proxy (proxyEndpoint) in production.");
168
+ providers.push(createUnsplashProvider(options.unsplash));
169
+ }
170
+ }
171
+ return createCompositeAssetSource({
172
+ source: resolved,
173
+ registry,
174
+ upload,
175
+ ...providers.length > 0 ? {
176
+ providers
177
+ } : {},
178
+ ...options.getThumbnail ? {
179
+ getThumbnail: options.getThumbnail
180
+ } : {}
181
+ });
182
+ }
121
183
  function normalizeOptions(options) {
122
184
  return {
123
185
  ...options,
186
+ uploader: options.uploader ?? inMemoryUploader(),
124
187
  ...options.acceptedMimeTypes ? {
125
188
  acceptedMimeTypes: Object.freeze([
126
189
  ...options.acceptedMimeTypes
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ createCompositeAssetSource: ()=>createCompositeAssetSource
32
+ });
33
+ const asset_reference_cjs_namespaceObject = require("../utils/asset-reference.cjs");
34
+ const studio_asset_source_cjs_namespaceObject = require("../utils/studio-asset-source.cjs");
35
+ const external_federated_search_cjs_namespaceObject = require("./federated-search.cjs");
36
+ function createCompositeAssetSource(options) {
37
+ const { source, registry, upload, getThumbnail } = options;
38
+ const base = (0, studio_asset_source_cjs_namespaceObject.createStudioAssetSource)({
39
+ registry,
40
+ upload,
41
+ ...getThumbnail ? {
42
+ getThumbnail
43
+ } : {}
44
+ });
45
+ const project = (entry)=>{
46
+ const attribution = entry.meta?.attribution;
47
+ const isExternal = entry.id.startsWith("unsplash:");
48
+ return {
49
+ ...(0, studio_asset_source_cjs_namespaceObject.toStudioAsset)(entry, getThumbnail),
50
+ ...isExternal ? {
51
+ url: entry.url
52
+ } : {},
53
+ folderId: source.folders.folderOf(entry.id),
54
+ source: isExternal ? "unsplash" : "local",
55
+ ...attribution ? {
56
+ attribution: {
57
+ photographerName: attribution.photographerName,
58
+ photographerUrl: attribution.photographerUrl,
59
+ sourceUrl: attribution.unsplashUrl
60
+ }
61
+ } : {}
62
+ };
63
+ };
64
+ const providers = [
65
+ (0, external_federated_search_cjs_namespaceObject.createLocalProvider)(source, registry),
66
+ ...options.providers ?? []
67
+ ];
68
+ const runList = (filter, signal)=>1 === providers.length ? source.list(filter, signal) : (0, external_federated_search_cjs_namespaceObject.federatedSearch)({
69
+ providers,
70
+ filter,
71
+ signal
72
+ });
73
+ return {
74
+ async list () {
75
+ const page = await runList({});
76
+ return Object.freeze(page.items.map(project));
77
+ },
78
+ async listPaginated (query) {
79
+ const page = await runList({
80
+ ...query
81
+ });
82
+ return {
83
+ items: Object.freeze(page.items.map(project)),
84
+ total: page.total,
85
+ nextCursor: page.nextCursor,
86
+ ...page.folders ? {
87
+ folders: page.folders
88
+ } : {},
89
+ ...page.folderPath ? {
90
+ folderPath: page.folderPath
91
+ } : {},
92
+ ...page.sourceCursors ? {
93
+ sourceCursors: page.sourceCursors
94
+ } : {}
95
+ };
96
+ },
97
+ upload: base.upload,
98
+ setTags: base.setTags,
99
+ subscribeUploads: base.subscribeUploads,
100
+ getUrl: (assetId)=>(0, asset_reference_cjs_namespaceObject.createAssetReference)(assetId),
101
+ async delete (assetId) {
102
+ await source.remove(assetId);
103
+ },
104
+ async rename (assetId, nextName) {
105
+ await source.rename(assetId, nextName);
106
+ },
107
+ async replace (assetId, file) {
108
+ return project(await source.replace(assetId, file));
109
+ },
110
+ subscribe: (listener)=>source.subscribe(listener),
111
+ createFolder: (parentId, name)=>source.createFolder(parentId, name),
112
+ renameFolder: (id, name)=>source.renameFolder(id, name),
113
+ removeFolder: (id, opts)=>source.removeFolder(id, opts),
114
+ moveFolder: (id, parentId)=>source.moveFolder(id, parentId),
115
+ moveAsset: (assetId, folderId)=>source.move(assetId, folderId),
116
+ async pickResult (asset) {
117
+ const provider = providers.find((p)=>p.id === asset.source);
118
+ if (void 0 === provider || "local" === provider.id) return asset;
119
+ const result = await provider.pickResult(asset);
120
+ registry.register(result);
121
+ return project(result);
122
+ },
123
+ subscribeStatus: (listener)=>source.subscribeStatus(listener),
124
+ async listThemes () {
125
+ const themes = [];
126
+ for (const provider of providers)if ("local" !== provider.id) themes.push(...await provider.listThemes());
127
+ return themes;
128
+ }
129
+ };
130
+ }
131
+ exports.createCompositeAssetSource = __webpack_exports__.createCompositeAssetSource;
132
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
133
+ "createCompositeAssetSource"
134
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
135
+ Object.defineProperty(exports, '__esModule', {
136
+ value: true
137
+ });
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @file `CompositeAssetSource` (PRD 0002 §6.1, §8.1). Implements core's
3
+ * `StudioAssetSource` by routing reads + catalog mutations through the resolved
4
+ * `AssetDataSource` (so host backends and folder scoping work), while reusing
5
+ * the proven upload pipeline + projection from `createStudioAssetSource`.
6
+ *
7
+ * Lazy-loaded by the factory only when a host opts into a richer surface
8
+ * (`dataSource`/`providers`/`unsplash`), so flat callers never pull this — or
9
+ * the folder/data-source code it imports — into the headless entry chunk.
10
+ */
11
+ import type { StudioAssetSource } from "@anvilkit/core/types";
12
+ import type { AssetFolder, FolderId } from "../types/folders.js";
13
+ import type { AssetRegistry, UploadResult } from "../types/types.js";
14
+ import type { ResolvedAssetDataSource, UploadFn } from "../utils/data-source.js";
15
+ import type { AssetSourceProvider } from "./provider.js";
16
+ export interface CreateCompositeAssetSourceOptions {
17
+ readonly source: ResolvedAssetDataSource;
18
+ readonly registry: AssetRegistry;
19
+ readonly upload: UploadFn;
20
+ readonly getThumbnail?: (entry: UploadResult) => string | undefined;
21
+ /** External read-only sources (e.g. Unsplash) federated alongside the local library. */
22
+ readonly providers?: readonly AssetSourceProvider[];
23
+ }
24
+ /**
25
+ * The core `StudioAssetSource` plus the folder methods the plugin's `./ui` and
26
+ * (Phase 2) core `ImageModule` consume. The folder methods are additive — core
27
+ * ignores what it doesn't know until its sidebar types adopt them.
28
+ */
29
+ export interface CompositeAssetSource extends StudioAssetSource {
30
+ createFolder(parentId: FolderId | null, name: string): Promise<AssetFolder>;
31
+ renameFolder(id: FolderId, name: string): Promise<AssetFolder>;
32
+ removeFolder(id: FolderId, opts?: {
33
+ readonly cascade?: boolean;
34
+ }): Promise<void>;
35
+ moveFolder(id: FolderId, parentId: FolderId | null): Promise<AssetFolder>;
36
+ moveAsset(assetId: string, folderId: FolderId | null): Promise<void>;
37
+ }
38
+ export declare function createCompositeAssetSource(options: CreateCompositeAssetSourceOptions): CompositeAssetSource;
39
+ //# sourceMappingURL=composite-source.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composite-source.d.cts","sourceRoot":"","sources":["../../src/sources/composite-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAIX,iBAAiB,EAEjB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,KAAK,EACX,uBAAuB,EACvB,QAAQ,EACR,MAAM,yBAAyB,CAAC;AAMjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,MAAM,WAAW,iCAAiC;IACjD,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,GAAG,SAAS,CAAC;IACpE,wFAAwF;IACxF,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACpD;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC9D,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5E,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/D,YAAY,CACX,EAAE,EAAE,QAAQ,EACZ,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE;AAED,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,iCAAiC,GACxC,oBAAoB,CA8HtB"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @file `CompositeAssetSource` (PRD 0002 §6.1, §8.1). Implements core's
3
+ * `StudioAssetSource` by routing reads + catalog mutations through the resolved
4
+ * `AssetDataSource` (so host backends and folder scoping work), while reusing
5
+ * the proven upload pipeline + projection from `createStudioAssetSource`.
6
+ *
7
+ * Lazy-loaded by the factory only when a host opts into a richer surface
8
+ * (`dataSource`/`providers`/`unsplash`), so flat callers never pull this — or
9
+ * the folder/data-source code it imports — into the headless entry chunk.
10
+ */
11
+ import type { StudioAssetSource } from "@anvilkit/core/types";
12
+ import type { AssetFolder, FolderId } from "../types/folders.js";
13
+ import type { AssetRegistry, UploadResult } from "../types/types.js";
14
+ import type { ResolvedAssetDataSource, UploadFn } from "../utils/data-source.js";
15
+ import type { AssetSourceProvider } from "./provider.js";
16
+ export interface CreateCompositeAssetSourceOptions {
17
+ readonly source: ResolvedAssetDataSource;
18
+ readonly registry: AssetRegistry;
19
+ readonly upload: UploadFn;
20
+ readonly getThumbnail?: (entry: UploadResult) => string | undefined;
21
+ /** External read-only sources (e.g. Unsplash) federated alongside the local library. */
22
+ readonly providers?: readonly AssetSourceProvider[];
23
+ }
24
+ /**
25
+ * The core `StudioAssetSource` plus the folder methods the plugin's `./ui` and
26
+ * (Phase 2) core `ImageModule` consume. The folder methods are additive — core
27
+ * ignores what it doesn't know until its sidebar types adopt them.
28
+ */
29
+ export interface CompositeAssetSource extends StudioAssetSource {
30
+ createFolder(parentId: FolderId | null, name: string): Promise<AssetFolder>;
31
+ renameFolder(id: FolderId, name: string): Promise<AssetFolder>;
32
+ removeFolder(id: FolderId, opts?: {
33
+ readonly cascade?: boolean;
34
+ }): Promise<void>;
35
+ moveFolder(id: FolderId, parentId: FolderId | null): Promise<AssetFolder>;
36
+ moveAsset(assetId: string, folderId: FolderId | null): Promise<void>;
37
+ }
38
+ export declare function createCompositeAssetSource(options: CreateCompositeAssetSourceOptions): CompositeAssetSource;
39
+ //# sourceMappingURL=composite-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composite-source.d.ts","sourceRoot":"","sources":["../../src/sources/composite-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAIX,iBAAiB,EAEjB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,KAAK,EACX,uBAAuB,EACvB,QAAQ,EACR,MAAM,yBAAyB,CAAC;AAMjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,MAAM,WAAW,iCAAiC;IACjD,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,GAAG,SAAS,CAAC;IACpE,wFAAwF;IACxF,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACpD;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC9D,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5E,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/D,YAAY,CACX,EAAE,EAAE,QAAQ,EACZ,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE;AAED,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,iCAAiC,GACxC,oBAAoB,CA8HtB"}
@@ -0,0 +1,99 @@
1
+ import { createAssetReference } from "../utils/asset-reference.js";
2
+ import { createStudioAssetSource, toStudioAsset } from "../utils/studio-asset-source.js";
3
+ import { createLocalProvider, federatedSearch } from "./federated-search.js";
4
+ function createCompositeAssetSource(options) {
5
+ const { source, registry, upload, getThumbnail } = options;
6
+ const base = createStudioAssetSource({
7
+ registry,
8
+ upload,
9
+ ...getThumbnail ? {
10
+ getThumbnail
11
+ } : {}
12
+ });
13
+ const project = (entry)=>{
14
+ const attribution = entry.meta?.attribution;
15
+ const isExternal = entry.id.startsWith("unsplash:");
16
+ return {
17
+ ...toStudioAsset(entry, getThumbnail),
18
+ ...isExternal ? {
19
+ url: entry.url
20
+ } : {},
21
+ folderId: source.folders.folderOf(entry.id),
22
+ source: isExternal ? "unsplash" : "local",
23
+ ...attribution ? {
24
+ attribution: {
25
+ photographerName: attribution.photographerName,
26
+ photographerUrl: attribution.photographerUrl,
27
+ sourceUrl: attribution.unsplashUrl
28
+ }
29
+ } : {}
30
+ };
31
+ };
32
+ const providers = [
33
+ createLocalProvider(source, registry),
34
+ ...options.providers ?? []
35
+ ];
36
+ const runList = (filter, signal)=>1 === providers.length ? source.list(filter, signal) : federatedSearch({
37
+ providers,
38
+ filter,
39
+ signal
40
+ });
41
+ return {
42
+ async list () {
43
+ const page = await runList({});
44
+ return Object.freeze(page.items.map(project));
45
+ },
46
+ async listPaginated (query) {
47
+ const page = await runList({
48
+ ...query
49
+ });
50
+ return {
51
+ items: Object.freeze(page.items.map(project)),
52
+ total: page.total,
53
+ nextCursor: page.nextCursor,
54
+ ...page.folders ? {
55
+ folders: page.folders
56
+ } : {},
57
+ ...page.folderPath ? {
58
+ folderPath: page.folderPath
59
+ } : {},
60
+ ...page.sourceCursors ? {
61
+ sourceCursors: page.sourceCursors
62
+ } : {}
63
+ };
64
+ },
65
+ upload: base.upload,
66
+ setTags: base.setTags,
67
+ subscribeUploads: base.subscribeUploads,
68
+ getUrl: (assetId)=>createAssetReference(assetId),
69
+ async delete (assetId) {
70
+ await source.remove(assetId);
71
+ },
72
+ async rename (assetId, nextName) {
73
+ await source.rename(assetId, nextName);
74
+ },
75
+ async replace (assetId, file) {
76
+ return project(await source.replace(assetId, file));
77
+ },
78
+ subscribe: (listener)=>source.subscribe(listener),
79
+ createFolder: (parentId, name)=>source.createFolder(parentId, name),
80
+ renameFolder: (id, name)=>source.renameFolder(id, name),
81
+ removeFolder: (id, opts)=>source.removeFolder(id, opts),
82
+ moveFolder: (id, parentId)=>source.moveFolder(id, parentId),
83
+ moveAsset: (assetId, folderId)=>source.move(assetId, folderId),
84
+ async pickResult (asset) {
85
+ const provider = providers.find((p)=>p.id === asset.source);
86
+ if (void 0 === provider || "local" === provider.id) return asset;
87
+ const result = await provider.pickResult(asset);
88
+ registry.register(result);
89
+ return project(result);
90
+ },
91
+ subscribeStatus: (listener)=>source.subscribeStatus(listener),
92
+ async listThemes () {
93
+ const themes = [];
94
+ for (const provider of providers)if ("local" !== provider.id) themes.push(...await provider.listThemes());
95
+ return themes;
96
+ }
97
+ };
98
+ }
99
+ export { createCompositeAssetSource };
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ createLocalProvider: ()=>createLocalProvider,
32
+ decodeCompositeCursor: ()=>decodeCompositeCursor,
33
+ encodeCompositeCursor: ()=>encodeCompositeCursor,
34
+ federatedSearch: ()=>federatedSearch,
35
+ providerCanSatisfy: ()=>providerCanSatisfy
36
+ });
37
+ const infer_kind_cjs_namespaceObject = require("../utils/infer-kind.cjs");
38
+ function toBase64Url(json) {
39
+ return btoa(json).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
40
+ }
41
+ function fromBase64Url(token) {
42
+ const padded = token.length % 4 === 0 ? token : token + "=".repeat(4 - token.length % 4);
43
+ return atob(padded.replace(/-/g, "+").replace(/_/g, "/"));
44
+ }
45
+ function encodeCompositeCursor(cursor) {
46
+ return toBase64Url(JSON.stringify(cursor));
47
+ }
48
+ function decodeCompositeCursor(token) {
49
+ if (void 0 === token || "" === token) return {};
50
+ try {
51
+ const parsed = JSON.parse(fromBase64Url(token));
52
+ return "object" == typeof parsed && null !== parsed ? parsed : {};
53
+ } catch {
54
+ return {};
55
+ }
56
+ }
57
+ function providerCanSatisfy(provider, filter) {
58
+ if (void 0 !== filter.folderId && true !== provider.capabilities.folders) return false;
59
+ return true;
60
+ }
61
+ function createLocalProvider(source, registry, label = "assetManager.source.library") {
62
+ return {
63
+ id: "local",
64
+ label,
65
+ capabilities: {
66
+ searchable: true,
67
+ themed: false,
68
+ mutable: true,
69
+ requiresAttribution: false,
70
+ folders: true
71
+ },
72
+ listThemes: ()=>[],
73
+ search: (filter, page, signal)=>source.list(void 0 !== page ? {
74
+ ...filter,
75
+ cursor: page
76
+ } : filter, signal),
77
+ pickResult: async (asset)=>registry.get(asset.id) ?? {
78
+ id: asset.id,
79
+ url: asset.url
80
+ }
81
+ };
82
+ }
83
+ function sortKey(entry, field) {
84
+ switch(field){
85
+ case "name":
86
+ return (entry.name ?? "").toLowerCase();
87
+ case "size":
88
+ return entry.meta?.size ?? 0;
89
+ case "kind":
90
+ return (0, infer_kind_cjs_namespaceObject.inferAssetKind)(entry);
91
+ }
92
+ }
93
+ function compareEntries(a, b, field) {
94
+ const ka = sortKey(a, field);
95
+ const kb = sortKey(b, field);
96
+ if ("number" == typeof ka && "number" == typeof kb) return ka - kb;
97
+ return String(ka).localeCompare(String(kb));
98
+ }
99
+ function mergePages(pages, filter) {
100
+ const field = filter.sort?.field ?? "recent";
101
+ const comparable = "name" === field || "size" === field || "kind" === field;
102
+ const items = pages.flatMap((p)=>[
103
+ ...p.page.items
104
+ ]);
105
+ if (comparable) {
106
+ const dir = filter.sort?.direction ?? ("name" === field ? "asc" : "desc");
107
+ const sign = "asc" === dir ? 1 : -1;
108
+ items.sort((a, b)=>compareEntries(a, b, field) * sign);
109
+ }
110
+ const total = pages.reduce((n, p)=>n + p.page.total, 0);
111
+ const sourceCursors = {};
112
+ const next = {};
113
+ let hasNext = false;
114
+ for (const { provider, page } of pages){
115
+ sourceCursors[provider.id] = page.nextCursor;
116
+ if (void 0 !== page.nextCursor) {
117
+ next[provider.id] = page.nextCursor;
118
+ hasNext = true;
119
+ }
120
+ }
121
+ return {
122
+ items: Object.freeze(items),
123
+ total,
124
+ nextCursor: hasNext ? encodeCompositeCursor(next) : void 0,
125
+ sourceCursors
126
+ };
127
+ }
128
+ async function federatedSearch(input) {
129
+ const { providers, filter, signal } = input;
130
+ const eligible = providers.filter((p)=>providerCanSatisfy(p, filter));
131
+ const targets = filter.sources && filter.sources.length > 0 ? eligible.filter((p)=>filter.sources?.includes(p.id)) : eligible;
132
+ if (0 === targets.length) return {
133
+ items: Object.freeze([]),
134
+ total: 0,
135
+ nextCursor: void 0
136
+ };
137
+ const cursors = decodeCompositeCursor(filter.cursor);
138
+ const settled = await Promise.allSettled(targets.map((p)=>p.search(filter, cursors[p.id], signal)));
139
+ const ok = [];
140
+ settled.forEach((result, index)=>{
141
+ const provider = targets[index];
142
+ if (void 0 !== provider && "fulfilled" === result.status) ok.push({
143
+ provider,
144
+ page: result.value
145
+ });
146
+ });
147
+ return mergePages(ok, filter);
148
+ }
149
+ exports.createLocalProvider = __webpack_exports__.createLocalProvider;
150
+ exports.decodeCompositeCursor = __webpack_exports__.decodeCompositeCursor;
151
+ exports.encodeCompositeCursor = __webpack_exports__.encodeCompositeCursor;
152
+ exports.federatedSearch = __webpack_exports__.federatedSearch;
153
+ exports.providerCanSatisfy = __webpack_exports__.providerCanSatisfy;
154
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
155
+ "createLocalProvider",
156
+ "decodeCompositeCursor",
157
+ "encodeCompositeCursor",
158
+ "federatedSearch",
159
+ "providerCanSatisfy"
160
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
161
+ Object.defineProperty(exports, '__esModule', {
162
+ value: true
163
+ });
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @file Federated search across asset source providers (PRD 0002 §9.3).
3
+ *
4
+ * Routes a single-source query to one provider, or federates across many with
5
+ * `Promise.allSettled` (one failing remote never blanks the rest). The page
6
+ * cursor is an OPAQUE composite token carrying one sub-cursor per source, so
7
+ * each provider paginates independently. Comparable sorts (name/size/kind) are
8
+ * k-way merged; `recent`/`relevance` fall back to provider-grouped order
9
+ * (incomparable across heterogeneous sources).
10
+ */
11
+ import type { AssetFilter, AssetListPage } from "../types/filter.js";
12
+ import type { AssetRegistry } from "../types/types.js";
13
+ import type { ResolvedAssetDataSource } from "../utils/data-source.js";
14
+ import type { AssetSourceProvider } from "./provider.js";
15
+ type CompositeCursor = Record<string, string | undefined>;
16
+ export declare function encodeCompositeCursor(cursor: CompositeCursor): string;
17
+ export declare function decodeCompositeCursor(token: string | undefined): CompositeCursor;
18
+ /** A provider is eligible only if it can satisfy every required axis of the filter. */
19
+ export declare function providerCanSatisfy(provider: AssetSourceProvider, filter: AssetFilter): boolean;
20
+ /** Adapt the resolved (local) data source into an `AssetSourceProvider`. */
21
+ export declare function createLocalProvider(source: ResolvedAssetDataSource, registry: AssetRegistry, label?: string): AssetSourceProvider;
22
+ export interface FederatedSearchInput {
23
+ readonly providers: readonly AssetSourceProvider[];
24
+ readonly filter: AssetFilter;
25
+ readonly signal?: AbortSignal;
26
+ }
27
+ /**
28
+ * Run a filter across providers. `filter.sources` naming exactly one provider
29
+ * ROUTES to it (zero other calls); otherwise eligible providers FEDERATE.
30
+ */
31
+ export declare function federatedSearch(input: FederatedSearchInput): Promise<AssetListPage>;
32
+ export {};
33
+ //# sourceMappingURL=federated-search.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federated-search.d.cts","sourceRoot":"","sources":["../../src/sources/federated-search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAY1D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAErE;AAED,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,MAAM,GAAG,SAAS,GACvB,eAAe,CAUjB;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,WAAW,GACjB,OAAO,CAKT;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,uBAAuB,EAC/B,QAAQ,EAAE,aAAa,EACvB,KAAK,SAAgC,GACnC,mBAAmB,CAqBrB;AA+DD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACpC,KAAK,EAAE,oBAAoB,GACzB,OAAO,CAAC,aAAa,CAAC,CA4BxB"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @file Federated search across asset source providers (PRD 0002 §9.3).
3
+ *
4
+ * Routes a single-source query to one provider, or federates across many with
5
+ * `Promise.allSettled` (one failing remote never blanks the rest). The page
6
+ * cursor is an OPAQUE composite token carrying one sub-cursor per source, so
7
+ * each provider paginates independently. Comparable sorts (name/size/kind) are
8
+ * k-way merged; `recent`/`relevance` fall back to provider-grouped order
9
+ * (incomparable across heterogeneous sources).
10
+ */
11
+ import type { AssetFilter, AssetListPage } from "../types/filter.js";
12
+ import type { AssetRegistry } from "../types/types.js";
13
+ import type { ResolvedAssetDataSource } from "../utils/data-source.js";
14
+ import type { AssetSourceProvider } from "./provider.js";
15
+ type CompositeCursor = Record<string, string | undefined>;
16
+ export declare function encodeCompositeCursor(cursor: CompositeCursor): string;
17
+ export declare function decodeCompositeCursor(token: string | undefined): CompositeCursor;
18
+ /** A provider is eligible only if it can satisfy every required axis of the filter. */
19
+ export declare function providerCanSatisfy(provider: AssetSourceProvider, filter: AssetFilter): boolean;
20
+ /** Adapt the resolved (local) data source into an `AssetSourceProvider`. */
21
+ export declare function createLocalProvider(source: ResolvedAssetDataSource, registry: AssetRegistry, label?: string): AssetSourceProvider;
22
+ export interface FederatedSearchInput {
23
+ readonly providers: readonly AssetSourceProvider[];
24
+ readonly filter: AssetFilter;
25
+ readonly signal?: AbortSignal;
26
+ }
27
+ /**
28
+ * Run a filter across providers. `filter.sources` naming exactly one provider
29
+ * ROUTES to it (zero other calls); otherwise eligible providers FEDERATE.
30
+ */
31
+ export declare function federatedSearch(input: FederatedSearchInput): Promise<AssetListPage>;
32
+ export {};
33
+ //# sourceMappingURL=federated-search.d.ts.map