@valbuild/core 0.141.0 → 0.144.0
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/CHANGELOG.md +67 -0
- package/dist/declarations/src/index.d.ts +13 -4
- package/dist/declarations/src/initSchema.d.ts +108 -18
- package/dist/declarations/src/initVal.d.ts +2 -2
- package/dist/declarations/src/mimeType/font.d.ts +36 -0
- package/dist/declarations/src/mimeType/index.d.ts +1 -0
- package/dist/declarations/src/render.d.ts +1 -1
- package/dist/declarations/src/schema/file.d.ts +4 -4
- package/dist/declarations/src/schema/filedir.d.ts +83 -0
- package/dist/declarations/src/schema/font.d.ts +16 -0
- package/dist/declarations/src/schema/fontdir.d.ts +63 -0
- package/dist/declarations/src/schema/hasRemoteFileSchema.d.ts +3 -3
- package/dist/declarations/src/schema/image.d.ts +4 -4
- package/dist/declarations/src/schema/{imageset.d.ts → imagedir.d.ts} +63 -29
- package/dist/declarations/src/schema/record.d.ts +17 -6
- package/dist/declarations/src/schema/video.d.ts +7 -7
- package/dist/declarations/src/schema/{videoset.d.ts → videodir.d.ts} +55 -27
- package/dist/declarations/src/source/media.d.ts +26 -3
- package/dist/{index-13cf45b1.cjs.prod.js → index-2d194c90.cjs.prod.js} +504 -79
- package/dist/{index-fae161b5.cjs.dev.js → index-8b22b2c1.cjs.dev.js} +504 -79
- package/dist/{index-a6c53286.esm.js → index-aa16dd90.esm.js} +503 -80
- package/dist/valbuild-core.cjs.dev.js +3 -1
- package/dist/valbuild-core.cjs.prod.js +3 -1
- package/dist/valbuild-core.esm.js +1 -1
- package/package.json +1 -1
- package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
- package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
- package/patch/dist/valbuild-core-patch.esm.js +2 -2
- package/dist/declarations/src/schema/fileset.d.ts +0 -57
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# @valbuild/core
|
|
2
2
|
|
|
3
|
+
## 0.144.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#826](https://github.com/valbuild/val/pull/826) [`860ab2b`](https://github.com/valbuild/val/commit/860ab2b87333daf95a48215b0e4a1b44f441c878) Thanks [@freekh](https://github.com/freekh)! - New names for the media collections: `s.imagedir()`, `s.filedir()`, `s.fontdir()` and `s.videodir()`. The directory the uploads land in is now the first argument instead of the `dir` option:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// before
|
|
11
|
+
s.imageset({ dir: "/public/val/images", accept: "image/webp" });
|
|
12
|
+
s.fileset({ dir: "/public/val/docs", accept: "application/pdf" });
|
|
13
|
+
s.fontset({ dir: "/public/val/fonts" });
|
|
14
|
+
s.videoset({ dir: "/public/val/videos", stream: { type: "hls" } });
|
|
15
|
+
|
|
16
|
+
// after
|
|
17
|
+
s.imagedir("/public/val/images", { accept: "image/webp" });
|
|
18
|
+
s.filedir("/public/val/docs", { accept: "application/pdf" });
|
|
19
|
+
s.fontdir("/public/val/fonts");
|
|
20
|
+
s.videodir("/public/val/videos", { stream: { type: "hls" } });
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Every other option is unchanged, and so is the content: a module only needs its schema call changed. The options object can now be left out entirely where nothing else is set, as in `s.fontdir("/public/val/fonts")`.
|
|
24
|
+
|
|
25
|
+
`s.imageset()`, `s.fileset()`, `s.fontset()` and `s.videoset()` still work and build exactly the same schema, but are deprecated and will be removed in a later release. The exported `VideosetEntryMetadata`, `VideosetOptions` and `SerializedVideosetSchema` types are deprecated in favour of `VideodirEntryMetadata`, `VideodirOptions` and `SerializedVideodirSchema`, and the image, file and font equivalents (`ImagedirOptions`, `ImagedirEntryMetadata`, `FiledirOptions`, `FiledirEntryMetadata`, `FontdirOptions`, `MediaDir`, …) are now exported too.
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- [#788](https://github.com/valbuild/val/pull/788) [`a84271c`](https://github.com/valbuild/val/commit/a84271c534822071c1e428cf9990602459682d25) Thanks [@freekh](https://github.com/freekh)! - Fixes to `npx val validate` for `s.imagedir()` and `s.filedir()`, and the `s.image(galleryVal)` / `s.file(filesVal)` fields that use them:
|
|
30
|
+
|
|
31
|
+
- **`--fix` now updates every field that uses an uploaded image or file.** When `--fix` moves an entry of an `s.imagedir(dir).remote()` or `s.filedir(dir, options).remote()` to Val Remote, the entry's key changes from the local path to the remote URL. Fields that held the old path were left pointing at it, and reported "The gallery does not have an image at …" with nothing to fix it. Now `s.image(galleryVal)` and `s.file(filesVal)` fields, and images in rich text (`s.richtext({ img: s.image(galleryVal) })`), are updated in the same run. The VS Code extension's "upload to Val Remote" updates them in the same edit, including fields inside `.jsonValues()` entries, which live in their own `*.val.json` files.
|
|
32
|
+
- **A field that uses an image or file from a `.remote()` gallery is no longer reported as "Expected local image, but found remote".** The gallery decides whether its files are on Val Remote; the field only has to name a file the gallery has. Before, `--fix` would download the file and point the field at a path the gallery did not have.
|
|
33
|
+
- **Images uploaded through a field into a `.remote()` gallery.** When you upload an image through an `s.image(galleryVal)` field in Val Studio, the field stores the remote URL and the gallery stores the image under its local path. Validation now accepts this, and `useVal` / `fetchVal` now fill in the image's `width`, `height` and `mimeType` from the gallery for it, as they do for every other gallery image.
|
|
34
|
+
- **Errors in a gallery's keys are reported.** A remote URL in a gallery that is not `.remote()`, a remote URL that is not valid, or one outside the gallery's `dir` was silently ignored by `npx val validate`. It is now reported as an error. `--fix` does not change it: you decide whether the key or the gallery's options are wrong.
|
|
35
|
+
- **A file is no longer reported as valid when it still has an error.** When `--fix` fixed one error in a file and another error was left, the file could be printed as "✔ valid".
|
|
36
|
+
|
|
37
|
+
## 0.143.0
|
|
38
|
+
|
|
39
|
+
### Minor Changes
|
|
40
|
+
|
|
41
|
+
- [#813](https://github.com/valbuild/val/pull/813) [`f7c25bd`](https://github.com/valbuild/val/commit/f7c25bd4b44c288db8e5ab914e6d8a72c0216ba5) Thanks [@freekh](https://github.com/freekh)! - New: `s.font(fontsVal)`, a field that picks a font from an `s.fontset()`.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
s.object({
|
|
45
|
+
headingFont: s.font(fontsVal),
|
|
46
|
+
title: s.string(),
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
It stores `{ path }` like `s.file(fontsVal)` does, and refuses a module that is not a font set. In the Studio, a font field is shown among its object's other fields as a small row — the letter "A" set in the chosen font, and the font's file name. Click it to open the field, which shows every font in the set to pick from, an upload button, and a full specimen of the chosen font. This applies to `s.file()` fields that point at a font set too.
|
|
51
|
+
|
|
52
|
+
- [#813](https://github.com/valbuild/val/pull/813) [`729c4ed`](https://github.com/valbuild/val/commit/729c4edfa28f5a2942c435ccf225e65858b080cc) Thanks [@freekh](https://github.com/freekh)! - New: `s.fontset()`, a collection of fonts.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
const fontsVal = c.define(
|
|
56
|
+
"/content/fonts.val.ts",
|
|
57
|
+
s.fontset({ dir: "/public/val/fonts" }),
|
|
58
|
+
{},
|
|
59
|
+
);
|
|
60
|
+
// a field that picks one of them
|
|
61
|
+
s.object({ headingFont: s.file(fontsVal) });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
It is an `s.fileset()` whose `accept` defaults to the web font formats (`font/woff2`, `font/woff`, `font/ttf`, `font/otf`); pass `accept: "font/woff2"` to allow only WOFF2. Fonts are not converted on upload.
|
|
65
|
+
|
|
66
|
+
The Studio now previews fonts set in themselves — in the gallery, in the picker of a field that points at a font set, and in the field — wherever a file is a font, including fonts in an ordinary `s.fileset()`.
|
|
67
|
+
|
|
68
|
+
Font uploads are typed from their bytes, so a font is stored as `font/woff2`, `font/ttf` and so on even when the browser reports no type for it. Files ending in `.ttf`, `.otf` and `.woff` now map to the `font/` types rather than the older `application/x-font-*` names, which are still accepted where they are already stored.
|
|
69
|
+
|
|
3
70
|
## 0.141.0
|
|
4
71
|
|
|
5
72
|
### Minor Changes
|
|
@@ -7,8 +7,12 @@ export { hasRemoteFileSchema, hasMediaSchema, } from "./schema/hasRemoteFileSche
|
|
|
7
7
|
export type { ImageMetadata, ImageEncodeOption, ImageEncodeOptions, } from "./schema/image.js";
|
|
8
8
|
export type { FileMetadata } from "./schema/file.js";
|
|
9
9
|
export type { GalleryVideoOptions, VideoMetadata, VideoOptions, VideoStreamOption, VideoStreamOptions, } from "./schema/video.js";
|
|
10
|
-
import { videosetEntryVideoSchema } from "./schema/
|
|
11
|
-
export type { VideosetEntryMetadata, VideosetOptions, SerializedVideosetSchema, } from "./schema/
|
|
10
|
+
import { videosetEntryVideoSchema } from "./schema/videodir.js";
|
|
11
|
+
export type { VideodirEntryMetadata, VideodirOptions, SerializedVideodirSchema, VideosetEntryMetadata, VideosetOptions, SerializedVideosetSchema, } from "./schema/videodir.js";
|
|
12
|
+
export type { ImagedirEntryMetadata, ImagedirOptions, SerializedImagedirSchema, } from "./schema/imagedir.js";
|
|
13
|
+
export type { FiledirEntryMetadata, FiledirOptions, SerializedFiledirSchema, } from "./schema/filedir.js";
|
|
14
|
+
export type { FontdirOptions } from "./schema/fontdir.js";
|
|
15
|
+
export type { MediaDir } from "./schema/record.js";
|
|
12
16
|
export type { ValModule, SerializedModule, InferValModuleType } from "./module.js";
|
|
13
17
|
export type { SourceObject, SourcePrimitive, Source } from "./source/index.js";
|
|
14
18
|
export type { FileSource } from "./source/media.js";
|
|
@@ -35,7 +39,7 @@ import { ModulePath, SourcePath, getValPath, isVal } from "./val/index.js";
|
|
|
35
39
|
import { createValPathOfItem } from "./selector/SelectorProxy.js";
|
|
36
40
|
import { Operation } from "./patch/index.js";
|
|
37
41
|
import { initSchema } from "./initSchema.js";
|
|
38
|
-
import { getMimeType, mimeTypeToFileExt, filenameToMimeType, mimeTypeMatchesAccept } from "./mimeType/index.js";
|
|
42
|
+
import { getMimeType, mimeTypeToFileExt, filenameToMimeType, mimeTypeMatchesAccept, isFontMimeType, sniffFontMimeType } from "./mimeType/index.js";
|
|
39
43
|
import { type ImageMetadata } from "./schema/image.js";
|
|
40
44
|
import { type FileMetadata } from "./schema/file.js";
|
|
41
45
|
import { isJson, getJsonImport, resolveJsonValues } from "./source/json.js";
|
|
@@ -47,7 +51,7 @@ import { getValidationBasis, getValidationHash } from "./remote/validationBasis.
|
|
|
47
51
|
import { getFileHash, hashToRemoteFileHash } from "./remote/fileHash.js";
|
|
48
52
|
import { splitRemoteRef } from "./remote/splitRemoteRef.js";
|
|
49
53
|
import { galleriesOf } from "./source/galleries.js";
|
|
50
|
-
import { fillFromGallery, galleryEntryOf, isHlsVideo, isRemoteMediaPath, mediaUrl, resolveMedia, resolveVideo } from "./source/media.js";
|
|
54
|
+
import { fillFromGallery, galleryEntryOf, galleryKeyOf, isHlsVideo, isRemoteMediaPath, mediaUrl, resolveMedia, resolveVideo } from "./source/media.js";
|
|
51
55
|
import { colorToHex, convertColor, detectColorFormat, formatColor, parseColor } from "./schema/colorFormat.js";
|
|
52
56
|
export { type SerializedArraySchema, ArraySchema } from "./schema/array.js";
|
|
53
57
|
export { type SerializedObjectSchema, ObjectSchema } from "./schema/object.js";
|
|
@@ -57,6 +61,7 @@ export { type SerializedNumberSchema, NumberSchema } from "./schema/number.js";
|
|
|
57
61
|
export { type SerializedBooleanSchema, BooleanSchema } from "./schema/boolean.js";
|
|
58
62
|
export { type SerializedImageSchema, ImageSchema } from "./schema/image.js";
|
|
59
63
|
export { type SerializedFileSchema, FileSchema } from "./schema/file.js";
|
|
64
|
+
export { DEFAULT_FONT_ACCEPT, FONT_MIME_TYPES } from "./mimeType/font.js";
|
|
60
65
|
export { type SerializedVideoSchema, VideoSchema, DEFAULT_VIDEO_ACCEPT, DEFAULT_VIDEO_RENDITIONS, DEFAULT_VIDEO_SEGMENT_DURATION, } from "./schema/video.js";
|
|
61
66
|
export { type SerializedDateSchema, DateSchema } from "./schema/date.js";
|
|
62
67
|
export { type SerializedSettingsSchema, SettingsSchema, } from "./schema/settings.js";
|
|
@@ -147,6 +152,7 @@ declare const Internal: {
|
|
|
147
152
|
fillFromGallery: typeof fillFromGallery;
|
|
148
153
|
galleriesOf: typeof galleriesOf;
|
|
149
154
|
galleryEntryOf: typeof galleryEntryOf;
|
|
155
|
+
galleryKeyOf: typeof galleryKeyOf;
|
|
150
156
|
GALLERY_DEFAULT_GROUPS: readonly (readonly string[])[];
|
|
151
157
|
isHlsVideo: typeof isHlsVideo;
|
|
152
158
|
HLS_MIME_TYPE: string;
|
|
@@ -208,6 +214,9 @@ declare const Internal: {
|
|
|
208
214
|
MIME_TYPES_TO_EXT: {
|
|
209
215
|
[k: string]: string;
|
|
210
216
|
};
|
|
217
|
+
FONT_MIME_TYPE_EXTENSIONS: Record<string, string>;
|
|
218
|
+
isFontMimeType: typeof isFontMimeType;
|
|
219
|
+
sniffFontMimeType: typeof sniffFontMimeType;
|
|
211
220
|
ModuleFilePathSep: string;
|
|
212
221
|
notFileOp: (op: Operation) => op is {
|
|
213
222
|
op: "add";
|
|
@@ -13,8 +13,10 @@ import { keyOf } from "./schema/keyOf.js";
|
|
|
13
13
|
import { view } from "./schema/view.js";
|
|
14
14
|
import { record } from "./schema/record.js";
|
|
15
15
|
import { file } from "./schema/file.js";
|
|
16
|
+
import { font } from "./schema/font.js";
|
|
16
17
|
import { video } from "./schema/video.js";
|
|
17
|
-
import { fileset } from "./schema/
|
|
18
|
+
import { filedir, fileset } from "./schema/filedir.js";
|
|
19
|
+
import { fontdir, fontset } from "./schema/fontdir.js";
|
|
18
20
|
import { date } from "./schema/date.js";
|
|
19
21
|
import { datetime } from "./schema/datetime.js";
|
|
20
22
|
import { code } from "./schema/code.js";
|
|
@@ -22,8 +24,8 @@ import { color } from "./schema/color.js";
|
|
|
22
24
|
import { locale } from "./schema/locale.js";
|
|
23
25
|
import { route } from "./schema/route.js";
|
|
24
26
|
import { router } from "./schema/router.js";
|
|
25
|
-
import { imageset } from "./schema/
|
|
26
|
-
import { videoset } from "./schema/
|
|
27
|
+
import { imagedir, imageset } from "./schema/imagedir.js";
|
|
28
|
+
import { videodir, videoset } from "./schema/videodir.js";
|
|
27
29
|
import { settings } from "./schema/settings.js";
|
|
28
30
|
export type InitSchema = {
|
|
29
31
|
/**
|
|
@@ -151,7 +153,7 @@ export type InitSchema = {
|
|
|
151
153
|
*
|
|
152
154
|
* @example
|
|
153
155
|
* // Backed by a gallery: width, height and mimeType live there.
|
|
154
|
-
* import galleryVal from "./gallery.val"; // an s.
|
|
156
|
+
* import galleryVal from "./gallery.val"; // an s.imagedir() module
|
|
155
157
|
* const schema = s.image(galleryVal);
|
|
156
158
|
* export default c.define("/example.val.ts", schema, {
|
|
157
159
|
* path: "/public/val/example.png",
|
|
@@ -219,6 +221,19 @@ export type InitSchema = {
|
|
|
219
221
|
*
|
|
220
222
|
*/
|
|
221
223
|
readonly file: typeof file;
|
|
224
|
+
/**
|
|
225
|
+
* A font picked from an `s.fontdir()`: `s.file(fontsVal)` for fonts, which
|
|
226
|
+
* refuses a module that is not a font set. The Studio shows it in its parent
|
|
227
|
+
* as the font's "A" and file name, and opens it on the set to pick from.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* import fontsVal from "./fonts.val"; // an s.fontdir() module
|
|
232
|
+
* const schema = s.object({ headingFont: s.font(fontsVal) });
|
|
233
|
+
* // source: { headingFont: { path: "/public/val/fonts/inter_a1b2c.woff2" } }
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
readonly font: typeof font;
|
|
222
237
|
/**
|
|
223
238
|
* Define a video.
|
|
224
239
|
*
|
|
@@ -246,7 +261,7 @@ export type InitSchema = {
|
|
|
246
261
|
*
|
|
247
262
|
* @example
|
|
248
263
|
* // Picked from a set: mimeType, width, height and duration live there.
|
|
249
|
-
* import videosVal from "./videos.val"; // an s.
|
|
264
|
+
* import videosVal from "./videos.val"; // an s.videodir() module
|
|
250
265
|
* const schema = s.video(videosVal);
|
|
251
266
|
* export default c.define("/example.val.ts", schema, {
|
|
252
267
|
* path: "/public/val/videos/intro_51df2.mp4",
|
|
@@ -362,13 +377,16 @@ export type InitSchema = {
|
|
|
362
377
|
*/
|
|
363
378
|
readonly router: typeof router;
|
|
364
379
|
/**
|
|
365
|
-
* Define a
|
|
380
|
+
* Define a directory of images: a whole module of images, keyed by file
|
|
381
|
+
* path, that fields pick from with `s.image(galleryVal)`.
|
|
382
|
+
*
|
|
383
|
+
* The first argument is the directory uploads land in, and must start with
|
|
384
|
+
* `/public`.
|
|
366
385
|
*
|
|
367
386
|
* @example
|
|
368
387
|
* ```typescript
|
|
369
|
-
* const schema = s.
|
|
388
|
+
* const schema = s.imagedir("/public/val/images", {
|
|
370
389
|
* accept: "image/webp",
|
|
371
|
-
* dir: "/public/val/images",
|
|
372
390
|
* alt: s.string().minLength(4),
|
|
373
391
|
* });
|
|
374
392
|
* export default c.define("/content/images.val.ts", schema, {
|
|
@@ -381,15 +399,18 @@ export type InitSchema = {
|
|
|
381
399
|
* });
|
|
382
400
|
* ```
|
|
383
401
|
*/
|
|
384
|
-
readonly
|
|
402
|
+
readonly imagedir: typeof imagedir;
|
|
385
403
|
/**
|
|
386
|
-
* Define a
|
|
404
|
+
* Define a directory of files: a whole module of files, keyed by file path,
|
|
405
|
+
* that fields pick from with `s.file(filesVal)`.
|
|
406
|
+
*
|
|
407
|
+
* The first argument is the directory uploads land in, and must start with
|
|
408
|
+
* `/public`.
|
|
387
409
|
*
|
|
388
410
|
* @example
|
|
389
411
|
* ```typescript
|
|
390
|
-
* const schema = s.
|
|
412
|
+
* const schema = s.filedir("/public/val/documents", {
|
|
391
413
|
* accept: "application/pdf",
|
|
392
|
-
* dir: "/public/val/documents",
|
|
393
414
|
* });
|
|
394
415
|
* export default c.define("/content/documents.val.ts", schema, {
|
|
395
416
|
* "/public/val/documents/report.pdf": {
|
|
@@ -398,15 +419,30 @@ export type InitSchema = {
|
|
|
398
419
|
* });
|
|
399
420
|
* ```
|
|
400
421
|
*/
|
|
401
|
-
readonly
|
|
422
|
+
readonly filedir: typeof filedir;
|
|
402
423
|
/**
|
|
403
|
-
* Define a
|
|
424
|
+
* Define a directory of fonts: an `s.filedir()` that accepts the web font
|
|
425
|
+
* formats, and whose files the Studio previews as type. A field picks from
|
|
426
|
+
* it with `s.font(fontsVal)`.
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* ```typescript
|
|
430
|
+
* const schema = s.fontdir("/public/val/fonts");
|
|
431
|
+
* export default c.define("/content/fonts.val.ts", schema, {
|
|
432
|
+
* "/public/val/fonts/inter_a1b2c.woff2": {
|
|
433
|
+
* mimeType: "font/woff2",
|
|
434
|
+
* },
|
|
435
|
+
* });
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
readonly fontdir: typeof fontdir;
|
|
439
|
+
/**
|
|
440
|
+
* Define a directory of videos. A field picks from it with
|
|
404
441
|
* `s.video(videosVal)`.
|
|
405
442
|
*
|
|
406
443
|
* @example
|
|
407
444
|
* ```typescript
|
|
408
|
-
* const schema = s.
|
|
409
|
-
* dir: "/public/val/videos",
|
|
445
|
+
* const schema = s.videodir("/public/val/videos", {
|
|
410
446
|
* stream: { type: "hls" },
|
|
411
447
|
* });
|
|
412
448
|
* export default c.define("/content/videos.val.ts", schema, {
|
|
@@ -420,6 +456,60 @@ export type InitSchema = {
|
|
|
420
456
|
* });
|
|
421
457
|
* ```
|
|
422
458
|
*/
|
|
459
|
+
readonly videodir: typeof videodir;
|
|
460
|
+
/**
|
|
461
|
+
* Define a collection of images.
|
|
462
|
+
*
|
|
463
|
+
* @deprecated Use `s.imagedir(dir, options)`: the directory moved out of the
|
|
464
|
+
* options and into the first argument.
|
|
465
|
+
*
|
|
466
|
+
* @example
|
|
467
|
+
* ```typescript
|
|
468
|
+
* // was: s.imageset({ dir: "/public/val/images", accept: "image/webp" })
|
|
469
|
+
* const schema = s.imagedir("/public/val/images", { accept: "image/webp" });
|
|
470
|
+
* ```
|
|
471
|
+
*/
|
|
472
|
+
readonly imageset: typeof imageset;
|
|
473
|
+
/**
|
|
474
|
+
* Define a collection of files.
|
|
475
|
+
*
|
|
476
|
+
* @deprecated Use `s.filedir(dir, options)`: the directory moved out of the
|
|
477
|
+
* options and into the first argument.
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* ```typescript
|
|
481
|
+
* // was: s.fileset({ dir: "/public/val/documents", accept: "application/pdf" })
|
|
482
|
+
* const schema = s.filedir("/public/val/documents", {
|
|
483
|
+
* accept: "application/pdf",
|
|
484
|
+
* });
|
|
485
|
+
* ```
|
|
486
|
+
*/
|
|
487
|
+
readonly fileset: typeof fileset;
|
|
488
|
+
/**
|
|
489
|
+
* Define a collection of fonts.
|
|
490
|
+
*
|
|
491
|
+
* @deprecated Use `s.fontdir(dir, options)`: the directory moved out of the
|
|
492
|
+
* options and into the first argument.
|
|
493
|
+
*
|
|
494
|
+
* @example
|
|
495
|
+
* ```typescript
|
|
496
|
+
* // was: s.fontset({ dir: "/public/val/fonts" })
|
|
497
|
+
* const schema = s.fontdir("/public/val/fonts");
|
|
498
|
+
* ```
|
|
499
|
+
*/
|
|
500
|
+
readonly fontset: typeof fontset;
|
|
501
|
+
/**
|
|
502
|
+
* Define a collection of videos.
|
|
503
|
+
*
|
|
504
|
+
* @deprecated Use `s.videodir(dir, options)`: the directory moved out of the
|
|
505
|
+
* options and into the first argument.
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* ```typescript
|
|
509
|
+
* // was: s.videoset({ dir: "/public/val/videos", stream: { type: "hls" } })
|
|
510
|
+
* const schema = s.videodir("/public/val/videos", { stream: { type: "hls" } });
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
423
513
|
readonly videoset: typeof videoset;
|
|
424
514
|
/**
|
|
425
515
|
* Define the project's settings.
|
|
@@ -451,8 +541,8 @@ export type InitSchemaOptions = {
|
|
|
451
541
|
/**
|
|
452
542
|
* Every media schema is remote: `files.remote` in `val.config.ts`.
|
|
453
543
|
*
|
|
454
|
-
* `s.image()`, `s.file()`, `s.video()`, `s.
|
|
455
|
-
* `s.
|
|
544
|
+
* `s.image()`, `s.file()`, `s.video()`, `s.imagedir()`, `s.filedir()`,
|
|
545
|
+
* `s.fontdir()` and `s.videodir()` (and their deprecated `*set` names) come back with `.remote()` already applied, and so does the
|
|
456
546
|
* image `s.richtext({ img: true })` builds for itself. Nothing downstream
|
|
457
547
|
* needs to know: the Studio, the MCP tools, validation and publishing all
|
|
458
548
|
* read `remote` off the schema, exactly as they do for a `.remote()` written
|
|
@@ -80,8 +80,8 @@ export type ValConfig = {
|
|
|
80
80
|
* Store every image, file and video on Val's remote content host instead
|
|
81
81
|
* of in the repository.
|
|
82
82
|
*
|
|
83
|
-
* `s.image()`, `s.file()`, `s.video()`, `s.
|
|
84
|
-
* `s.
|
|
83
|
+
* `s.image()`, `s.file()`, `s.video()`, `s.imagedir()`, `s.filedir()`,
|
|
84
|
+
* `s.fontdir()`, `s.videodir()` and `s.richtext({ img: true })` all behave as though
|
|
85
85
|
* `.remote()` had been written on them. Required for a project in the Val
|
|
86
86
|
* app, which has no repository for the bytes to go into: there the Val
|
|
87
87
|
* server refuses to start without it.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fonts, as far as a mime type can tell.
|
|
3
|
+
*
|
|
4
|
+
* The four web formats have IANA types under `font/` (RFC 8081), and those are
|
|
5
|
+
* what Val stores. Browsers and operating systems disagree about them: a file
|
|
6
|
+
* picker reports `.woff2` as `font/woff2`, `application/font-woff2` or nothing
|
|
7
|
+
* at all depending on the platform, and nothing at all reads as
|
|
8
|
+
* `application/octet-stream` once the file is a data URL. That is why an upload
|
|
9
|
+
* asks the BYTES ({@link sniffFontMimeType}) rather than trusting the picker.
|
|
10
|
+
*/
|
|
11
|
+
/** The formats `s.fontdir()` accepts unless told otherwise, best first. */
|
|
12
|
+
export declare const FONT_MIME_TYPES: readonly ["font/woff2", "font/woff", "font/ttf", "font/otf"];
|
|
13
|
+
/** `s.fontdir()`'s `accept` when none is given. */
|
|
14
|
+
export declare const DEFAULT_FONT_ACCEPT: string;
|
|
15
|
+
/**
|
|
16
|
+
* The extension of each font type, for a file input: a picker matches an
|
|
17
|
+
* `accept` of mime types through the operating system's own table, and where
|
|
18
|
+
* that table does not know `font/woff2` the file is greyed out.
|
|
19
|
+
*/
|
|
20
|
+
export declare const FONT_MIME_TYPE_EXTENSIONS: Record<string, string>;
|
|
21
|
+
/** `mimeType`, with a legacy font name read as its `font/` type. */
|
|
22
|
+
export declare function canonicalFontMimeType(mimeType: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Whether a file of `mimeType` is a font a browser can draw: the `font/` types,
|
|
25
|
+
* and the pre-RFC 8081 names still found in older data.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isFontMimeType(mimeType: string | null | undefined): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The font type of `bytes`, read from the signature every font format starts
|
|
30
|
+
* with, or `null` when they are not a font.
|
|
31
|
+
*
|
|
32
|
+
* Only the first four bytes are needed: the WOFF signatures (`wOFF`, `wOF2`),
|
|
33
|
+
* the SFNT versions of TrueType (`0x00010000`, or `true` from old Apple fonts)
|
|
34
|
+
* and of CFF-flavoured OpenType (`OTTO`), and a collection's tag (`ttcf`).
|
|
35
|
+
*/
|
|
36
|
+
export declare function sniffFontMimeType(bytes: Uint8Array): string | null;
|
|
@@ -75,7 +75,7 @@ import type { SerializedSchema } from "./schema/index.js";
|
|
|
75
75
|
* `s.array(s.object({ tags: s.array(s.string()) })).render({ as: "inline" })`
|
|
76
76
|
* the objects are inline and `tags` keeps its own default.
|
|
77
77
|
*
|
|
78
|
-
* Not available on `s.router(...)`, `s.
|
|
78
|
+
* Not available on `s.router(...)`, `s.imagedir(...)` or `s.filedir(...)`:
|
|
79
79
|
* pages and media have UIs of their own, and `RecordSchema.render` throws there.
|
|
80
80
|
*
|
|
81
81
|
* On `s.keyOf(...)` the same value means something else: the selected entry's
|
|
@@ -5,7 +5,7 @@ import { ModulePath, SourcePath } from "../val/index.js";
|
|
|
5
5
|
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
6
6
|
import { ValModule } from "../index.js";
|
|
7
7
|
import { ItemPreviewInput, PreviewItem } from "../preview.js";
|
|
8
|
-
import {
|
|
8
|
+
import { FiledirEntryMetadata } from "./filedir.js";
|
|
9
9
|
export type FileOptions = {
|
|
10
10
|
accept?: string;
|
|
11
11
|
};
|
|
@@ -32,7 +32,7 @@ export declare class FileSchema<Src extends FileSource | null> extends Schema<Sr
|
|
|
32
32
|
private readonly isHidden;
|
|
33
33
|
private readonly description?;
|
|
34
34
|
private readonly previewInput;
|
|
35
|
-
constructor(options?: FileOptions | undefined, opt?: boolean, isRemote?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], moduleMetadata?: Record<ModulePath, Record<string,
|
|
35
|
+
constructor(options?: FileOptions | undefined, opt?: boolean, isRemote?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], moduleMetadata?: Record<ModulePath, Record<string, FiledirEntryMetadata>>, isReadonly?: boolean, isHidden?: boolean, description?: string | undefined, previewInput?: ItemPreviewInput<Src> | null);
|
|
36
36
|
/**
|
|
37
37
|
* Describe this field.
|
|
38
38
|
*
|
|
@@ -135,7 +135,7 @@ export declare class FileSchema<Src extends FileSource | null> extends Schema<Sr
|
|
|
135
135
|
* A file picked from a gallery. Its mime type lives in the gallery, so the
|
|
136
136
|
* field carries only the path.
|
|
137
137
|
*/
|
|
138
|
-
export declare function file(galleryModule: ValModule<Record<string,
|
|
138
|
+
export declare function file(galleryModule: ValModule<Record<string, FiledirEntryMetadata>>): FileSchema<GalleryFileSource>;
|
|
139
139
|
/** A file of its own, carrying its own mime type. */
|
|
140
140
|
export declare function file(options?: FileOptions): FileSchema<FileSource>;
|
|
141
141
|
/**
|
|
@@ -143,5 +143,5 @@ export declare function file(options?: FileOptions): FileSchema<FileSource>;
|
|
|
143
143
|
* `val.config.ts`): the same schema, with `.remote()` already applied. See
|
|
144
144
|
* `initSchema`.
|
|
145
145
|
*/
|
|
146
|
-
export declare function remoteFile(galleryModule: ValModule<Record<string,
|
|
146
|
+
export declare function remoteFile(galleryModule: ValModule<Record<string, FiledirEntryMetadata>>): FileSchema<GalleryFileSource>;
|
|
147
147
|
export declare function remoteFile(options?: FileOptions): FileSchema<FileSource>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Schema } from "./index.js";
|
|
2
|
+
import type { MediaDir, SerializedRecordSchema } from "./record.js";
|
|
3
|
+
import { RecordSchema } from "./record.js";
|
|
4
|
+
import { ObjectSchema } from "./object.js";
|
|
5
|
+
import { StringSchema } from "./string.js";
|
|
6
|
+
/**
|
|
7
|
+
* Options for `s.filedir(dir, options)`: everything but the directory, which
|
|
8
|
+
* is the first argument.
|
|
9
|
+
*/
|
|
10
|
+
export type FiledirOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* The accepted mime type pattern (e.g., "application/pdf", "text/*", "*\/*")
|
|
13
|
+
*/
|
|
14
|
+
accept: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Options for the deprecated `s.fileset(options)`, which took the directory
|
|
18
|
+
* as `dir`.
|
|
19
|
+
*
|
|
20
|
+
* @deprecated Use `s.filedir(dir, options)` and `FiledirOptions`.
|
|
21
|
+
*/
|
|
22
|
+
export type FilesetOptions = FiledirOptions & {
|
|
23
|
+
/**
|
|
24
|
+
* The directory where files should be stored.
|
|
25
|
+
* Must start with "/public" (e.g., "/public/val/files")
|
|
26
|
+
*/
|
|
27
|
+
dir: MediaDir;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Metadata for a file entry in the files record
|
|
31
|
+
*/
|
|
32
|
+
export type FiledirEntryMetadata = {
|
|
33
|
+
mimeType: string;
|
|
34
|
+
};
|
|
35
|
+
/** @deprecated Use `FiledirEntryMetadata`. */
|
|
36
|
+
export type FilesetEntryMetadata = FiledirEntryMetadata;
|
|
37
|
+
export type SerializedFiledirSchema = SerializedRecordSchema;
|
|
38
|
+
/** @deprecated Use `SerializedFiledirSchema`. */
|
|
39
|
+
export type SerializedFilesetSchema = SerializedFiledirSchema;
|
|
40
|
+
type FiledirItemProps = {
|
|
41
|
+
mimeType: StringSchema<string>;
|
|
42
|
+
};
|
|
43
|
+
type FiledirItemSrc = {
|
|
44
|
+
mimeType: string;
|
|
45
|
+
};
|
|
46
|
+
type FiledirSchema = RecordSchema<ObjectSchema<FiledirItemProps, FiledirItemSrc>, Schema<string>, Record<string, FiledirEntryMetadata>>;
|
|
47
|
+
/**
|
|
48
|
+
* Define a directory of files: a whole module that holds many files, keyed by
|
|
49
|
+
* their file path, that fields pick from with `s.file(filesVal)`.
|
|
50
|
+
*
|
|
51
|
+
* The directory is the first argument and is required — it decides where
|
|
52
|
+
* uploads land. Remote is off by default: call `.remote()` on the result to
|
|
53
|
+
* allow remote files.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const schema = s.filedir("/public/val/documents", {
|
|
58
|
+
* accept: "application/pdf",
|
|
59
|
+
* });
|
|
60
|
+
* export default c.define("/content/documents.val.ts", schema, {
|
|
61
|
+
* "/public/val/documents/report.pdf": {
|
|
62
|
+
* mimeType: "application/pdf",
|
|
63
|
+
* },
|
|
64
|
+
* });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare const filedir: (dir: MediaDir, options: FiledirOptions) => FiledirSchema;
|
|
68
|
+
/**
|
|
69
|
+
* Define a collection of files.
|
|
70
|
+
*
|
|
71
|
+
* @deprecated Use `s.filedir(dir, options)`: the directory moved out of the
|
|
72
|
+
* options and into the first argument, and nothing else changed.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // was: s.fileset({ dir: "/public/val/documents", accept: "application/pdf" })
|
|
77
|
+
* const schema = s.filedir("/public/val/documents", {
|
|
78
|
+
* accept: "application/pdf",
|
|
79
|
+
* });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export declare const fileset: (options: FilesetOptions) => FiledirSchema;
|
|
83
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ValModule } from "../index.js";
|
|
2
|
+
import { FileSchema } from "./file.js";
|
|
3
|
+
import { FiledirEntryMetadata } from "./filedir.js";
|
|
4
|
+
import { GalleryFileSource } from "../source/media.js";
|
|
5
|
+
/**
|
|
6
|
+
* A font picked from an `s.fontdir()`.
|
|
7
|
+
*
|
|
8
|
+
* The same field `s.file(fontsVal)` is — it stores `{ path }` and serializes
|
|
9
|
+
* identically — with one thing more: it refuses a set that is not a font set,
|
|
10
|
+
* at definition, so a field called a font cannot end up offering PDFs. What the
|
|
11
|
+
* Studio does with it (a specimen in its parent, the set to pick from when
|
|
12
|
+
* opened) it does for any file field backed by a font set.
|
|
13
|
+
*/
|
|
14
|
+
export declare function font(fontsetModule: ValModule<Record<string, FiledirEntryMetadata>>): FileSchema<GalleryFileSource>;
|
|
15
|
+
/** `s.font()` with `.remote()` applied: see `files.remote` in `initSchema`. */
|
|
16
|
+
export declare function remoteFont(fontsetModule: ValModule<Record<string, FiledirEntryMetadata>>): FileSchema<GalleryFileSource>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { filedir } from "./filedir.js";
|
|
2
|
+
import type { MediaDir } from "./record.js";
|
|
3
|
+
/**
|
|
4
|
+
* Options for `s.fontdir(dir, options)`: everything but the directory, which
|
|
5
|
+
* is the first argument.
|
|
6
|
+
*/
|
|
7
|
+
export type FontdirOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* The accepted font types. Defaults to every web font format:
|
|
10
|
+
* `"font/woff2,font/woff,font/ttf,font/otf"`. Narrow it to `"font/woff2"` to
|
|
11
|
+
* keep the site's fonts to the one format every current browser reads and
|
|
12
|
+
* that is smallest on the wire.
|
|
13
|
+
*/
|
|
14
|
+
accept?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Options for the deprecated `s.fontset(options)`, which took the directory
|
|
18
|
+
* as `dir`.
|
|
19
|
+
*
|
|
20
|
+
* @deprecated Use `s.fontdir(dir, options)` and `FontdirOptions`.
|
|
21
|
+
*/
|
|
22
|
+
export type FontsetOptions = FontdirOptions & {
|
|
23
|
+
/**
|
|
24
|
+
* The directory where fonts should be stored.
|
|
25
|
+
* Must start with "/public" (e.g., "/public/val/fonts")
|
|
26
|
+
*/
|
|
27
|
+
dir: MediaDir;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Define a directory of fonts.
|
|
31
|
+
*
|
|
32
|
+
* A fontdir IS a filedir — the same source, the same `s.font(fontsVal)` field
|
|
33
|
+
* to pick from it, the same checks and fixes — with `accept` defaulting to the
|
|
34
|
+
* web font formats. What a font gets that any other file does not is decided
|
|
35
|
+
* by its mime type rather than by the directory: the Studio previews any file
|
|
36
|
+
* it knows is a font, wherever it is shown.
|
|
37
|
+
*
|
|
38
|
+
* Remote is off by default: call `.remote()` on the result to allow remote files.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const schema = s.fontdir("/public/val/fonts");
|
|
43
|
+
* export default c.define("/content/fonts.val.ts", schema, {
|
|
44
|
+
* "/public/val/fonts/inter_a1b2c.woff2": {
|
|
45
|
+
* mimeType: "font/woff2",
|
|
46
|
+
* },
|
|
47
|
+
* });
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare const fontdir: (dir: MediaDir, options?: FontdirOptions) => ReturnType<typeof filedir>;
|
|
51
|
+
/**
|
|
52
|
+
* Define a collection of fonts.
|
|
53
|
+
*
|
|
54
|
+
* @deprecated Use `s.fontdir(dir, options)`: the directory moved out of the
|
|
55
|
+
* options and into the first argument, and nothing else changed.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* // was: s.fontset({ dir: "/public/val/fonts" })
|
|
60
|
+
* const schema = s.fontdir("/public/val/fonts");
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare const fontset: (options: FontsetOptions) => ReturnType<typeof filedir>;
|
|
@@ -5,7 +5,7 @@ import type { SerializedSchema } from "./index.js";
|
|
|
5
5
|
* The one answer to that question. There used to be two — `hasRemoteFileSchema`
|
|
6
6
|
* in the server, gating whether `/save` demands remote credentials, and
|
|
7
7
|
* `findRequiredRemoteFiles` in the Studio, gating the `/remote/settings` fetch —
|
|
8
|
-
* and they disagreed about `s.
|
|
8
|
+
* and they disagreed about `s.imagedir(dir, { ... }).remote()`: the Studio's version
|
|
9
9
|
* counted a remote media record, the server's did not, because a media
|
|
10
10
|
* collection serializes as a `record` of metadata rather than as an image
|
|
11
11
|
* schema.
|
|
@@ -43,8 +43,8 @@ export declare function hasRemoteFileSchema(schema: SerializedSchema): boolean;
|
|
|
43
43
|
*
|
|
44
44
|
* It is a walk over the SERIALIZED schema for the reasons given above, and for
|
|
45
45
|
* one more that is specific to this question: the two cases most likely to be
|
|
46
|
-
* missed are invisible to a value type. A media collection (`s.
|
|
47
|
-
* `s.
|
|
46
|
+
* missed are invisible to a value type. A media collection (`s.imagedir()` /
|
|
47
|
+
* `s.filedir()`) serializes as a record of metadata with no image schema inside
|
|
48
48
|
* it, and a richtext inline image lives in a constructor argument. A check
|
|
49
49
|
* written against the item TYPE would silently pass both — and the gallery case
|
|
50
50
|
* already has a data-loss incident attached to it (see above).
|