@anvilkit/plugin-asset-manager 0.1.8 → 0.1.10

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 (235) hide show
  1. package/README.md +96 -3
  2. package/dist/adapters/data-url.d.cts +1 -0
  3. package/dist/adapters/data-url.d.cts.map +1 -1
  4. package/dist/adapters/data-url.d.ts +1 -0
  5. package/dist/adapters/data-url.d.ts.map +1 -1
  6. package/dist/adapters/s3-multipart.cjs +425 -0
  7. package/dist/adapters/s3-multipart.d.cts +43 -0
  8. package/dist/adapters/s3-multipart.d.cts.map +1 -0
  9. package/dist/adapters/s3-multipart.d.ts +43 -0
  10. package/dist/adapters/s3-multipart.d.ts.map +1 -0
  11. package/dist/adapters/s3-multipart.js +387 -0
  12. package/dist/adapters/s3-presigned.d.cts +2 -0
  13. package/dist/adapters/s3-presigned.d.cts.map +1 -1
  14. package/dist/adapters/s3-presigned.d.ts +2 -0
  15. package/dist/adapters/s3-presigned.d.ts.map +1 -1
  16. package/dist/i18n/provider.d.cts +1 -0
  17. package/dist/i18n/provider.d.cts.map +1 -1
  18. package/dist/i18n/provider.d.ts +1 -0
  19. package/dist/i18n/provider.d.ts.map +1 -1
  20. package/dist/index.cjs +14 -0
  21. package/dist/index.d.cts +9 -3
  22. package/dist/index.d.cts.map +1 -1
  23. package/dist/index.d.ts +9 -3
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +3 -1
  26. package/dist/plugin.cjs +152 -12
  27. package/dist/plugin.d.cts +49 -1
  28. package/dist/plugin.d.cts.map +1 -1
  29. package/dist/plugin.d.ts +49 -1
  30. package/dist/plugin.d.ts.map +1 -1
  31. package/dist/plugin.js +147 -13
  32. package/dist/sources/composite-source.cjs +3 -0
  33. package/dist/sources/composite-source.d.cts.map +1 -1
  34. package/dist/sources/composite-source.d.ts.map +1 -1
  35. package/dist/sources/composite-source.js +3 -0
  36. package/dist/sources/federated-search.cjs +45 -7
  37. package/dist/sources/federated-search.d.cts.map +1 -1
  38. package/dist/sources/federated-search.d.ts.map +1 -1
  39. package/dist/sources/federated-search.js +45 -7
  40. package/dist/sources/provider.d.cts +5 -0
  41. package/dist/sources/provider.d.cts.map +1 -1
  42. package/dist/sources/provider.d.ts +5 -0
  43. package/dist/sources/provider.d.ts.map +1 -1
  44. package/dist/sources/unsplash/index.d.cts +1 -0
  45. package/dist/sources/unsplash/index.d.cts.map +1 -1
  46. package/dist/sources/unsplash/index.d.ts +1 -0
  47. package/dist/sources/unsplash/index.d.ts.map +1 -1
  48. package/dist/testing/index.d.cts +4 -0
  49. package/dist/testing/index.d.cts.map +1 -1
  50. package/dist/testing/index.d.ts +4 -0
  51. package/dist/testing/index.d.ts.map +1 -1
  52. package/dist/types/categories.d.cts +3 -0
  53. package/dist/types/categories.d.cts.map +1 -1
  54. package/dist/types/categories.d.ts +3 -0
  55. package/dist/types/categories.d.ts.map +1 -1
  56. package/dist/types/data-source.d.cts +9 -0
  57. package/dist/types/data-source.d.cts.map +1 -1
  58. package/dist/types/data-source.d.ts +9 -0
  59. package/dist/types/data-source.d.ts.map +1 -1
  60. package/dist/types/filter.d.cts +11 -0
  61. package/dist/types/filter.d.cts.map +1 -1
  62. package/dist/types/filter.d.ts +11 -0
  63. package/dist/types/filter.d.ts.map +1 -1
  64. package/dist/types/folders.d.cts +2 -0
  65. package/dist/types/folders.d.cts.map +1 -1
  66. package/dist/types/folders.d.ts +2 -0
  67. package/dist/types/folders.d.ts.map +1 -1
  68. package/dist/types/options.d.cts +57 -1
  69. package/dist/types/options.d.cts.map +1 -1
  70. package/dist/types/options.d.ts +57 -1
  71. package/dist/types/options.d.ts.map +1 -1
  72. package/dist/types/resumable.cjs +42 -0
  73. package/dist/types/resumable.d.cts +204 -0
  74. package/dist/types/resumable.d.cts.map +1 -0
  75. package/dist/types/resumable.d.ts +204 -0
  76. package/dist/types/resumable.d.ts.map +1 -0
  77. package/dist/types/resumable.js +4 -0
  78. package/dist/types/transform.cjs +18 -0
  79. package/dist/types/transform.d.cts +45 -0
  80. package/dist/types/transform.d.cts.map +1 -0
  81. package/dist/types/transform.d.ts +45 -0
  82. package/dist/types/transform.d.ts.map +1 -0
  83. package/dist/types/transform.js +1 -0
  84. package/dist/types/types.d.cts +17 -0
  85. package/dist/types/types.d.cts.map +1 -1
  86. package/dist/types/types.d.ts +17 -0
  87. package/dist/types/types.d.ts.map +1 -1
  88. package/dist/types/unsplash.d.cts +2 -0
  89. package/dist/types/unsplash.d.cts.map +1 -1
  90. package/dist/types/unsplash.d.ts +2 -0
  91. package/dist/types/unsplash.d.ts.map +1 -1
  92. package/dist/ui/AssetBrowser.d.cts +3 -1
  93. package/dist/ui/AssetBrowser.d.cts.map +1 -1
  94. package/dist/ui/AssetBrowser.d.ts +3 -1
  95. package/dist/ui/AssetBrowser.d.ts.map +1 -1
  96. package/dist/ui/AssetCommandPalette.d.cts +4 -1
  97. package/dist/ui/AssetCommandPalette.d.cts.map +1 -1
  98. package/dist/ui/AssetCommandPalette.d.ts +4 -1
  99. package/dist/ui/AssetCommandPalette.d.ts.map +1 -1
  100. package/dist/ui/AssetManagerUI.cjs +3 -1
  101. package/dist/ui/AssetManagerUI.d.cts +11 -2
  102. package/dist/ui/AssetManagerUI.d.cts.map +1 -1
  103. package/dist/ui/AssetManagerUI.d.ts +11 -2
  104. package/dist/ui/AssetManagerUI.d.ts.map +1 -1
  105. package/dist/ui/AssetManagerUI.js +3 -1
  106. package/dist/ui/DeleteAssetDialog.d.cts +4 -1
  107. package/dist/ui/DeleteAssetDialog.d.cts.map +1 -1
  108. package/dist/ui/DeleteAssetDialog.d.ts +4 -1
  109. package/dist/ui/DeleteAssetDialog.d.ts.map +1 -1
  110. package/dist/ui/DeleteFolderDialog.d.cts +4 -1
  111. package/dist/ui/DeleteFolderDialog.d.cts.map +1 -1
  112. package/dist/ui/DeleteFolderDialog.d.ts +4 -1
  113. package/dist/ui/DeleteFolderDialog.d.ts.map +1 -1
  114. package/dist/ui/EmptyFolderState.d.cts +4 -1
  115. package/dist/ui/EmptyFolderState.d.cts.map +1 -1
  116. package/dist/ui/EmptyFolderState.d.ts +4 -1
  117. package/dist/ui/EmptyFolderState.d.ts.map +1 -1
  118. package/dist/ui/FolderBreadcrumb.d.cts +4 -1
  119. package/dist/ui/FolderBreadcrumb.d.cts.map +1 -1
  120. package/dist/ui/FolderBreadcrumb.d.ts +4 -1
  121. package/dist/ui/FolderBreadcrumb.d.ts.map +1 -1
  122. package/dist/ui/FolderNameDialog.d.cts +3 -1
  123. package/dist/ui/FolderNameDialog.d.cts.map +1 -1
  124. package/dist/ui/FolderNameDialog.d.ts +3 -1
  125. package/dist/ui/FolderNameDialog.d.ts.map +1 -1
  126. package/dist/ui/FolderTree.d.cts +4 -1
  127. package/dist/ui/FolderTree.d.cts.map +1 -1
  128. package/dist/ui/FolderTree.d.ts +4 -1
  129. package/dist/ui/FolderTree.d.ts.map +1 -1
  130. package/dist/ui/MetadataPanel.d.cts +4 -1
  131. package/dist/ui/MetadataPanel.d.cts.map +1 -1
  132. package/dist/ui/MetadataPanel.d.ts +4 -1
  133. package/dist/ui/MetadataPanel.d.ts.map +1 -1
  134. package/dist/ui/MoveTargetPicker.d.cts +3 -1
  135. package/dist/ui/MoveTargetPicker.d.cts.map +1 -1
  136. package/dist/ui/MoveTargetPicker.d.ts +3 -1
  137. package/dist/ui/MoveTargetPicker.d.ts.map +1 -1
  138. package/dist/ui/ReplaceAssetDialog.cjs +7 -2
  139. package/dist/ui/ReplaceAssetDialog.d.cts +5 -2
  140. package/dist/ui/ReplaceAssetDialog.d.cts.map +1 -1
  141. package/dist/ui/ReplaceAssetDialog.d.ts +5 -2
  142. package/dist/ui/ReplaceAssetDialog.d.ts.map +1 -1
  143. package/dist/ui/ReplaceAssetDialog.js +7 -2
  144. package/dist/ui/UnsplashPanel.d.cts +4 -1
  145. package/dist/ui/UnsplashPanel.d.cts.map +1 -1
  146. package/dist/ui/UnsplashPanel.d.ts +4 -1
  147. package/dist/ui/UnsplashPanel.d.ts.map +1 -1
  148. package/dist/ui/UploadButton.cjs +7 -2
  149. package/dist/ui/UploadButton.d.cts +6 -2
  150. package/dist/ui/UploadButton.d.cts.map +1 -1
  151. package/dist/ui/UploadButton.d.ts +6 -2
  152. package/dist/ui/UploadButton.d.ts.map +1 -1
  153. package/dist/ui/UploadButton.js +7 -2
  154. package/dist/utils/asset-reference.cjs +87 -4
  155. package/dist/utils/asset-reference.d.cts +30 -6
  156. package/dist/utils/asset-reference.d.cts.map +1 -1
  157. package/dist/utils/asset-reference.d.ts +30 -6
  158. package/dist/utils/asset-reference.d.ts.map +1 -1
  159. package/dist/utils/asset-reference.js +83 -3
  160. package/dist/utils/csp.cjs +16 -0
  161. package/dist/utils/csp.d.cts +23 -0
  162. package/dist/utils/csp.d.cts.map +1 -1
  163. package/dist/utils/csp.d.ts +23 -0
  164. package/dist/utils/csp.d.ts.map +1 -1
  165. package/dist/utils/csp.js +16 -0
  166. package/dist/utils/data-source.cjs +19 -5
  167. package/dist/utils/data-source.d.cts +5 -1
  168. package/dist/utils/data-source.d.cts.map +1 -1
  169. package/dist/utils/data-source.d.ts +5 -1
  170. package/dist/utils/data-source.d.ts.map +1 -1
  171. package/dist/utils/data-source.js +19 -5
  172. package/dist/utils/errors.d.cts +5 -0
  173. package/dist/utils/errors.d.cts.map +1 -1
  174. package/dist/utils/errors.d.ts +5 -0
  175. package/dist/utils/errors.d.ts.map +1 -1
  176. package/dist/utils/query-param-transform.cjs +101 -0
  177. package/dist/utils/query-param-transform.d.cts +46 -0
  178. package/dist/utils/query-param-transform.d.cts.map +1 -0
  179. package/dist/utils/query-param-transform.d.ts +46 -0
  180. package/dist/utils/query-param-transform.d.ts.map +1 -0
  181. package/dist/utils/query-param-transform.js +60 -0
  182. package/dist/utils/registry.cjs +3 -0
  183. package/dist/utils/registry.d.cts +8 -0
  184. package/dist/utils/registry.d.cts.map +1 -1
  185. package/dist/utils/registry.d.ts +8 -0
  186. package/dist/utils/registry.d.ts.map +1 -1
  187. package/dist/utils/registry.js +3 -0
  188. package/dist/utils/resolver.cjs +19 -11
  189. package/dist/utils/resolver.d.cts +24 -0
  190. package/dist/utils/resolver.d.cts.map +1 -1
  191. package/dist/utils/resolver.d.ts +24 -0
  192. package/dist/utils/resolver.d.ts.map +1 -1
  193. package/dist/utils/resolver.js +19 -11
  194. package/dist/utils/retry.d.cts +2 -0
  195. package/dist/utils/retry.d.cts.map +1 -1
  196. package/dist/utils/retry.d.ts +2 -0
  197. package/dist/utils/retry.d.ts.map +1 -1
  198. package/dist/utils/run-resumable-upload.cjs +160 -0
  199. package/dist/utils/run-resumable-upload.d.cts +56 -0
  200. package/dist/utils/run-resumable-upload.d.cts.map +1 -0
  201. package/dist/utils/run-resumable-upload.d.ts +56 -0
  202. package/dist/utils/run-resumable-upload.d.ts.map +1 -0
  203. package/dist/utils/run-resumable-upload.js +122 -0
  204. package/dist/utils/sniff-file-type.cjs +209 -0
  205. package/dist/utils/sniff-file-type.d.cts +25 -0
  206. package/dist/utils/sniff-file-type.d.cts.map +1 -0
  207. package/dist/utils/sniff-file-type.d.ts +25 -0
  208. package/dist/utils/sniff-file-type.d.ts.map +1 -0
  209. package/dist/utils/sniff-file-type.js +164 -0
  210. package/dist/utils/studio-asset-source.cjs +11 -6
  211. package/dist/utils/studio-asset-source.d.cts +5 -1
  212. package/dist/utils/studio-asset-source.d.cts.map +1 -1
  213. package/dist/utils/studio-asset-source.d.ts +5 -1
  214. package/dist/utils/studio-asset-source.d.ts.map +1 -1
  215. package/dist/utils/studio-asset-source.js +11 -6
  216. package/dist/utils/upload-session-store.cjs +125 -0
  217. package/dist/utils/upload-session-store.d.cts +55 -0
  218. package/dist/utils/upload-session-store.d.cts.map +1 -0
  219. package/dist/utils/upload-session-store.d.ts +55 -0
  220. package/dist/utils/upload-session-store.d.ts.map +1 -0
  221. package/dist/utils/upload-session-store.js +84 -0
  222. package/dist/utils/validate-upload-result.cjs +9 -1
  223. package/dist/utils/validate-upload-result.d.cts +1 -0
  224. package/dist/utils/validate-upload-result.d.cts.map +1 -1
  225. package/dist/utils/validate-upload-result.d.ts +1 -0
  226. package/dist/utils/validate-upload-result.d.ts.map +1 -1
  227. package/dist/utils/validate-upload-result.js +9 -1
  228. package/dist/version.cjs +1 -1
  229. package/dist/version.d.cts +1 -1
  230. package/dist/version.d.cts.map +1 -1
  231. package/dist/version.d.ts +1 -1
  232. package/dist/version.d.ts.map +1 -1
  233. package/dist/version.js +1 -1
  234. package/meta/config.json +1 -1
  235. package/package.json +42 -12
