@routier/core 0.2.1 → 0.4.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/LICENSE +21 -0
- package/{readme.md → README.md} +3 -3
- package/dist/assertions/index.cjs +191 -0
- package/dist/assertions/index.cjs.map +1 -0
- package/dist/assertions/index.js +43 -63
- package/dist/assertions/index.js.map +1 -1
- package/dist/capabilities/index.cjs +820 -0
- package/dist/capabilities/index.cjs.map +1 -0
- package/dist/capabilities/index.js +584 -558
- package/dist/capabilities/index.js.map +1 -1
- package/dist/codegen/handlers/CloneHandlerBuilder.d.ts +10 -1
- package/dist/codegen/handlers/clone/CloneArrayHandler.d.ts +3 -0
- package/dist/codegen/handlers/clone/CloneDateHandler.d.ts +13 -0
- package/dist/codegen/handlers/clone/CloneValueHandler.d.ts +16 -0
- package/dist/codegen/handlers/compare/CompareComputedHandler.d.ts +10 -0
- package/dist/codegen/handlers/compare/CompareFunctionHandler.d.ts +10 -0
- package/dist/codegen/handlers/deserialize/DeserializeArrayHandler.d.ts +14 -0
- package/dist/codegen/handlers/enableChangeTracking/EnableChangeTrackingArrayHandler.d.ts +11 -0
- package/dist/codegen/handlers/enrichment/EnrichmentArrayHandler.d.ts +11 -0
- package/dist/codegen/handlers/freeze/FreezeArrayHandler.d.ts +6 -0
- package/dist/codegen/handlers/hash/HashArrayHandler.d.ts +10 -0
- package/dist/codegen/handlers/hash/HashFileHandler.d.ts +24 -0
- package/dist/codegen/handlers/hash/HashObjectHandler.d.ts +10 -0
- package/dist/codegen/handlers/hash/HashTransformHandler.d.ts +23 -0
- package/dist/codegen/handlers/merge/MergeArrayHandler.d.ts +20 -0
- package/dist/codegen/handlers/merge/MergeObjectHandler.d.ts +10 -0
- package/dist/codegen/handlers/serialize/SerializeArrayHandler.d.ts +19 -0
- package/dist/codegen/handlers/strip/StripComputedHandler.d.ts +10 -0
- package/dist/codegen/handlers/strip/StripFunctionHandler.d.ts +9 -0
- package/dist/codegen/handlers/types.d.ts +55 -1
- package/dist/codegen/index.cjs +618 -0
- package/dist/codegen/index.cjs.map +1 -0
- package/dist/codegen/index.js +99 -127
- package/dist/codegen/index.js.map +1 -1
- package/dist/collections/MemoryDataCollection.d.ts +15 -1
- package/dist/collections/TagCollection.d.ts +0 -1
- package/dist/collections/index.cjs +702 -0
- package/dist/collections/index.cjs.map +1 -0
- package/dist/collections/index.js +282 -276
- package/dist/collections/index.js.map +1 -1
- package/dist/errors/OptimisticConcurrencyError.d.ts +18 -0
- package/dist/errors/PluginDestroyedError.d.ts +10 -0
- package/dist/errors/index.cjs +132 -0
- package/dist/errors/index.cjs.map +1 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.js +61 -19
- package/dist/errors/index.js.map +1 -1
- package/dist/expressions/evaluate.d.ts +53 -0
- package/dist/expressions/index.cjs +2087 -0
- package/dist/expressions/index.cjs.map +1 -0
- package/dist/expressions/index.d.ts +1 -1
- package/dist/expressions/index.js +1727 -1082
- package/dist/expressions/index.js.map +1 -1
- package/dist/expressions/parser.d.ts +19 -0
- package/dist/expressions/types.d.ts +87 -2
- package/dist/index.cjs +14377 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +12374 -7931
- package/dist/index.js.map +1 -1
- package/dist/performance/index.cjs +217 -0
- package/dist/performance/index.cjs.map +1 -0
- package/dist/performance/index.js +120 -55
- package/dist/performance/index.js.map +1 -1
- package/dist/pipeline/index.cjs +576 -0
- package/dist/pipeline/index.cjs.map +1 -0
- package/dist/pipeline/index.js +223 -161
- package/dist/pipeline/index.js.map +1 -1
- package/dist/plugins/BatchingDbPlugin.d.ts +139 -0
- package/dist/plugins/CacheDbPlugin.d.ts +70 -0
- package/dist/plugins/ConcurrencyDbPlugin.d.ts +78 -0
- package/dist/plugins/EphemeralDataPlugin.d.ts +57 -1
- package/dist/plugins/RetryDbPlugin.d.ts +77 -0
- package/dist/plugins/index.cjs +6551 -0
- package/dist/plugins/index.cjs.map +1 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.js +6271 -1170
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/query/QueryOptionsCollection.d.ts +34 -0
- package/dist/plugins/query/explain.d.ts +82 -0
- package/dist/plugins/query/formatExplanation.d.ts +9 -0
- package/dist/plugins/query/index.d.ts +4 -0
- package/dist/plugins/query/join.d.ts +210 -0
- package/dist/plugins/query/similarity.d.ts +38 -0
- package/dist/plugins/query/types.d.ts +75 -1
- package/dist/plugins/translators/DataTranslator.d.ts +28 -0
- package/dist/plugins/translators/JsonTranslator.d.ts +27 -0
- package/dist/plugins/translators/SqlTranslator.d.ts +45 -0
- package/dist/plugins/translators/TupleTranslator.d.ts +45 -0
- package/dist/plugins/translators/index.d.ts +1 -0
- package/dist/plugins/types.d.ts +125 -3
- package/dist/plugins/wire/handler.d.ts +122 -0
- package/dist/plugins/wire/index.d.ts +4 -0
- package/dist/plugins/wire/persist.d.ts +43 -0
- package/dist/plugins/wire/query.d.ts +49 -0
- package/dist/plugins/wire/types.d.ts +139 -0
- package/dist/results/index.cjs +174 -0
- package/dist/results/index.cjs.map +1 -0
- package/dist/results/index.js +29 -44
- package/dist/results/index.js.map +1 -1
- package/dist/schema/PropertyInfo.d.ts +31 -2
- package/dist/schema/SchemaDefinition.d.ts +23 -1
- package/dist/schema/builder.d.ts +35 -1
- package/dist/schema/communication/broadcast.d.ts +17 -1
- package/dist/schema/index.cjs +6911 -0
- package/dist/schema/index.cjs.map +1 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +5330 -4541
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/property/base/SchemaBase.d.ts +48 -2
- package/dist/schema/property/modifiers/SchemaNullable.d.ts +10 -0
- package/dist/schema/property/modifiers/SchemaOptional.d.ts +19 -0
- package/dist/schema/property/modifiers/SchemaSearchable.d.ts +34 -0
- package/dist/schema/property/modifiers/index.d.ts +1 -0
- package/dist/schema/property/types/SchemaFile.d.ts +60 -0
- package/dist/schema/property/types/SchemaString.d.ts +21 -1
- package/dist/schema/property/types/SchemaVector.d.ts +61 -0
- package/dist/schema/property/types/index.d.ts +2 -0
- package/dist/schema/table/SchemaTransform.d.ts +40 -0
- package/dist/schema/table/index.d.ts +1 -0
- package/dist/schema/types.d.ts +166 -8
- package/dist/schema/utils/propertyKind.d.ts +4 -0
- package/dist/types/index.cjs +23 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.js +0 -14
- package/dist/types/index.js.map +1 -1
- package/dist/utilities/index.cjs +1013 -0
- package/dist/utilities/index.cjs.map +1 -0
- package/dist/utilities/index.js +541 -379
- package/dist/utilities/index.js.map +1 -1
- package/dist/utilities/logger.d.ts +48 -0
- package/package.json +156 -98
- package/dist/codegen/SlotPath.test.d.ts +0 -1
- package/dist/codegen/blocks.test.d.ts +0 -1
- package/dist/codegen/utils.test.d.ts +0 -1
- package/dist/collections/Changes.test.d.ts +0 -1
- package/dist/collections/IdSet.test.d.ts +0 -1
- package/dist/collections/MemoryDataCollection.test.d.ts +0 -1
- package/dist/collections/TagCollection.contract.test.d.ts +0 -1
- package/dist/collections/TagCollection.test.d.ts +0 -1
- package/dist/expressions/parser.test.d.ts +0 -1
- package/dist/expressions/sql.d.ts +0 -28
- package/dist/expressions/sql.test.d.ts +0 -1
- package/dist/expressions/utils.test.d.ts +0 -1
- package/dist/pipeline/SyncronousQueue.test.d.ts +0 -1
- package/dist/plugins/EphemeralDataPlugin.test.d.ts +0 -1
- package/dist/plugins/query/Query.test.d.ts +0 -1
- package/dist/plugins/query/QueryOptionsCollection.test.d.ts +0 -1
- package/dist/plugins/translators/JsonTranslator.test.d.ts +0 -1
- package/dist/plugins/translators/SqlTranslator.test.d.ts +0 -1
- package/dist/plugins/translators/TranslatedValues.test.d.ts +0 -1
- package/dist/results/Result.test.d.ts +0 -1
- package/dist/results/utils.test.d.ts +0 -1
- package/dist/schema/PropertyInfo.test.d.ts +0 -1
- package/dist/schema/communication/broadcast.test.d.ts +0 -1
- package/dist/schema/schemaGeneration.test.d.ts +0 -1
- package/dist/schema/utils/standardJsonSchema.test.d.ts +0 -1
- package/dist/utilities/arrays.test.d.ts +0 -1
- package/dist/utilities/dates.test.d.ts +0 -1
- package/dist/utilities/runtime.test.d.ts +0 -1
- package/dist/utilities/strings.test.d.ts +0 -1
- package/dist/utilities/uuid.test.d.ts +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DefaultValue, ForeignKey, FunctionBody, PropertyDeserializer, PropertySerializer, SchemaModifiers, SchemaTypes } from "../../types";
|
|
1
|
+
import { DefaultValue, ForeignKey, FunctionBody, PropertyDeserializer, PropertySerializer, SchemaModifiers, SchemaTypes, PropertyTransform } from "../../types";
|
|
2
2
|
export declare abstract class SchemaBase<T extends any, TModifiers extends SchemaModifiers> {
|
|
3
3
|
abstract instance: T;
|
|
4
4
|
modifiers: TModifiers;
|
|
@@ -8,9 +8,55 @@ export declare abstract class SchemaBase<T extends any, TModifiers extends Schem
|
|
|
8
8
|
isKey: boolean;
|
|
9
9
|
isIdentity: boolean;
|
|
10
10
|
isReadonly: boolean;
|
|
11
|
-
|
|
11
|
+
isDistinct: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Set by `.modify(x => x.transform(...))`. A live reference, never stringified.
|
|
14
|
+
* `null` when the property is stored as it is.
|
|
15
|
+
*/
|
|
16
|
+
transform: PropertyTransform<unknown> | null;
|
|
12
17
|
indexes: string[];
|
|
13
18
|
fromPropertyName: string | null;
|
|
19
|
+
/**
|
|
20
|
+
* How many numbers a vector holds. `null` for every other type.
|
|
21
|
+
*
|
|
22
|
+
* Declared here rather than on `SchemaVector` because a modifier WRAPS rather than
|
|
23
|
+
* extends: `s.vector(1536).optional()` is a `SchemaOptional`, and anything reachable only
|
|
24
|
+
* through the original class is lost the moment a modifier is added. `type` survives for
|
|
25
|
+
* exactly this reason — the copy constructor below carries it — and a dimension count has
|
|
26
|
+
* to travel with it, or an optional vector reaches a backend as a vector of unknown width
|
|
27
|
+
* and cannot be given a column.
|
|
28
|
+
*
|
|
29
|
+
* `innerSchema` is the cautionary example: it lives on `SchemaArray` alone, so a modified
|
|
30
|
+
* array arrives with no element type and clones through the slow path.
|
|
31
|
+
*/
|
|
32
|
+
dimensions: number | null;
|
|
33
|
+
/**
|
|
34
|
+
* The longest string the property is declared to hold. `null` for every other type, and
|
|
35
|
+
* for a string that declares nothing.
|
|
36
|
+
*
|
|
37
|
+
* Declared here rather than on `SchemaString` for the same reason as `dimensions` above:
|
|
38
|
+
* `s.string({ maxLength: 4000 }).optional()` is a `SchemaOptional`, so anything reachable
|
|
39
|
+
* only through `SchemaString` is lost the moment a modifier is added.
|
|
40
|
+
*
|
|
41
|
+
* A declaration, never a validation. Core does not check a value against it and does not
|
|
42
|
+
* truncate. The backend that can use the number does: MySQL gives the column
|
|
43
|
+
* `VARCHAR(maxLength)` instead of the blanket `VARCHAR(255)`. Every other backend ignores
|
|
44
|
+
* it, because a string column that is already unbounded cannot be made more correct by
|
|
45
|
+
* knowing a bound.
|
|
46
|
+
*/
|
|
47
|
+
maxLength: number | null;
|
|
48
|
+
/**
|
|
49
|
+
* Whether this string may be tokenised into a full-text search index.
|
|
50
|
+
*
|
|
51
|
+
* Set by `.searchable()`, and only ever true on a string. Eligibility, not membership: a
|
|
52
|
+
* collection that never declares `.searchIndex()` indexes nothing regardless.
|
|
53
|
+
*
|
|
54
|
+
* Copied by the constructor below, so `s.string().searchable().optional()` stays searchable.
|
|
55
|
+
* Every flag on this class is copied for the same reason: a modifier WRAPS rather than
|
|
56
|
+
* extends, so anything the constructor forgets is silently dropped the moment a property
|
|
57
|
+
* gains one more modifier.
|
|
58
|
+
*/
|
|
59
|
+
isSearchable: boolean;
|
|
14
60
|
foreignKeyDefinition: ForeignKey<unknown> | null;
|
|
15
61
|
tags: string[];
|
|
16
62
|
injected: any;
|
|
@@ -3,11 +3,21 @@ import { SchemaBase } from "../base/SchemaBase";
|
|
|
3
3
|
import { SchemaDefault } from "./SchemaDefault";
|
|
4
4
|
import { SchemaDeserialize } from "./SchemaDeserialize";
|
|
5
5
|
import { SchemaOptional } from "./SchemaOptional";
|
|
6
|
+
import { SchemaSearchable } from "./SchemaSearchable";
|
|
6
7
|
export declare class SchemaNullable<T extends any, TModifiers extends SchemaModifiers> extends SchemaBase<T, TModifiers> {
|
|
7
8
|
instance: T;
|
|
8
9
|
private _schemaNullable;
|
|
9
10
|
constructor(current: SchemaBase<T, TModifiers>);
|
|
10
11
|
optional(): SchemaOptional<T, "optional" | TModifiers>;
|
|
12
|
+
/**
|
|
13
|
+
* Only callable when the property underneath is a string — see the same method on
|
|
14
|
+
* `SchemaOptional` for why the constraint is on `instance` rather than the whole class.
|
|
15
|
+
*
|
|
16
|
+
* A null value contributes no tokens.
|
|
17
|
+
*/
|
|
18
|
+
searchable(this: {
|
|
19
|
+
instance: string;
|
|
20
|
+
}): SchemaSearchable<T, "searchable" | TModifiers>;
|
|
11
21
|
default<I = never>(value: DefaultValue<T | null, I>, injected?: I): SchemaDefault<T, I, "default" | TModifiers>;
|
|
12
22
|
deserialize(deserializer: PropertyDeserializer<T | null>): SchemaDeserialize<T, "deserialize" | TModifiers>;
|
|
13
23
|
}
|
|
@@ -2,10 +2,29 @@ import { PropertyDeserializer, SchemaModifiers } from "../../types";
|
|
|
2
2
|
import { SchemaBase } from "../base/SchemaBase";
|
|
3
3
|
import { SchemaDeserialize } from "./SchemaDeserialize";
|
|
4
4
|
import { SchemaNullable } from "./SchemaNullable";
|
|
5
|
+
import { SchemaSearchable } from "./SchemaSearchable";
|
|
5
6
|
export declare class SchemaOptional<T extends any, TModifiers extends SchemaModifiers> extends SchemaBase<T, TModifiers> {
|
|
6
7
|
instance: T;
|
|
7
8
|
private _schemaOptional;
|
|
8
9
|
constructor(current: SchemaBase<T, TModifiers>);
|
|
9
10
|
nullable(): SchemaNullable<T, "nullable" | TModifiers>;
|
|
11
|
+
/**
|
|
12
|
+
* Only callable when the property underneath is a string.
|
|
13
|
+
*
|
|
14
|
+
* A wrapper does not know what it wraps at runtime, but the type does: `T` is the value
|
|
15
|
+
* type, so `s.number().optional()` is a `SchemaOptional<number>` and fails this `this`
|
|
16
|
+
* constraint. That is the gate — there is no runtime check, because a builder that offers
|
|
17
|
+
* a method it will then reject has already failed at its job.
|
|
18
|
+
*
|
|
19
|
+
* Constrained on `instance` alone rather than the whole class. `SchemaBase` holds `T` in
|
|
20
|
+
* contravariant positions too (`valueSerializer`, `defaultValue`), so requiring the full
|
|
21
|
+
* `SchemaOptional<string, ...>` would reject a literal union like
|
|
22
|
+
* `s.string("draft", "published")`, which is a perfectly good searchable string.
|
|
23
|
+
*
|
|
24
|
+
* An absent value contributes no tokens.
|
|
25
|
+
*/
|
|
26
|
+
searchable(this: {
|
|
27
|
+
instance: string;
|
|
28
|
+
}): SchemaSearchable<T, "searchable" | TModifiers>;
|
|
10
29
|
deserialize(deserializer: PropertyDeserializer<T | undefined>): SchemaDeserialize<T, "deserialize" | TModifiers>;
|
|
11
30
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SchemaModifiers } from "../../types";
|
|
2
|
+
import { SchemaBase } from "../base/SchemaBase";
|
|
3
|
+
import { SchemaNullable } from "./SchemaNullable";
|
|
4
|
+
import { SchemaOptional } from "./SchemaOptional";
|
|
5
|
+
/**
|
|
6
|
+
* Marks a string property as eligible for a full-text search index.
|
|
7
|
+
*
|
|
8
|
+
* Eligible, not indexed. The schema says what COULD be indexed; the collection builder's
|
|
9
|
+
* `.searchIndex()` says that it IS. A property marked here on a collection that never declares
|
|
10
|
+
* an index costs nothing at all — no rows, no write amplification, no storage.
|
|
11
|
+
*
|
|
12
|
+
* Like `s.vector()`, this exists to be RECOGNISED rather than to behave. It changes nothing
|
|
13
|
+
* about how the property is stored, cloned, compared, serialized or queried. The datastore
|
|
14
|
+
* reads the flag off the compiled schema to decide which values to tokenise; every plugin is
|
|
15
|
+
* unaware the property is any different from another string.
|
|
16
|
+
*
|
|
17
|
+
* Declared on `SchemaString` only, so `s.number().searchable()` is a compile error rather than
|
|
18
|
+
* a runtime surprise. The one case the type system cannot catch — a searchable string nested
|
|
19
|
+
* inside an `s.object()` — is rejected when the schema compiles: v1 indexes root-level string
|
|
20
|
+
* properties only.
|
|
21
|
+
*/
|
|
22
|
+
export declare class SchemaSearchable<T extends any, TModifiers extends SchemaModifiers> extends SchemaBase<T, TModifiers> {
|
|
23
|
+
instance: T;
|
|
24
|
+
private _schemaSearchable;
|
|
25
|
+
constructor(current: SchemaBase<T, TModifiers>);
|
|
26
|
+
/**
|
|
27
|
+
* Declared here so `.searchable()` composes in BOTH senses — `.searchable().optional()` and
|
|
28
|
+
* `.optional().searchable()` mean the same thing and both keep the flag. `SchemaDistinct`
|
|
29
|
+
* exposes neither, which is why `.distinct().optional()` is unwritable and its copy-loss
|
|
30
|
+
* (see `SchemaBase.isSearchable`) has never been noticed.
|
|
31
|
+
*/
|
|
32
|
+
optional(): SchemaOptional<T, "optional" | TModifiers>;
|
|
33
|
+
nullable(): SchemaNullable<T, "nullable" | TModifiers>;
|
|
34
|
+
}
|
|
@@ -7,6 +7,7 @@ export * from './SchemaKey';
|
|
|
7
7
|
export * from './SchemaNullable';
|
|
8
8
|
export * from './SchemaOptional';
|
|
9
9
|
export * from './SchemaReadonly';
|
|
10
|
+
export * from './SchemaSearchable';
|
|
10
11
|
export * from './SchemaSerialize';
|
|
11
12
|
export * from './SchemaTracked';
|
|
12
13
|
export * from './SchemaFrom';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { DefaultValue, SchemaModifiers, SchemaTypes } from "../../types";
|
|
2
|
+
import { SchemaBase } from "../base/SchemaBase";
|
|
3
|
+
import { SchemaDefault } from "../modifiers/SchemaDefault";
|
|
4
|
+
import { SchemaFrom } from "../modifiers/SchemaFrom";
|
|
5
|
+
import { SchemaNullable } from "../modifiers/SchemaNullable";
|
|
6
|
+
import { SchemaOptional } from "../modifiers/SchemaOptional";
|
|
7
|
+
import { SchemaReadonly } from "../modifiers/SchemaReadonly";
|
|
8
|
+
import { SchemaTag } from "../modifiers/SchemaTag";
|
|
9
|
+
/**
|
|
10
|
+
* A file: content on the way in, a reference on the way out.
|
|
11
|
+
*
|
|
12
|
+
* This is the one property type whose write shape differs from its stored shape. You assign
|
|
13
|
+
* a `File`, a `Blob`, a `Uint8Array` or a string; what is stored, and what a query gives
|
|
14
|
+
* back, is a reference — where the bytes live and what they are.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* const documentSchema = s.define('documents', {
|
|
18
|
+
* id: s.string().key().identity(),
|
|
19
|
+
* title: s.string(),
|
|
20
|
+
* file: s.file(),
|
|
21
|
+
* }).compile();
|
|
22
|
+
*
|
|
23
|
+
* await store.documents.addAsync({ title: 'Q3', file: fileFromInput });
|
|
24
|
+
* await store.saveChangesAsync();
|
|
25
|
+
*
|
|
26
|
+
* doc.file.size // 2_400_112
|
|
27
|
+
* doc.file.contentType // 'application/pdf'
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* ## Why this cannot be `s.object({ key, size, ... })`
|
|
31
|
+
*
|
|
32
|
+
* The generated `preprocess` rebuilds an object property field by field from its declared
|
|
33
|
+
* children — `result.file = {}` and then one assignment per child. Content assigned there is
|
|
34
|
+
* therefore discarded by construction, before any plugin sees the entity: the property does
|
|
35
|
+
* not arrive mangled, it does not arrive at all.
|
|
36
|
+
*
|
|
37
|
+
* A file is a LEAF here, with no child properties, so the generated code passes it through
|
|
38
|
+
* untouched. The bytes survive as far as the plugin, which is the only place an upload can
|
|
39
|
+
* happen — `preprocess` is synchronous and is called from the change tracker and the
|
|
40
|
+
* broadcast path, so it cannot await one.
|
|
41
|
+
*
|
|
42
|
+
* ## What actually stores it
|
|
43
|
+
*
|
|
44
|
+
* Nothing in core uploads anything. `@routier/blob-plugin` wraps your real plugin, swaps
|
|
45
|
+
* pending content for a reference during `bulkPersist`, and hands the reference down. Without
|
|
46
|
+
* that wrapper a file property stores whatever you assigned, which is a mistake this type
|
|
47
|
+
* cannot detect on its own.
|
|
48
|
+
*/
|
|
49
|
+
export declare class SchemaFile<T extends any, TModifiers extends SchemaModifiers> extends SchemaBase<T, TModifiers> {
|
|
50
|
+
instance: T;
|
|
51
|
+
type: SchemaTypes;
|
|
52
|
+
private _schemaFile;
|
|
53
|
+
constructor();
|
|
54
|
+
from(propertyName: string): SchemaFrom<T, TModifiers>;
|
|
55
|
+
optional(): SchemaOptional<T, "optional" | TModifiers>;
|
|
56
|
+
nullable(): SchemaNullable<T, "nullable" | TModifiers>;
|
|
57
|
+
readonly(): SchemaReadonly<T, "readonly" | TModifiers>;
|
|
58
|
+
default<I = never>(value: DefaultValue<T, I>, injected?: I): SchemaDefault<T, I, "default" | TModifiers>;
|
|
59
|
+
tag(...tags: string[]): SchemaTag<T, TModifiers>;
|
|
60
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CompiledSchema, DefaultValue, InferType, PropertyDeserializer, PropertySerializer, SchemaModifiers, SchemaTypes } from "../../types";
|
|
1
|
+
import { CompiledSchema, DefaultValue, InferType, PropertyDeserializer, PropertySerializer, SchemaModifiers, SchemaTypes, StringOptions } from "../../types";
|
|
2
2
|
import { SchemaBase } from "../base/SchemaBase";
|
|
3
3
|
import { SchemaDefault } from "../modifiers/SchemaDefault";
|
|
4
4
|
import { SchemaDeserialize } from "../modifiers/SchemaDeserialize";
|
|
@@ -11,6 +11,7 @@ import { SchemaKey } from "../modifiers/SchemaKey";
|
|
|
11
11
|
import { SchemaNullable } from "../modifiers/SchemaNullable";
|
|
12
12
|
import { SchemaOptional } from "../modifiers/SchemaOptional";
|
|
13
13
|
import { SchemaReadonly } from "../modifiers/SchemaReadonly";
|
|
14
|
+
import { SchemaSearchable } from "../modifiers/SchemaSearchable";
|
|
14
15
|
import { SchemaSerialize } from "../modifiers/SchemaSerialize";
|
|
15
16
|
import { SchemaTag } from "../modifiers/SchemaTag";
|
|
16
17
|
import { SchemaArray } from "./SchemaArray";
|
|
@@ -18,6 +19,12 @@ export declare class SchemaString<T extends string, TModifiers extends SchemaMod
|
|
|
18
19
|
instance: T;
|
|
19
20
|
type: SchemaTypes;
|
|
20
21
|
private _schemaString;
|
|
22
|
+
/**
|
|
23
|
+
* @param entity Copied from when a modifier wraps this property.
|
|
24
|
+
* @param literals The allowed values, when the string is a literal union.
|
|
25
|
+
* @param options Declarations a backend may use. See `StringOptions`.
|
|
26
|
+
*/
|
|
27
|
+
constructor(entity?: SchemaBase<T, TModifiers> | null, literals?: T[], options?: StringOptions);
|
|
21
28
|
from(propertyName: string): SchemaFrom<T, TModifiers>;
|
|
22
29
|
constrain<K extends T>(): SchemaString<K, TModifiers>;
|
|
23
30
|
optional(): SchemaOptional<T, "optional" | TModifiers>;
|
|
@@ -32,5 +39,18 @@ export declare class SchemaString<T extends string, TModifiers extends SchemaMod
|
|
|
32
39
|
array(): SchemaArray<this, TModifiers>;
|
|
33
40
|
index(...indexes: string[]): SchemaIndex<T, TModifiers>;
|
|
34
41
|
distinct(): SchemaDistinct<T, "distinct" | TModifiers>;
|
|
42
|
+
/**
|
|
43
|
+
* Marks this string as eligible for the collection's full-text search index.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* title: s.string().searchable(),
|
|
47
|
+
* body: s.string({ maxLength: 4000 }).searchable(),
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* Nothing is indexed until the collection declares `.searchIndex()`. Combines with
|
|
51
|
+
* `.optional()` and `.nullable()` in either sense — an absent or null value contributes no
|
|
52
|
+
* tokens.
|
|
53
|
+
*/
|
|
54
|
+
searchable(): SchemaSearchable<T, "searchable" | TModifiers>;
|
|
35
55
|
tag(...tags: string[]): SchemaTag<T, TModifiers>;
|
|
36
56
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DefaultValue, SchemaModifiers, SchemaTypes } from "../../types";
|
|
2
|
+
import { SchemaBase } from "../base/SchemaBase";
|
|
3
|
+
import { SchemaDefault } from "../modifiers/SchemaDefault";
|
|
4
|
+
import { SchemaFrom } from "../modifiers/SchemaFrom";
|
|
5
|
+
import { SchemaNullable } from "../modifiers/SchemaNullable";
|
|
6
|
+
import { SchemaOptional } from "../modifiers/SchemaOptional";
|
|
7
|
+
import { SchemaReadonly } from "../modifiers/SchemaReadonly";
|
|
8
|
+
import { SchemaTag } from "../modifiers/SchemaTag";
|
|
9
|
+
/**
|
|
10
|
+
* An embedding: a fixed-length list of numbers you can search by similarity.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const documentSchema = s.define('documents', {
|
|
14
|
+
* id: s.string().key().identity(),
|
|
15
|
+
* title: s.string(),
|
|
16
|
+
* embedding: s.vector(1536),
|
|
17
|
+
* }).compile();
|
|
18
|
+
*
|
|
19
|
+
* const similar = await store.documents
|
|
20
|
+
* .nearest(x => x.embedding, queryEmbedding, 10)
|
|
21
|
+
* .toArrayAsync();
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ## Why this is not `s.array(s.number())`
|
|
25
|
+
*
|
|
26
|
+
* By value it is exactly that, and every codegen handler treats the two the same on purpose —
|
|
27
|
+
* a vector clones with a spread, compares by JSON and freezes like any other array. What an
|
|
28
|
+
* array cannot carry is the DIMENSION COUNT, and a backend that stores vectors natively needs
|
|
29
|
+
* it at DDL time: pgvector's column type is `vector(1536)`, not `vector`.
|
|
30
|
+
*
|
|
31
|
+
* So this exists to be RECOGNISED, not to behave differently. A backend that knows what a
|
|
32
|
+
* vector is stores one; every other backend sees a list of numbers and stores JSON, which is
|
|
33
|
+
* why the feature works everywhere rather than only on PostgreSQL.
|
|
34
|
+
*
|
|
35
|
+
* ## Dimensions are not enforced here
|
|
36
|
+
*
|
|
37
|
+
* `dimensions` is a declaration, and core never checks a value against it. The check belongs
|
|
38
|
+
* where the cost of being wrong is paid: a backend with a native `vector(n)` column rejects a
|
|
39
|
+
* mismatched write itself, with an error naming the column. Validating in core would duplicate
|
|
40
|
+
* that on the backends that already do it and add a per-save array scan to the ones that
|
|
41
|
+
* cannot use the information at all.
|
|
42
|
+
*
|
|
43
|
+
* ## Similarity is cosine, and it is not a filter
|
|
44
|
+
*
|
|
45
|
+
* `.nearest()` is an ordering plus a limit — it returns the closest rows, not the matching
|
|
46
|
+
* ones. Distance itself is not exposed: the entity shape is fixed, and the ordering is what
|
|
47
|
+
* callers act on. A backend with no vector support scores in memory, so the answer is the
|
|
48
|
+
* same everywhere; only the amount of data read differs.
|
|
49
|
+
*/
|
|
50
|
+
export declare class SchemaVector<T extends any, TModifiers extends SchemaModifiers> extends SchemaBase<T, TModifiers> {
|
|
51
|
+
instance: T;
|
|
52
|
+
type: SchemaTypes;
|
|
53
|
+
private _schemaVector;
|
|
54
|
+
constructor(dimensions: number);
|
|
55
|
+
from(propertyName: string): SchemaFrom<T, TModifiers>;
|
|
56
|
+
optional(): SchemaOptional<T, "optional" | TModifiers>;
|
|
57
|
+
nullable(): SchemaNullable<T, "nullable" | TModifiers>;
|
|
58
|
+
readonly(): SchemaReadonly<T, "readonly" | TModifiers>;
|
|
59
|
+
default<I = never>(value: DefaultValue<T, I>, injected?: I): SchemaDefault<T, I, "default" | TModifiers>;
|
|
60
|
+
tag(...tags: string[]): SchemaTag<T, TModifiers>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { SchemaBase } from "../property/base/SchemaBase";
|
|
2
|
+
import { PropertyTransform, SchemaModifiers } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* A two-way transform between the value your application holds and the value that is stored.
|
|
5
|
+
*
|
|
6
|
+
* Declared in `.modify()`, beside `computed` and `function`, because it belongs to the same
|
|
7
|
+
* family: a property whose stored form is derived rather than assigned. `computed` derives one
|
|
8
|
+
* way and cannot come back; a transform declares both directions.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const cipher = myEncryption(keyring); // whatever you use — {} with `to` and `from`
|
|
12
|
+
*
|
|
13
|
+
* const userSchema = s.define('users', {
|
|
14
|
+
* id: s.string().key().identity(),
|
|
15
|
+
* ssn: s.string(),
|
|
16
|
+
* }).modify(x => ({
|
|
17
|
+
* ssn: x.transform(cipher),
|
|
18
|
+
* })).compile();
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* `to` and `from` may be async, and they are held as LIVE references — never stringified into
|
|
22
|
+
* generated code the way `computed` is. So they close over whatever they need, which is why
|
|
23
|
+
* there is no `injected` argument to pass and no property to repeat.
|
|
24
|
+
*
|
|
25
|
+
* Nothing about this is encryption. Encryption is one thing a caller might write here;
|
|
26
|
+
* compression, redaction, unit conversion and a custom codec are others. The library ships no
|
|
27
|
+
* behaviour of its own for this — it only carries what you supply.
|
|
28
|
+
*/
|
|
29
|
+
export declare class SchemaTransform<T extends any, TModifiers extends SchemaModifiers = never> extends SchemaBase<T, TModifiers> {
|
|
30
|
+
instance: T;
|
|
31
|
+
private _schemaTransform;
|
|
32
|
+
/**
|
|
33
|
+
* Bound to the property it replaces when the schema is assembled.
|
|
34
|
+
*
|
|
35
|
+
* You do not pass the property in. `.modify()` already knows which one you mean — it is
|
|
36
|
+
* the key you assigned to — so repeating `s.string()` would be ceremony for nothing.
|
|
37
|
+
*/
|
|
38
|
+
bindTo(underlying: SchemaBase<T, TModifiers>): this;
|
|
39
|
+
constructor(transform: PropertyTransform<T>);
|
|
40
|
+
}
|
package/dist/schema/types.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { SchemaDefinition } from "./SchemaDefinition";
|
|
2
2
|
import type { SchemaBase } from "./property/base/SchemaBase";
|
|
3
3
|
import type { SchemaArray } from "./property/types/SchemaArray";
|
|
4
|
+
import type { SchemaVector } from "./property/types/SchemaVector";
|
|
4
5
|
import type { SchemaObject } from "./property/types/SchemaObject";
|
|
5
6
|
import type { PropertyInfo } from "./PropertyInfo";
|
|
6
7
|
import type { DeepPartial } from "../types";
|
|
7
8
|
import type { SchemaFunction } from "./table";
|
|
8
|
-
import type { SchemaOptional } from "./property/modifiers";
|
|
9
|
+
import type { SchemaOptional, SchemaTag } from "./property/modifiers";
|
|
9
10
|
import type { Branded } from "../utilities/types";
|
|
11
|
+
import type { SchemaSubscriptionOptions } from "./communication/broadcast";
|
|
10
12
|
export type DefaultValue<T, I = never> = T | ((injected: I) => T);
|
|
11
13
|
export type FunctionBody<TEntity, TResult> = (entity: TEntity, collectionName: CollectionName) => TResult;
|
|
12
14
|
export type IdType = string | number;
|
|
@@ -23,9 +25,70 @@ export declare enum SchemaTypes {
|
|
|
23
25
|
String = "String",
|
|
24
26
|
Definition = "Definition",
|
|
25
27
|
Function = "Function",
|
|
26
|
-
Computed = "Computed"
|
|
28
|
+
Computed = "Computed",
|
|
29
|
+
/**
|
|
30
|
+
* Content in, reference out. The only type whose write shape differs from its stored
|
|
31
|
+
* shape, and a leaf on purpose — see `SchemaFile`.
|
|
32
|
+
*/
|
|
33
|
+
File = "File",
|
|
34
|
+
/**
|
|
35
|
+
* A fixed-length list of numbers, carrying its dimension count — see `SchemaVector`.
|
|
36
|
+
*
|
|
37
|
+
* Value-shaped exactly like `s.array(s.number())`, which is why every array codegen
|
|
38
|
+
* handler accepts it. It is a distinct type only so a backend can recognise it and store
|
|
39
|
+
* it natively; nothing else needs to tell the two apart.
|
|
40
|
+
*/
|
|
41
|
+
Vector = "Vector"
|
|
27
42
|
}
|
|
28
43
|
export type ArrayShape = string | number | Date | {};
|
|
44
|
+
/**
|
|
45
|
+
* What a file property gives back: where the bytes are and what they are.
|
|
46
|
+
*
|
|
47
|
+
* Declared in core so `InferType` can name it. Core never reads or writes the bytes — it only
|
|
48
|
+
* carries this shape — and `@routier/blob-plugin` is what puts one here.
|
|
49
|
+
*/
|
|
50
|
+
export type FileReferenceValue = {
|
|
51
|
+
/** Where the bytes live, content-addressed by the blob plugin. */
|
|
52
|
+
key: string;
|
|
53
|
+
/** Byte length. */
|
|
54
|
+
size: number;
|
|
55
|
+
/** Media type as supplied at upload. */
|
|
56
|
+
contentType: string;
|
|
57
|
+
/** SHA-256 of the bytes, lowercase hex. */
|
|
58
|
+
checksum: string;
|
|
59
|
+
/** The name to show a user. Not part of the key. */
|
|
60
|
+
fileName: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* What a file property ACCEPTS: content, or a reference you already have.
|
|
64
|
+
*
|
|
65
|
+
* `Blob` covers `File`, which is what an `<input type="file">` yields. A reference is accepted
|
|
66
|
+
* too, so re-saving an entity that was read from the database does not have to re-upload it.
|
|
67
|
+
*/
|
|
68
|
+
export type FileContentValue = FileReferenceValue | Uint8Array | ArrayBuffer | Blob | string;
|
|
69
|
+
/**
|
|
70
|
+
* What a vector property holds, in and out: a plain list of numbers.
|
|
71
|
+
*
|
|
72
|
+
* Named rather than written inline because the inference rules have to recognise it after a
|
|
73
|
+
* modifier has erased which class produced it — the same problem `FileReferenceValue` solves
|
|
74
|
+
* above, and for the same reason.
|
|
75
|
+
*/
|
|
76
|
+
export type VectorValue = number[];
|
|
77
|
+
/**
|
|
78
|
+
* What `s.string({ ... })` accepts.
|
|
79
|
+
*
|
|
80
|
+
* Declarations only. Core stores them and never acts on them; a backend that can use one does.
|
|
81
|
+
*/
|
|
82
|
+
export type StringOptions = {
|
|
83
|
+
/**
|
|
84
|
+
* The longest value the property is declared to hold.
|
|
85
|
+
*
|
|
86
|
+
* MySQL uses it for `VARCHAR(maxLength)`; without it every string column is
|
|
87
|
+
* `VARCHAR(255)`, which silently truncates longer values. Other backends ignore it. Core
|
|
88
|
+
* never validates a value against it — see `SchemaBase.maxLength`.
|
|
89
|
+
*/
|
|
90
|
+
maxLength?: number;
|
|
91
|
+
};
|
|
29
92
|
export type ExpandedProperty = ExpandedChildProperty & {
|
|
30
93
|
assignmentPath: string;
|
|
31
94
|
selectorPath: string;
|
|
@@ -99,7 +162,7 @@ export type Preprocess<TEntity extends {}> = {
|
|
|
99
162
|
(entity: InferCreateType<TEntity>): InferType<TEntity>;
|
|
100
163
|
(entity: InferType<TEntity>): InferType<TEntity>;
|
|
101
164
|
};
|
|
102
|
-
export type SetProperties<TEntity extends {}> = (destination: InferType<TEntity> | InferCreateType<TEntity
|
|
165
|
+
export type SetProperties<TEntity extends {}> = (destination: DeepPartial<InferType<TEntity> | InferCreateType<TEntity>>, source: DeepPartial<InferType<TEntity> | InferCreateType<TEntity>>) => void;
|
|
103
166
|
export type CompiledSchemaCore<TEntity extends {}> = Omit<CompiledSchema<TEntity>, "createSubscription">;
|
|
104
167
|
export type CompiledSchemaWithMetadata<TEntity extends {}, TMetadata> = {
|
|
105
168
|
readonly metadata: TMetadata;
|
|
@@ -109,13 +172,22 @@ export type CompiledSchemaWithMetadata<TEntity extends {}, TMetadata> = {
|
|
|
109
172
|
*/
|
|
110
173
|
export type CompiledSchema<TEntity extends {}> = {
|
|
111
174
|
deserializePartial: (item: Record<string, unknown>, properties: PropertyInfo<TEntity>[]) => DeepPartial<InferType<TEntity>>;
|
|
112
|
-
createSubscription: (abortSignal?: AbortSignal) => ISchemaSubscription<TEntity>;
|
|
175
|
+
createSubscription: (abortSignal?: AbortSignal, scope?: string, options?: SchemaSubscriptionOptions) => ISchemaSubscription<TEntity>;
|
|
113
176
|
/** Returns the property info for a given id (full path) */
|
|
114
177
|
getProperty: (id: string) => PropertyInfo<TEntity>;
|
|
115
178
|
/** Returns the ID of the given entity. */
|
|
116
179
|
getId: (entity: InferType<TEntity>) => IdType;
|
|
117
180
|
/** Returns a deep clone of the given entity. */
|
|
118
181
|
clone: (entity: InferType<TEntity>) => InferType<TEntity>;
|
|
182
|
+
/**
|
|
183
|
+
* Returns a deep clone of a record that is still in the STORAGE shape — renamed properties
|
|
184
|
+
* under their `from` names rather than their in-memory names.
|
|
185
|
+
*
|
|
186
|
+
* `clone` reads in-memory names, so it returns `undefined` for every renamed property of a
|
|
187
|
+
* stored record. Use this when copying rows a store holds before they have been deserialized.
|
|
188
|
+
* Generated on first call; schemas that are never cloned in storage shape never build it.
|
|
189
|
+
*/
|
|
190
|
+
cloneStorage: (entity: InferType<TEntity>) => InferType<TEntity>;
|
|
119
191
|
/** Removes unmapped or extraneous properties from the entity. */
|
|
120
192
|
strip: (entity: InferType<TEntity>) => InferType<TEntity>;
|
|
121
193
|
/** Prepares a new entity for creation, applying defaults and transformations. */
|
|
@@ -169,12 +241,79 @@ export type CompiledSchema<TEntity extends {}> = {
|
|
|
169
241
|
};
|
|
170
242
|
export type PropertySerializer<T extends any> = (value: T) => string | number;
|
|
171
243
|
export type PropertyDeserializer<T extends any> = (value: string | number) => T;
|
|
244
|
+
/**
|
|
245
|
+
* A two-way transform between the application value and the stored value.
|
|
246
|
+
*
|
|
247
|
+
* Both directions may be async. Held as a live reference rather than stringified, so a
|
|
248
|
+
* closure works and `injected` is a convenience rather than the only way in.
|
|
249
|
+
*/
|
|
250
|
+
export type PropertyTransform<T extends any> = {
|
|
251
|
+
/**
|
|
252
|
+
* Application value to stored value. Runs before the plugin sees it. May be async.
|
|
253
|
+
*
|
|
254
|
+
* `entity` is there for the one-way case: a transform with no `from` derives a value
|
|
255
|
+
* rather than converting one, which is what `computed` does.
|
|
256
|
+
*/
|
|
257
|
+
to: (value: T, entity: Record<string, unknown>) => unknown | Promise<unknown>;
|
|
258
|
+
/**
|
|
259
|
+
* Stored value back to application value. Runs after the plugin returns it.
|
|
260
|
+
*
|
|
261
|
+
* Optional. Leave it out and the transform is one-way: the stored value is the value.
|
|
262
|
+
*/
|
|
263
|
+
from?: (value: unknown) => T | Promise<T>;
|
|
264
|
+
/**
|
|
265
|
+
* What the column becomes, when the stored form is not the property's own type.
|
|
266
|
+
*
|
|
267
|
+
* Defaults to the property's own type, so nothing changes unless you say it does. A
|
|
268
|
+
* library that always produces text — a cipher, a compressor — sets this once, and the
|
|
269
|
+
* caller who uses that library never writes it.
|
|
270
|
+
*/
|
|
271
|
+
stores?: SchemaTypes;
|
|
272
|
+
/**
|
|
273
|
+
* Whether a filter on this property can still run in the database.
|
|
274
|
+
*
|
|
275
|
+
* Defaults to `none`, which rejects the filter rather than returning wrong rows. Set
|
|
276
|
+
* `equality` only when `to` is deterministic.
|
|
277
|
+
*/
|
|
278
|
+
comparable?: 'equality' | 'none';
|
|
279
|
+
};
|
|
172
280
|
export type SchemaId = Branded<number, "SchemaId">;
|
|
173
281
|
export type CollectionName = Branded<string, "CollectionName">;
|
|
174
|
-
export type SchemaModifiers = "default" | "deserialize" | "identity" | "key" | "nullable" | "optional" | "readonly" | "serialize" | "unmapped" | "computed" | "distinct";
|
|
175
|
-
|
|
282
|
+
export type SchemaModifiers = "default" | "deserialize" | "identity" | "key" | "nullable" | "optional" | "readonly" | "serialize" | "unmapped" | "computed" | "distinct" | "searchable";
|
|
283
|
+
/**
|
|
284
|
+
* What a tagged property infers to.
|
|
285
|
+
*
|
|
286
|
+
* `tag()` is metadata and must not change a type, but `SchemaTag<T>` carries the same `T` as
|
|
287
|
+
* whatever it wrapped without carrying which class that was. For a string `T` is already
|
|
288
|
+
* `string`; for an object `T` is the map of child schemas, which only the `SchemaObject`
|
|
289
|
+
* branch below knows how to unwrap. Falling through to the generic `SchemaBase` branch
|
|
290
|
+
* therefore handed the raw map back, so `s.object({ key: s.string() }).tag('x')` typed
|
|
291
|
+
* `key` as `SchemaString` instead of `string` — everything ran, and only the types lied.
|
|
292
|
+
*
|
|
293
|
+
* An array is distinguishable because `SchemaArray`'s parameter is the ELEMENT schema, so a
|
|
294
|
+
* tagged array arrives here as a `SchemaBase` rather than a plain map.
|
|
295
|
+
*/
|
|
296
|
+
type InferTagged<C> = ResolveWrapped<C>;
|
|
297
|
+
/**
|
|
298
|
+
* What a wrapping modifier's inner type resolves to.
|
|
299
|
+
*
|
|
300
|
+
* `SchemaOptional`, `SchemaNullable` and `SchemaTag` all carry the same `C` as whatever they
|
|
301
|
+
* wrapped, without carrying which class that was, so each has to work out what it is holding.
|
|
302
|
+
* Three shapes are possible:
|
|
303
|
+
*
|
|
304
|
+
* - an already-resolved value (`string` from `s.string()`, a file reference from `s.file()`)
|
|
305
|
+
* - an ELEMENT schema, which is what `SchemaArray` parameterises on
|
|
306
|
+
* - a map of child schemas, which is what `SchemaObject` parameterises on
|
|
307
|
+
*
|
|
308
|
+
* Getting this wrong is silent. The map branch applied to an already-resolved object walks
|
|
309
|
+
* its keys and infers `never` for each, so `s.file().optional()` typed as
|
|
310
|
+
* `{ key: never, size: never, ... }` — which no value can satisfy and no test would catch at
|
|
311
|
+
* runtime.
|
|
312
|
+
*/
|
|
313
|
+
type ResolveWrapped<C> = C extends string | number | boolean | Date | FileReferenceValue ? C : C extends VectorValue ? C : C extends SchemaBase<any, any> ? InferPrimitive<C>[] : {
|
|
176
314
|
[K in keyof C]: InferPrimitive<C[K]>;
|
|
177
|
-
}
|
|
315
|
+
};
|
|
316
|
+
type InferPrimitive<T> = T extends SchemaOptional<infer C, infer __> ? ResolveWrapped<C> : T extends SchemaTag<infer C, infer __> ? InferTagged<C> : T extends SchemaVector<infer __, infer ___> ? VectorValue : T extends SchemaArray<infer Y, infer __> ? InferPrimitive<Y>[] : T extends SchemaObject<infer Obj, infer _> ? {
|
|
178
317
|
[K in keyof Obj]: InferPrimitive<Obj[K]>;
|
|
179
318
|
} : T extends SchemaFunction<infer F, infer __> ? F : T extends SchemaBase<infer X, infer _> ? X extends Array<infer A> ? InferPrimitive<A>[] : X : never;
|
|
180
319
|
export type InferType<T> = T extends CompiledSchema<infer R> ? InferCompiledSchema<R> : T extends {} ? InferCompiledSchema<T> : T;
|
|
@@ -208,7 +347,26 @@ type IsCreateOptional<T, K extends keyof T> = [
|
|
|
208
347
|
false
|
|
209
348
|
] ? false : true;
|
|
210
349
|
type IsCreateNullable<T, K extends keyof T> = HasModifier<T, K, "nullable"> extends true ? true : false;
|
|
211
|
-
|
|
350
|
+
/**
|
|
351
|
+
* What a property ACCEPTS on the way in, which is not always what it gives back.
|
|
352
|
+
*
|
|
353
|
+
* Only a file differs today: you assign content and read a reference. Matching on the read
|
|
354
|
+
* type rather than on `SchemaFile` itself is deliberate — it keeps working through every
|
|
355
|
+
* modifier. `s.file().optional()` is a `SchemaOptional`, `s.file().tag('x')` is a
|
|
356
|
+
* `SchemaTag`, and neither carries the original class, so a check against the class alone
|
|
357
|
+
* would silently stop accepting content the moment anyone added a modifier.
|
|
358
|
+
*
|
|
359
|
+
* Assignability is required in BOTH directions, and the tuple wrappers are load-bearing.
|
|
360
|
+
* One-way `extends` matches `never` — which is assignable to everything — so a generic
|
|
361
|
+
* property over `Record<string, unknown>` resolved to file content and broke the Dexie
|
|
362
|
+
* plugin's types. It also matched any object that merely happens to have these five fields
|
|
363
|
+
* plus more. Mutual assignability admits the reference shape and nothing else, and the
|
|
364
|
+
* tuples stop the conditional distributing over a union.
|
|
365
|
+
*/
|
|
366
|
+
type InferWritePrimitive<T> = [
|
|
367
|
+
InferPrimitive<T>
|
|
368
|
+
] extends [FileReferenceValue] ? [FileReferenceValue] extends [InferPrimitive<T>] ? FileContentValue : InferPrimitive<T> : InferPrimitive<T>;
|
|
369
|
+
type InferCreateProperty<T, K extends keyof T> = IsCreateNullable<T, K> extends true ? null | InferWritePrimitive<T[K]> : InferWritePrimitive<T[K]>;
|
|
212
370
|
type InferCompiledSchema<T> = CoalesceEmpty<{
|
|
213
371
|
[K in keyof T as IsPlainProperty<T, K> extends true ? K : never]: InferPrimitive<T[K]>;
|
|
214
372
|
}, {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SchemaTypes } from "../types";
|
|
2
|
+
/** True when the property's value is a JS array and needs value rather than reference semantics. */
|
|
3
|
+
export declare const isArrayValued: (type: SchemaTypes) => boolean;
|
|
4
|
+
export declare const hasPrimitiveElements: (type: SchemaTypes, elementType: SchemaTypes | undefined) => boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
"use strict";
|
|
3
|
+
// The require scope
|
|
4
|
+
var __webpack_require__ = {};
|
|
5
|
+
|
|
6
|
+
// webpack/runtime/make_namespace_object
|
|
7
|
+
(() => {
|
|
8
|
+
// define __esModule on exports
|
|
9
|
+
__webpack_require__.r = (exports) => {
|
|
10
|
+
if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
11
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
var __webpack_exports__ = {};
|
|
17
|
+
__webpack_require__.r(__webpack_exports__);
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
module.exports = __webpack_exports__;
|
|
21
|
+
})()
|
|
22
|
+
;
|
|
23
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types/index.cjs","sources":["webpack://@routier/core/webpack/runtime/make_namespace_object","webpack://@routier/core/./src/types/index.ts"],"sourcesContent":["// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export type DeepPartial<T> = T extends object ? {\n [P in keyof T]?: DeepPartial<T[P]>;\n} : T;\n\nexport type GenericFunction<T, R> = (value: T) => R;"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA,uDAAuD,iBAAiB;AACxE;AACA,gDAAgD,aAAa;AAC7D,E;;;;ACFoD"}
|