@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
@@ -0,0 +1,151 @@
1
+ import { AssetSourceError } from "../../utils/errors.js";
2
+ function createTimedSignal(timeoutMs, caller) {
3
+ const controller = new AbortController();
4
+ let didTimeout = false;
5
+ const timer = setTimeout(()=>{
6
+ didTimeout = true;
7
+ controller.abort();
8
+ }, timeoutMs);
9
+ timer.unref?.();
10
+ const onCallerAbort = ()=>controller.abort();
11
+ if (caller) if (caller.aborted) controller.abort();
12
+ else caller.addEventListener("abort", onCallerAbort, {
13
+ once: true
14
+ });
15
+ return {
16
+ signal: controller.signal,
17
+ timedOut: ()=>didTimeout,
18
+ dispose: ()=>{
19
+ clearTimeout(timer);
20
+ caller?.removeEventListener("abort", onCallerAbort);
21
+ }
22
+ };
23
+ }
24
+ function isAbortError(error) {
25
+ return "object" == typeof error && null !== error && "AbortError" === error.name;
26
+ }
27
+ function parseRetryAfterMs(headers) {
28
+ const retryAfter = headers.get("retry-after");
29
+ if (null !== retryAfter) {
30
+ const seconds = Number(retryAfter);
31
+ if (Number.isFinite(seconds)) return 1000 * seconds;
32
+ }
33
+ const reset = headers.get("x-ratelimit-reset");
34
+ if (null !== reset) {
35
+ const epochSeconds = Number(reset);
36
+ if (Number.isFinite(epochSeconds)) {
37
+ const ms = 1000 * epochSeconds - Date.now();
38
+ if (ms > 0) return ms;
39
+ }
40
+ }
41
+ }
42
+ function mapHttpError(response) {
43
+ if (429 === response.status) {
44
+ const retryAfterMs = parseRetryAfterMs(response.headers);
45
+ return new AssetSourceError("PROVIDER_RATE_LIMITED", "Unsplash rate limit reached.", {
46
+ retryable: true,
47
+ status: 429,
48
+ ...void 0 !== retryAfterMs ? {
49
+ retryAfterMs
50
+ } : {}
51
+ });
52
+ }
53
+ if (401 === response.status || 403 === response.status) return new AssetSourceError("PROVIDER_UNAUTHORIZED", "Unsplash rejected the request — check the access key / proxy.", {
54
+ status: response.status
55
+ });
56
+ return new AssetSourceError("PROVIDER_BAD_RESPONSE", `Unsplash returned HTTP ${response.status}.`, {
57
+ status: response.status,
58
+ retryable: response.status >= 500
59
+ });
60
+ }
61
+ function createUnsplashClient(options) {
62
+ const doFetch = options.fetch ?? globalThis.fetch;
63
+ const usingProxy = void 0 !== options.proxyEndpoint;
64
+ const base = (usingProxy ? String(options.proxyEndpoint) : "https://api.unsplash.com").replace(/\/$/, "");
65
+ const timeoutMs = options.timeoutMs ?? 15000;
66
+ const trackDownloadTimeoutMs = options.trackDownloadTimeoutMs ?? 6000;
67
+ const authHeaders = ()=>!usingProxy && options.accessKey ? {
68
+ Authorization: `Client-ID ${options.accessKey}`
69
+ } : {};
70
+ const readJson = async (response)=>{
71
+ try {
72
+ return await response.json();
73
+ } catch (cause) {
74
+ throw new AssetSourceError("PROVIDER_BAD_RESPONSE", "Unsplash returned an unreadable response.", {
75
+ cause
76
+ });
77
+ }
78
+ };
79
+ const requestJson = async (path, params, signal)=>{
80
+ const search = new URLSearchParams();
81
+ for (const [key, value] of Object.entries(params))if (void 0 !== value) search.set(key, String(value));
82
+ const query = search.toString();
83
+ const url = `${base}${path}${query ? `?${query}` : ""}`;
84
+ const timed = createTimedSignal(timeoutMs, signal);
85
+ try {
86
+ let response;
87
+ try {
88
+ response = await doFetch(url, {
89
+ headers: authHeaders(),
90
+ signal: timed.signal
91
+ });
92
+ } catch (cause) {
93
+ if (timed.timedOut()) throw new AssetSourceError("PROVIDER_NETWORK", `Unsplash request timed out after ${timeoutMs} ms.`, {
94
+ retryable: true,
95
+ cause
96
+ });
97
+ if (isAbortError(cause)) throw cause;
98
+ throw new AssetSourceError("PROVIDER_NETWORK", "Network error contacting Unsplash.", {
99
+ retryable: true,
100
+ cause
101
+ });
102
+ }
103
+ if (!response.ok) throw mapHttpError(response);
104
+ return await readJson(response);
105
+ } finally{
106
+ timed.dispose();
107
+ }
108
+ };
109
+ return {
110
+ async searchPhotos (params, signal) {
111
+ const body = await requestJson("/search/photos", {
112
+ query: params.query,
113
+ page: params.page,
114
+ per_page: params.perPage,
115
+ orientation: params.orientation,
116
+ content_filter: params.contentFilter
117
+ }, signal);
118
+ return {
119
+ total: body.total ?? 0,
120
+ results: body.results ?? []
121
+ };
122
+ },
123
+ async topicPhotos (slug, params, signal) {
124
+ return await requestJson(`/topics/${encodeURIComponent(slug)}/photos`, {
125
+ page: params.page,
126
+ per_page: params.perPage,
127
+ orientation: params.orientation
128
+ }, signal) ?? [];
129
+ },
130
+ async listTopics (signal) {
131
+ return await requestJson("/topics", {
132
+ per_page: 30
133
+ }, signal) ?? [];
134
+ },
135
+ async getPhoto (id, signal) {
136
+ return requestJson(`/photos/${encodeURIComponent(id)}`, {}, signal);
137
+ },
138
+ async trackDownload (downloadLocation, signal) {
139
+ const timed = createTimedSignal(trackDownloadTimeoutMs, signal);
140
+ try {
141
+ await doFetch(downloadLocation, {
142
+ headers: authHeaders(),
143
+ signal: timed.signal
144
+ });
145
+ } catch {} finally{
146
+ timed.dispose();
147
+ }
148
+ }
149
+ };
150
+ }
151
+ export { createUnsplashClient };
@@ -0,0 +1,192 @@
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
+ UNSPLASH_THEME_FACET: ()=>UNSPLASH_THEME_FACET,
32
+ createUnsplashProvider: ()=>createUnsplashProvider,
33
+ unsplashEnabled: ()=>unsplashEnabled
34
+ });
35
+ const external_client_cjs_namespaceObject = require("./client.cjs");
36
+ const external_themes_cjs_namespaceObject = require("./themes.cjs");
37
+ const external_throttle_cache_cjs_namespaceObject = require("./throttle-cache.cjs");
38
+ const UNSPLASH_THEME_FACET = "unsplash:theme";
39
+ function unsplashEnabled(options) {
40
+ return options.enabled ?? (void 0 !== options.proxyEndpoint || void 0 !== options.accessKey);
41
+ }
42
+ function clamp(value, min, max) {
43
+ return Math.min(max, Math.max(min, value));
44
+ }
45
+ function createUnsplashProvider(options) {
46
+ const client = (0, external_client_cjs_namespaceObject.createUnsplashClient)({
47
+ ...void 0 !== options.proxyEndpoint ? {
48
+ proxyEndpoint: options.proxyEndpoint
49
+ } : {},
50
+ ...void 0 !== options.accessKey ? {
51
+ accessKey: options.accessKey
52
+ } : {},
53
+ ...void 0 !== options.fetch ? {
54
+ fetch: options.fetch
55
+ } : {},
56
+ ..."number" == typeof options.requestTimeoutMs && Number.isFinite(options.requestTimeoutMs) && options.requestTimeoutMs > 0 ? {
57
+ timeoutMs: options.requestTimeoutMs
58
+ } : {}
59
+ });
60
+ const utm = `utm_source=${encodeURIComponent(options.appName)}&utm_medium=referral`;
61
+ const themes = (0, external_themes_cjs_namespaceObject.resolveThemes)(options.themes);
62
+ const defaultThemeId = (0, external_themes_cjs_namespaceObject.resolveDefaultThemeId)(themes, options.themes);
63
+ const perPage = clamp(Math.trunc(options.perPage ?? 24), 1, 30);
64
+ const cache = (0, external_throttle_cache_cjs_namespaceObject.createTtlCache)(options.cacheTtlMs ?? 300000);
65
+ const throttle = (0, external_throttle_cache_cjs_namespaceObject.createSingleFlightThrottle)({
66
+ minIntervalMs: options.minRequestIntervalMs ?? 1200
67
+ });
68
+ const byId = new Map();
69
+ const toUploadResult = (photo)=>Object.freeze({
70
+ id: `unsplash:${photo.id}`,
71
+ url: photo.urls.regular,
72
+ name: photo.description?.trim() || photo.alt_description?.trim() || `Unsplash ${photo.id}`,
73
+ meta: {
74
+ ...void 0 !== photo.width ? {
75
+ width: photo.width
76
+ } : {},
77
+ ...void 0 !== photo.height ? {
78
+ height: photo.height
79
+ } : {},
80
+ mimeType: "image/jpeg",
81
+ attribution: {
82
+ source: "unsplash",
83
+ photographerName: photo.user.name,
84
+ photographerUrl: `${photo.user.links.html}?${utm}`,
85
+ unsplashUrl: `https://unsplash.com/?${utm}`,
86
+ photoUrl: photo.links.html,
87
+ downloadLocation: photo.links.download_location
88
+ }
89
+ }
90
+ });
91
+ const findTheme = (id)=>themes.find((theme)=>theme.id === id);
92
+ const search = async (filter, page, signal)=>{
93
+ const pageNum = void 0 !== page ? Math.max(1, Number(page) || 1) : 1;
94
+ const themeId = filter.facets?.[UNSPLASH_THEME_FACET]?.[0] ?? defaultThemeId;
95
+ const theme = findTheme(themeId);
96
+ const freeText = filter.query?.trim() ?? "";
97
+ const cacheKey = `${themeId ?? ""}|${freeText}|${pageNum}`;
98
+ const hit = cache.get(cacheKey, Date.now());
99
+ if (void 0 !== hit) return hit;
100
+ let photos;
101
+ let total;
102
+ if (theme?.topicSlugs && theme.topicSlugs.length > 0 && "" === freeText && themeId !== external_themes_cjs_namespaceObject.ALL_THEME_ID) {
103
+ const slug = theme.topicSlugs[0] ?? "";
104
+ photos = await throttle.run(()=>client.topicPhotos(slug, {
105
+ page: pageNum,
106
+ perPage,
107
+ ...theme.orientation ? {
108
+ orientation: theme.orientation
109
+ } : {}
110
+ }, signal));
111
+ total = photos.length;
112
+ } else {
113
+ const query = [
114
+ theme?.query,
115
+ freeText
116
+ ].filter((part)=>Boolean(part)).join(" ") || "editorial";
117
+ const result = await throttle.run(()=>client.searchPhotos({
118
+ query,
119
+ page: pageNum,
120
+ perPage,
121
+ contentFilter: theme?.contentFilter ?? "high",
122
+ ...theme?.orientation ? {
123
+ orientation: theme.orientation
124
+ } : {}
125
+ }, signal));
126
+ photos = result.results;
127
+ total = result.total;
128
+ }
129
+ const items = photos.map(toUploadResult);
130
+ for (const item of items)byId.set(item.id, item);
131
+ const listPage = {
132
+ items,
133
+ total,
134
+ nextCursor: photos.length >= perPage ? String(pageNum + 1) : void 0
135
+ };
136
+ cache.set(cacheKey, listPage, Date.now());
137
+ return listPage;
138
+ };
139
+ const pickResult = async (asset, signal)=>{
140
+ const cached = byId.get(asset.id);
141
+ if (cached?.meta?.attribution !== void 0) {
142
+ client.trackDownload(cached.meta.attribution.downloadLocation, signal);
143
+ return cached;
144
+ }
145
+ const photoId = asset.id.startsWith("unsplash:") ? asset.id.slice(9) : asset.id;
146
+ try {
147
+ const result = toUploadResult(await client.getPhoto(photoId, signal));
148
+ byId.set(result.id, result);
149
+ if (result.meta?.attribution !== void 0) client.trackDownload(result.meta.attribution.downloadLocation, signal);
150
+ return result;
151
+ } catch {
152
+ return {
153
+ id: asset.id,
154
+ url: asset.url
155
+ };
156
+ }
157
+ };
158
+ const listThemes = ()=>themes;
159
+ return {
160
+ id: "unsplash",
161
+ label: "assetManager.source.unsplash",
162
+ capabilities: {
163
+ searchable: true,
164
+ themed: true,
165
+ mutable: false,
166
+ requiresAttribution: true,
167
+ folders: false
168
+ },
169
+ requiredCsp: ()=>({
170
+ connectSrc: [
171
+ "https://api.unsplash.com"
172
+ ],
173
+ imgSrc: [
174
+ "https://images.unsplash.com"
175
+ ]
176
+ }),
177
+ listThemes,
178
+ search,
179
+ pickResult
180
+ };
181
+ }
182
+ exports.UNSPLASH_THEME_FACET = __webpack_exports__.UNSPLASH_THEME_FACET;
183
+ exports.createUnsplashProvider = __webpack_exports__.createUnsplashProvider;
184
+ exports.unsplashEnabled = __webpack_exports__.unsplashEnabled;
185
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
186
+ "UNSPLASH_THEME_FACET",
187
+ "createUnsplashProvider",
188
+ "unsplashEnabled"
189
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
190
+ Object.defineProperty(exports, '__esModule', {
191
+ value: true
192
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @file Unsplash `AssetSourceProvider` (PRD 0002 §8). Lazy entry point reached
3
+ * only via `import()` from the factory — never in the headless chunk. Public
4
+ * subpath: `@anvilkit/plugin-asset-manager/providers/unsplash`.
5
+ *
6
+ * Compliance baked in: search returns hotlinked `urls.regular` + full
7
+ * attribution metadata; `pickResult` fires the MANDATORY download trigger.
8
+ */
9
+ import type { UnsplashSourceOptions } from "../../types/unsplash.js";
10
+ import type { AssetSourceProvider } from "../provider.js";
11
+ /** The facet key the UI uses to carry the active theme into a query. */
12
+ export declare const UNSPLASH_THEME_FACET = "unsplash:theme";
13
+ /** Enabled when a proxy endpoint or access key is present (or forced via `enabled`). */
14
+ export declare function unsplashEnabled(options: UnsplashSourceOptions): boolean;
15
+ export declare function createUnsplashProvider(options: UnsplashSourceOptions): AssetSourceProvider;
16
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +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;AAErD,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAKvE;AAMD,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,qBAAqB,GAC5B,mBAAmB,CAmLrB"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @file Unsplash `AssetSourceProvider` (PRD 0002 §8). Lazy entry point reached
3
+ * only via `import()` from the factory — never in the headless chunk. Public
4
+ * subpath: `@anvilkit/plugin-asset-manager/providers/unsplash`.
5
+ *
6
+ * Compliance baked in: search returns hotlinked `urls.regular` + full
7
+ * attribution metadata; `pickResult` fires the MANDATORY download trigger.
8
+ */
9
+ import type { UnsplashSourceOptions } from "../../types/unsplash.js";
10
+ import type { AssetSourceProvider } from "../provider.js";
11
+ /** The facet key the UI uses to carry the active theme into a query. */
12
+ export declare const UNSPLASH_THEME_FACET = "unsplash:theme";
13
+ /** Enabled when a proxy endpoint or access key is present (or forced via `enabled`). */
14
+ export declare function unsplashEnabled(options: UnsplashSourceOptions): boolean;
15
+ export declare function createUnsplashProvider(options: UnsplashSourceOptions): AssetSourceProvider;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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;AAErD,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAKvE;AAMD,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,qBAAqB,GAC5B,mBAAmB,CAmLrB"}
@@ -0,0 +1,148 @@
1
+ import { createUnsplashClient } from "./client.js";
2
+ import { ALL_THEME_ID, resolveDefaultThemeId, resolveThemes } from "./themes.js";
3
+ import { createSingleFlightThrottle, createTtlCache } from "./throttle-cache.js";
4
+ const UNSPLASH_THEME_FACET = "unsplash:theme";
5
+ function unsplashEnabled(options) {
6
+ return options.enabled ?? (void 0 !== options.proxyEndpoint || void 0 !== options.accessKey);
7
+ }
8
+ function clamp(value, min, max) {
9
+ return Math.min(max, Math.max(min, value));
10
+ }
11
+ function createUnsplashProvider(options) {
12
+ const client = createUnsplashClient({
13
+ ...void 0 !== options.proxyEndpoint ? {
14
+ proxyEndpoint: options.proxyEndpoint
15
+ } : {},
16
+ ...void 0 !== options.accessKey ? {
17
+ accessKey: options.accessKey
18
+ } : {},
19
+ ...void 0 !== options.fetch ? {
20
+ fetch: options.fetch
21
+ } : {},
22
+ ..."number" == typeof options.requestTimeoutMs && Number.isFinite(options.requestTimeoutMs) && options.requestTimeoutMs > 0 ? {
23
+ timeoutMs: options.requestTimeoutMs
24
+ } : {}
25
+ });
26
+ const utm = `utm_source=${encodeURIComponent(options.appName)}&utm_medium=referral`;
27
+ const themes = resolveThemes(options.themes);
28
+ const defaultThemeId = resolveDefaultThemeId(themes, options.themes);
29
+ const perPage = clamp(Math.trunc(options.perPage ?? 24), 1, 30);
30
+ const cache = createTtlCache(options.cacheTtlMs ?? 300000);
31
+ const throttle = createSingleFlightThrottle({
32
+ minIntervalMs: options.minRequestIntervalMs ?? 1200
33
+ });
34
+ const byId = new Map();
35
+ const toUploadResult = (photo)=>Object.freeze({
36
+ id: `unsplash:${photo.id}`,
37
+ url: photo.urls.regular,
38
+ name: photo.description?.trim() || photo.alt_description?.trim() || `Unsplash ${photo.id}`,
39
+ meta: {
40
+ ...void 0 !== photo.width ? {
41
+ width: photo.width
42
+ } : {},
43
+ ...void 0 !== photo.height ? {
44
+ height: photo.height
45
+ } : {},
46
+ mimeType: "image/jpeg",
47
+ attribution: {
48
+ source: "unsplash",
49
+ photographerName: photo.user.name,
50
+ photographerUrl: `${photo.user.links.html}?${utm}`,
51
+ unsplashUrl: `https://unsplash.com/?${utm}`,
52
+ photoUrl: photo.links.html,
53
+ downloadLocation: photo.links.download_location
54
+ }
55
+ }
56
+ });
57
+ const findTheme = (id)=>themes.find((theme)=>theme.id === id);
58
+ const search = async (filter, page, signal)=>{
59
+ const pageNum = void 0 !== page ? Math.max(1, Number(page) || 1) : 1;
60
+ const themeId = filter.facets?.[UNSPLASH_THEME_FACET]?.[0] ?? defaultThemeId;
61
+ const theme = findTheme(themeId);
62
+ const freeText = filter.query?.trim() ?? "";
63
+ const cacheKey = `${themeId ?? ""}|${freeText}|${pageNum}`;
64
+ const hit = cache.get(cacheKey, Date.now());
65
+ if (void 0 !== hit) return hit;
66
+ let photos;
67
+ let total;
68
+ if (theme?.topicSlugs && theme.topicSlugs.length > 0 && "" === freeText && themeId !== ALL_THEME_ID) {
69
+ const slug = theme.topicSlugs[0] ?? "";
70
+ photos = await throttle.run(()=>client.topicPhotos(slug, {
71
+ page: pageNum,
72
+ perPage,
73
+ ...theme.orientation ? {
74
+ orientation: theme.orientation
75
+ } : {}
76
+ }, signal));
77
+ total = photos.length;
78
+ } else {
79
+ const query = [
80
+ theme?.query,
81
+ freeText
82
+ ].filter((part)=>Boolean(part)).join(" ") || "editorial";
83
+ const result = await throttle.run(()=>client.searchPhotos({
84
+ query,
85
+ page: pageNum,
86
+ perPage,
87
+ contentFilter: theme?.contentFilter ?? "high",
88
+ ...theme?.orientation ? {
89
+ orientation: theme.orientation
90
+ } : {}
91
+ }, signal));
92
+ photos = result.results;
93
+ total = result.total;
94
+ }
95
+ const items = photos.map(toUploadResult);
96
+ for (const item of items)byId.set(item.id, item);
97
+ const listPage = {
98
+ items,
99
+ total,
100
+ nextCursor: photos.length >= perPage ? String(pageNum + 1) : void 0
101
+ };
102
+ cache.set(cacheKey, listPage, Date.now());
103
+ return listPage;
104
+ };
105
+ const pickResult = async (asset, signal)=>{
106
+ const cached = byId.get(asset.id);
107
+ if (cached?.meta?.attribution !== void 0) {
108
+ client.trackDownload(cached.meta.attribution.downloadLocation, signal);
109
+ return cached;
110
+ }
111
+ const photoId = asset.id.startsWith("unsplash:") ? asset.id.slice(9) : asset.id;
112
+ try {
113
+ const result = toUploadResult(await client.getPhoto(photoId, signal));
114
+ byId.set(result.id, result);
115
+ if (result.meta?.attribution !== void 0) client.trackDownload(result.meta.attribution.downloadLocation, signal);
116
+ return result;
117
+ } catch {
118
+ return {
119
+ id: asset.id,
120
+ url: asset.url
121
+ };
122
+ }
123
+ };
124
+ const listThemes = ()=>themes;
125
+ return {
126
+ id: "unsplash",
127
+ label: "assetManager.source.unsplash",
128
+ capabilities: {
129
+ searchable: true,
130
+ themed: true,
131
+ mutable: false,
132
+ requiresAttribution: true,
133
+ folders: false
134
+ },
135
+ requiredCsp: ()=>({
136
+ connectSrc: [
137
+ "https://api.unsplash.com"
138
+ ],
139
+ imgSrc: [
140
+ "https://images.unsplash.com"
141
+ ]
142
+ }),
143
+ listThemes,
144
+ search,
145
+ pickResult
146
+ };
147
+ }
148
+ export { UNSPLASH_THEME_FACET, createUnsplashProvider, unsplashEnabled };
@@ -0,0 +1,141 @@
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
+ const ALL_THEME_ID = "__all__";
31
+ const DEFAULT_UNSPLASH_THEMES = Object.freeze([
32
+ {
33
+ id: "nature",
34
+ label: "assetManager.unsplash.theme.nature",
35
+ topicSlugs: [
36
+ "nature"
37
+ ],
38
+ query: "nature landscape",
39
+ orientation: "landscape"
40
+ },
41
+ {
42
+ id: "architecture",
43
+ label: "assetManager.unsplash.theme.architecture",
44
+ topicSlugs: [
45
+ "architecture-interior"
46
+ ],
47
+ query: "architecture building"
48
+ },
49
+ {
50
+ id: "business",
51
+ label: "assetManager.unsplash.theme.business",
52
+ topicSlugs: [
53
+ "business-work"
54
+ ],
55
+ query: "business office work"
56
+ },
57
+ {
58
+ id: "food",
59
+ label: "assetManager.unsplash.theme.food",
60
+ topicSlugs: [
61
+ "food-drink"
62
+ ],
63
+ query: "food meal"
64
+ },
65
+ {
66
+ id: "technology",
67
+ label: "assetManager.unsplash.theme.technology",
68
+ topicSlugs: [
69
+ "experimental"
70
+ ],
71
+ query: "technology computer"
72
+ },
73
+ {
74
+ id: "travel",
75
+ label: "assetManager.unsplash.theme.travel",
76
+ topicSlugs: [
77
+ "travel"
78
+ ],
79
+ query: "travel destination"
80
+ },
81
+ {
82
+ id: "texture",
83
+ label: "assetManager.unsplash.theme.texture",
84
+ topicSlugs: [
85
+ "textures-patterns"
86
+ ],
87
+ query: "abstract texture",
88
+ orientation: "squarish"
89
+ },
90
+ {
91
+ id: "people",
92
+ label: "assetManager.unsplash.theme.people",
93
+ topicSlugs: [
94
+ "people"
95
+ ],
96
+ query: "people portrait"
97
+ }
98
+ ]);
99
+ function resolveThemes(config) {
100
+ let base;
101
+ if (config?.themes) base = config.themes;
102
+ else {
103
+ const excluded = new Set(config?.excludeThemes ?? []);
104
+ const filtered = excluded.size > 0 ? DEFAULT_UNSPLASH_THEMES.filter((t)=>!excluded.has(t.id)) : DEFAULT_UNSPLASH_THEMES;
105
+ base = config?.additionalThemes ? [
106
+ ...filtered,
107
+ ...config.additionalThemes
108
+ ] : filtered;
109
+ }
110
+ const themes = [];
111
+ if (config?.allowFreeSearch !== false) themes.push({
112
+ id: ALL_THEME_ID,
113
+ label: "assetManager.unsplash.theme.all"
114
+ });
115
+ themes.push(...base);
116
+ return Object.freeze(themes);
117
+ }
118
+ function resolveDefaultThemeId(themes, config) {
119
+ if (config?.defaultThemeId && themes.some((t)=>t.id === config.defaultThemeId)) return config.defaultThemeId;
120
+ return themes[0]?.id;
121
+ }
122
+ __webpack_require__.d(__webpack_exports__, {
123
+ resolveDefaultThemeId: ()=>resolveDefaultThemeId,
124
+ resolveThemes: ()=>resolveThemes
125
+ }, {
126
+ ALL_THEME_ID: ALL_THEME_ID,
127
+ DEFAULT_UNSPLASH_THEMES: DEFAULT_UNSPLASH_THEMES
128
+ });
129
+ exports.ALL_THEME_ID = __webpack_exports__.ALL_THEME_ID;
130
+ exports.DEFAULT_UNSPLASH_THEMES = __webpack_exports__.DEFAULT_UNSPLASH_THEMES;
131
+ exports.resolveDefaultThemeId = __webpack_exports__.resolveDefaultThemeId;
132
+ exports.resolveThemes = __webpack_exports__.resolveThemes;
133
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
134
+ "ALL_THEME_ID",
135
+ "DEFAULT_UNSPLASH_THEMES",
136
+ "resolveDefaultThemeId",
137
+ "resolveThemes"
138
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
139
+ Object.defineProperty(exports, '__esModule', {
140
+ value: true
141
+ });