@kosdev-code/kos-asset-manager 0.0.1-next.30 → 0.0.1-next.32
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/README.md +81 -0
- package/bin/lib/declare-assets.mjs +43 -3
- package/index.d.ts +1 -0
- package/index.js +3337 -3311
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -184,6 +184,55 @@ tell what the root is, rather than guessing one. The target it writes then
|
|
|
184
184
|
scans the right folder and follows the project's own `descriptor` target
|
|
185
185
|
wherever that writes.
|
|
186
186
|
|
|
187
|
+
## Content in its own section
|
|
188
|
+
|
|
189
|
+
Content usually ships inside an application's section, and then it belongs to
|
|
190
|
+
that application: the kab's assets join the application's context and are
|
|
191
|
+
addressed by its id. Content that ships in a section of its own has no
|
|
192
|
+
application to take a name from, so it names itself:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"kondra": {
|
|
197
|
+
"ui": {
|
|
198
|
+
"assets": {
|
|
199
|
+
"context": "tccc.brandset",
|
|
200
|
+
"mediaSrc": "assets/logos",
|
|
201
|
+
"mediaRoot": "/logos"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
That name is what a ui asks for and addresses it by, exactly like an
|
|
209
|
+
application id:
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
<KosAssetProvider contexts={['my.app.id', 'tccc.brandset']} gate>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
wrapAsset('tccc.brandset:coke/pour');
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Content in its own section that names nothing belongs to its manifest
|
|
220
|
+
section, under the section's name. Two kabs naming the same context
|
|
221
|
+
contribute to the same one.
|
|
222
|
+
|
|
223
|
+
Shipping separately is also what lets content replace what an application
|
|
224
|
+
declares. Within one context the first declaration of a key wins and the rest
|
|
225
|
+
are ignored, so a brandset packaged alongside an application can only add to
|
|
226
|
+
it. As its own context it is a separate set of keys, and a ui chooses which
|
|
227
|
+
one wins by the order it lists them in `contexts`.
|
|
228
|
+
|
|
229
|
+
Everything you author under `kondra.ui.assets` carries through to the
|
|
230
|
+
declaration, with what the build derives landing on top. The exception is the
|
|
231
|
+
handful of settings that drive the build rather than describe the result —
|
|
232
|
+
`keys`, `tags`, `mediaSrc`, `mediaRoot`, and the pattern form of `groups` and
|
|
233
|
+
`entries` — which are expanded into what the device reads and not shipped as
|
|
234
|
+
written.
|
|
235
|
+
|
|
187
236
|
## Installing
|
|
188
237
|
|
|
189
238
|
```sh
|
|
@@ -275,6 +324,38 @@ branching on an optional asset without the warning `wrapAsset` logs.
|
|
|
275
324
|
A key resolves in the contexts named at the provider, first match winning,
|
|
276
325
|
unless it names one: `other.app.id:brand/logo-primary`.
|
|
277
326
|
|
|
327
|
+
## Loading data in a model
|
|
328
|
+
|
|
329
|
+
Json is declared like any other asset, which makes it fetchable by key:
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
import { loadAsset } from '@kosdev-code/kos-asset-manager';
|
|
333
|
+
|
|
334
|
+
@kosModel({ modelTypeId: MODEL_TYPE })
|
|
335
|
+
export class MenuModelImpl {
|
|
336
|
+
async load(): Promise<void> {
|
|
337
|
+
const menu = await loadAsset<MenuDto>('config/menu');
|
|
338
|
+
if (!menu) return;
|
|
339
|
+
this.reconcile(menu.items);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Data usually has to be parsed and normalised into a model's own shape
|
|
345
|
+
anyway, so this is deliberately a plain async call rather than something a
|
|
346
|
+
component reads. The point is the key: the file can be renamed, moved, or
|
|
347
|
+
moved into a different kab without the model changing.
|
|
348
|
+
|
|
349
|
+
Undefined comes back when the key isn't declared, the fetch fails, or the
|
|
350
|
+
content isn't valid json, each logged with the key — so a model handles it
|
|
351
|
+
the way it already handles a service returning nothing. `loadAssetText(key)`
|
|
352
|
+
is the same without the parse.
|
|
353
|
+
|
|
354
|
+
Json files are declared and keyed like anything else, but they don't count
|
|
355
|
+
as media when `kos-assets init` works out where a project keeps its media —
|
|
356
|
+
a manifest sitting beside a folder of images is what marks the images as the
|
|
357
|
+
media, not the whole folder.
|
|
358
|
+
|
|
278
359
|
## Selecting sets
|
|
279
360
|
|
|
280
361
|
Sets of assets are selected rather than named, so adding a file to a folder
|
|
@@ -45,6 +45,35 @@ const TYPES = {
|
|
|
45
45
|
'.webm': 'video/webm',
|
|
46
46
|
'.webp': 'image/webp',
|
|
47
47
|
'.woff2': 'font/woff2',
|
|
48
|
+
'.json': 'application/json',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Data assets are declared like any other, but they are not what makes a
|
|
53
|
+
* directory a project's media directory -- a brandset keeps its manifest
|
|
54
|
+
* beside its images, and it is the manifest sitting there that tells you the
|
|
55
|
+
* images are the media rather than the whole folder. So layout detection
|
|
56
|
+
* looks past them.
|
|
57
|
+
*/
|
|
58
|
+
const DATA_TYPES = new Set(['.json']);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Authored to drive the build rather than to be read on the device. Patterns
|
|
62
|
+
* and partial entries are expanded into the real thing, so passing them
|
|
63
|
+
* through would ship a `groups` of patterns the device would read as keys.
|
|
64
|
+
*/
|
|
65
|
+
const BUILD_INPUTS = new Set([
|
|
66
|
+
'keys',
|
|
67
|
+
'tags',
|
|
68
|
+
'entries',
|
|
69
|
+
'groups',
|
|
70
|
+
'mediaSrc',
|
|
71
|
+
'mediaRoot',
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
const isMedia = (name) => {
|
|
75
|
+
const ext = name.slice(name.lastIndexOf('.')).toLowerCase();
|
|
76
|
+
return Boolean(TYPES[ext]) && !DATA_TYPES.has(ext);
|
|
48
77
|
};
|
|
49
78
|
|
|
50
79
|
/**
|
|
@@ -280,8 +309,7 @@ const scanMedia = (dir, prefix = '') =>
|
|
|
280
309
|
if (item.name.startsWith('.') || SKIP_DIRS.has(item.name)) return [];
|
|
281
310
|
const rel = prefix ? `${prefix}/${item.name}` : item.name;
|
|
282
311
|
if (item.isDirectory()) return scanMedia(join(dir, item.name), rel);
|
|
283
|
-
|
|
284
|
-
return TYPES[ext] ? [rel] : [];
|
|
312
|
+
return isMedia(item.name) ? [rel] : [];
|
|
285
313
|
});
|
|
286
314
|
|
|
287
315
|
/** The deepest directory every one of these paths sits under. */
|
|
@@ -319,7 +347,7 @@ const climbToMedia = (projectRoot, dir) => {
|
|
|
319
347
|
const onlyMedia = entries.every((item) =>
|
|
320
348
|
item.isDirectory()
|
|
321
349
|
? holdsMedia(resolve(projectRoot, ...parent, item.name))
|
|
322
|
-
:
|
|
350
|
+
: isMedia(item.name)
|
|
323
351
|
);
|
|
324
352
|
if (!onlyMedia) {
|
|
325
353
|
break;
|
|
@@ -512,7 +540,16 @@ const buildAssets = (projectRoot) => {
|
|
|
512
540
|
);
|
|
513
541
|
}
|
|
514
542
|
|
|
543
|
+
// what a project authors under kondra.ui.assets carries through to the
|
|
544
|
+
// declaration, and what the build derives lands on top of it -- so a field
|
|
545
|
+
// the device reads, like the context a brandset belongs to, is authored
|
|
546
|
+
// once and needs nothing here to know about it
|
|
547
|
+
const authored = Object.fromEntries(
|
|
548
|
+
Object.entries(declared).filter(([key]) => !BUILD_INPUTS.has(key))
|
|
549
|
+
);
|
|
550
|
+
|
|
515
551
|
return {
|
|
552
|
+
...authored,
|
|
516
553
|
root: mediaRoot(declared),
|
|
517
554
|
entries,
|
|
518
555
|
...(Object.keys(groups).length > 0 ? { groups } : {}),
|
|
@@ -524,6 +561,9 @@ export {
|
|
|
524
561
|
SOURCE_DIR,
|
|
525
562
|
ASSETS_ROOT,
|
|
526
563
|
TYPES,
|
|
564
|
+
DATA_TYPES,
|
|
565
|
+
BUILD_INPUTS,
|
|
566
|
+
isMedia,
|
|
527
567
|
mediaSource,
|
|
528
568
|
mediaRoot,
|
|
529
569
|
scanMedia,
|
package/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { registerAssetModels } from './registration';
|
|
|
5
5
|
export { contextNames } from './runtime/assets';
|
|
6
6
|
export { KosAssetProvider, KosAssetContext, useAssetManager, useKosAssetContext, } from './runtime/asset-provider';
|
|
7
7
|
export { resolveAsset, wrapAsset, hasAsset, listAssets } from './runtime/resolve';
|
|
8
|
+
export { loadAsset, loadAssetText } from './runtime/data';
|
|
8
9
|
export { preloadAssets, preloadDeclared, releaseAssets, } from './runtime/preload';
|
|
9
10
|
export type { AssetSelector, PreloadOptions, PreloadProgress, ResolvedAsset, } from './runtime/types';
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|