@afora/core 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -733
- package/dist/core/application/application.d.ts +9 -1
- package/dist/core/application/exceptions.d.ts +28 -0
- package/dist/core/application/registry.d.ts +33 -0
- package/dist/core/application/start.d.ts +75 -0
- package/dist/core/application/types/application.interface.d.ts +229 -7
- package/dist/core/blueprint/types/blueprint.interface.d.ts +66 -11
- package/dist/core/blueprint/types/slice.interface.d.ts +7 -2
- package/dist/core/command/command.d.ts +25 -0
- package/dist/core/command/exceptions.d.ts +33 -0
- package/dist/core/command/types/command.interface.d.ts +108 -0
- package/dist/core/entity/event.d.ts +12 -2
- package/dist/core/environment/environment.d.ts +4 -1
- package/dist/core/exception/exception.d.ts +4 -0
- package/dist/core/exception/exported.d.ts +4 -0
- package/dist/core/json.d.ts +10 -0
- package/dist/core/logger/exceptions.d.ts +4 -0
- package/dist/core/logger/logger.d.ts +106 -0
- package/dist/core/output/exceptions.d.ts +8 -0
- package/dist/core/output/openapi-sink.d.ts +83 -0
- package/dist/core/output/output.d.ts +19 -0
- package/dist/core/output/problem.d.ts +15 -0
- package/dist/core/output/select.d.ts +14 -0
- package/dist/core/output/stage.d.ts +24 -0
- package/dist/core/output/status.d.ts +17 -0
- package/dist/core/output/types/output.interface.d.ts +171 -0
- package/dist/core/property/abstract-property.d.ts +8 -7
- package/dist/core/property/define-property.d.ts +8 -7
- package/dist/core/property/property.d.ts +26 -15
- package/dist/core/property/types/abstract-property-constructor.type.d.ts +8 -7
- package/dist/core/property/types/define-property.interface.d.ts +5 -4
- package/dist/core/property/types/optional-property.type.d.ts +5 -5
- package/dist/core/property/types/property-collection.type.d.ts +2 -2
- package/dist/core/property/types/property-constructor.type.d.ts +5 -1
- package/dist/core/property/types/property-options.interface.d.ts +17 -8
- package/dist/core/property/types/property-type.interface.d.ts +7 -3
- package/dist/core/property/types/property.interface.d.ts +5 -4
- package/dist/core/record/abstract-record.d.ts +12 -4
- package/dist/core/record/types/plugin.interface.d.ts +13 -3
- package/dist/core/record/types/record.interface.d.ts +20 -8
- package/dist/core/repository/exceptions.d.ts +4 -0
- package/dist/core/repository/in-memory.d.ts +3 -0
- package/dist/core/repository/provider.d.ts +6 -0
- package/dist/core/repository/query.d.ts +9 -0
- package/dist/core/repository/references.d.ts +4 -2
- package/dist/core/repository/repository.d.ts +4 -2
- package/dist/core/repository/state.d.ts +4 -0
- package/dist/core/repository/types/query.interface.d.ts +67 -0
- package/dist/core/repository/types/repository.interface.d.ts +13 -13
- package/dist/core/schema/types/schema.interface.d.ts +11 -4
- package/dist/core/symbols/meta.d.ts +2 -0
- package/dist/core/use-case/exceptions.d.ts +10 -0
- package/dist/core/use-case/scope.d.ts +24 -0
- package/dist/core/use-case/steps/describe.d.ts +13 -0
- package/dist/core/use-case/steps/references.d.ts +27 -0
- package/dist/core/use-case/steps/run.d.ts +20 -0
- package/dist/core/use-case/steps/types/steps.interface.d.ts +153 -0
- package/dist/core/use-case/steps/validate.d.ts +17 -0
- package/dist/core/use-case/use-case.d.ts +79 -13
- package/dist/experimental.d.ts +6 -0
- package/dist/experimental.js +123 -0
- package/dist/index-ewm6r4nw.js +5335 -0
- package/dist/index-hn82hm31.js +1651 -0
- package/dist/index.d.ts +34 -12
- package/dist/index.js +343 -4142
- package/dist/std/blueprint-plugin.d.ts +10 -10
- package/dist/std/blueprint.d.ts +10 -10
- package/dist/std/entity.d.ts +2 -2
- package/dist/std/properties/contact.d.ts +4 -4
- package/dist/std/properties/enum.d.ts +1 -1
- package/dist/std/properties/headless.d.ts +1 -1
- package/dist/std/properties/identity.d.ts +2 -2
- package/dist/std/properties/password.d.ts +1 -1
- package/dist/std/properties/primitives.d.ts +5 -5
- package/dist/std/properties/time.d.ts +2 -2
- package/dist/std/record-plugins.d.ts +12 -12
- package/dist/std/record.d.ts +1 -1
- package/dist/std/stages.d.ts +2 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +502 -0
- package/dist/testing/provider-contract.d.ts +22 -0
- package/package.json +28 -8
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { AnyBlueprint, BlueprintInput, BlueprintValue, IBlueprint, IBlueprintCollection } from "../blueprint/types/blueprint.interface.js";
|
|
2
2
|
import type { EntityEvent } from "../entity/event.js";
|
|
3
3
|
import { type AnyEnvironment, type EnvironmentValue } from "../environment/environment.js";
|
|
4
|
+
import { type DeclaredExceptionClass } from "../exception/exception.js";
|
|
5
|
+
import { type ILogger, type LoggerDeclaration } from "../logger/logger.js";
|
|
4
6
|
import type { AnyRepository } from "../repository/types/repository.interface.js";
|
|
5
7
|
import { Kind } from "../symbols/kind.js";
|
|
8
|
+
import type { UseCaseStep } from "./steps/types/steps.interface.js";
|
|
6
9
|
/** A concrete UseCase declaration, usable as a dependency. */
|
|
7
10
|
export interface AnyUseCaseClass {
|
|
8
11
|
readonly [Kind]: "use-case";
|
|
@@ -10,16 +13,23 @@ export interface AnyUseCaseClass {
|
|
|
10
13
|
readonly blueprint: AnyBlueprint;
|
|
11
14
|
readonly response: AnyBlueprint;
|
|
12
15
|
readonly dependencies: UseCaseCollection;
|
|
13
|
-
|
|
16
|
+
readonly context: AnyBlueprint | undefined;
|
|
17
|
+
readonly description: string | undefined;
|
|
18
|
+
readonly tags: readonly string[];
|
|
19
|
+
readonly deprecated: boolean;
|
|
20
|
+
readonly errors: readonly AnyExceptionClass[];
|
|
21
|
+
new (input: any, ...options: any[]): {
|
|
14
22
|
execute(): Promise<unknown>;
|
|
15
23
|
pullEvents(): EntityEvent[];
|
|
16
24
|
};
|
|
17
25
|
}
|
|
26
|
+
/** Any class made by `exceptionOf`. */
|
|
27
|
+
export type AnyExceptionClass = DeclaredExceptionClass<any>;
|
|
18
28
|
/**
|
|
19
29
|
* What a use case can depend on: another use case, a repository made by
|
|
20
|
-
* `repositoryOf`,
|
|
30
|
+
* `repositoryOf`, an environment made by `environmentOf`, or `Logger`.
|
|
21
31
|
*/
|
|
22
|
-
export type UseCaseDependency = AnyUseCaseClass | AnyRepository | AnyEnvironment;
|
|
32
|
+
export type UseCaseDependency = AnyUseCaseClass | AnyRepository | AnyEnvironment | LoggerDeclaration;
|
|
23
33
|
export type UseCaseCollection = Readonly<Record<string, UseCaseDependency>>;
|
|
24
34
|
type Declaration = {
|
|
25
35
|
readonly blueprint: AnyBlueprint;
|
|
@@ -29,11 +39,26 @@ type Declaration = {
|
|
|
29
39
|
export type UseCaseInput<Class extends Declaration> = BlueprintInput<Class["blueprint"]["properties"]>;
|
|
30
40
|
export type UseCaseResponse<Class extends Declaration> = BlueprintValue<Class["response"]["properties"]>;
|
|
31
41
|
export type UseCaseDependencies<Class extends Declaration> = DependencyFunctions<Class["dependencies"]>;
|
|
42
|
+
/** The context of a use case class, as `this.context` gives it; `undefined` without one. */
|
|
43
|
+
export type UseCaseContext<Class extends {
|
|
44
|
+
readonly context: unknown;
|
|
45
|
+
}> = Class["context"] extends IBlueprint<infer Properties> ? Readonly<BlueprintValue<Properties>> : undefined;
|
|
46
|
+
/**
|
|
47
|
+
* The second argument of the constructor of a use case: `{ context }`,
|
|
48
|
+
* required when the use case declares a context, not accepted otherwise.
|
|
49
|
+
*/
|
|
50
|
+
export type UseCaseOptions<Context extends IBlueprintCollection | undefined = undefined> = Context extends IBlueprintCollection ? {
|
|
51
|
+
readonly context: BlueprintInput<Context>;
|
|
52
|
+
} : {
|
|
53
|
+
readonly context?: undefined;
|
|
54
|
+
};
|
|
55
|
+
/** @internal */
|
|
56
|
+
type OptionsArgs<Context extends IBlueprintCollection | undefined> = Context extends IBlueprintCollection ? [options: UseCaseOptions<Context>] : [];
|
|
32
57
|
/**
|
|
33
58
|
* What a use case gets for a dependency: a function for a use case, the
|
|
34
|
-
* repository itself,
|
|
59
|
+
* repository itself, the variables of an environment, or an `ILogger`.
|
|
35
60
|
*/
|
|
36
|
-
export type DependencyOf<Dependency> = Dependency extends AnyUseCaseClass ? (input: UseCaseInput<Dependency>) => Promise<UseCaseResponse<Dependency>> : Dependency extends AnyEnvironment ? EnvironmentValue<Dependency> : Dependency;
|
|
61
|
+
export type DependencyOf<Dependency> = Dependency extends AnyUseCaseClass ? (input: UseCaseInput<Dependency>) => Promise<UseCaseResponse<Dependency>> : Dependency extends AnyEnvironment ? EnvironmentValue<Dependency> : Dependency extends LoggerDeclaration ? ILogger : Dependency;
|
|
37
62
|
export type DependencyFunctions<Dependencies extends UseCaseCollection> = {
|
|
38
63
|
readonly [Key in keyof Dependencies]: DependencyOf<Dependencies[Key]>;
|
|
39
64
|
};
|
|
@@ -44,36 +69,77 @@ export type DependencyFunctions<Dependencies extends UseCaseCollection> = {
|
|
|
44
69
|
export type DependencyOverrides<Dependencies extends UseCaseCollection> = {
|
|
45
70
|
readonly [Key in keyof Dependencies]?: Dependencies[Key] extends AnyRepository ? Partial<Dependencies[Key]> : DependencyOf<Dependencies[Key]>;
|
|
46
71
|
};
|
|
47
|
-
export interface UseCaseSettings<Input extends IBlueprintCollection, Output extends IBlueprintCollection, Dependencies extends UseCaseCollection> {
|
|
72
|
+
export interface UseCaseSettings<Input extends IBlueprintCollection, Output extends IBlueprintCollection, Dependencies extends UseCaseCollection, Context extends IBlueprintCollection | undefined = undefined> {
|
|
48
73
|
readonly name: string;
|
|
49
74
|
readonly blueprint: IBlueprint<Input>;
|
|
50
75
|
readonly response: IBlueprint<Output>;
|
|
51
76
|
readonly dependencies?: Dependencies;
|
|
77
|
+
/** What the caller supplies with each call, e.g. the user and the request; validated by this blueprint. */
|
|
78
|
+
readonly context?: IBlueprint<Exclude<Context, undefined>>;
|
|
79
|
+
readonly description?: string;
|
|
80
|
+
readonly tags?: readonly string[];
|
|
81
|
+
readonly deprecated?: boolean;
|
|
82
|
+
/** The exceptions (made by `exceptionOf`) a caller should expect; documentation only. */
|
|
83
|
+
readonly errors?: readonly AnyExceptionClass[];
|
|
52
84
|
}
|
|
53
|
-
|
|
85
|
+
/** `UseCaseSettings` with the `steps` that are its `execute`. */
|
|
86
|
+
export interface UseCaseStepsSettings<Input extends IBlueprintCollection, Output extends IBlueprintCollection, Dependencies extends UseCaseCollection, Context extends IBlueprintCollection | undefined = undefined> extends UseCaseSettings<Input, Output, Dependencies, Context> {
|
|
87
|
+
/**
|
|
88
|
+
* What the use case does, as data (see `UseCaseStep`): validated here,
|
|
89
|
+
* interpreted by its `execute`, and described by `describe()`.
|
|
90
|
+
*/
|
|
91
|
+
readonly steps: readonly UseCaseStep<NoInfer<Dependencies>>[];
|
|
92
|
+
}
|
|
93
|
+
export declare const InvalidUseCaseDeclaration: DeclaredExceptionClass<{
|
|
54
94
|
reason: string;
|
|
55
95
|
}>;
|
|
56
|
-
export declare const UseCaseAlreadyExecuted:
|
|
57
|
-
export declare const InvalidUseCaseDependencies:
|
|
96
|
+
export declare const UseCaseAlreadyExecuted: DeclaredExceptionClass<undefined>;
|
|
97
|
+
export declare const InvalidUseCaseDependencies: DeclaredExceptionClass<undefined>;
|
|
58
98
|
/** An operation with validated input, dependency functions and a drainable event queue. */
|
|
59
99
|
export declare abstract class AbstractUseCase<Input extends IBlueprintCollection, Output extends IBlueprintCollection, Dependencies extends UseCaseCollection> {
|
|
60
100
|
readonly input: Readonly<BlueprintValue<Input>>;
|
|
61
|
-
constructor(input: BlueprintInput<Input
|
|
101
|
+
constructor(input: BlueprintInput<Input>, ...args: unknown[]);
|
|
62
102
|
/** Default parameter for implementations: `execute(deps = this.dependencies)`. */
|
|
63
103
|
get dependencies(): DependencyFunctions<Dependencies>;
|
|
64
104
|
abstract execute(dependencies?: DependencyOverrides<Dependencies>): Promise<BlueprintValue<Output>>;
|
|
65
105
|
/** Immediately drains collected events; never executes their handlers. */
|
|
66
106
|
pullEvents(): EntityEvent[];
|
|
67
107
|
}
|
|
68
|
-
|
|
108
|
+
/** What every use case class carries, abstract or not. */
|
|
109
|
+
type UseCaseStatics<Input extends IBlueprintCollection, Output extends IBlueprintCollection, Dependencies extends UseCaseCollection, Context extends IBlueprintCollection | undefined> = {
|
|
69
110
|
readonly [Kind]: "use-case";
|
|
70
111
|
readonly useCaseName: string;
|
|
71
112
|
readonly blueprint: IBlueprint<Input>;
|
|
72
113
|
readonly response: IBlueprint<Output>;
|
|
73
114
|
readonly dependencies: Dependencies;
|
|
115
|
+
/** The blueprint of the context of each call, or `undefined`. */
|
|
116
|
+
readonly context: Context extends IBlueprintCollection ? IBlueprint<Context> : undefined;
|
|
117
|
+
readonly description: string | undefined;
|
|
118
|
+
readonly tags: readonly string[];
|
|
119
|
+
readonly deprecated: boolean;
|
|
120
|
+
/** The exceptions a caller should expect. */
|
|
121
|
+
readonly errors: readonly AnyExceptionClass[];
|
|
122
|
+
};
|
|
123
|
+
/** What a use case instance carries beyond `AbstractUseCase`. */
|
|
124
|
+
type UseCaseInstanceContext<Context extends IBlueprintCollection | undefined> = {
|
|
125
|
+
/** What the caller supplied with the call, parsed and frozen; `undefined` without a declared context. */
|
|
126
|
+
readonly context: Context extends IBlueprintCollection ? Readonly<BlueprintValue<Context>> : undefined;
|
|
74
127
|
};
|
|
75
|
-
|
|
76
|
-
|
|
128
|
+
export type UseCaseConstructor<Input extends IBlueprintCollection, Output extends IBlueprintCollection, Dependencies extends UseCaseCollection, Context extends IBlueprintCollection | undefined = undefined> = (abstract new (input: BlueprintInput<Input>, ...options: OptionsArgs<Context>) => AbstractUseCase<Input, Output, Dependencies> & UseCaseInstanceContext<Context>) & UseCaseStatics<Input, Output, Dependencies, Context>;
|
|
129
|
+
/**
|
|
130
|
+
* What `useCaseOf` gives with `steps`: concrete, its `execute` interprets the
|
|
131
|
+
* steps. A subclass may still override `execute`.
|
|
132
|
+
*/
|
|
133
|
+
export type StepsUseCaseConstructor<Input extends IBlueprintCollection, Output extends IBlueprintCollection, Dependencies extends UseCaseCollection, Context extends IBlueprintCollection | undefined = undefined> = (new (input: BlueprintInput<Input>, ...options: OptionsArgs<Context>) => Omit<AbstractUseCase<Input, Output, Dependencies>, "execute"> & UseCaseInstanceContext<Context> & {
|
|
134
|
+
execute(dependencies?: DependencyOverrides<Dependencies>): Promise<BlueprintValue<Output>>;
|
|
135
|
+
}) & UseCaseStatics<Input, Output, Dependencies, Context>;
|
|
136
|
+
/**
|
|
137
|
+
* Declares an operation. With `steps` the class is concrete: its `execute`
|
|
138
|
+
* interprets them. Without, it is abstract: extend it and implement an async
|
|
139
|
+
* execute method.
|
|
140
|
+
*/
|
|
141
|
+
export declare function useCaseOf<Input extends IBlueprintCollection, Output extends IBlueprintCollection, const Dependencies extends UseCaseCollection = Record<never, never>, Context extends IBlueprintCollection | undefined = undefined>(settings: UseCaseStepsSettings<Input, Output, Dependencies, Context>): StepsUseCaseConstructor<Input, Output, Dependencies, Context>;
|
|
142
|
+
export declare function useCaseOf<Input extends IBlueprintCollection, Output extends IBlueprintCollection, const Dependencies extends UseCaseCollection = Record<never, never>, Context extends IBlueprintCollection | undefined = undefined>(settings: UseCaseSettings<Input, Output, Dependencies, Context>): UseCaseConstructor<Input, Output, Dependencies, Context>;
|
|
77
143
|
export declare function isUseCaseClass(value: unknown): value is AnyUseCaseClass;
|
|
78
144
|
export declare function isUseCase(value: unknown): value is AbstractUseCase<IBlueprintCollection, IBlueprintCollection, UseCaseCollection>;
|
|
79
145
|
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@afora/core/experimental`: features that may change in any release. Not
|
|
3
|
+
* covered by the compatibility policy in `VERSIONING.md`.
|
|
4
|
+
*/
|
|
5
|
+
export { sliceOf, sliceValue } from "./core/blueprint/slice.js";
|
|
6
|
+
export type { SlicedBlueprint, SlicedValue, SliceMask, ValueMask, } from "./core/blueprint/types/slice.interface.js";
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isBlueprint2,
|
|
3
|
+
isRecordClass2,
|
|
4
|
+
recordFieldOf2,
|
|
5
|
+
listOf2,
|
|
6
|
+
isBlueprintList2,
|
|
7
|
+
AbstractRecord2,
|
|
8
|
+
declareRecord,
|
|
9
|
+
UndeclaredBlueprintProperty2,
|
|
10
|
+
optionalOf2,
|
|
11
|
+
blueprintFromProperties
|
|
12
|
+
} from "./index-hn82hm31.js";
|
|
13
|
+
|
|
14
|
+
// src/core/blueprint/slice.ts
|
|
15
|
+
function propertiesOfField(field) {
|
|
16
|
+
if (field === undefined)
|
|
17
|
+
return;
|
|
18
|
+
if (isBlueprintList2(field))
|
|
19
|
+
return propertiesOfField(field.item);
|
|
20
|
+
const record = recordFieldOf2(field);
|
|
21
|
+
if (record)
|
|
22
|
+
return record.record.blueprint.properties;
|
|
23
|
+
return isBlueprint2(field) ? field.properties : undefined;
|
|
24
|
+
}
|
|
25
|
+
function maskOf(selector, against) {
|
|
26
|
+
if (isRecordClass2(selector))
|
|
27
|
+
return maskOf(selector.blueprint, against);
|
|
28
|
+
if (isBlueprint2(selector)) {
|
|
29
|
+
return Object.fromEntries(Object.entries(selector.properties).map(([key, field]) => [key, fieldMaskOf(field, against?.[key])]));
|
|
30
|
+
}
|
|
31
|
+
return selector;
|
|
32
|
+
}
|
|
33
|
+
function fieldMaskOf(field, other) {
|
|
34
|
+
if (isBlueprintList2(field)) {
|
|
35
|
+
return fieldMaskOf(field.item, isBlueprintList2(other) ? other.item : other);
|
|
36
|
+
}
|
|
37
|
+
const record = recordFieldOf2(field);
|
|
38
|
+
if (record) {
|
|
39
|
+
if (record.record === recordFieldOf2(other)?.record)
|
|
40
|
+
return true;
|
|
41
|
+
return maskOf(record.record, propertiesOfField(other));
|
|
42
|
+
}
|
|
43
|
+
if (isBlueprint2(field)) {
|
|
44
|
+
return field === other ? true : maskOf(field, propertiesOfField(other));
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
function sliceCollection(properties, mask, path) {
|
|
49
|
+
const sliced = {};
|
|
50
|
+
for (const [key, selected] of Object.entries(mask)) {
|
|
51
|
+
if (!selected)
|
|
52
|
+
continue;
|
|
53
|
+
if (!Object.hasOwn(properties, key)) {
|
|
54
|
+
throw new UndeclaredBlueprintProperty2({
|
|
55
|
+
source: "blueprint",
|
|
56
|
+
details: { key: path + key }
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
sliced[key] = sliceField(properties[key], selected, path + key);
|
|
60
|
+
}
|
|
61
|
+
return sliced;
|
|
62
|
+
}
|
|
63
|
+
function slicedRecordOf(Original, mask, path) {
|
|
64
|
+
const source = Original.blueprint;
|
|
65
|
+
const blueprint = blueprintFromProperties(source.plugins, sliceCollection(source.properties, mask, `${path}.`));
|
|
66
|
+
const kept = (keys) => keys.filter((key) => Object.hasOwn(blueprint.properties, key));
|
|
67
|
+
const { sensitive, unique, change } = Original.options;
|
|
68
|
+
const Sliced = declareRecord(AbstractRecord2, blueprint, {
|
|
69
|
+
sensitive: kept(sensitive),
|
|
70
|
+
unique: kept(unique),
|
|
71
|
+
change: kept(change)
|
|
72
|
+
}, Original.name);
|
|
73
|
+
Object.defineProperty(Sliced, Symbol.hasInstance, {
|
|
74
|
+
value(value) {
|
|
75
|
+
return Function.prototype[Symbol.hasInstance].call(this, value) || value instanceof Original;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return Sliced;
|
|
79
|
+
}
|
|
80
|
+
function sliceField(field, selected, path) {
|
|
81
|
+
if (selected === true)
|
|
82
|
+
return field;
|
|
83
|
+
if (isBlueprintList2(field)) {
|
|
84
|
+
const list = listOf2(sliceField(field.item, selected, path), {
|
|
85
|
+
minItems: field.minItems,
|
|
86
|
+
maxItems: field.maxItems
|
|
87
|
+
});
|
|
88
|
+
return field.optional ? optionalOf2(list) : list;
|
|
89
|
+
}
|
|
90
|
+
const record = recordFieldOf2(field);
|
|
91
|
+
if (record) {
|
|
92
|
+
const sliced = slicedRecordOf(record.record, selected, path);
|
|
93
|
+
return record.optional ? optionalOf2(sliced) : sliced;
|
|
94
|
+
}
|
|
95
|
+
if (isBlueprint2(field)) {
|
|
96
|
+
const sliced = blueprintFromProperties(field.plugins, sliceCollection(field.properties, selected, `${path}.`));
|
|
97
|
+
return field.optional ? optionalOf2(sliced) : sliced;
|
|
98
|
+
}
|
|
99
|
+
throw new UndeclaredBlueprintProperty2({
|
|
100
|
+
source: "blueprint",
|
|
101
|
+
details: { key: `${path}.${Object.keys(selected)[0] ?? ""}` }
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
var sliceOf = (blueprint, selector) => blueprintFromProperties(blueprint.plugins, sliceCollection(blueprint.properties, maskOf(selector, blueprint.properties), ""));
|
|
105
|
+
var sliceValue = (value, selector) => pick(value, maskOf(selector));
|
|
106
|
+
function pick(value, mask) {
|
|
107
|
+
if (Array.isArray(value))
|
|
108
|
+
return value.map((item) => pick(item, mask));
|
|
109
|
+
if (typeof value !== "object" || value === null)
|
|
110
|
+
return value;
|
|
111
|
+
const source = isRecordClass2(value.constructor) ? value.toJSON() : value;
|
|
112
|
+
const picked = {};
|
|
113
|
+
for (const [key, selected] of Object.entries(mask)) {
|
|
114
|
+
if (!selected || !Object.hasOwn(source, key))
|
|
115
|
+
continue;
|
|
116
|
+
picked[key] = selected === true ? source[key] : pick(source[key], selected);
|
|
117
|
+
}
|
|
118
|
+
return picked;
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
sliceOf,
|
|
122
|
+
sliceValue
|
|
123
|
+
};
|