@valbuild/core 0.101.0 → 0.103.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/dist/declarations/src/extractValModules.d.ts +1 -1
- package/dist/declarations/src/index.d.ts +13 -11
- package/dist/declarations/src/initSchema.d.ts +28 -15
- package/dist/declarations/src/initVal.d.ts +0 -6
- package/dist/declarations/src/module.d.ts +1 -4
- package/dist/declarations/src/render.d.ts +58 -9
- package/dist/declarations/src/schema/array.d.ts +13 -3
- package/dist/declarations/src/schema/file.d.ts +17 -17
- package/dist/declarations/src/schema/files.d.ts +6 -2
- package/dist/declarations/src/schema/hasRemoteFileSchema.d.ts +34 -0
- package/dist/declarations/src/schema/image.d.ts +15 -6
- package/dist/declarations/src/schema/images.d.ts +10 -5
- package/dist/declarations/src/schema/index.d.ts +10 -3
- package/dist/declarations/src/schema/object.d.ts +2 -2
- package/dist/declarations/src/schema/record.d.ts +7 -7
- package/dist/declarations/src/schema/remote.d.ts +0 -10
- package/dist/declarations/src/schema/string.d.ts +4 -2
- package/dist/declarations/src/schema/union.d.ts +2 -2
- package/dist/declarations/src/selector/SelectorProxy.d.ts +9 -2
- package/dist/declarations/src/selector/index.d.ts +3 -7
- package/dist/declarations/src/source/file.d.ts +6 -24
- package/dist/declarations/src/source/index.d.ts +3 -7
- package/dist/declarations/src/source/json.d.ts +1 -1
- package/dist/declarations/src/source/media.d.ts +98 -0
- package/dist/declarations/src/source/remote.d.ts +0 -14
- package/dist/declarations/src/source/richtext.d.ts +5 -7
- package/dist/declarations/src/val/index.d.ts +2 -5
- package/dist/{index-a18c24c2.esm.js → index-267a8e9c.esm.js} +1086 -813
- package/dist/{index-3e2d700e.cjs.dev.js → index-2e40f2ae.cjs.dev.js} +1086 -813
- package/dist/{index-049780fa.cjs.prod.js → index-3572060f.cjs.prod.js} +1086 -813
- package/dist/{result-4bd63123.esm.js → result-daff1cae.esm.js} +1 -1
- package/dist/valbuild-core.cjs.dev.js +3 -3
- package/dist/valbuild-core.cjs.prod.js +3 -3
- package/dist/valbuild-core.esm.js +2 -2
- package/fp/dist/valbuild-core-fp.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 +3 -3
- package/dist/declarations/src/selector/file.d.ts +0 -10
- package/dist/declarations/src/selector/image.d.ts +0 -3
- package/dist/declarations/src/source/image.d.ts +0 -19
|
@@ -21,7 +21,7 @@ export type ExtractedValModules = {
|
|
|
21
21
|
* Extracts schemas and sources from a ValModules registry and computes the
|
|
22
22
|
* deterministic SHAs that the server and client both use to detect changes.
|
|
23
23
|
*
|
|
24
|
-
* Used by ValOps on the server and by
|
|
24
|
+
* Used by ValOps on the server and by `HostStore` on the client so the
|
|
25
25
|
* hash algorithm has a single source of truth.
|
|
26
26
|
*/
|
|
27
27
|
export declare function extractValModules(valModules: ValModules): Promise<ExtractedValModules>;
|
|
@@ -3,22 +3,23 @@ export { modules, type ValModules } from "./modules.js";
|
|
|
3
3
|
export { extractValModules, type ExtractedValModules, type ExtractedModuleError, } from "./extractValModules.js";
|
|
4
4
|
export type { InitVal, ValConfig, ValConstructor, ContentConstructor, } from "./initVal.js";
|
|
5
5
|
export { Schema, type SerializedSchema, type SelectorOfSchema } from "./schema/index.js";
|
|
6
|
+
export { hasRemoteFileSchema } from "./schema/hasRemoteFileSchema.js";
|
|
6
7
|
export type { ImageMetadata } from "./schema/image.js";
|
|
7
8
|
export type { FileMetadata } from "./schema/file.js";
|
|
8
9
|
export type { ValModule, SerializedModule, InferValModuleType } from "./module.js";
|
|
9
10
|
export type { SourceObject, SourcePrimitive, Source } from "./source/index.js";
|
|
10
|
-
export type { FileSource } from "./source/
|
|
11
|
+
export type { FileSource } from "./source/media.js";
|
|
11
12
|
export type { JsonSource, JsonOf, JsonImportThunk } from "./source/json.js";
|
|
12
|
-
export type {
|
|
13
|
+
export type { RemoteRef } from "./source/remote.js";
|
|
13
14
|
export { DEFAULT_VAL_REMOTE_HOST } from "./schema/remote.js";
|
|
14
15
|
export type { RawString } from "./schema/string.js";
|
|
15
|
-
export type { ImageSource } from "./source/
|
|
16
|
+
export type { ImageSource } from "./source/media.js";
|
|
17
|
+
export type { MediaHotspot, MediaSource, GalleryImageSource, GalleryFileSource, } from "./source/media.js";
|
|
16
18
|
export type { AllRichTextOptions, Bold, Styles, HeadingNode, ImageNode, Italic, LineThrough, ListItemNode, LinkNode, OrderedListNode, ParagraphNode, BrNode, RichTextNode, RichTextOptions, SerializedRichTextOptions, RichTextSource, BlockNode, SpanNode, UnorderedListNode, } from "./source/richtext.js";
|
|
17
19
|
export { type Val, type SerializedVal, type ModuleFilePath, type PatchId, type ModulePath, type SourcePath, type JsonOfSource, type ParentPatchId, } from "./val/index.js";
|
|
18
20
|
export type { Json, JsonPrimitive, JsonArray, JsonObject } from "./Json.js";
|
|
19
21
|
export type { ValidationError, ValidationErrors, } from "./schema/validation/ValidationError.js";
|
|
20
22
|
export type { ValidationFix } from "./schema/validation/ValidationFix.js";
|
|
21
|
-
export { FILE_REF_PROP, FILE_REF_SUBTYPE_TAG } from "./source/file.js";
|
|
22
23
|
export { VAL_EXTENSION, type SourceArray } from "./source/index.js";
|
|
23
24
|
export { derefPatch } from "./patch/deref.js";
|
|
24
25
|
export { type SelectorSource, type SelectorOf, GenericSelector, } from "./selector/index.js";
|
|
@@ -27,20 +28,18 @@ declare const ModuleFilePathSep = "?p=";
|
|
|
27
28
|
export { ModuleFilePathSep };
|
|
28
29
|
import { SelectorSource, getSchema } from "./selector/index.js";
|
|
29
30
|
import { ModulePath, SourcePath, getValPath, isVal } from "./val/index.js";
|
|
30
|
-
import { convertFileSource } from "./schema/file.js";
|
|
31
31
|
import { createValPathOfItem } from "./selector/SelectorProxy.js";
|
|
32
32
|
import { Operation } from "./patch/index.js";
|
|
33
33
|
import { initSchema } from "./initSchema.js";
|
|
34
34
|
import { getMimeType, mimeTypeToFileExt, filenameToMimeType } from "./mimeType/index.js";
|
|
35
35
|
import { type ImageMetadata } from "./schema/image.js";
|
|
36
36
|
import { type FileMetadata } from "./schema/file.js";
|
|
37
|
-
import { isFile } from "./source/file.js";
|
|
38
37
|
import { isJson, getJsonImport, resolveJsonValues } from "./source/json.js";
|
|
39
38
|
import { createRemoteRef } from "./source/remote.js";
|
|
40
39
|
import { getValidationBasis, getValidationHash } from "./remote/validationBasis.js";
|
|
41
40
|
import { getFileHash, hashToRemoteFileHash } from "./remote/fileHash.js";
|
|
42
41
|
import { splitRemoteRef } from "./remote/splitRemoteRef.js";
|
|
43
|
-
import {
|
|
42
|
+
import { fillFromGallery, isRemoteMediaPath, mediaUrl, resolveMedia } from "./source/media.js";
|
|
44
43
|
import { colorToHex, convertColor, detectColorFormat, formatColor, parseColor } from "./schema/colorFormat.js";
|
|
45
44
|
export { type SerializedArraySchema, ArraySchema } from "./schema/array.js";
|
|
46
45
|
export { type SerializedObjectSchema, ObjectSchema } from "./schema/object.js";
|
|
@@ -60,7 +59,7 @@ export { type SerializedRichTextSchema, RichTextSchema, } from "./schema/richtex
|
|
|
60
59
|
export { type SerializedUnionSchema, UnionSchema, type SerializedStringUnionSchema, type SerializedObjectUnionSchema, } from "./schema/union.js";
|
|
61
60
|
export { type SerializedLiteralSchema, LiteralSchema } from "./schema/literal.js";
|
|
62
61
|
export { deserializeSchema } from "./schema/deserialize.js";
|
|
63
|
-
export { type ListRecordRender, type ListArrayRender, type ReifiedRender, type CodeLanguage, type CodeRender, } from "./render.js";
|
|
62
|
+
export { type ListRecordRender, type ListArrayRender, type ReifiedRender, type RenderScope, type CodeLanguage, type CodeRender, renderScope, } from "./render.js";
|
|
64
63
|
export type { ValRouter, RouteValidationError } from "./router.js";
|
|
65
64
|
export { getSourcePathFromRoute } from "./getSourcePathFromRoute.js";
|
|
66
65
|
export declare const FATAL_ERROR_TYPES: readonly ["no-schema", "no-source", "invalid-id", "no-module", "invalid-patch"];
|
|
@@ -71,8 +70,12 @@ declare const Internal: {
|
|
|
71
70
|
VERSION: {
|
|
72
71
|
core: string | null;
|
|
73
72
|
};
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
mediaUrl: typeof mediaUrl;
|
|
74
|
+
resolveMedia: typeof resolveMedia;
|
|
75
|
+
isRemoteMediaPath: typeof isRemoteMediaPath;
|
|
76
|
+
media: {
|
|
77
|
+
fillFromGallery: typeof fillFromGallery;
|
|
78
|
+
};
|
|
76
79
|
getSchema: typeof getSchema;
|
|
77
80
|
getValPath: typeof getValPath;
|
|
78
81
|
getSource: typeof getSource;
|
|
@@ -99,7 +102,6 @@ declare const Internal: {
|
|
|
99
102
|
};
|
|
100
103
|
validate: (val: ValModule<SelectorSource>, path: SourcePath, src: unknown) => import("./schema/validation/ValidationError.js").ValidationErrors | undefined;
|
|
101
104
|
isVal: typeof isVal;
|
|
102
|
-
isFile: typeof isFile;
|
|
103
105
|
isJson: typeof isJson;
|
|
104
106
|
getJsonImport: typeof getJsonImport;
|
|
105
107
|
resolveJsonValues: typeof resolveJsonValues;
|
|
@@ -99,19 +99,28 @@ export type InitSchema = {
|
|
|
99
99
|
/**
|
|
100
100
|
* Define an image.
|
|
101
101
|
*
|
|
102
|
-
*
|
|
102
|
+
* An image is an object with a `path`. `width`, `height` and `mimeType` are
|
|
103
|
+
* read from the file — the VS Code extension fills them in as you type the
|
|
104
|
+
* path, and `npx val validate --fix` adds any that are missing. `alt` and
|
|
105
|
+
* `hotspot` are yours to set.
|
|
103
106
|
*
|
|
104
107
|
* @example
|
|
105
108
|
* const schema = s.image();
|
|
106
|
-
* export default c.define("/example.val.ts", schema,
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
109
|
+
* export default c.define("/example.val.ts", schema, {
|
|
110
|
+
* path: "/public/val/example.png",
|
|
111
|
+
* width: 100,
|
|
112
|
+
* height: 100,
|
|
113
|
+
* mimeType: "image/png",
|
|
114
|
+
* alt: "An example",
|
|
115
|
+
* hotspot: { x: 0.5, y: 0.5 },
|
|
116
|
+
* });
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* // Backed by a gallery: width, height and mimeType live there.
|
|
120
|
+
* const schema = s.image(galleryVal);
|
|
121
|
+
* export default c.define("/example.val.ts", schema, {
|
|
122
|
+
* path: "/public/val/example.png",
|
|
123
|
+
* });
|
|
115
124
|
*
|
|
116
125
|
*/
|
|
117
126
|
readonly image: typeof image;
|
|
@@ -146,11 +155,15 @@ export type InitSchema = {
|
|
|
146
155
|
/**
|
|
147
156
|
* Define a file.
|
|
148
157
|
*
|
|
149
|
-
*
|
|
158
|
+
* A file is an object with a `path`. `mimeType` comes from the extension —
|
|
159
|
+
* `npx val validate --fix` adds it.
|
|
150
160
|
*
|
|
151
161
|
* @example
|
|
152
162
|
* const schema = s.file();
|
|
153
|
-
* export default c.define("/example.val.ts", schema,
|
|
163
|
+
* export default c.define("/example.val.ts", schema, {
|
|
164
|
+
* path: "/public/val/example.pdf",
|
|
165
|
+
* mimeType: "application/pdf",
|
|
166
|
+
* });
|
|
154
167
|
*
|
|
155
168
|
*/
|
|
156
169
|
readonly file: typeof file;
|
|
@@ -291,11 +304,11 @@ export declare function initSchema(): {
|
|
|
291
304
|
}) => import("./schema/number.js").NumberSchema<number>;
|
|
292
305
|
union: <Key extends string | import("./schema/index.js").Schema<string>, T extends import("./schema/index.js").Schema<Key extends string ? import("./source/index.js").SourceObject & { [k in Key]: string; } : Key extends import("./schema/index.js").Schema<string> ? string : unknown>[]>(key: Key, ...objects: T) => import("./schema/union.js").UnionSchema<Key, T, T extends import("./schema/index.js").Schema<infer S extends import("./selector/index.js").SelectorSource>[] ? S extends import("./selector/index.js").SelectorSource ? S | (Key extends import("./schema/index.js").Schema<infer K extends import("./selector/index.js").SelectorSource> ? K : never) : never : never>;
|
|
293
306
|
richtext: <O extends import("./index.js").RichTextOptions>(options?: O) => import("./schema/richtext.js").RichTextSchema<O, import("./index.js").RichTextSource<O>>;
|
|
294
|
-
image:
|
|
307
|
+
image: typeof image;
|
|
295
308
|
literal: <T extends string>(value: T) => import("./schema/literal.js").LiteralSchema<T>;
|
|
296
309
|
keyOf: <Src extends import("./selector/index.js").GenericSelector<import("./source/index.js").SourceObject> & import("./module.js").ValModuleBrand>(valModule: Src) => import("./schema/keyOf.js").KeyOfSchema<Src, Src extends import("./selector/index.js").GenericSelector<infer S extends import("./source/index.js").Source, undefined> ? S extends readonly import("./source/index.js").Source[] ? number : S extends import("./source/index.js").SourceObject ? string extends keyof S ? import("./schema/string.js").RawString : keyof S : S extends Record<string, import("./source/index.js").Source> ? import("./schema/string.js").RawString : never : never>;
|
|
297
310
|
record: typeof record;
|
|
298
|
-
file:
|
|
311
|
+
file: typeof file;
|
|
299
312
|
files: (options: import("./schema/files.js").FilesOptions) => import("./schema/record.js").RecordSchema<import("./schema/object.js").ObjectSchema<{
|
|
300
313
|
mimeType: import("./schema/string.js").StringSchema<string>;
|
|
301
314
|
}, {
|
|
@@ -306,7 +319,7 @@ export declare function initSchema(): {
|
|
|
306
319
|
color: (options?: import("./schema/color.js").ColorOptions) => import("./schema/color.js").ColorSchema<import("./schema/string.js").RawString>;
|
|
307
320
|
route: <T extends string>(options?: Record<string, never>) => import("./schema/route.js").RouteSchema<T>;
|
|
308
321
|
router: typeof router;
|
|
309
|
-
images: <Accept extends `image/${string}`>(options
|
|
322
|
+
images: <Accept extends `image/${string}`>(options: import("./schema/images.js").ImagesOptions<Accept>) => import("./schema/record.js").RecordSchema<import("./schema/object.js").ObjectSchema<{
|
|
310
323
|
width: import("./schema/number.js").NumberSchema<number>;
|
|
311
324
|
height: import("./schema/number.js").NumberSchema<number>;
|
|
312
325
|
mimeType: import("./schema/string.js").StringSchema<string>;
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import { define } from "./module.js";
|
|
2
2
|
import { InitSchema } from "./initSchema.js";
|
|
3
3
|
import { getValPath as getPath } from "./val/index.js";
|
|
4
|
-
import { initFile } from "./source/file.js";
|
|
5
|
-
import { initImage } from "./source/image.js";
|
|
6
4
|
import { json } from "./source/json.js";
|
|
7
|
-
import { initRemote } from "./source/remote.js";
|
|
8
5
|
export type ContentConstructor = {
|
|
9
6
|
define: typeof define;
|
|
10
|
-
file: ReturnType<typeof initFile>;
|
|
11
|
-
image: ReturnType<typeof initImage>;
|
|
12
|
-
remote: ReturnType<typeof initRemote>;
|
|
13
7
|
json: typeof json;
|
|
14
8
|
};
|
|
15
9
|
export type ValConstructor = {
|
|
@@ -4,22 +4,19 @@ import { Source } from "./source/index.js";
|
|
|
4
4
|
import { ModuleFilePath, ModulePath, SourcePath } from "./val/index.js";
|
|
5
5
|
import { Json } from "./Json.js";
|
|
6
6
|
import { RawString } from "./schema/string.js";
|
|
7
|
-
import { ImageSelector } from "./selector/image.js";
|
|
8
|
-
import { ImageSource } from "./source/image.js";
|
|
9
7
|
declare const brand: unique symbol;
|
|
10
8
|
export type ValModule<T extends SelectorSource> = SelectorOf<T> & ValModuleBrand;
|
|
11
9
|
export type ValModuleBrand = {
|
|
12
10
|
[brand]: "ValModule";
|
|
13
11
|
};
|
|
14
12
|
export type InferValModuleType<T extends ValModule<SelectorSource>> = T extends GenericSelector<infer S> ? S : never;
|
|
15
|
-
export type ReplaceRawStringWithString<T extends SelectorSource> = SelectorSource extends T ? T : T extends RawString ? string : T extends
|
|
13
|
+
export type ReplaceRawStringWithString<T extends SelectorSource> = SelectorSource extends T ? T : T extends RawString ? string : T extends {
|
|
16
14
|
[key in string]: SelectorSource;
|
|
17
15
|
} ? {
|
|
18
16
|
[key in keyof T]: ReplaceRawStringWithString<T[key]>;
|
|
19
17
|
} : T extends SelectorSource[] ? ReplaceRawStringWithString<T[number]>[] : T;
|
|
20
18
|
export declare function define<T extends Schema<SelectorSource>>(id: string, // TODO: `/${string}`
|
|
21
19
|
schema: T, source: ReplaceRawStringWithString<SelectorOfSchema<T>>): ValModule<SelectorOfSchema<T>>;
|
|
22
|
-
export declare function enrichFileImageRemoteSourceWithMetadata<T extends SelectorSource>(source: T, schema: Schema<SelectorSource>): T;
|
|
23
20
|
export declare function getSource<T extends Source>(valModule: ValModule<T>): T;
|
|
24
21
|
export declare function splitModuleFilePathAndModulePath(path: SourcePath | ModuleFilePath): [moduleId: ModuleFilePath, path: ModulePath];
|
|
25
22
|
export declare function joinModuleFilePathAndModulePath(moduleFilePath: ModuleFilePath, modulePath: ModulePath): SourcePath;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Schema } from "./schema/index.js";
|
|
2
|
-
import { ImageMetadata } from "./schema/image.js";
|
|
3
2
|
import { SelectorSource } from "./selector/index.js";
|
|
4
|
-
import { ImageSource } from "./source/
|
|
5
|
-
import { RemoteSource } from "./source/remote.js";
|
|
3
|
+
import { ImageSource } from "./source/media.js";
|
|
6
4
|
import { ModuleFilePath, SourcePath } from "./val/index.js";
|
|
7
5
|
export type ListRecordRender = {
|
|
8
6
|
layout: "list";
|
|
@@ -12,18 +10,32 @@ export type ListRecordRender = {
|
|
|
12
10
|
value: {
|
|
13
11
|
title: string;
|
|
14
12
|
subtitle?: string | null;
|
|
15
|
-
image?: ImageSource |
|
|
13
|
+
image?: ImageSource | null;
|
|
16
14
|
}
|
|
17
15
|
][];
|
|
18
16
|
};
|
|
19
17
|
export type ListArrayRender = {
|
|
20
18
|
layout: "list";
|
|
21
19
|
parent: "array";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
/**
|
|
21
|
+
* The rendered items, each PAIRED WITH ITS INDEX — the same
|
|
22
|
+
* `[key, value][]` shape {@link ListRecordRender} uses.
|
|
23
|
+
*
|
|
24
|
+
* Not a positionally-indexed array, and the reason is
|
|
25
|
+
* {@link RenderScope}: a render computed for a subset of paths carries only
|
|
26
|
+
* those items, so `items[i]` would silently read the wrong row. Carrying the
|
|
27
|
+
* index makes a windowed render impossible to misread — a consumer looks its
|
|
28
|
+
* index up rather than trusting a position — and makes the array and record
|
|
29
|
+
* shapes symmetric.
|
|
30
|
+
*/
|
|
31
|
+
items: [
|
|
32
|
+
index: number,
|
|
33
|
+
value: {
|
|
34
|
+
title: string;
|
|
35
|
+
subtitle?: string | null;
|
|
36
|
+
image?: ImageSource | null;
|
|
37
|
+
}
|
|
38
|
+
][];
|
|
27
39
|
};
|
|
28
40
|
export type TextareaRender = {
|
|
29
41
|
layout: "textarea";
|
|
@@ -45,5 +57,42 @@ type WithStatus<T> = {
|
|
|
45
57
|
data: T;
|
|
46
58
|
};
|
|
47
59
|
export type ReifiedRender = Record<SourcePath | ModuleFilePath, WithStatus<RenderTypes>>;
|
|
60
|
+
/**
|
|
61
|
+
* Which paths a render is being computed FOR.
|
|
62
|
+
*
|
|
63
|
+
* `executeRender` takes a whole module, so one request has always walked every
|
|
64
|
+
* node in it and run every `select` closure — for `handboka`, with `select` at
|
|
65
|
+
* two nested array levels, that is every chapter and every section to serve one
|
|
66
|
+
* visible row. A scope is what makes the walk proportional to what is being
|
|
67
|
+
* looked at instead of to the project.
|
|
68
|
+
*
|
|
69
|
+
* Two questions, because a container and its items need different answers:
|
|
70
|
+
*
|
|
71
|
+
* - {@link RenderScope.wants} — is a render AT this exact path wanted? A
|
|
72
|
+
* container answers `true` here when the whole of it is being shown, and its
|
|
73
|
+
* list render is then computed in full.
|
|
74
|
+
* - {@link RenderScope.wantsUnder} — could anything at or below this path be
|
|
75
|
+
* wanted? Recursion is pruned where this is `false`, and a container whose own
|
|
76
|
+
* path is not wanted but which has wanted descendants renders a WINDOW: only
|
|
77
|
+
* the items that were asked for. That is the case a single visible row is, and
|
|
78
|
+
* it is why {@link ListArrayRender} carries indices.
|
|
79
|
+
*
|
|
80
|
+
* Absent scope means the whole module, which is what every existing caller
|
|
81
|
+
* passes and what every existing caller got.
|
|
82
|
+
*/
|
|
83
|
+
export type RenderScope = {
|
|
84
|
+
wants(path: SourcePath | ModuleFilePath): boolean;
|
|
85
|
+
wantsUnder(path: SourcePath | ModuleFilePath): boolean;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* A scope covering exactly `paths` and their subtrees.
|
|
89
|
+
*
|
|
90
|
+
* Compares SEGMENTS rather than string prefixes. A source path's module path is
|
|
91
|
+
* a quoted, dot-joined encoding (`?p="a".1."b"`), so `startsWith` gets the
|
|
92
|
+
* ancestor test wrong wherever a key is a prefix of a sibling key or contains a
|
|
93
|
+
* dot or a quote — `"title"` against `"titles"` being the cheapest example.
|
|
94
|
+
* Segments are parsed once here, not per comparison.
|
|
95
|
+
*/
|
|
96
|
+
export declare function renderScope(paths: readonly SourcePath[]): RenderScope;
|
|
48
97
|
export type RenderSelector<T extends Schema<SelectorSource>> = T extends Schema<infer S> ? S : never;
|
|
49
98
|
export {};
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import { Schema, SchemaAssertResult, SelectorOfSchema, SerializedSchema } from "./index.js";
|
|
2
|
-
import { RenderSelector, ReifiedRender } from "../render.js";
|
|
2
|
+
import { RenderSelector, ReifiedRender, RenderScope } from "../render.js";
|
|
3
3
|
import { SelectorSource } from "../selector/index.js";
|
|
4
|
-
import { ImageSource } from "../source/
|
|
4
|
+
import { ImageSource } from "../source/media.js";
|
|
5
5
|
import { ModuleFilePath, SourcePath } from "../val/index.js";
|
|
6
6
|
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
7
7
|
export type SerializedArraySchema = {
|
|
8
8
|
type: "array";
|
|
9
9
|
item: SerializedSchema;
|
|
10
10
|
opt: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Set when this schema declares a `render`.
|
|
13
|
+
*
|
|
14
|
+
* The render itself cannot be serialized — `select` is a user closure — but
|
|
15
|
+
* whether one EXISTS can be, and that is worth carrying: it lets the non-host
|
|
16
|
+
* side skip asking the host to render a module that cannot produce one.
|
|
17
|
+
* Measured in a browser: mounting 260 fields across 141 modules spent ~2.3ms
|
|
18
|
+
* of 3.1ms calling `executeRender` on modules that returned nothing.
|
|
19
|
+
*/
|
|
20
|
+
render?: true;
|
|
11
21
|
customValidate?: boolean;
|
|
12
22
|
readonly?: boolean;
|
|
13
23
|
hidden?: boolean;
|
|
@@ -41,7 +51,7 @@ export declare class ArraySchema<T extends Schema<SelectorSource>, Src extends S
|
|
|
41
51
|
hidden(): ArraySchema<T, Src>;
|
|
42
52
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
43
53
|
protected executeSerialize(): SerializedArraySchema;
|
|
44
|
-
protected executeRender(sourcePath: SourcePath | ModuleFilePath, src: Src): ReifiedRender;
|
|
54
|
+
protected executeRender(sourcePath: SourcePath | ModuleFilePath, src: Src, scope?: RenderScope): ReifiedRender;
|
|
45
55
|
render(input: ArrayRenderInput<T>): ArraySchema<T, Src>;
|
|
46
56
|
}
|
|
47
57
|
export declare const array: <S extends Schema<SelectorSource>>(schema: S) => ArraySchema<S, SelectorOfSchema<S>[]>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { FileSource, GalleryFileSource } from "../source/media.js";
|
|
2
|
+
export type { FileMetadata } from "../source/file.js";
|
|
3
3
|
import { CustomValidateFunction, Schema, SchemaAssertResult, SerializedSchema } from "./index.js";
|
|
4
4
|
import { ModulePath, SourcePath } from "../val/index.js";
|
|
5
5
|
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
6
|
-
import {
|
|
6
|
+
import { ValModule } from "../index.js";
|
|
7
7
|
import { ReifiedRender } from "../render.js";
|
|
8
8
|
import { FilesEntryMetadata } from "./files.js";
|
|
9
9
|
export type FileOptions = {
|
|
@@ -20,10 +20,7 @@ export type SerializedFileSchema = {
|
|
|
20
20
|
hidden?: boolean;
|
|
21
21
|
description?: string;
|
|
22
22
|
};
|
|
23
|
-
export
|
|
24
|
-
mimeType?: string;
|
|
25
|
-
};
|
|
26
|
-
export declare class FileSchema<Src extends FileSource<FileMetadata | undefined> | RemoteSource<FileMetadata | undefined> | null> extends Schema<Src> {
|
|
23
|
+
export declare class FileSchema<Src extends FileSource | null> extends Schema<Src> {
|
|
27
24
|
private readonly options?;
|
|
28
25
|
private readonly opt;
|
|
29
26
|
protected readonly isRemote: boolean;
|
|
@@ -34,9 +31,14 @@ export declare class FileSchema<Src extends FileSource<FileMetadata | undefined>
|
|
|
34
31
|
private readonly description?;
|
|
35
32
|
constructor(options?: FileOptions | undefined, opt?: boolean, isRemote?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], moduleMetadata?: Record<ModulePath, Record<string, FilesEntryMetadata>>, isReadonly?: boolean, isHidden?: boolean, description?: string | undefined);
|
|
36
33
|
describe(description: string | null): FileSchema<Src>;
|
|
37
|
-
remote(): FileSchema<Src
|
|
34
|
+
remote(): FileSchema<Src>;
|
|
38
35
|
validate(validationFunction: CustomValidateFunction<Src>): FileSchema<Src>;
|
|
39
36
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
37
|
+
/**
|
|
38
|
+
* The entries of the gallery this field points at, or null when it is a
|
|
39
|
+
* standalone field.
|
|
40
|
+
*/
|
|
41
|
+
private galleryEntries;
|
|
40
42
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
41
43
|
nullable(): FileSchema<Src | null>;
|
|
42
44
|
readonly(): FileSchema<Src>;
|
|
@@ -45,12 +47,10 @@ export declare class FileSchema<Src extends FileSource<FileMetadata | undefined>
|
|
|
45
47
|
protected executeSerialize(): SerializedSchema;
|
|
46
48
|
protected executeRender(): ReifiedRender;
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
metadata?: Metadata;
|
|
56
|
-
};
|
|
50
|
+
/**
|
|
51
|
+
* A file picked from a gallery. Its mime type lives in the gallery, so the
|
|
52
|
+
* field carries only the path.
|
|
53
|
+
*/
|
|
54
|
+
export declare function file(galleryModule: ValModule<Record<string, FilesEntryMetadata>>): FileSchema<GalleryFileSource>;
|
|
55
|
+
/** A file of its own, carrying its own mime type. */
|
|
56
|
+
export declare function file(options?: FileOptions): FileSchema<FileSource>;
|
|
@@ -14,9 +14,13 @@ export type FilesOptions = {
|
|
|
14
14
|
/**
|
|
15
15
|
* The directory where files should be stored.
|
|
16
16
|
* Must start with "/public" (e.g., "/public/val/files")
|
|
17
|
-
*
|
|
17
|
+
*
|
|
18
|
+
* Required, and deliberately so: it decides where every uploaded file in this
|
|
19
|
+
* collection lands, and it used to default to "/public/val" — which meant a
|
|
20
|
+
* collection that had simply not said where it wanted its files silently shared
|
|
21
|
+
* a directory with every other one.
|
|
18
22
|
*/
|
|
19
|
-
directory
|
|
23
|
+
directory: "/public" | `/public/${string}`;
|
|
20
24
|
/**
|
|
21
25
|
* Whether remote files are allowed
|
|
22
26
|
* @default false
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SerializedSchema } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Does this schema store any file remotely?
|
|
4
|
+
*
|
|
5
|
+
* The one answer to that question. There used to be two — `hasRemoteFileSchema`
|
|
6
|
+
* in the server, gating whether `/save` demands remote credentials, and
|
|
7
|
+
* `findRequiredRemoteFiles` in the Studio, gating the `/remote/settings` fetch —
|
|
8
|
+
* and they disagreed about `s.images({ remote: true })`: the Studio's counted a
|
|
9
|
+
* remote media record, the server's did not, because a media collection
|
|
10
|
+
* serializes as a `record` of metadata rather than as an image schema.
|
|
11
|
+
*
|
|
12
|
+
* The server's answer was the wrong one, and silently so. With it false,
|
|
13
|
+
* `/save` runs `saveOrUploadFiles` in `skip-remote` mode, and that mode does not
|
|
14
|
+
* merely skip the upload — it drops every remote descriptor without an error. The
|
|
15
|
+
* commit then lands a remote ref with no bytes behind it: a broken image, in the
|
|
16
|
+
* repository, with nothing anywhere saying why.
|
|
17
|
+
*
|
|
18
|
+
* ## Why it stays a walk over the SERIALIZED schema
|
|
19
|
+
*
|
|
20
|
+
* Both callers have a `SerializedSchema` and not a `Schema`: the server reads
|
|
21
|
+
* them out of `getSchemas()`, and the Studio is handed them by `host.receive`.
|
|
22
|
+
* Asking the schema classes directly would mean a method on every one of them,
|
|
23
|
+
* and the two places that need the answer cannot call it.
|
|
24
|
+
*
|
|
25
|
+
* ## Throwing
|
|
26
|
+
*
|
|
27
|
+
* The `never` assignment at the end is the point of the default branch: adding a
|
|
28
|
+
* schema type without teaching this function about it must not compile. The throw
|
|
29
|
+
* is what happens if one arrives anyway — which for a caller reading schemas out
|
|
30
|
+
* of its own process should be impossible. A caller that cannot afford to throw
|
|
31
|
+
* (the Studio, whose whole UI is downstream of this) catches it; returning `false`
|
|
32
|
+
* instead would reintroduce exactly the silent skip described above.
|
|
33
|
+
*/
|
|
34
|
+
export declare function hasRemoteFileSchema(schema: SerializedSchema): boolean;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { CustomValidateFunction, Schema, SchemaAssertResult, SerializedSchema } from "./index.js";
|
|
2
|
-
import {
|
|
3
|
-
import { ImageSource } from "../source/image.js";
|
|
2
|
+
import { GalleryImageSource, ImageSource } from "../source/media.js";
|
|
4
3
|
import { ModulePath, SourcePath } from "../val/index.js";
|
|
5
4
|
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
6
5
|
import { ValModule } from "../index.js";
|
|
7
|
-
import { RemoteSource } from "../source/remote.js";
|
|
8
6
|
import { ReifiedRender } from "../render.js";
|
|
9
7
|
import { ImagesEntryMetadata } from "./images.js";
|
|
10
8
|
export type ImageOptions = {
|
|
@@ -34,7 +32,7 @@ export type ImageMetadata = {
|
|
|
34
32
|
y: number;
|
|
35
33
|
};
|
|
36
34
|
};
|
|
37
|
-
export declare class ImageSchema<Src extends
|
|
35
|
+
export declare class ImageSchema<Src extends ImageSource | null> extends Schema<Src> {
|
|
38
36
|
private readonly options?;
|
|
39
37
|
private readonly opt;
|
|
40
38
|
protected readonly isRemote: boolean;
|
|
@@ -45,9 +43,14 @@ export declare class ImageSchema<Src extends FileSource<ImageMetadata | undefine
|
|
|
45
43
|
private readonly description?;
|
|
46
44
|
constructor(options?: ImageOptions | undefined, opt?: boolean, isRemote?: boolean, customValidateFunctions?: CustomValidateFunction<Src>[], moduleMetadata?: Record<ModulePath, Record<string, ImagesEntryMetadata>>, isReadonly?: boolean, isHidden?: boolean, description?: string | undefined);
|
|
47
45
|
describe(description: string | null): ImageSchema<Src>;
|
|
48
|
-
remote(): ImageSchema<Src
|
|
46
|
+
remote(): ImageSchema<Src>;
|
|
49
47
|
validate(validationFunction: CustomValidateFunction<Src>): ImageSchema<Src>;
|
|
50
48
|
protected executeValidate(path: SourcePath, src: Src): ValidationErrors;
|
|
49
|
+
/**
|
|
50
|
+
* The entries of the gallery this field points at, or null when it is a
|
|
51
|
+
* standalone field.
|
|
52
|
+
*/
|
|
53
|
+
private galleryEntries;
|
|
51
54
|
protected executeAssert(path: SourcePath, src: unknown): SchemaAssertResult<Src>;
|
|
52
55
|
nullable(): ImageSchema<Src | null>;
|
|
53
56
|
readonly(): ImageSchema<Src>;
|
|
@@ -56,4 +59,10 @@ export declare class ImageSchema<Src extends FileSource<ImageMetadata | undefine
|
|
|
56
59
|
protected executeSerialize(): SerializedSchema;
|
|
57
60
|
protected executeRender(): ReifiedRender;
|
|
58
61
|
}
|
|
59
|
-
|
|
62
|
+
/**
|
|
63
|
+
* An image picked from a gallery. Its dimensions and mime type live in the
|
|
64
|
+
* gallery, so the field carries only what a person typed.
|
|
65
|
+
*/
|
|
66
|
+
export declare function image(galleryModule: ValModule<Record<string, ImagesEntryMetadata>>): ImageSchema<GalleryImageSource>;
|
|
67
|
+
/** An image of its own, carrying its own dimensions and mime type. */
|
|
68
|
+
export declare function image(options?: ImageOptions): ImageSchema<ImageSource>;
|
|
@@ -20,9 +20,13 @@ export type ImagesOptions<Accept extends `image/${string}`> = {
|
|
|
20
20
|
/**
|
|
21
21
|
* The directory where images should be stored.
|
|
22
22
|
* Must start with "/public" (e.g., "/public/val/images")
|
|
23
|
-
*
|
|
23
|
+
*
|
|
24
|
+
* Required, and deliberately so: it decides where every uploaded file in this
|
|
25
|
+
* collection lands, and it used to default to "/public/val" — which meant a
|
|
26
|
+
* gallery that had simply not said where it wanted its files silently shared a
|
|
27
|
+
* directory with every other one.
|
|
24
28
|
*/
|
|
25
|
-
directory
|
|
29
|
+
directory: "/public" | `/public/${string}`;
|
|
26
30
|
/**
|
|
27
31
|
* Alt text schema. Can be:
|
|
28
32
|
* - s.string() for required alt text
|
|
@@ -65,8 +69,9 @@ type ImagesItemSrc = {
|
|
|
65
69
|
/**
|
|
66
70
|
* Define a collection of images.
|
|
67
71
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
72
|
+
* `directory` is required — it decides where uploads land, so it is not something
|
|
73
|
+
* to be inferred. The rest defaults: any image type (`"image/*"`), nullable alt
|
|
74
|
+
* text, remote disabled.
|
|
70
75
|
*
|
|
71
76
|
* @example
|
|
72
77
|
* ```typescript
|
|
@@ -85,5 +90,5 @@ type ImagesItemSrc = {
|
|
|
85
90
|
* });
|
|
86
91
|
* ```
|
|
87
92
|
*/
|
|
88
|
-
export declare const images: <Accept extends `image/${string}`>(options
|
|
93
|
+
export declare const images: <Accept extends `image/${string}`>(options: ImagesOptions<Accept>) => RecordSchema<ObjectSchema<ImagesItemProps, ImagesItemSrc>, Schema<string>, Record<string, ImagesEntryMetadata>>;
|
|
89
94
|
export {};
|
|
@@ -17,9 +17,9 @@ import { SerializedDateSchema } from "./date.js";
|
|
|
17
17
|
import { SerializedDateTimeSchema } from "./datetime.js";
|
|
18
18
|
import { SerializedRouteSchema } from "./route.js";
|
|
19
19
|
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
20
|
-
import { FileSource } from "../source/
|
|
20
|
+
import { FileSource } from "../source/media.js";
|
|
21
21
|
import { GenericRichTextSourceNode, RichTextSource } from "../source/richtext.js";
|
|
22
|
-
import { ReifiedRender } from "../render.js";
|
|
22
|
+
import { ReifiedRender, RenderScope } from "../render.js";
|
|
23
23
|
export type SerializedSchema = SerializedStringSchema | SerializedLiteralSchema | SerializedBooleanSchema | SerializedNumberSchema | SerializedObjectSchema | SerializedArraySchema | SerializedUnionSchema | SerializedRichTextSchema | SerializedRecordSchema | SerializedKeyOfSchema | SerializedFileSchema | SerializedDateSchema | SerializedDateTimeSchema | SerializedColorSchema | SerializedRouteSchema | SerializedImageSchema;
|
|
24
24
|
type Primitives = number | string | boolean | null | FileSource;
|
|
25
25
|
export type AssertError = {
|
|
@@ -106,7 +106,14 @@ export declare abstract class Schema<Src extends SelectorSource> {
|
|
|
106
106
|
*/
|
|
107
107
|
abstract hidden(): Schema<Src>;
|
|
108
108
|
protected abstract executeSerialize(): SerializedSchema;
|
|
109
|
-
|
|
109
|
+
/**
|
|
110
|
+
* @param scope Which paths the caller needs a render for. Absent means the
|
|
111
|
+
* whole module, which is what every caller passed before scoping existed.
|
|
112
|
+
* See {@link RenderScope}: a container prunes recursion where nothing is
|
|
113
|
+
* wanted, and renders a WINDOW when its own path is not wanted but some of its
|
|
114
|
+
* items are — which is the single-visible-row case.
|
|
115
|
+
*/
|
|
116
|
+
protected abstract executeRender(sourcePath: SourcePath | ModuleFilePath, src: Src, scope?: RenderScope): ReifiedRender;
|
|
110
117
|
/** MUTATES! since internal and perf sensitive */
|
|
111
118
|
protected appendValidationError(current: ValidationErrors, path: SourcePath, message: string, value: unknown, schemaError?: boolean): ValidationErrors;
|
|
112
119
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CustomValidateFunction, Schema, SchemaAssertResult, SelectorOfSchema, SerializedSchema } from "./index.js";
|
|
2
|
-
import { ReifiedRender } from "../render.js";
|
|
2
|
+
import { ReifiedRender, RenderScope } from "../render.js";
|
|
3
3
|
import { SelectorSource } from "../selector/index.js";
|
|
4
4
|
import { ModuleFilePath, SourcePath } from "../val/index.js";
|
|
5
5
|
import { ValidationError, ValidationErrors } from "./validation/ValidationError.js";
|
|
@@ -52,7 +52,7 @@ export declare class ObjectSchema<Props extends ObjectSchemaProps, Src extends O
|
|
|
52
52
|
hidden(): ObjectSchema<Props, Src>;
|
|
53
53
|
protected executeCustomValidateAt(path: SourcePath, src: Src): ValidationError[];
|
|
54
54
|
protected executeSerialize(): SerializedSchema;
|
|
55
|
-
protected executeRender(sourcePath: SourcePath | ModuleFilePath, src: Src): ReifiedRender;
|
|
55
|
+
protected executeRender(sourcePath: SourcePath | ModuleFilePath, src: Src, scope?: RenderScope): ReifiedRender;
|
|
56
56
|
}
|
|
57
57
|
export declare const object: <Props extends ObjectSchemaProps>(schema: Props) => ObjectSchema<Props, ObjectSchemaSrcOf<Props>>;
|
|
58
58
|
export {};
|