@anvilkit/plugin-asset-manager 0.1.1
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.
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/adapters/data-url.cjs +78 -0
- package/dist/adapters/data-url.d.cts +6 -0
- package/dist/adapters/data-url.d.cts.map +1 -0
- package/dist/adapters/data-url.d.ts +6 -0
- package/dist/adapters/data-url.d.ts.map +1 -0
- package/dist/adapters/data-url.js +44 -0
- package/dist/adapters/extract-image-dimensions.cjs +69 -0
- package/dist/adapters/extract-image-dimensions.d.cts +21 -0
- package/dist/adapters/extract-image-dimensions.d.cts.map +1 -0
- package/dist/adapters/extract-image-dimensions.d.ts +21 -0
- package/dist/adapters/extract-image-dimensions.d.ts.map +1 -0
- package/dist/adapters/extract-image-dimensions.js +35 -0
- package/dist/adapters/in-memory.cjs +62 -0
- package/dist/adapters/in-memory.d.cts +3 -0
- package/dist/adapters/in-memory.d.cts.map +1 -0
- package/dist/adapters/in-memory.d.ts +3 -0
- package/dist/adapters/in-memory.d.ts.map +1 -0
- package/dist/adapters/in-memory.js +28 -0
- package/dist/adapters/s3-presigned.cjs +166 -0
- package/dist/adapters/s3-presigned.d.cts +59 -0
- package/dist/adapters/s3-presigned.d.cts.map +1 -0
- package/dist/adapters/s3-presigned.d.ts +59 -0
- package/dist/adapters/s3-presigned.d.ts.map +1 -0
- package/dist/adapters/s3-presigned.js +129 -0
- package/dist/asset-reference.cjs +38 -0
- package/dist/asset-reference.d.cts +10 -0
- package/dist/asset-reference.d.cts.map +1 -0
- package/dist/asset-reference.d.ts +10 -0
- package/dist/asset-reference.d.ts.map +1 -0
- package/dist/asset-reference.js +4 -0
- package/dist/csp.cjs +83 -0
- package/dist/csp.d.cts +45 -0
- package/dist/csp.d.cts.map +1 -0
- package/dist/csp.d.ts +45 -0
- package/dist/csp.d.ts.map +1 -0
- package/dist/csp.js +49 -0
- package/dist/errors.cjs +58 -0
- package/dist/errors.d.cts +15 -0
- package/dist/errors.d.cts.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +21 -0
- package/dist/header-action.cjs +44 -0
- package/dist/header-action.d.cts +3 -0
- package/dist/header-action.d.cts.map +1 -0
- package/dist/header-action.d.ts +3 -0
- package/dist/header-action.d.ts.map +1 -0
- package/dist/header-action.js +10 -0
- package/dist/index.cjs +90 -0
- package/dist/index.d.cts +18 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/infer-kind.cjs +45 -0
- package/dist/infer-kind.d.cts +8 -0
- package/dist/infer-kind.d.cts.map +1 -0
- package/dist/infer-kind.d.ts +8 -0
- package/dist/infer-kind.d.ts.map +1 -0
- package/dist/infer-kind.js +11 -0
- package/dist/plugin.cjs +258 -0
- package/dist/plugin.d.cts +9 -0
- package/dist/plugin.d.cts.map +1 -0
- package/dist/plugin.d.ts +9 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +212 -0
- package/dist/registry.cjs +198 -0
- package/dist/registry.d.cts +3 -0
- package/dist/registry.d.cts.map +1 -0
- package/dist/registry.d.ts +3 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +164 -0
- package/dist/resolver.cjs +185 -0
- package/dist/resolver.d.cts +10 -0
- package/dist/resolver.d.cts.map +1 -0
- package/dist/resolver.d.ts +10 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +148 -0
- package/dist/retry.cjs +123 -0
- package/dist/retry.d.cts +71 -0
- package/dist/retry.d.cts.map +1 -0
- package/dist/retry.d.ts +71 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +86 -0
- package/dist/studio-asset-source.cjs +211 -0
- package/dist/studio-asset-source.d.cts +52 -0
- package/dist/studio-asset-source.d.cts.map +1 -0
- package/dist/studio-asset-source.d.ts +52 -0
- package/dist/studio-asset-source.d.ts.map +1 -0
- package/dist/studio-asset-source.js +171 -0
- package/dist/testing/index.cjs +66 -0
- package/dist/testing/index.d.cts +24 -0
- package/dist/testing/index.d.cts.map +1 -0
- package/dist/testing/index.d.ts +24 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +29 -0
- package/dist/types.cjs +18 -0
- package/dist/types.d.cts +132 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.ts +132 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/dist/ui/AssetBrowser.cjs +271 -0
- package/dist/ui/AssetBrowser.d.cts +45 -0
- package/dist/ui/AssetBrowser.d.cts.map +1 -0
- package/dist/ui/AssetBrowser.d.ts +45 -0
- package/dist/ui/AssetBrowser.d.ts.map +1 -0
- package/dist/ui/AssetBrowser.js +237 -0
- package/dist/ui/AssetCommandPalette.cjs +135 -0
- package/dist/ui/AssetCommandPalette.d.cts +21 -0
- package/dist/ui/AssetCommandPalette.d.cts.map +1 -0
- package/dist/ui/AssetCommandPalette.d.ts +21 -0
- package/dist/ui/AssetCommandPalette.d.ts.map +1 -0
- package/dist/ui/AssetCommandPalette.js +101 -0
- package/dist/ui/AssetManagerUI.cjs +169 -0
- package/dist/ui/AssetManagerUI.d.cts +15 -0
- package/dist/ui/AssetManagerUI.d.cts.map +1 -0
- package/dist/ui/AssetManagerUI.d.ts +15 -0
- package/dist/ui/AssetManagerUI.d.ts.map +1 -0
- package/dist/ui/AssetManagerUI.js +135 -0
- package/dist/ui/DeleteAssetDialog.cjs +70 -0
- package/dist/ui/DeleteAssetDialog.d.cts +22 -0
- package/dist/ui/DeleteAssetDialog.d.cts.map +1 -0
- package/dist/ui/DeleteAssetDialog.d.ts +22 -0
- package/dist/ui/DeleteAssetDialog.d.ts.map +1 -0
- package/dist/ui/DeleteAssetDialog.js +36 -0
- package/dist/ui/MetadataPanel.cjs +147 -0
- package/dist/ui/MetadataPanel.d.cts +21 -0
- package/dist/ui/MetadataPanel.d.cts.map +1 -0
- package/dist/ui/MetadataPanel.d.ts +21 -0
- package/dist/ui/MetadataPanel.d.ts.map +1 -0
- package/dist/ui/MetadataPanel.js +113 -0
- package/dist/ui/ReplaceAssetDialog.cjs +125 -0
- package/dist/ui/ReplaceAssetDialog.d.cts +14 -0
- package/dist/ui/ReplaceAssetDialog.d.cts.map +1 -0
- package/dist/ui/ReplaceAssetDialog.d.ts +14 -0
- package/dist/ui/ReplaceAssetDialog.d.ts.map +1 -0
- package/dist/ui/ReplaceAssetDialog.js +91 -0
- package/dist/ui/UploadButton.cjs +189 -0
- package/dist/ui/UploadButton.d.cts +17 -0
- package/dist/ui/UploadButton.d.cts.map +1 -0
- package/dist/ui/UploadButton.d.ts +17 -0
- package/dist/ui/UploadButton.d.ts.map +1 -0
- package/dist/ui/UploadButton.js +155 -0
- package/dist/ui/index.cjs +60 -0
- package/dist/ui/index.d.cts +15 -0
- package/dist/ui/index.d.cts.map +1 -0
- package/dist/ui/index.d.ts +15 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +7 -0
- package/dist/validate-upload-result.cjs +149 -0
- package/dist/validate-upload-result.d.cts +9 -0
- package/dist/validate-upload-result.d.cts.map +1 -0
- package/dist/validate-upload-result.d.ts +9 -0
- package/dist/validate-upload-result.d.ts.map +1 -0
- package/dist/validate-upload-result.js +115 -0
- package/package.json +131 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
MAX_CONCURRENT_UPLOADS: ()=>MAX_CONCURRENT_UPLOADS,
|
|
28
|
+
inferStudioAssetKind: ()=>inferStudioAssetKind,
|
|
29
|
+
createStudioAssetSource: ()=>createStudioAssetSource
|
|
30
|
+
});
|
|
31
|
+
const external_asset_reference_cjs_namespaceObject = require("./asset-reference.cjs");
|
|
32
|
+
const external_infer_kind_cjs_namespaceObject = require("./infer-kind.cjs");
|
|
33
|
+
const MAX_CONCURRENT_UPLOADS = 3;
|
|
34
|
+
function createStudioAssetSource(options) {
|
|
35
|
+
const { registry, upload, getThumbnail } = options;
|
|
36
|
+
const maxConcurrent = Math.max(1, options.maxConcurrentUploads ?? MAX_CONCURRENT_UPLOADS);
|
|
37
|
+
const project = (entry)=>toStudioAsset(entry, getThumbnail);
|
|
38
|
+
const uploadListeners = new Set();
|
|
39
|
+
const fanOut = (event)=>{
|
|
40
|
+
for (const listener of uploadListeners)listener(event);
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
list () {
|
|
44
|
+
return registry.list().map(project);
|
|
45
|
+
},
|
|
46
|
+
listPaginated (query) {
|
|
47
|
+
const page = registry.search({
|
|
48
|
+
...void 0 !== query.query ? {
|
|
49
|
+
query: query.query
|
|
50
|
+
} : {},
|
|
51
|
+
...query.kinds ? {
|
|
52
|
+
kinds: query.kinds
|
|
53
|
+
} : {},
|
|
54
|
+
...query.tags ? {
|
|
55
|
+
tags: query.tags
|
|
56
|
+
} : {},
|
|
57
|
+
...void 0 !== query.cursor ? {
|
|
58
|
+
cursor: query.cursor
|
|
59
|
+
} : {},
|
|
60
|
+
...void 0 !== query.limit ? {
|
|
61
|
+
limit: query.limit
|
|
62
|
+
} : {}
|
|
63
|
+
});
|
|
64
|
+
const projected = {
|
|
65
|
+
items: Object.freeze(page.items.map(project)),
|
|
66
|
+
total: page.total,
|
|
67
|
+
nextCursor: page.nextCursor
|
|
68
|
+
};
|
|
69
|
+
return Promise.resolve(projected);
|
|
70
|
+
},
|
|
71
|
+
async upload (files, listener) {
|
|
72
|
+
const fileList = Array.from(files);
|
|
73
|
+
if (0 === fileList.length) return [];
|
|
74
|
+
const totalBytes = fileList.reduce((acc, file)=>acc + file.size, 0);
|
|
75
|
+
let bytesUploaded = 0;
|
|
76
|
+
const results = new Array(fileList.length).fill(null);
|
|
77
|
+
let nextIndex = 0;
|
|
78
|
+
let abortError;
|
|
79
|
+
const emit = (event)=>{
|
|
80
|
+
listener?.(event);
|
|
81
|
+
fanOut(event);
|
|
82
|
+
};
|
|
83
|
+
const runWorker = async ()=>{
|
|
84
|
+
while(true){
|
|
85
|
+
if (void 0 !== abortError) return;
|
|
86
|
+
const index = nextIndex++;
|
|
87
|
+
if (index >= fileList.length) return;
|
|
88
|
+
const file = fileList[index];
|
|
89
|
+
if (void 0 === file) return;
|
|
90
|
+
try {
|
|
91
|
+
const result = await upload(file);
|
|
92
|
+
bytesUploaded += file.size;
|
|
93
|
+
const asset = project(result);
|
|
94
|
+
results[index] = asset;
|
|
95
|
+
emit({
|
|
96
|
+
type: "progress",
|
|
97
|
+
bytesUploaded,
|
|
98
|
+
bytesTotal: totalBytes
|
|
99
|
+
});
|
|
100
|
+
emit({
|
|
101
|
+
type: "done",
|
|
102
|
+
asset
|
|
103
|
+
});
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (isAbortError(error)) {
|
|
106
|
+
abortError = error;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
110
|
+
emit({
|
|
111
|
+
type: "error",
|
|
112
|
+
message
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const workerCount = Math.min(maxConcurrent, fileList.length);
|
|
118
|
+
const workers = [];
|
|
119
|
+
for(let i = 0; i < workerCount; i += 1)workers.push(runWorker());
|
|
120
|
+
await Promise.all(workers);
|
|
121
|
+
if (void 0 !== abortError) throw abortError;
|
|
122
|
+
return results.filter((value)=>null !== value);
|
|
123
|
+
},
|
|
124
|
+
delete (assetId) {
|
|
125
|
+
registry.delete(assetId);
|
|
126
|
+
return Promise.resolve();
|
|
127
|
+
},
|
|
128
|
+
rename (assetId, nextName) {
|
|
129
|
+
registry.rename(assetId, nextName);
|
|
130
|
+
return Promise.resolve();
|
|
131
|
+
},
|
|
132
|
+
setTags (assetId, tags) {
|
|
133
|
+
registry.setTags(assetId, tags);
|
|
134
|
+
return Promise.resolve();
|
|
135
|
+
},
|
|
136
|
+
async replace (assetId, file) {
|
|
137
|
+
const result = await upload(file);
|
|
138
|
+
const replaced = registry.replace(assetId, result);
|
|
139
|
+
if (void 0 === replaced) return project(result);
|
|
140
|
+
return project(replaced);
|
|
141
|
+
},
|
|
142
|
+
getUrl (assetId) {
|
|
143
|
+
return (0, external_asset_reference_cjs_namespaceObject.createAssetReference)(assetId);
|
|
144
|
+
},
|
|
145
|
+
subscribe (listener) {
|
|
146
|
+
return registry.subscribe(listener);
|
|
147
|
+
},
|
|
148
|
+
subscribeUploads (listener) {
|
|
149
|
+
uploadListeners.add(listener);
|
|
150
|
+
return ()=>{
|
|
151
|
+
uploadListeners.delete(listener);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function toStudioAsset(entry, getThumbnail) {
|
|
157
|
+
const kind = (0, external_infer_kind_cjs_namespaceObject.inferAssetKind)(entry);
|
|
158
|
+
const url = (0, external_asset_reference_cjs_namespaceObject.createAssetReference)(entry.id);
|
|
159
|
+
const name = entry.name ?? deriveFallbackName(entry);
|
|
160
|
+
const thumbnailUrl = deriveThumbnailUrl(entry, kind, getThumbnail);
|
|
161
|
+
const studioAsset = {
|
|
162
|
+
id: entry.id,
|
|
163
|
+
kind,
|
|
164
|
+
name,
|
|
165
|
+
url,
|
|
166
|
+
...void 0 !== thumbnailUrl ? {
|
|
167
|
+
thumbnailUrl
|
|
168
|
+
} : {},
|
|
169
|
+
...entry.meta?.mimeType !== void 0 ? {
|
|
170
|
+
mimeType: entry.meta.mimeType
|
|
171
|
+
} : {},
|
|
172
|
+
...entry.meta?.size !== void 0 ? {
|
|
173
|
+
size: entry.meta.size
|
|
174
|
+
} : {},
|
|
175
|
+
...entry.tags && entry.tags.length > 0 ? {
|
|
176
|
+
tags: Object.freeze([
|
|
177
|
+
...entry.tags
|
|
178
|
+
])
|
|
179
|
+
} : {}
|
|
180
|
+
};
|
|
181
|
+
return studioAsset;
|
|
182
|
+
}
|
|
183
|
+
function inferStudioAssetKind(entry) {
|
|
184
|
+
return (0, external_infer_kind_cjs_namespaceObject.inferAssetKind)(entry);
|
|
185
|
+
}
|
|
186
|
+
function deriveThumbnailUrl(entry, kind, getThumbnail) {
|
|
187
|
+
if (void 0 !== getThumbnail) return getThumbnail(entry);
|
|
188
|
+
return "image" === kind ? entry.url : void 0;
|
|
189
|
+
}
|
|
190
|
+
function deriveFallbackName(entry) {
|
|
191
|
+
const tail = entry.url.split(/[/?#]/).filter(Boolean).pop();
|
|
192
|
+
if (void 0 !== tail && "" !== tail && !tail.startsWith("data:")) return tail;
|
|
193
|
+
const idTail = entry.id.length > 12 ? `${entry.id.slice(0, 8)}…` : entry.id;
|
|
194
|
+
return `Asset ${idTail}`;
|
|
195
|
+
}
|
|
196
|
+
function isAbortError(error) {
|
|
197
|
+
if (null === error || "object" != typeof error) return false;
|
|
198
|
+
const name = error.name;
|
|
199
|
+
return "AbortError" === name;
|
|
200
|
+
}
|
|
201
|
+
exports.MAX_CONCURRENT_UPLOADS = __webpack_exports__.MAX_CONCURRENT_UPLOADS;
|
|
202
|
+
exports.createStudioAssetSource = __webpack_exports__.createStudioAssetSource;
|
|
203
|
+
exports.inferStudioAssetKind = __webpack_exports__.inferStudioAssetKind;
|
|
204
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
205
|
+
"MAX_CONCURRENT_UPLOADS",
|
|
206
|
+
"createStudioAssetSource",
|
|
207
|
+
"inferStudioAssetKind"
|
|
208
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
209
|
+
Object.defineProperty(exports, '__esModule', {
|
|
210
|
+
value: true
|
|
211
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file `StudioAssetSource` adapter — bridges the asset-manager
|
|
3
|
+
* registry into the sidebar's `image` module.
|
|
4
|
+
*
|
|
5
|
+
* The sidebar reads through `ctx.registerAssetSource(source)`. This
|
|
6
|
+
* file shapes the registry's `UploadResult` rows into the `StudioAsset`
|
|
7
|
+
* shape the sidebar consumes, threads the upload pipeline through
|
|
8
|
+
* `uploadAsset()`, and notifies subscribers on every mutation.
|
|
9
|
+
*
|
|
10
|
+
* The adapter does not own state — it is a thin projection over the
|
|
11
|
+
* shared `AssetRegistry`. Mutation methods route back through the
|
|
12
|
+
* registry so the IR resolver and the sidebar see the same data.
|
|
13
|
+
*/
|
|
14
|
+
import type { StudioAssetKind, StudioAssetSource } from "@anvilkit/core/types";
|
|
15
|
+
import type { AssetRegistry, UploadResult } from "./types.js";
|
|
16
|
+
/**
|
|
17
|
+
* Default concurrency cap for batched uploads. Editors typically drag
|
|
18
|
+
* 1–10 files at a time; three concurrent uploads strikes a balance
|
|
19
|
+
* between throughput and politeness to host endpoints.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_CONCURRENT_UPLOADS = 3;
|
|
22
|
+
export interface CreateStudioAssetSourceOptions {
|
|
23
|
+
readonly registry: AssetRegistry;
|
|
24
|
+
/**
|
|
25
|
+
* Performs the upload. Provided by the plugin so the adapter does
|
|
26
|
+
* not need to depend on `StudioPluginContext` directly.
|
|
27
|
+
*/
|
|
28
|
+
readonly upload: (file: File) => Promise<UploadResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Optional thumbnail derivation. Returning a string sets
|
|
31
|
+
* `StudioAsset.thumbnailUrl`; returning `undefined` suppresses the
|
|
32
|
+
* thumbnail (overriding the default-for-images behavior).
|
|
33
|
+
*
|
|
34
|
+
* When omitted, image-kind assets get the original URL as their
|
|
35
|
+
* thumbnail and other kinds get no thumbnail.
|
|
36
|
+
*/
|
|
37
|
+
readonly getThumbnail?: (entry: UploadResult) => string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Maximum number of uploads in flight. Defaults to
|
|
40
|
+
* `MAX_CONCURRENT_UPLOADS` (3). Set to 1 to restore the previous
|
|
41
|
+
* sequential behavior.
|
|
42
|
+
*/
|
|
43
|
+
readonly maxConcurrentUploads?: number;
|
|
44
|
+
}
|
|
45
|
+
export declare function createStudioAssetSource(options: CreateStudioAssetSourceOptions): StudioAssetSource;
|
|
46
|
+
/**
|
|
47
|
+
* Public alias for {@link inferAssetKind}. Preserved as the documented
|
|
48
|
+
* Studio-side projection so existing imports keep working; library
|
|
49
|
+
* search now uses the same logic via `infer-kind.ts`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function inferStudioAssetKind(entry: UploadResult): StudioAssetKind;
|
|
52
|
+
//# sourceMappingURL=studio-asset-source.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-asset-source.d.cts","sourceRoot":"","sources":["../src/studio-asset-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAEX,eAAe,EAGf,iBAAiB,EAGjB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACvD;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,GAAG,SAAS,CAAC;IACpE;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,8BAA8B,GACrC,iBAAiB,CAqJnB;AA4BD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,eAAe,CAEzE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file `StudioAssetSource` adapter — bridges the asset-manager
|
|
3
|
+
* registry into the sidebar's `image` module.
|
|
4
|
+
*
|
|
5
|
+
* The sidebar reads through `ctx.registerAssetSource(source)`. This
|
|
6
|
+
* file shapes the registry's `UploadResult` rows into the `StudioAsset`
|
|
7
|
+
* shape the sidebar consumes, threads the upload pipeline through
|
|
8
|
+
* `uploadAsset()`, and notifies subscribers on every mutation.
|
|
9
|
+
*
|
|
10
|
+
* The adapter does not own state — it is a thin projection over the
|
|
11
|
+
* shared `AssetRegistry`. Mutation methods route back through the
|
|
12
|
+
* registry so the IR resolver and the sidebar see the same data.
|
|
13
|
+
*/
|
|
14
|
+
import type { StudioAssetKind, StudioAssetSource } from "@anvilkit/core/types";
|
|
15
|
+
import type { AssetRegistry, UploadResult } from "./types.js";
|
|
16
|
+
/**
|
|
17
|
+
* Default concurrency cap for batched uploads. Editors typically drag
|
|
18
|
+
* 1–10 files at a time; three concurrent uploads strikes a balance
|
|
19
|
+
* between throughput and politeness to host endpoints.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_CONCURRENT_UPLOADS = 3;
|
|
22
|
+
export interface CreateStudioAssetSourceOptions {
|
|
23
|
+
readonly registry: AssetRegistry;
|
|
24
|
+
/**
|
|
25
|
+
* Performs the upload. Provided by the plugin so the adapter does
|
|
26
|
+
* not need to depend on `StudioPluginContext` directly.
|
|
27
|
+
*/
|
|
28
|
+
readonly upload: (file: File) => Promise<UploadResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Optional thumbnail derivation. Returning a string sets
|
|
31
|
+
* `StudioAsset.thumbnailUrl`; returning `undefined` suppresses the
|
|
32
|
+
* thumbnail (overriding the default-for-images behavior).
|
|
33
|
+
*
|
|
34
|
+
* When omitted, image-kind assets get the original URL as their
|
|
35
|
+
* thumbnail and other kinds get no thumbnail.
|
|
36
|
+
*/
|
|
37
|
+
readonly getThumbnail?: (entry: UploadResult) => string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Maximum number of uploads in flight. Defaults to
|
|
40
|
+
* `MAX_CONCURRENT_UPLOADS` (3). Set to 1 to restore the previous
|
|
41
|
+
* sequential behavior.
|
|
42
|
+
*/
|
|
43
|
+
readonly maxConcurrentUploads?: number;
|
|
44
|
+
}
|
|
45
|
+
export declare function createStudioAssetSource(options: CreateStudioAssetSourceOptions): StudioAssetSource;
|
|
46
|
+
/**
|
|
47
|
+
* Public alias for {@link inferAssetKind}. Preserved as the documented
|
|
48
|
+
* Studio-side projection so existing imports keep working; library
|
|
49
|
+
* search now uses the same logic via `infer-kind.ts`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function inferStudioAssetKind(entry: UploadResult): StudioAssetKind;
|
|
52
|
+
//# sourceMappingURL=studio-asset-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-asset-source.d.ts","sourceRoot":"","sources":["../src/studio-asset-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAEX,eAAe,EAGf,iBAAiB,EAGjB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IACvD;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,GAAG,SAAS,CAAC;IACpE;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,8BAA8B,GACrC,iBAAiB,CAqJnB;AA4BD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,eAAe,CAEzE"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { createAssetReference } from "./asset-reference.js";
|
|
2
|
+
import { inferAssetKind } from "./infer-kind.js";
|
|
3
|
+
const MAX_CONCURRENT_UPLOADS = 3;
|
|
4
|
+
function createStudioAssetSource(options) {
|
|
5
|
+
const { registry, upload, getThumbnail } = options;
|
|
6
|
+
const maxConcurrent = Math.max(1, options.maxConcurrentUploads ?? MAX_CONCURRENT_UPLOADS);
|
|
7
|
+
const project = (entry)=>toStudioAsset(entry, getThumbnail);
|
|
8
|
+
const uploadListeners = new Set();
|
|
9
|
+
const fanOut = (event)=>{
|
|
10
|
+
for (const listener of uploadListeners)listener(event);
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
list () {
|
|
14
|
+
return registry.list().map(project);
|
|
15
|
+
},
|
|
16
|
+
listPaginated (query) {
|
|
17
|
+
const page = registry.search({
|
|
18
|
+
...void 0 !== query.query ? {
|
|
19
|
+
query: query.query
|
|
20
|
+
} : {},
|
|
21
|
+
...query.kinds ? {
|
|
22
|
+
kinds: query.kinds
|
|
23
|
+
} : {},
|
|
24
|
+
...query.tags ? {
|
|
25
|
+
tags: query.tags
|
|
26
|
+
} : {},
|
|
27
|
+
...void 0 !== query.cursor ? {
|
|
28
|
+
cursor: query.cursor
|
|
29
|
+
} : {},
|
|
30
|
+
...void 0 !== query.limit ? {
|
|
31
|
+
limit: query.limit
|
|
32
|
+
} : {}
|
|
33
|
+
});
|
|
34
|
+
const projected = {
|
|
35
|
+
items: Object.freeze(page.items.map(project)),
|
|
36
|
+
total: page.total,
|
|
37
|
+
nextCursor: page.nextCursor
|
|
38
|
+
};
|
|
39
|
+
return Promise.resolve(projected);
|
|
40
|
+
},
|
|
41
|
+
async upload (files, listener) {
|
|
42
|
+
const fileList = Array.from(files);
|
|
43
|
+
if (0 === fileList.length) return [];
|
|
44
|
+
const totalBytes = fileList.reduce((acc, file)=>acc + file.size, 0);
|
|
45
|
+
let bytesUploaded = 0;
|
|
46
|
+
const results = new Array(fileList.length).fill(null);
|
|
47
|
+
let nextIndex = 0;
|
|
48
|
+
let abortError;
|
|
49
|
+
const emit = (event)=>{
|
|
50
|
+
listener?.(event);
|
|
51
|
+
fanOut(event);
|
|
52
|
+
};
|
|
53
|
+
const runWorker = async ()=>{
|
|
54
|
+
while(true){
|
|
55
|
+
if (void 0 !== abortError) return;
|
|
56
|
+
const index = nextIndex++;
|
|
57
|
+
if (index >= fileList.length) return;
|
|
58
|
+
const file = fileList[index];
|
|
59
|
+
if (void 0 === file) return;
|
|
60
|
+
try {
|
|
61
|
+
const result = await upload(file);
|
|
62
|
+
bytesUploaded += file.size;
|
|
63
|
+
const asset = project(result);
|
|
64
|
+
results[index] = asset;
|
|
65
|
+
emit({
|
|
66
|
+
type: "progress",
|
|
67
|
+
bytesUploaded,
|
|
68
|
+
bytesTotal: totalBytes
|
|
69
|
+
});
|
|
70
|
+
emit({
|
|
71
|
+
type: "done",
|
|
72
|
+
asset
|
|
73
|
+
});
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (isAbortError(error)) {
|
|
76
|
+
abortError = error;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
80
|
+
emit({
|
|
81
|
+
type: "error",
|
|
82
|
+
message
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const workerCount = Math.min(maxConcurrent, fileList.length);
|
|
88
|
+
const workers = [];
|
|
89
|
+
for(let i = 0; i < workerCount; i += 1)workers.push(runWorker());
|
|
90
|
+
await Promise.all(workers);
|
|
91
|
+
if (void 0 !== abortError) throw abortError;
|
|
92
|
+
return results.filter((value)=>null !== value);
|
|
93
|
+
},
|
|
94
|
+
delete (assetId) {
|
|
95
|
+
registry.delete(assetId);
|
|
96
|
+
return Promise.resolve();
|
|
97
|
+
},
|
|
98
|
+
rename (assetId, nextName) {
|
|
99
|
+
registry.rename(assetId, nextName);
|
|
100
|
+
return Promise.resolve();
|
|
101
|
+
},
|
|
102
|
+
setTags (assetId, tags) {
|
|
103
|
+
registry.setTags(assetId, tags);
|
|
104
|
+
return Promise.resolve();
|
|
105
|
+
},
|
|
106
|
+
async replace (assetId, file) {
|
|
107
|
+
const result = await upload(file);
|
|
108
|
+
const replaced = registry.replace(assetId, result);
|
|
109
|
+
if (void 0 === replaced) return project(result);
|
|
110
|
+
return project(replaced);
|
|
111
|
+
},
|
|
112
|
+
getUrl (assetId) {
|
|
113
|
+
return createAssetReference(assetId);
|
|
114
|
+
},
|
|
115
|
+
subscribe (listener) {
|
|
116
|
+
return registry.subscribe(listener);
|
|
117
|
+
},
|
|
118
|
+
subscribeUploads (listener) {
|
|
119
|
+
uploadListeners.add(listener);
|
|
120
|
+
return ()=>{
|
|
121
|
+
uploadListeners.delete(listener);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function toStudioAsset(entry, getThumbnail) {
|
|
127
|
+
const kind = inferAssetKind(entry);
|
|
128
|
+
const url = createAssetReference(entry.id);
|
|
129
|
+
const name = entry.name ?? deriveFallbackName(entry);
|
|
130
|
+
const thumbnailUrl = deriveThumbnailUrl(entry, kind, getThumbnail);
|
|
131
|
+
const studioAsset = {
|
|
132
|
+
id: entry.id,
|
|
133
|
+
kind,
|
|
134
|
+
name,
|
|
135
|
+
url,
|
|
136
|
+
...void 0 !== thumbnailUrl ? {
|
|
137
|
+
thumbnailUrl
|
|
138
|
+
} : {},
|
|
139
|
+
...entry.meta?.mimeType !== void 0 ? {
|
|
140
|
+
mimeType: entry.meta.mimeType
|
|
141
|
+
} : {},
|
|
142
|
+
...entry.meta?.size !== void 0 ? {
|
|
143
|
+
size: entry.meta.size
|
|
144
|
+
} : {},
|
|
145
|
+
...entry.tags && entry.tags.length > 0 ? {
|
|
146
|
+
tags: Object.freeze([
|
|
147
|
+
...entry.tags
|
|
148
|
+
])
|
|
149
|
+
} : {}
|
|
150
|
+
};
|
|
151
|
+
return studioAsset;
|
|
152
|
+
}
|
|
153
|
+
function inferStudioAssetKind(entry) {
|
|
154
|
+
return inferAssetKind(entry);
|
|
155
|
+
}
|
|
156
|
+
function deriveThumbnailUrl(entry, kind, getThumbnail) {
|
|
157
|
+
if (void 0 !== getThumbnail) return getThumbnail(entry);
|
|
158
|
+
return "image" === kind ? entry.url : void 0;
|
|
159
|
+
}
|
|
160
|
+
function deriveFallbackName(entry) {
|
|
161
|
+
const tail = entry.url.split(/[/?#]/).filter(Boolean).pop();
|
|
162
|
+
if (void 0 !== tail && "" !== tail && !tail.startsWith("data:")) return tail;
|
|
163
|
+
const idTail = entry.id.length > 12 ? `${entry.id.slice(0, 8)}…` : entry.id;
|
|
164
|
+
return `Asset ${idTail}`;
|
|
165
|
+
}
|
|
166
|
+
function isAbortError(error) {
|
|
167
|
+
if (null === error || "object" != typeof error) return false;
|
|
168
|
+
const name = error.name;
|
|
169
|
+
return "AbortError" === name;
|
|
170
|
+
}
|
|
171
|
+
export { MAX_CONCURRENT_UPLOADS, createStudioAssetSource, inferStudioAssetKind };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
createTestRegistry: ()=>createTestRegistry,
|
|
28
|
+
fakeUploader: ()=>fakeUploader
|
|
29
|
+
});
|
|
30
|
+
const external_registry_cjs_namespaceObject = require("../registry.cjs");
|
|
31
|
+
function createTestRegistry(options = {}) {
|
|
32
|
+
const registry = (0, external_registry_cjs_namespaceObject.createAssetRegistry)();
|
|
33
|
+
for (const entry of options.initial ?? [])registry.register(entry);
|
|
34
|
+
return registry;
|
|
35
|
+
}
|
|
36
|
+
function fakeUploader(options = {}) {
|
|
37
|
+
const responses = options.responses ?? {};
|
|
38
|
+
return async (file)=>{
|
|
39
|
+
const canned = responses[file.name];
|
|
40
|
+
if (void 0 !== canned) return canned;
|
|
41
|
+
const meta = {
|
|
42
|
+
size: file.size,
|
|
43
|
+
...file.type ? {
|
|
44
|
+
mimeType: file.type
|
|
45
|
+
} : {}
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
id: `asset-${slug(file.name)}`,
|
|
49
|
+
url: `https://test.local/${encodeURIComponent(file.name)}`,
|
|
50
|
+
name: file.name,
|
|
51
|
+
meta
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function slug(value) {
|
|
56
|
+
return value.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
57
|
+
}
|
|
58
|
+
exports.createTestRegistry = __webpack_exports__.createTestRegistry;
|
|
59
|
+
exports.fakeUploader = __webpack_exports__.fakeUploader;
|
|
60
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
61
|
+
"createTestRegistry",
|
|
62
|
+
"fakeUploader"
|
|
63
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
64
|
+
Object.defineProperty(exports, '__esModule', {
|
|
65
|
+
value: true
|
|
66
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Test fixtures for downstream plugin authors building on
|
|
3
|
+
* `@anvilkit/plugin-asset-manager`.
|
|
4
|
+
*
|
|
5
|
+
* For Studio plugin context fakes, use
|
|
6
|
+
* `@anvilkit/core/testing.createFakeStudioContext` — these helpers focus
|
|
7
|
+
* on the registry + uploader contracts owned by this package.
|
|
8
|
+
*/
|
|
9
|
+
import type { AssetRegistry, UploadAdapter, UploadResult } from "../types.js";
|
|
10
|
+
export interface CreateTestRegistryOptions {
|
|
11
|
+
readonly initial?: readonly UploadResult[];
|
|
12
|
+
}
|
|
13
|
+
export declare function createTestRegistry(options?: CreateTestRegistryOptions): AssetRegistry;
|
|
14
|
+
export interface FakeUploaderOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Optional map keyed by `File.name`. When a file is uploaded whose
|
|
17
|
+
* name appears in the map, the corresponding `UploadResult` is
|
|
18
|
+
* returned verbatim. Otherwise a deterministic synthetic result is
|
|
19
|
+
* returned (`asset-{name}`, `https://test.local/{name}`).
|
|
20
|
+
*/
|
|
21
|
+
readonly responses?: Record<string, UploadResult>;
|
|
22
|
+
}
|
|
23
|
+
export declare function fakeUploader(options?: FakeUploaderOptions): UploadAdapter;
|
|
24
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAEX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,MAAM,aAAa,CAAC;AAErB,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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Test fixtures for downstream plugin authors building on
|
|
3
|
+
* `@anvilkit/plugin-asset-manager`.
|
|
4
|
+
*
|
|
5
|
+
* For Studio plugin context fakes, use
|
|
6
|
+
* `@anvilkit/core/testing.createFakeStudioContext` — these helpers focus
|
|
7
|
+
* on the registry + uploader contracts owned by this package.
|
|
8
|
+
*/
|
|
9
|
+
import type { AssetRegistry, UploadAdapter, UploadResult } from "../types.js";
|
|
10
|
+
export interface CreateTestRegistryOptions {
|
|
11
|
+
readonly initial?: readonly UploadResult[];
|
|
12
|
+
}
|
|
13
|
+
export declare function createTestRegistry(options?: CreateTestRegistryOptions): AssetRegistry;
|
|
14
|
+
export interface FakeUploaderOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Optional map keyed by `File.name`. When a file is uploaded whose
|
|
17
|
+
* name appears in the map, the corresponding `UploadResult` is
|
|
18
|
+
* returned verbatim. Otherwise a deterministic synthetic result is
|
|
19
|
+
* returned (`asset-{name}`, `https://test.local/{name}`).
|
|
20
|
+
*/
|
|
21
|
+
readonly responses?: Record<string, UploadResult>;
|
|
22
|
+
}
|
|
23
|
+
export declare function fakeUploader(options?: FakeUploaderOptions): UploadAdapter;
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAEX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,MAAM,aAAa,CAAC;AAErB,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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createAssetRegistry } from "../registry.js";
|
|
2
|
+
function createTestRegistry(options = {}) {
|
|
3
|
+
const registry = createAssetRegistry();
|
|
4
|
+
for (const entry of options.initial ?? [])registry.register(entry);
|
|
5
|
+
return registry;
|
|
6
|
+
}
|
|
7
|
+
function fakeUploader(options = {}) {
|
|
8
|
+
const responses = options.responses ?? {};
|
|
9
|
+
return async (file)=>{
|
|
10
|
+
const canned = responses[file.name];
|
|
11
|
+
if (void 0 !== canned) return canned;
|
|
12
|
+
const meta = {
|
|
13
|
+
size: file.size,
|
|
14
|
+
...file.type ? {
|
|
15
|
+
mimeType: file.type
|
|
16
|
+
} : {}
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
id: `asset-${slug(file.name)}`,
|
|
20
|
+
url: `https://test.local/${encodeURIComponent(file.name)}`,
|
|
21
|
+
name: file.name,
|
|
22
|
+
meta
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function slug(value) {
|
|
27
|
+
return value.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
28
|
+
}
|
|
29
|
+
export { createTestRegistry, fakeUploader };
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.r = (exports1)=>{
|
|
5
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
6
|
+
value: 'Module'
|
|
7
|
+
});
|
|
8
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
})();
|
|
13
|
+
var __webpack_exports__ = {};
|
|
14
|
+
__webpack_require__.r(__webpack_exports__);
|
|
15
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
16
|
+
Object.defineProperty(exports, '__esModule', {
|
|
17
|
+
value: true
|
|
18
|
+
});
|