package/dist/plugin.js CHANGED
@@ -14,6 +14,8 @@ import { createIRAssetResolver } from "./utils/resolver.js";
14
14
  import { createStudioAssetSource } from "./utils/studio-asset-source.js";
15
15
  import { validateUploadResult } from "./utils/validate-upload-result.js";
16
16
  import { ASSET_MANAGER_VERSION } from "./version.js";
17
+ const ASSET_MANAGER_UPLOADED_EVENT = "asset-manager:uploaded";
18
+ const ASSET_MANAGER_ERROR_EVENT = "asset-manager:error";
17
19
  const META = {
18
20
  ...config,
19
21
  version: ASSET_MANAGER_VERSION,
@@ -28,7 +30,10 @@ function createAssetManagerPlugin(options = {}) {
28
30
  const assetResolver = createIRAssetResolver({
29
31
  registry,
30
32
  dataUrlAllowlistOptIn: normalizedOptions.dataUrlAllowlistOptIn,
31
- allowMixedScriptHostnames: normalizedOptions.allowMixedScriptHostnames
33
+ allowMixedScriptHostnames: normalizedOptions.allowMixedScriptHostnames,
34
+ ...normalizedOptions.transformResolver ? {
35
+ transformResolver: normalizedOptions.transformResolver
36
+ } : {}
32
37
  });
33
38
  return {
34
39
  meta: META,
@@ -50,9 +55,11 @@ function createAssetManagerPlugin(options = {}) {
50
55
  tokenByContext.set(initCtx, token);
51
56
  initCtx.registerAssetResolver(assetResolver);
52
57
  const upload = (file, opts)=>uploadAsset(initCtx, file, opts?.signal);
58
+ const onDelete = createAssetDeletedHandler(normalizedOptions, !hostOwnsAssetPlane(normalizedOptions));
53
59
  const studioAssetSource = createStudioAssetSource({
54
60
  registry,
55
61
  upload,
62
+ onDelete,
56
63
  ...normalizedOptions.getThumbnail ? {
57
64
  getThumbnail: normalizedOptions.getThumbnail
58
65
  } : {}
@@ -99,39 +106,146 @@ async function uploadAsset(ctx, file, signal) {
99
106
  const { options, registry } = state;
100
107
  try {
101
108
  validateSelectedFile(file, options);
102
- const uploadResult = await options.uploader(file, signal ? {
103
- signal
104
- } : void 0);
109
+ await assertSniffedContentType(file, options, signal);
110
+ let contentHash;
111
+ if (true === options.dedupe) {
112
+ if (signal?.aborted) throw makePluginAbortError();
113
+ contentHash = await computeFileHash(file);
114
+ if (signal?.aborted) throw makePluginAbortError();
115
+ if (void 0 !== contentHash) {
116
+ const existing = registry.list().find((entry)=>entry.meta?.hash === contentHash);
117
+ if (void 0 !== existing) {
118
+ dispatchAssetReference(ctx, existing);
119
+ ctx.emit(ASSET_MANAGER_UPLOADED_EVENT, {
120
+ asset: existing,
121
+ reference: createAssetReference(existing.id)
122
+ });
123
+ return existing;
124
+ }
125
+ }
126
+ }
127
+ if (signal?.aborted) throw makePluginAbortError();
128
+ const uploadResult = await performUpload(options, file, signal);
105
129
  if (signal?.aborted) throw makePluginAbortError();
106
130
  const validated = validateUploadResult(mergeUploadMeta(uploadResult, file), options);
107
- const tagged = withDerivedTags(validated, file);
131
+ const hashed = void 0 !== contentHash ? {
132
+ ...validated,
133
+ meta: {
134
+ ...validated.meta ?? {},
135
+ hash: contentHash
136
+ }
137
+ } : validated;
138
+ const tagged = withDerivedTags(hashed, file);
108
139
  const stored = registry.register(tagged);
109
140
  dispatchAssetReference(ctx, stored);
110
- ctx.emit("asset-manager:uploaded", {
141
+ const payload = {
111
142
  asset: stored,
112
143
  reference: createAssetReference(stored.id)
113
- });
144
+ };
145
+ ctx.emit(ASSET_MANAGER_UPLOADED_EVENT, payload);
114
146
  return stored;
115
147
  } catch (error) {
116
148
  if (isAbortLikeError(error) || signal?.aborted) throw error;
117
149
  const normalizedError = error instanceof AssetValidationError ? error : new AssetValidationError("UPLOAD_FAILED", error instanceof Error ? error.message : String(error), {
118
150
  cause: error
119
151
  });
120
- ctx.emit("asset-manager:error", {
152
+ const payload = {
121
153
  code: normalizedError.code,
122
154
  message: normalizedError.message
123
- });
155
+ };
156
+ ctx.emit(ASSET_MANAGER_ERROR_EVENT, payload);
124
157
  ctx.log("error", normalizedError.message, {
125
158
  code: normalizedError.code
126
159
  });
127
160
  throw normalizedError;
128
161
  }
129
162
  }
163
+ const DEFAULT_RESUMABLE_THRESHOLD = 8388608;
164
+ async function performUpload(options, file, signal) {
165
+ const { resumable } = options;
166
+ if (void 0 !== resumable && shouldUseResumable(resumable, file)) {
167
+ if (signal?.aborted) throw makePluginAbortError();
168
+ const { runResumableUpload } = await import("./utils/run-resumable-upload.js");
169
+ return runResumableUpload(resumable.adapter, file, {
170
+ ...void 0 !== resumable.partSize ? {
171
+ partSize: resumable.partSize
172
+ } : {},
173
+ ...resumable.sessionStore ? {
174
+ sessionStore: resumable.sessionStore
175
+ } : {},
176
+ ...signal ? {
177
+ signal
178
+ } : {}
179
+ });
180
+ }
181
+ return options.uploader(file, signal ? {
182
+ signal
183
+ } : void 0);
184
+ }
185
+ function shouldUseResumable(resumable, file) {
186
+ const threshold = resumable.threshold ?? resumable.partSize ?? DEFAULT_RESUMABLE_THRESHOLD;
187
+ return file.size >= threshold;
188
+ }
189
+ function createAssetDeletedHandler(options, callHostHook) {
190
+ return async (asset)=>{
191
+ revokeBlobUrl(asset.url);
192
+ if (callHostHook) await options.onAssetDeleted?.(asset);
193
+ };
194
+ }
195
+ const HOST_ASSET_PLANE_METHODS = [
196
+ "list",
197
+ "remove",
198
+ "replace",
199
+ "rename",
200
+ "move"
201
+ ];
202
+ function hostOwnsAssetPlane(options) {
203
+ const ds = options.dataSource;
204
+ if (void 0 === ds) return false;
205
+ return HOST_ASSET_PLANE_METHODS.every((method)=>"function" == typeof ds[method]);
206
+ }
207
+ function revokeBlobUrl(url) {
208
+ if (url.startsWith("blob:") && "u" > typeof URL && "function" == typeof URL.revokeObjectURL) URL.revokeObjectURL(url);
209
+ }
210
+ async function computeFileHash(file) {
211
+ const subtle = globalThis.crypto?.subtle;
212
+ if (void 0 === subtle || "function" != typeof file.arrayBuffer) return;
213
+ try {
214
+ const digest = await subtle.digest("SHA-256", await file.arrayBuffer());
215
+ const bytes = new Uint8Array(digest);
216
+ let hex = "";
217
+ for (const byte of bytes)hex += byte.toString(16).padStart(2, "0");
218
+ return hex;
219
+ } catch {
220
+ return;
221
+ }
222
+ }
223
+ async function assertSniffedContentType(file, options, signal) {
224
+ if (true !== options.sniffContent) return;
225
+ const declared = normalizeMime(file.type);
226
+ if ("" === declared || "application/octet-stream" === declared) return;
227
+ if (signal?.aborted) throw makePluginAbortError();
228
+ const { sniffFileMime } = await import("./utils/sniff-file-type.js");
229
+ const sniffed = await sniffFileMime(file);
230
+ if (signal?.aborted) throw makePluginAbortError();
231
+ if (void 0 === sniffed) return;
232
+ if (normalizeMime(sniffed) !== declared) throw new AssetValidationError("CONTENT_TYPE_MISMATCH", `File content was detected as "${sniffed}" but its declared type is "${file.type}".`);
233
+ }
234
+ function normalizeMime(mime) {
235
+ const lower = mime.trim().toLowerCase();
236
+ return "image/jpg" === lower ? "image/jpeg" : lower;
237
+ }
130
238
  function validateSelectedFile(file, options) {
131
239
  if (void 0 !== options.maxFileSize && file.size > options.maxFileSize) throw new AssetValidationError("FILE_TOO_LARGE", `File size ${file.size} bytes exceeds the configured maxFileSize of ${options.maxFileSize} bytes.`);
132
- if (options.acceptedMimeTypes && options.acceptedMimeTypes.length > 0 && !mimeTypeMatches(file.type, options.acceptedMimeTypes)) {
133
- const mimeType = file.type || "unknown";
134
- throw new AssetValidationError("UNSUPPORTED_MIME_TYPE", `File MIME type "${mimeType}" is not in acceptedMimeTypes.`);
240
+ const acceptedMimeTypes = options.acceptedMimeTypes ?? [];
241
+ const acceptedFileExtensions = options.acceptedFileExtensions ?? [];
242
+ const hasMimeAllowlist = acceptedMimeTypes.length > 0;
243
+ const hasExtensionAllowlist = acceptedFileExtensions.length > 0;
244
+ if (hasMimeAllowlist && "" !== file.type && !mimeTypeMatches(file.type, acceptedMimeTypes)) throw new AssetValidationError("UNSUPPORTED_MIME_TYPE", `File MIME type "${file.type}" is not in acceptedMimeTypes.`);
245
+ if (hasMimeAllowlist && "" === file.type && !hasExtensionAllowlist) throw new AssetValidationError("UNSUPPORTED_MIME_TYPE", 'File MIME type "unknown" is not in acceptedMimeTypes.');
246
+ if (hasExtensionAllowlist && !fileExtensionMatches(file.name, acceptedFileExtensions)) {
247
+ const extension = file.name.includes(".") ? file.name.slice(file.name.lastIndexOf(".")).toLowerCase() : "unknown";
248
+ throw new AssetValidationError("UNSUPPORTED_FILE_EXTENSION", `File extension "${extension}" is not in acceptedFileExtensions.`);
135
249
  }
136
250
  }
137
251
  function getRuntimeState(ctx) {
@@ -149,15 +263,20 @@ async function loadRichSource(ctx, registry, upload, options) {
149
263
  import("./sources/composite-source.js")
150
264
  ]);
151
265
  const maxDepth = "object" == typeof options.folders ? options.folders.maxDepth : void 0;
266
+ const allowMove = "object" == typeof options.folders ? options.folders.allowMove : void 0;
152
267
  const resolved = resolveDataSource({
153
268
  registry,
154
269
  upload,
270
+ onDelete: createAssetDeletedHandler(options, !hostOwnsAssetPlane(options)),
155
271
  ...options.dataSource ? {
156
272
  hostDataSource: options.dataSource
157
273
  } : {},
158
274
  ...void 0 !== maxDepth ? {
159
275
  maxDepth
160
276
  } : {},
277
+ ...void 0 !== allowMove ? {
278
+ allowMove
279
+ } : {},
161
280
  warn: (message)=>ctx.log("warn", message)
162
281
  });
163
282
  const providers = [
@@ -190,6 +309,11 @@ function normalizeOptions(options) {
190
309
  acceptedMimeTypes: Object.freeze([
191
310
  ...options.acceptedMimeTypes
192
311
  ])
312
+ } : {},
313
+ ...options.acceptedFileExtensions ? {
314
+ acceptedFileExtensions: Object.freeze([
315
+ ...options.acceptedFileExtensions
316
+ ])
193
317
  } : {}
194
318
  };
195
319
  }
@@ -241,6 +365,16 @@ function mimeTypeMatches(input, acceptedMimeTypes) {
241
365
  return input === accepted;
242
366
  });
243
367
  }
368
+ function fileExtensionMatches(name, acceptedFileExtensions) {
369
+ const lowerName = name.toLowerCase();
370
+ if ("" === lowerName) return false;
371
+ return acceptedFileExtensions.some((accepted)=>{
372
+ const trimmed = accepted.trim().toLowerCase();
373
+ if ("" === trimmed) return false;
374
+ const extension = trimmed.startsWith(".") ? trimmed : `.${trimmed}`;
375
+ return lowerName.endsWith(extension);
376
+ });
377
+ }
244
378
  function dispatchAssetReference(ctx, asset) {
245
379
  const currentData = ctx.getData();
246
380
  const assetsView = currentData.assets;
@@ -294,4 +428,4 @@ function isAbortLikeError(error) {
294
428
  const name = error.name;
295
429
  return "AbortError" === name;
296
430
  }
297
- export { createAssetManagerPlugin, createAssetReference, getAssetRegistry, uploadAsset, validateSelectedFile };
431
+ export { ASSET_MANAGER_ERROR_EVENT, ASSET_MANAGER_UPLOADED_EVENT, createAssetManagerPlugin, createAssetReference, getAssetRegistry, uploadAsset, validateSelectedFile };
@@ -91,6 +91,9 @@ function createCompositeAssetSource(options) {
91
91
  } : {},
92
92
  ...page.sourceCursors ? {
93
93
  sourceCursors: page.sourceCursors
94
+ } : {},
95
+ ...page.sourceErrors ? {
96
+ sourceErrors: page.sourceErrors
94
97
  } : {}
95
98
  };
96
99
  },
@@ -1 +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,CAiItB"}
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,CAkItB"}
@@ -1 +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,CAiItB"}
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,CAkItB"}
@@ -59,6 +59,9 @@ function createCompositeAssetSource(options) {
59
59
  } : {},
60
60
  ...page.sourceCursors ? {
61
61
  sourceCursors: page.sourceCursors
62
+ } : {},
63
+ ...page.sourceErrors ? {
64
+ sourceErrors: page.sourceErrors
62
65
  } : {}
63
66
  };
64
67
  },
@@ -70,10 +70,10 @@ function createLocalProvider(source, registry, label = "assetManager.source.libr
70
70
  folders: true
71
71
  },
72
72
  listThemes: ()=>[],
73
- search: (filter, page, signal)=>source.list(void 0 !== page ? {
73
+ search: (filter, page, signal)=>source.list({
74
74
  ...filter,
75
75
  cursor: page
76
- } : filter, signal),
76
+ }, signal),
77
77
  pickResult: async (asset)=>registry.get(asset.id) ?? {
78
78
  id: asset.id,
79
79
  url: asset.url
@@ -96,7 +96,7 @@ function compareEntries(a, b, field) {
96
96
  if ("number" == typeof ka && "number" == typeof kb) return ka - kb;
97
97
  return String(ka).localeCompare(String(kb));
98
98
  }
99
- function mergePages(pages, filter, carryForward = {}) {
99
+ function mergePages(pages, filter, carryForward = {}, sourceErrors = {}) {
100
100
  const field = filter.sort?.field ?? "recent";
101
101
  const comparable = "name" === field || "size" === field || "kind" === field;
102
102
  const items = pages.flatMap((p)=>[
@@ -126,22 +126,59 @@ function mergePages(pages, filter, carryForward = {}) {
126
126
  items: Object.freeze(items),
127
127
  total,
128
128
  nextCursor: hasNext ? encodeCompositeCursor(next) : void 0,
129
- sourceCursors
129
+ sourceCursors,
130
+ ...Object.keys(sourceErrors).length > 0 ? {
131
+ sourceErrors: Object.freeze(sourceErrors)
132
+ } : {}
130
133
  };
131
134
  }
135
+ function describeReason(reason) {
136
+ if (reason instanceof Error) {
137
+ const code = reason.code;
138
+ return {
139
+ message: reason.message || reason.name,
140
+ ..."string" == typeof code ? {
141
+ code
142
+ } : {}
143
+ };
144
+ }
145
+ if (null !== reason && "object" == typeof reason) {
146
+ const message = reason.message;
147
+ const code = reason.code;
148
+ if ("string" == typeof message) return {
149
+ message,
150
+ ..."string" == typeof code ? {
151
+ code
152
+ } : {}
153
+ };
154
+ }
155
+ return {
156
+ message: safeString(reason)
157
+ };
158
+ }
159
+ function safeString(value) {
160
+ try {
161
+ return String(value);
162
+ } catch {
163
+ return "Unknown error";
164
+ }
165
+ }
132
166
  async function federatedSearch(input) {
133
167
  const { providers, filter, signal } = input;
168
+ const cursors = decodeCompositeCursor(filter.cursor);
169
+ const isContinuation = void 0 !== filter.cursor && Object.keys(cursors).length > 0;
134
170
  const eligible = providers.filter((p)=>providerCanSatisfy(p, filter));
135
- const targets = filter.sources && filter.sources.length > 0 ? eligible.filter((p)=>filter.sources?.includes(p.id)) : eligible;
171
+ const sourceScoped = filter.sources && filter.sources.length > 0 ? eligible.filter((p)=>filter.sources?.includes(p.id)) : eligible;
172
+ const targets = isContinuation ? sourceScoped.filter((p)=>void 0 !== cursors[p.id]) : sourceScoped;
136
173
  if (0 === targets.length) return {
137
174
  items: Object.freeze([]),
138
175
  total: 0,
139
176
  nextCursor: void 0
140
177
  };
141
- const cursors = decodeCompositeCursor(filter.cursor);
142
178
  const settled = await Promise.allSettled(targets.map((p)=>p.search(filter, cursors[p.id], signal)));
143
179
  const ok = [];
144
180
  const carryForward = {};
181
+ const sourceErrors = {};
145
182
  settled.forEach((result, index)=>{
146
183
  const provider = targets[index];
147
184
  if (void 0 === provider) return;
@@ -152,9 +189,10 @@ async function federatedSearch(input) {
152
189
  else {
153
190
  const incoming = cursors[provider.id];
154
191
  if (void 0 !== incoming) carryForward[provider.id] = incoming;
192
+ sourceErrors[provider.id] = describeReason(result.reason);
155
193
  }
156
194
  });
157
- return mergePages(ok, filter, carryForward);
195
+ return mergePages(ok, filter, carryForward, sourceErrors);
158
196
  }
159
197
  exports.createLocalProvider = __webpack_exports__.createLocalProvider;
160
198
  exports.decodeCompositeCursor = __webpack_exports__.decodeCompositeCursor;
@@ -1 +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;AAmED,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,CAqCxB"}
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;AAyGD,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,CAkDxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"federated-search.d.ts","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;AAmED,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,CAqCxB"}
1
+ {"version":3,"file":"federated-search.d.ts","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;AAyGD,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,CAkDxB"}
@@ -34,10 +34,10 @@ function createLocalProvider(source, registry, label = "assetManager.source.libr
34
34
  folders: true
35
35
  },
36
36
  listThemes: ()=>[],
37
- search: (filter, page, signal)=>source.list(void 0 !== page ? {
37
+ search: (filter, page, signal)=>source.list({
38
38
  ...filter,
39
39
  cursor: page
40
- } : filter, signal),
40
+ }, signal),
41
41
  pickResult: async (asset)=>registry.get(asset.id) ?? {
42
42
  id: asset.id,
43
43
  url: asset.url
@@ -60,7 +60,7 @@ function compareEntries(a, b, field) {
60
60
  if ("number" == typeof ka && "number" == typeof kb) return ka - kb;
61
61
  return String(ka).localeCompare(String(kb));
62
62
  }
63
- function mergePages(pages, filter, carryForward = {}) {
63
+ function mergePages(pages, filter, carryForward = {}, sourceErrors = {}) {
64
64
  const field = filter.sort?.field ?? "recent";
65
65
  const comparable = "name" === field || "size" === field || "kind" === field;
66
66
  const items = pages.flatMap((p)=>[
@@ -90,22 +90,59 @@ function mergePages(pages, filter, carryForward = {}) {
90
90
  items: Object.freeze(items),
91
91
  total,
92
92
  nextCursor: hasNext ? encodeCompositeCursor(next) : void 0,
93
- sourceCursors
93
+ sourceCursors,
94
+ ...Object.keys(sourceErrors).length > 0 ? {
95
+ sourceErrors: Object.freeze(sourceErrors)
96
+ } : {}
94
97
  };
95
98
  }
99
+ function describeReason(reason) {
100
+ if (reason instanceof Error) {
101
+ const code = reason.code;
102
+ return {
103
+ message: reason.message || reason.name,
104
+ ..."string" == typeof code ? {
105
+ code
106
+ } : {}
107
+ };
108
+ }
109
+ if (null !== reason && "object" == typeof reason) {
110
+ const message = reason.message;
111
+ const code = reason.code;
112
+ if ("string" == typeof message) return {
113
+ message,
114
+ ..."string" == typeof code ? {
115
+ code
116
+ } : {}
117
+ };
118
+ }
119
+ return {
120
+ message: safeString(reason)
121
+ };
122
+ }
123
+ function safeString(value) {
124
+ try {
125
+ return String(value);
126
+ } catch {
127
+ return "Unknown error";
128
+ }
129
+ }
96
130
  async function federatedSearch(input) {
97
131
  const { providers, filter, signal } = input;
132
+ const cursors = decodeCompositeCursor(filter.cursor);
133
+ const isContinuation = void 0 !== filter.cursor && Object.keys(cursors).length > 0;
98
134
  const eligible = providers.filter((p)=>providerCanSatisfy(p, filter));
99
- const targets = filter.sources && filter.sources.length > 0 ? eligible.filter((p)=>filter.sources?.includes(p.id)) : eligible;
135
+ const sourceScoped = filter.sources && filter.sources.length > 0 ? eligible.filter((p)=>filter.sources?.includes(p.id)) : eligible;
136
+ const targets = isContinuation ? sourceScoped.filter((p)=>void 0 !== cursors[p.id]) : sourceScoped;
100
137
  if (0 === targets.length) return {
101
138
  items: Object.freeze([]),
102
139
  total: 0,
103
140
  nextCursor: void 0
104
141
  };
105
- const cursors = decodeCompositeCursor(filter.cursor);
106
142
  const settled = await Promise.allSettled(targets.map((p)=>p.search(filter, cursors[p.id], signal)));
107
143
  const ok = [];
108
144
  const carryForward = {};
145
+ const sourceErrors = {};
109
146
  settled.forEach((result, index)=>{
110
147
  const provider = targets[index];
111
148
  if (void 0 === provider) return;
@@ -116,8 +153,9 @@ async function federatedSearch(input) {
116
153
  else {
117
154
  const incoming = cursors[provider.id];
118
155
  if (void 0 !== incoming) carryForward[provider.id] = incoming;
156
+ sourceErrors[provider.id] = describeReason(result.reason);
119
157
  }
120
158
  });
121
- return mergePages(ok, filter, carryForward);
159
+ return mergePages(ok, filter, carryForward, sourceErrors);
122
160
  }
123
161
  export { createLocalProvider, decodeCompositeCursor, encodeCompositeCursor, federatedSearch, providerCanSatisfy };
@@ -9,6 +9,7 @@
9
9
  import type { StudioAsset } from "@anvilkit/core/types";
10
10
  import type { AssetFilter, AssetListPage, AssetSourceId } from "../types/filter.js";
11
11
  import type { UploadResult } from "../types/types.js";
12
+ /** Capability flags advertised by an asset source provider. */
12
13
  export interface AssetSourceCapabilities {
13
14
  readonly searchable: boolean;
14
15
  readonly themed: boolean;
@@ -23,12 +24,14 @@ export interface AssetSourceCapabilities {
23
24
  */
24
25
  readonly folders?: boolean;
25
26
  }
27
+ /** Browse theme exposed by an external asset source provider. */
26
28
  export interface AssetTheme {
27
29
  readonly id: string;
28
30
  /** i18n message key (not inline copy). */
29
31
  readonly label: string;
30
32
  readonly description?: string;
31
33
  }
34
+ /** Read-only external provider contract for searchable asset sources. */
32
35
  export interface AssetSourceProvider {
33
36
  /** `"unsplash"` | host id. The built-in `"local"` provider wraps the data source. */
34
37
  readonly id: AssetSourceId;
@@ -39,7 +42,9 @@ export interface AssetSourceProvider {
39
42
  readonly connectSrc?: readonly string[];
40
43
  readonly imgSrc?: readonly string[];
41
44
  };
45
+ /** Return browse themes or categories this provider exposes. */
42
46
  listThemes(): readonly AssetTheme[] | Promise<readonly AssetTheme[]>;
47
+ /** Search or browse the provider and return one page of normalized assets. */
43
48
  search(query: AssetFilter, page: string | undefined, signal?: AbortSignal): Promise<AssetListPage>;
44
49
  /**
45
50
  * Convert a browsed result into a real asset (fires the source's
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.cts","sourceRoot":"","sources":["../../src/sources/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uBAAuB;IACvB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IACnC,qFAAqF;IACrF,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC/C,yFAAyF;IACzF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM;QAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,UAAU,IAAI,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACrE,MAAM,CACL,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5E"}
1
+ {"version":3,"file":"provider.d.cts","sourceRoot":"","sources":["../../src/sources/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,+DAA+D;AAC/D,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uBAAuB;IACvB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,iEAAiE;AACjE,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,yEAAyE;AACzE,MAAM,WAAW,mBAAmB;IACnC,qFAAqF;IACrF,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC/C,yFAAyF;IACzF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM;QAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,gEAAgE;IAChE,UAAU,IAAI,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACrE,8EAA8E;IAC9E,MAAM,CACL,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5E"}
@@ -9,6 +9,7 @@
9
9
  import type { StudioAsset } from "@anvilkit/core/types";
10
10
  import type { AssetFilter, AssetListPage, AssetSourceId } from "../types/filter.js";
11
11
  import type { UploadResult } from "../types/types.js";
12
+ /** Capability flags advertised by an asset source provider. */
12
13
  export interface AssetSourceCapabilities {
13
14
  readonly searchable: boolean;
14
15
  readonly themed: boolean;
@@ -23,12 +24,14 @@ export interface AssetSourceCapabilities {
23
24
  */
24
25
  readonly folders?: boolean;
25
26
  }
27
+ /** Browse theme exposed by an external asset source provider. */
26
28
  export interface AssetTheme {
27
29
  readonly id: string;
28
30
  /** i18n message key (not inline copy). */
29
31
  readonly label: string;
30
32
  readonly description?: string;
31
33
  }
34
+ /** Read-only external provider contract for searchable asset sources. */
32
35
  export interface AssetSourceProvider {
33
36
  /** `"unsplash"` | host id. The built-in `"local"` provider wraps the data source. */
34
37
  readonly id: AssetSourceId;
@@ -39,7 +42,9 @@ export interface AssetSourceProvider {
39
42
  readonly connectSrc?: readonly string[];
40
43
  readonly imgSrc?: readonly string[];
41
44
  };
45
+ /** Return browse themes or categories this provider exposes. */
42
46
  listThemes(): readonly AssetTheme[] | Promise<readonly AssetTheme[]>;
47
+ /** Search or browse the provider and return one page of normalized assets. */
43
48
  search(query: AssetFilter, page: string | undefined, signal?: AbortSignal): Promise<AssetListPage>;
44
49
  /**
45
50
  * Convert a browsed result into a real asset (fires the source's
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/sources/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uBAAuB;IACvB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IACnC,qFAAqF;IACrF,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC/C,yFAAyF;IACzF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM;QAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,UAAU,IAAI,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACrE,MAAM,CACL,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5E"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/sources/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,+DAA+D;AAC/D,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uBAAuB;IACvB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,iEAAiE;AACjE,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,yEAAyE;AACzE,MAAM,WAAW,mBAAmB;IACnC,qFAAqF;IACrF,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAC/C,yFAAyF;IACzF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM;QAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC,CAAC;IACF,gEAAgE;IAChE,UAAU,IAAI,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACrE,8EAA8E;IAC9E,MAAM,CACL,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5E"}
@@ -12,5 +12,6 @@ import type { AssetSourceProvider } from "../provider.js";
12
12
  export declare const UNSPLASH_THEME_FACET = "unsplash:theme";
13
13
  /** Enabled when a proxy endpoint or access key is present (or forced via `enabled`). */
14
14
  export declare function unsplashEnabled(options: UnsplashSourceOptions): boolean;
15
+ /** Create the Unsplash-backed read-only asset source provider. */
15
16
  export declare function createUnsplashProvider(options: UnsplashSourceOptions): AssetSourceProvider;
16
17
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/sources/unsplash/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAc,MAAM,gBAAgB,CAAC;AAYtE,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AASrD,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAKvE;AAMD,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,qBAAqB,GAC5B,mBAAmB,CA0LrB"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../../src/sources/unsplash/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAc,MAAM,gBAAgB,CAAC;AAYtE,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AASrD,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAKvE;AAMD,kEAAkE;AAClE,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,qBAAqB,GAC5B,mBAAmB,CA0LrB"}
@@ -12,5 +12,6 @@ import type { AssetSourceProvider } from "../provider.js";
12
12
  export declare const UNSPLASH_THEME_FACET = "unsplash:theme";
13
13
  /** Enabled when a proxy endpoint or access key is present (or forced via `enabled`). */
14
14
  export declare function unsplashEnabled(options: UnsplashSourceOptions): boolean;
15
+ /** Create the Unsplash-backed read-only asset source provider. */
15
16
  export declare function createUnsplashProvider(options: UnsplashSourceOptions): AssetSourceProvider;
16
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sources/unsplash/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAc,MAAM,gBAAgB,CAAC;AAYtE,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AASrD,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAKvE;AAMD,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,qBAAqB,GAC5B,mBAAmB,CA0LrB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sources/unsplash/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAc,MAAM,gBAAgB,CAAC;AAYtE,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AASrD,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAKvE;AAMD,kEAAkE;AAClE,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,qBAAqB,GAC5B,mBAAmB,CA0LrB"}
@@ -7,10 +7,13 @@
7
7
  * on the registry + uploader contracts owned by this package.
8
8
  */
9
9
  import type { AssetRegistry, UploadAdapter, UploadResult } from "../types/types.js";
10
+ /** Options for constructing a registry fixture in tests. */
10
11
  export interface CreateTestRegistryOptions {
11
12
  readonly initial?: readonly UploadResult[];
12
13
  }
14
+ /** Create an in-memory registry preloaded with optional upload rows. */
13
15
  export declare function createTestRegistry(options?: CreateTestRegistryOptions): AssetRegistry;
16
+ /** Options for the deterministic fake uploader helper. */
14
17
  export interface FakeUploaderOptions {
15
18
  /**
16
19
  * Optional map keyed by `File.name`. When a file is uploaded whose
@@ -20,5 +23,6 @@ export interface FakeUploaderOptions {
20
23
  */
21
24
  readonly responses?: Record<string, UploadResult>;
22
25
  }
26
+ /** Create a deterministic fake upload adapter for plugin and host tests. */
23
27
  export declare function fakeUploader(options?: FakeUploaderOptions): UploadAdapter;
24
28
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAEX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,wBAAgB,kBAAkB,CACjC,OAAO,GAAE,yBAA8B,GACrC,aAAa,CAMf;AAED,MAAM,WAAW,mBAAmB;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAClD;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa,CAkB7E"}
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAEX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,MAAM,mBAAmB,CAAC;AAG3B,4DAA4D;AAC5D,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CACjC,OAAO,GAAE,yBAA8B,GACrC,aAAa,CAMf;AAED,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAClD;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,aAAa,CAkB7E"}