@afora/core 0.0.6 → 0.0.8

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.
Files changed (63) hide show
  1. package/README.md +36 -7
  2. package/dist/core/application/start.d.ts +7 -0
  3. package/dist/core/application/types/application.interface.d.ts +47 -2
  4. package/dist/core/command/command.d.ts +11 -4
  5. package/dist/core/command/types/command.interface.d.ts +26 -0
  6. package/dist/core/entity/abstract-entity.d.ts +28 -1
  7. package/dist/core/entity/entity.d.ts +1 -1
  8. package/dist/core/entity/event.d.ts +13 -2
  9. package/dist/core/entity/exceptions.d.ts +8 -0
  10. package/dist/core/entity/types/entity.interface.d.ts +66 -2
  11. package/dist/core/entity/version.d.ts +13 -0
  12. package/dist/core/event-policy/event-policy.d.ts +25 -0
  13. package/dist/core/event-policy/exceptions.d.ts +11 -0
  14. package/dist/core/event-policy/publish.d.ts +17 -0
  15. package/dist/core/event-policy/publishers.d.ts +18 -0
  16. package/dist/core/event-policy/types/event-policy.interface.d.ts +72 -0
  17. package/dist/core/output/coerce.d.ts +9 -0
  18. package/dist/core/output/openapi-sink.d.ts +138 -38
  19. package/dist/core/output/status.d.ts +2 -1
  20. package/dist/core/parse/parse.d.ts +10 -0
  21. package/dist/core/parse/strip.d.ts +13 -0
  22. package/dist/core/property/input.d.ts +20 -0
  23. package/dist/core/record/plugin.d.ts +6 -2
  24. package/dist/core/repository/exceptions.d.ts +30 -0
  25. package/dist/core/repository/in-memory.d.ts +14 -1
  26. package/dist/core/repository/plan.d.ts +20 -0
  27. package/dist/core/repository/provider.d.ts +1 -1
  28. package/dist/core/repository/query.d.ts +9 -2
  29. package/dist/core/repository/repository.d.ts +40 -8
  30. package/dist/core/repository/state.d.ts +39 -2
  31. package/dist/core/repository/types/query.interface.d.ts +106 -5
  32. package/dist/core/repository/types/repository.interface.d.ts +113 -7
  33. package/dist/core/use-case/exceptions.d.ts +36 -0
  34. package/dist/core/use-case/plugin-catalog.d.ts +11 -0
  35. package/dist/core/use-case/plugin.d.ts +25 -0
  36. package/dist/core/use-case/steps/types/steps.interface.d.ts +23 -6
  37. package/dist/core/use-case/target.d.ts +9 -0
  38. package/dist/core/use-case/types/plugin.interface.d.ts +185 -0
  39. package/dist/experimental.js +3 -3
  40. package/dist/{index-3nd9bjnc.js → index-qxfkyd6k.js} +646 -635
  41. package/dist/{index-gbgc40xe.js → index-t5qwtyj5.js} +2798 -295
  42. package/dist/index.d.ts +35 -15
  43. package/dist/index.js +99 -15
  44. package/dist/std/blueprint-plugin.d.ts +6 -2
  45. package/dist/std/blueprint.d.ts +3 -0
  46. package/dist/std/command.d.ts +11 -0
  47. package/dist/std/entity.d.ts +2 -1
  48. package/dist/std/event-policies.d.ts +2 -0
  49. package/dist/std/properties/exceptions.d.ts +11 -0
  50. package/dist/std/properties/json.d.ts +54 -0
  51. package/dist/std/properties/password.d.ts +16 -1
  52. package/dist/std/properties/time.d.ts +4 -0
  53. package/dist/std/use-cases/auth.d.ts +5 -0
  54. package/dist/std/use-cases/crud.d.ts +25 -0
  55. package/dist/std/use-cases/index.d.ts +11 -0
  56. package/dist/std/use-cases/lifecycle.d.ts +13 -0
  57. package/dist/std/use-cases/shared.d.ts +88 -0
  58. package/dist/std/use-cases/types.d.ts +291 -0
  59. package/dist/testing/index.d.ts +2 -0
  60. package/dist/testing/index.js +355 -2
  61. package/dist/testing/memory-publisher.d.ts +16 -0
  62. package/dist/testing/provider-contract.d.ts +14 -0
  63. package/package.json +3 -2
@@ -0,0 +1,25 @@
1
+ import type { UseCaseCompilation, UseCaseTargetInfo } from "../../core/use-case/types/plugin.interface.js";
2
+ import type { AnyExceptionClass } from "../../core/use-case/use-case.js";
3
+ import { type Options, type Step } from "./shared.js";
4
+ import type { CreateMaker, DeleteMaker, GetMaker, ListMaker, RestoreMaker, UpdateMaker } from "./types.js";
5
+ /**
6
+ * The declaration of `create` and of `register`, which adds `checks` and
7
+ * their errors: an input of the keys of the entity, the entity built from
8
+ * it and stored. The option `before` runs first, and the steps after it read
9
+ * the input it gives; `checks` read it under `$input` all the same, rooted
10
+ * by the function given.
11
+ */
12
+ export declare function createCompilation(target: UseCaseTargetInfo, options: Options, verb: string, checks?: (input: string) => readonly Step[], errors?: readonly AnyExceptionClass[]): UseCaseCompilation;
13
+ /** Builds an entity from the input and stores it. */
14
+ export declare const create: import("../../index.js").IUseCasePlugin<"create", CreateMaker>;
15
+ /** Gives the entity of an id. */
16
+ export declare const get: import("../../index.js").IUseCasePlugin<"get", GetMaker>;
17
+ /** Gives a page of entities. */
18
+ export declare const list: import("../../index.js").IUseCasePlugin<"list", ListMaker>;
19
+ /** Changes the keys the input gives, of those the entity lets change. */
20
+ export declare const update: import("../../index.js").IUseCasePlugin<"update", UpdateMaker>;
21
+ /** Deletes the entity of an id, as the repository deletes: for good, or softly. */
22
+ declare const remove: import("../../index.js").IUseCasePlugin<"delete", DeleteMaker>;
23
+ export { remove as delete_ };
24
+ /** Brings back a soft-deleted entity. */
25
+ export declare const restore: import("../../index.js").IUseCasePlugin<"restore", RestoreMaker>;
@@ -0,0 +1,11 @@
1
+ import type { IUseCaseCatalog } from "../../core/use-case/types/plugin.interface.js";
2
+ import type { StdUseCasePlugins } from "./types.js";
3
+ /**
4
+ * The standard use cases, by name, for the `useCases` of `commandOf` to
5
+ * pick from, as `(ctx) => ({ create: ctx.create(Posts) })`: `create`, `get`,
6
+ * `list`, `update`, `delete` and `restore` for any entity; `publish`,
7
+ * `unpublish`, `archive`, `unarchive`, `tag` and `untag` for the entities
8
+ * with those record plugins; `register` and `login` for the
9
+ * authenticatable ones. `StdUseCases.context` is that `ctx`.
10
+ */
11
+ export declare const StdUseCases: IUseCaseCatalog<StdUseCasePlugins>;
@@ -0,0 +1,13 @@
1
+ import type { ArchiveMaker, PublishMaker, TagMaker } from "./types.js";
2
+ /** Publishes the entity of an id. */
3
+ export declare const publish: import("../../index.js").IUseCasePlugin<"publish", PublishMaker>;
4
+ /** Makes the entity of an id a draft again. */
5
+ export declare const unpublish: import("../../index.js").IUseCasePlugin<"unpublish", PublishMaker>;
6
+ /** Archives the entity of an id. */
7
+ export declare const archive: import("../../index.js").IUseCasePlugin<"archive", ArchiveMaker>;
8
+ /** Makes the archived entity of an id active again. */
9
+ export declare const unarchive: import("../../index.js").IUseCasePlugin<"unarchive", ArchiveMaker>;
10
+ /** Adds tags to the entity of an id. */
11
+ export declare const tag: import("../../index.js").IUseCasePlugin<"tag", TagMaker>;
12
+ /** Removes tags from the entity of an id. */
13
+ export declare const untag: import("../../index.js").IUseCasePlugin<"untag", TagMaker>;
@@ -0,0 +1,88 @@
1
+ import type { BlueprintField } from "../../core/blueprint/types/blueprint.interface.js";
2
+ import type { UseCaseCompilation, UseCaseFieldPlan, UseCaseTargetInfo } from "../../core/use-case/types/plugin.interface.js";
3
+ import type { AnyExceptionClass, UseCaseDependency } from "../../core/use-case/use-case.js";
4
+ /** A blueprint of the fields given, with no context of properties. */
5
+ export declare const fields: import("../../index.js").BlueprintBuilder<readonly []>;
6
+ export type Options = Readonly<Record<string, unknown>>;
7
+ export type Step = Readonly<Record<string, unknown>>;
8
+ export declare const capitalize: (key: string) => string;
9
+ /** A value given in options as a step takes it: a string that starts with `$` is not a reference. */
10
+ export declare function literal(value: unknown): unknown;
11
+ /** The option `key`, checked to be one of the `allowed` options of the use case. */
12
+ export declare function checkOptions(target: UseCaseTargetInfo, options: Options, allowed: readonly string[]): void;
13
+ /** The options of the use cases that write: `before`, `after`, `dependencies`, `throws`. */
14
+ export declare const HOOKS: readonly ["before", "after", "dependencies", "throws"];
15
+ /** The name, description, tags and `deprecated` of the use case. */
16
+ export declare function metaOf(target: UseCaseTargetInfo, options: Options, verb: string): Pick<UseCaseCompilation, "name" | "description" | "tags" | "deprecated">;
17
+ /** The key of the response that holds the entity: the option `as`, `item` by default. */
18
+ export declare function asOf(target: UseCaseTargetInfo, options: Options): string;
19
+ /** The error of `kind` the options give, else `fallback`. */
20
+ export declare function errorOf(target: UseCaseTargetInfo, options: Options, kind: "notFound" | "conflict" | "invalid" | "owner", fallback: AnyExceptionClass): AnyExceptionClass;
21
+ /** The list of names an option gives, each a key of the entity. */
22
+ export declare function keysOf(target: UseCaseTargetInfo, options: Options, option: string): readonly UseCaseFieldPlan[];
23
+ /** The object an option gives, by key of the entity. */
24
+ export declare function valuesOf(target: UseCaseTargetInfo, options: Options, option: string): Readonly<Record<string, unknown>>;
25
+ /** Who owns the entity, as the option `owner` says. */
26
+ export interface Owner {
27
+ readonly plan: UseCaseFieldPlan;
28
+ /** The key of the context that holds the id of the caller. */
29
+ readonly context: string;
30
+ /** The field of that context key: an id. */
31
+ readonly field: BlueprintField;
32
+ /** The reference to the id of the owner of the entity bound as `item`. */
33
+ readonly reference: string;
34
+ }
35
+ /**
36
+ * The option `owner: { key?, context }`: `key` (`ownerId` by default) holds
37
+ * the owner, an id or an entity, and `context` names the context key with
38
+ * the id of the caller.
39
+ */
40
+ export declare function ownerOf(target: UseCaseTargetInfo, options: Options): Owner | undefined;
41
+ /** The context blueprint an owner needs, if there is one. */
42
+ export declare function contextOf(owner: Owner | undefined): Pick<UseCaseCompilation, "context">;
43
+ /**
44
+ * The steps that load the entity of `$input.id` as `item`, throw `notFound`
45
+ * when there is none, and when it is not the caller's.
46
+ */
47
+ export declare function loadSteps(owner: Owner | undefined, notFound: AnyExceptionClass): Step[];
48
+ /** What the options `before`, `after`, `dependencies` and `throws` add to a use case. */
49
+ export interface Hooks {
50
+ /** The root of the input the steps read: `$input`, or `$prepared` after `before`. */
51
+ readonly input: string;
52
+ /** The dependencies the options give, joined to those the use case makes. */
53
+ readonly dependencies: Readonly<Record<string, UseCaseDependency>>;
54
+ readonly throws: readonly AnyExceptionClass[];
55
+ /** The step of `before`, if any: it binds `prepared`, the input it gives back or the one it got. */
56
+ before(entity?: string): Step[];
57
+ /** The step of `after`, if any, over the entity written. */
58
+ after(entity: string): Step[];
59
+ }
60
+ /**
61
+ * The options `before`, `after`, `dependencies` and `throws`, checked: each
62
+ * hook becomes a `run` step, whose function gets `{ input, entity?,
63
+ * dependencies, context }` (the bound dependencies of the call, overrides
64
+ * included).
65
+ */
66
+ export declare function hooksOf(target: UseCaseTargetInfo, options: Options): Hooks;
67
+ /**
68
+ * The dependencies a use case makes, joined to those of the option
69
+ * `dependencies`; a name taken by both is unavailable.
70
+ */
71
+ export declare function joinDependencies(target: UseCaseTargetInfo, made: Readonly<Record<string, UseCaseDependency>>, hooks: Hooks): Readonly<Record<string, UseCaseDependency>>;
72
+ /** The id field of the entity of `target`. */
73
+ export declare const idOf: (target: UseCaseTargetInfo) => BlueprintField;
74
+ /** The classes of `errors`, each once. */
75
+ export declare const distinct: (...errors: readonly AnyExceptionClass[]) => AnyExceptionClass[];
76
+ /**
77
+ * A use case over one entity found by id: `{ id }` in, `{ [as]: entity }`
78
+ * out; loads it, checks the owner, runs `before` (with `hooks`), `steps`
79
+ * (which leave the entity to give under `result`) and `after`, and gives it.
80
+ * `steps` read the input under `input`: `$input`, or what `before` gave.
81
+ */
82
+ export declare function entityUseCase(target: UseCaseTargetInfo, options: Options, verb: string, allowed: readonly string[], steps: (context: {
83
+ readonly owner: Owner | undefined;
84
+ readonly input: string;
85
+ }) => {
86
+ readonly steps: readonly Step[];
87
+ readonly result: string;
88
+ }, hooks?: boolean): UseCaseCompilation;
@@ -0,0 +1,291 @@
1
+ import type { AnyBlueprint, AnyBlueprintList, AnyRecordClass, BlueprintField, BlueprintValue, IBlueprint, IBlueprintCollection, IBlueprintList, OptionalBlueprint, OptionalBlueprintList, OptionalRecord } from "../../core/blueprint/types/blueprint.interface.js";
2
+ import type { EntityIdentityKey } from "../../core/entity/types/entity.interface.js";
3
+ import type { EntityVersion } from "../../core/entity/version.js";
4
+ import type { OptionalProperty } from "../../core/property/types/optional-property.type.js";
5
+ import type { AnyPropertyConstructor } from "../../core/property/types/property-collection.type.js";
6
+ import type { AnyRepository, AnyRepositoryEntity, EntityInstanceOf } from "../../core/repository/types/repository.interface.js";
7
+ import type { IUseCasePlugin, UseCaseTarget } from "../../core/use-case/types/plugin.interface.js";
8
+ import type { AnyExceptionClass, DependencyFunctions, StepsUseCaseConstructor, UseCaseCollection } from "../../core/use-case/use-case.js";
9
+ import type { Integer, StringProperty } from "../properties/primitives.js";
10
+ type EntityOf<Repository> = Repository extends {
11
+ readonly entity: infer Entity extends AnyRepositoryEntity;
12
+ } ? Entity : never;
13
+ type PropertiesOf<Entity> = Entity extends {
14
+ readonly blueprint: IBlueprint<infer Properties extends IBlueprintCollection>;
15
+ } ? Properties : never;
16
+ type Props<Repository> = PropertiesOf<EntityOf<Repository>>;
17
+ type FieldAt<Properties, Key extends string> = Properties extends {
18
+ readonly [Name in Key]: infer Field extends BlueprintField;
19
+ } ? Field : never;
20
+ type IdField<Repository> = FieldAt<Props<Repository>, "id">;
21
+ type KeyOf<Repository> = keyof Props<Repository> & string;
22
+ /** Whether a field holds an entity, one that may be absent, or a list of them. */
23
+ type HoldsEntity<Field> = Field extends AnyRepositoryEntity ? true : Field extends {
24
+ readonly record: AnyRepositoryEntity;
25
+ } ? true : Field extends IBlueprintList<infer Item> ? Item extends AnyRepositoryEntity ? true : false : false;
26
+ /** The field that accepts `undefined` too, as `optionalOf` gives it. */
27
+ type Optional<Field> = Field extends AnyPropertyConstructor ? OptionalProperty<Field> : Field extends AnyBlueprintList ? OptionalBlueprintList<Field> : Field extends AnyBlueprint ? OptionalBlueprint<Field> : Field extends AnyRecordClass ? OptionalRecord<Field> : never;
28
+ /** The errors a standard use case throws, in place of its defaults. */
29
+ export interface StdUseCaseErrors {
30
+ /** For an entity that is not found, or is not the caller's. `UseCaseEntityNotFound` by default. */
31
+ readonly notFound?: AnyExceptionClass;
32
+ /** For an entity that already exists (`register`). `UseCaseEntityConflict` by default. */
33
+ readonly conflict?: AnyExceptionClass;
34
+ /** For credentials that do not match (`login`). `UseCaseInvalidCredentials` by default. */
35
+ readonly invalid?: AnyExceptionClass;
36
+ /** For a caller that is not found, when it owns what `create` makes. `notFound` by default. */
37
+ readonly owner?: AnyExceptionClass;
38
+ }
39
+ /** The options every standard use case takes. */
40
+ export interface StdUseCaseOptions {
41
+ /** The `useCaseName`; the verb and the name of the entity by default, as `CreatePost`. */
42
+ readonly name?: string;
43
+ readonly description?: string;
44
+ readonly tags?: readonly string[];
45
+ readonly deprecated?: boolean;
46
+ readonly errors?: StdUseCaseErrors;
47
+ }
48
+ /** Who owns the entities: the caller, whose id the context gives. */
49
+ export interface StdOwnerOption<Repository> {
50
+ /**
51
+ * `key` holds the owner, as an id or as an entity (`ownerId` by default,
52
+ * the key of the `ownable` plugin), and `context` names the context key
53
+ * with the id of the caller: `create` fills the key from it, a use case
54
+ * over one entity throws `notFound` for another owner's, and `list` gives
55
+ * only the caller's.
56
+ */
57
+ readonly owner?: {
58
+ readonly key?: KeyOf<Repository>;
59
+ readonly context: string;
60
+ };
61
+ }
62
+ /** The options of a standard use case that gives one entity. */
63
+ export interface StdEntityOptions<Repository> extends StdUseCaseOptions, StdOwnerOption<Repository> {
64
+ /** The key of the response that holds the entity; `item` by default. */
65
+ readonly as?: string;
66
+ }
67
+ /** The options of `create` and `register`. */
68
+ export interface StdCreateOptions<Repository> extends StdEntityOptions<Repository> {
69
+ /** Optional keys the input does not take. */
70
+ readonly omit?: readonly KeyOf<Repository>[];
71
+ /** Values the entity is built with, in place of taking them from the input. */
72
+ readonly values?: {
73
+ readonly [Key in KeyOf<Repository>]?: unknown;
74
+ };
75
+ }
76
+ /** The options of `publish`, `unpublish`, `archive` and `unarchive`. */
77
+ export interface StdLifecycleOptions<Repository> extends StdEntityOptions<Repository> {
78
+ /** Change keys set before the entity is stored, e.g. `{ status: "published" }`. */
79
+ readonly set?: {
80
+ readonly [Key in KeyOf<Repository>]?: unknown;
81
+ };
82
+ }
83
+ /** The options of `list`. */
84
+ export interface StdListOptions<Repository> extends StdUseCaseOptions, StdOwnerOption<Repository> {
85
+ /** The order of the page; newest first (`createdAt`, descending) by default. */
86
+ readonly orderBy?: readonly {
87
+ readonly key: KeyOf<Repository>;
88
+ readonly direction?: "asc" | "desc";
89
+ }[];
90
+ }
91
+ type None = Record<never, never>;
92
+ /** What `before` and `after` get of the call. */
93
+ export interface StdHookArgs<Input, Dependencies, Context> {
94
+ /** The input of the call, parsed; for `after`, the one `before` gave back. */
95
+ readonly input: Input;
96
+ /**
97
+ * The dependencies of the call, as `execute` resolved them (overrides
98
+ * included): `repository`, those the use case makes to load what the
99
+ * input names, and those of the option `dependencies`.
100
+ */
101
+ readonly dependencies: Dependencies;
102
+ /** The context of the call: the id of the caller with `owner`, else `undefined`. */
103
+ readonly context: Context;
104
+ }
105
+ /**
106
+ * The options of a standard use case that writes: `before` runs before the
107
+ * write and may give back the input to write in place of the one given;
108
+ * `after` runs after it, within the transaction of the command; both get the
109
+ * dependencies of the use case and those of `dependencies`, and `throws` adds
110
+ * the exceptions they may throw to its errors (for `describe()` and statuses).
111
+ */
112
+ export interface StdHookOptions<Input, Entity, Dependencies extends UseCaseCollection, Bound, Context, Loaded extends boolean> {
113
+ /** Repositories, use cases or environments the hooks use, by name, beside those the use case makes. */
114
+ readonly dependencies?: Dependencies;
115
+ /**
116
+ * Runs before the write (after the entity is loaded and its owner
117
+ * checked, for a use case over one entity, which gets it as `entity`);
118
+ * what it gives back, if anything, is the input the use case goes on with.
119
+ */
120
+ readonly before?: (args: StdHookArgs<Input, Bound, Context> & (Loaded extends true ? {
121
+ readonly entity: Entity;
122
+ } : unknown)) => Input | void | Promise<Input | void>;
123
+ /** Runs after the write, with the entity written, before the response is given. */
124
+ readonly after?: (args: StdHookArgs<Input, Bound, Context> & {
125
+ readonly entity: Entity;
126
+ }) => unknown;
127
+ /** Exceptions (made by `exceptionOf`) `before` or `after` may throw: added to the errors of the use case. */
128
+ readonly throws?: readonly AnyExceptionClass[];
129
+ }
130
+ /** What `get`, `list` and `login` take in place of the hooks: none. */
131
+ export interface StdNoHookOptions {
132
+ readonly before?: never;
133
+ readonly after?: never;
134
+ readonly dependencies?: never;
135
+ readonly throws?: never;
136
+ }
137
+ type ContextValue<Repository, Options> = OwnerContext<Repository, Options> extends infer Context extends IBlueprintCollection ? Readonly<BlueprintValue<Context>> : undefined;
138
+ /** `Options` as `Hookable` infers them. */
139
+ type Shape<Omitted, Values, Owner> = {
140
+ readonly omit: readonly Omitted[];
141
+ readonly values: Values;
142
+ } & ([Owner] extends [undefined] ? unknown : {
143
+ readonly owner: Owner;
144
+ });
145
+ /** `StdHookOptions` for a use case over `Repository` that takes `Input`. */
146
+ type HookOptionsOf<Repository extends AnyRepository, Options, Input extends IBlueprintCollection, Dependencies extends UseCaseCollection, Loaded extends boolean> = StdHookOptions<BlueprintValue<Input>, EntityInstanceOf<EntityOf<Repository>>, Dependencies, DependencyFunctions<{
147
+ readonly repository: Repository;
148
+ } & Dependencies>, ContextValue<Repository, Options>, Loaded>;
149
+ /**
150
+ * The options of a use case that writes, as its maker reads them: those that
151
+ * type its input and context, inferred one by one (`Options` is inferred from
152
+ * the whole object only once the hooks are typed), and the hooks, typed by
153
+ * them and not inferred from. The types of `before` and `after` are only
154
+ * worked out for a call that gives them.
155
+ */
156
+ interface Hookable<Repository extends AnyRepository, Input extends IBlueprintCollection, Omitted, Values, Owner, Dependencies extends UseCaseCollection, Loaded extends boolean> {
157
+ readonly omit?: readonly Omitted[];
158
+ readonly values?: Values;
159
+ readonly owner?: Owner;
160
+ readonly dependencies?: Dependencies;
161
+ readonly throws?: readonly AnyExceptionClass[];
162
+ readonly before?: NoInfer<HookOptionsOf<Repository, Shape<Omitted, Values, Owner>, Input, Dependencies, Loaded>["before"]>;
163
+ readonly after?: NoInfer<HookOptionsOf<Repository, Shape<Omitted, Values, Owner>, Input, Dependencies, Loaded>["after"]>;
164
+ }
165
+ type AsOf<Options> = Options extends {
166
+ readonly as: infer Key extends string;
167
+ } ? Key : "item";
168
+ type EntityResponse<Repository, Options> = {
169
+ readonly [Key in AsOf<Options>]: EntityOf<Repository>;
170
+ };
171
+ type OwnerContext<Repository, Options> = Options extends {
172
+ readonly owner: {
173
+ readonly context: infer Key extends string;
174
+ };
175
+ } ? {
176
+ readonly [Name in Key]: IdField<Repository>;
177
+ } : undefined;
178
+ type OwnerKey<Options> = Options extends {
179
+ readonly owner: infer Owner;
180
+ } ? Owner extends {
181
+ readonly key: infer Key;
182
+ } ? Key : "ownerId" : never;
183
+ type LeftOut<Options> = EntityIdentityKey | OwnerKey<Options> | (Options extends {
184
+ readonly omit: readonly (infer Key)[];
185
+ } ? Key : never) | (Options extends {
186
+ readonly values: infer Values;
187
+ } ? keyof Values : never);
188
+ /** `"version"` for a versioned entity, whose `version` is part of its identity. */
189
+ type VersionKey<Repository> = Props<Repository> extends {
190
+ readonly version: typeof EntityVersion;
191
+ } ? "version" : never;
192
+ /** The input of `create`: the keys of the entity, an entity it holds by `<key>Id`. */
193
+ type CreateInput<Repository, Options> = {
194
+ readonly [Key in KeyOf<Repository> as Key extends LeftOut<Options> | VersionKey<Repository> ? never : Props<Repository>[Key] extends AnyRepositoryEntity ? `${Key}Id` : HoldsEntity<Props<Repository>[Key]> extends true ? never : Key]: Props<Repository>[Key] extends AnyRepositoryEntity ? FieldAt<PropertiesOf<Props<Repository>[Key]>, "id"> : Props<Repository>[Key];
195
+ };
196
+ type ChangeKey<Repository> = EntityInstanceOf<EntityOf<Repository>> extends {
197
+ readonly change: infer Changes;
198
+ } ? keyof Changes & KeyOf<Repository> : never;
199
+ /** The input of `update`: the id, and each change key, optional. */
200
+ type UpdateInput<Repository> = {
201
+ readonly [Key in "id" | ChangeKey<Repository> as Key extends "id" ? Key : HoldsEntity<Props<Repository>[Key]> extends true ? never : Key]: Key extends "id" ? IdField<Repository> : Optional<Props<Repository>[Key]>;
202
+ };
203
+ type EntityUseCase<Repository extends AnyRepository, Options, Input extends IBlueprintCollection, Dependencies extends UseCaseCollection = None> = StepsUseCaseConstructor<Input, EntityResponse<Repository, Options>, {
204
+ readonly repository: Repository;
205
+ } & Dependencies, OwnerContext<Repository, Options>>;
206
+ type ById<Repository> = {
207
+ readonly id: IdField<Repository>;
208
+ };
209
+ /** `create`: for a repository with the `create` action. */
210
+ export type CreateMaker = <Repository extends AnyRepository, const Options extends StdCreateOptions<Repository> = None, const Omitted extends KeyOf<Repository> = never, const Values = None, const Owner = undefined, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "create">, options?: Options & Hookable<Repository, CreateInput<Repository, Shape<Omitted, Values, Owner>>, Omitted, Values, Owner, Dependencies, false>) => EntityUseCase<Repository, Options, CreateInput<Repository, Options>, Dependencies>;
211
+ /** `get`: for a repository with `findById`. */
212
+ export type GetMaker = <Repository extends AnyRepository, const Options extends StdEntityOptions<Repository> & StdNoHookOptions = None>(repository: Repository & UseCaseTarget<Repository, "findById">, options?: Options) => EntityUseCase<Repository, Options, ById<Repository>>;
213
+ /** `list`: for a repository with `findPage`. */
214
+ export type ListMaker = <Repository extends AnyRepository, const Options extends StdListOptions<Repository> & StdNoHookOptions = None>(repository: Repository & UseCaseTarget<Repository, "findPage">, options?: Options) => StepsUseCaseConstructor<{
215
+ readonly limit: OptionalProperty<typeof Integer>;
216
+ readonly offset: OptionalProperty<typeof Integer>;
217
+ }, {
218
+ readonly items: IBlueprintList<EntityOf<Repository>>;
219
+ readonly total: typeof Integer;
220
+ readonly limit: typeof Integer;
221
+ readonly offset: typeof Integer;
222
+ }, {
223
+ readonly repository: Repository;
224
+ }, OwnerContext<Repository, Options>>;
225
+ /** `update`: for a repository with `findById` and `update`. */
226
+ export type UpdateMaker = <Repository extends AnyRepository, const Options extends StdEntityOptions<Repository> = None, const Owner = undefined, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "findById" | "update">, options?: Options & Hookable<Repository, UpdateInput<Repository>, never, None, Owner, Dependencies, true>) => EntityUseCase<Repository, Options, UpdateInput<Repository>, Dependencies>;
227
+ /** `delete`: for a repository with `findById` and `delete`. */
228
+ export type DeleteMaker = <Repository extends AnyRepository, const Options extends StdEntityOptions<Repository> = None, const Owner = undefined, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "findById" | "delete">, options?: Options & Hookable<Repository, ById<Repository>, never, None, Owner, Dependencies, true>) => EntityUseCase<Repository, Options, ById<Repository>, Dependencies>;
229
+ /** `restore`: for a repository with soft deletion and the `restore` action. */
230
+ export type RestoreMaker = <Repository extends AnyRepository, const Options extends StdUseCaseOptions & {
231
+ readonly as?: string;
232
+ } = None, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "restore">, options?: Options & Hookable<Repository, ById<Repository>, never, None, undefined, Dependencies, false>) => StepsUseCaseConstructor<ById<Repository>, EntityResponse<Repository, Options>, {
233
+ readonly repository: Repository;
234
+ } & Dependencies>;
235
+ /** `publish` and `unpublish`: for a publishable entity. */
236
+ export type PublishMaker = <Repository extends AnyRepository, const Options extends StdLifecycleOptions<Repository> = None, const Owner = undefined, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "findById" | "update", {
237
+ publish(at?: string): unknown;
238
+ unpublish(): unknown;
239
+ }, "publishable">, options?: Options & Hookable<Repository, ById<Repository>, never, None, Owner, Dependencies, true>) => EntityUseCase<Repository, Options, ById<Repository>, Dependencies>;
240
+ /** `archive` and `unarchive`: for an archivable entity. */
241
+ export type ArchiveMaker = <Repository extends AnyRepository, const Options extends StdLifecycleOptions<Repository> = None, const Owner = undefined, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "findById" | "update", {
242
+ archive(at?: string): unknown;
243
+ readonly isArchived: boolean;
244
+ }, "archivable">, options?: Options & Hookable<Repository, ById<Repository>, never, None, Owner, Dependencies, true>) => EntityUseCase<Repository, Options, ById<Repository>, Dependencies>;
245
+ /** `tag` and `untag`: for a taggable entity. */
246
+ export type TagMaker = <Repository extends AnyRepository, const Options extends StdEntityOptions<Repository> = None, const Owner = undefined, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "findById" | "update", {
247
+ tag(...tags: string[]): unknown;
248
+ untag(...tags: string[]): unknown;
249
+ }, "taggable">, options?: Options & Hookable<Repository, TagInput<Repository>, never, None, Owner, Dependencies, true>) => EntityUseCase<Repository, Options, TagInput<Repository>, Dependencies>;
250
+ type TagInput<Repository> = ById<Repository> & {
251
+ readonly tags: IBlueprintList<typeof StringProperty>;
252
+ };
253
+ type Authenticatable = {
254
+ verifyPassword(plain: string): Promise<boolean>;
255
+ };
256
+ /** `register`: for an authenticatable entity, with `findByEmail` and `create`. */
257
+ export type RegisterMaker = <Repository extends AnyRepository, const Options extends StdCreateOptions<Repository> = None, const Omitted extends KeyOf<Repository> = never, const Values = None, const Owner = undefined, const Dependencies extends UseCaseCollection = None>(repository: Repository & UseCaseTarget<Repository, "findByEmail" | "create", Authenticatable, "authenticatable">, options?: Options & Hookable<Repository, CreateInput<Repository, Shape<Omitted, Values, Owner>>, Omitted, Values, Owner, Dependencies, false>) => EntityUseCase<Repository, Options, CreateInput<Repository, Options>, Dependencies>;
258
+ /** `login`: for an authenticatable entity, with `findByEmail`. */
259
+ export type LoginMaker = <Repository extends AnyRepository, const Options extends StdUseCaseOptions & {
260
+ readonly as?: string;
261
+ } & StdNoHookOptions = None>(repository: Repository & UseCaseTarget<Repository, "findByEmail", Authenticatable, "authenticatable">, options?: Options) => StepsUseCaseConstructor<{
262
+ readonly email: FieldAt<Props<Repository>, "email">;
263
+ readonly password: typeof StringProperty;
264
+ }, EntityResponse<Repository, Options>, {
265
+ readonly repository: Repository;
266
+ }>;
267
+ /**
268
+ * The standard use cases, by name: what the `useCases` of `commandOf` gets
269
+ * to pick from, each called with a repository and its options.
270
+ */
271
+ export interface StdUseCaseContext {
272
+ readonly create: CreateMaker;
273
+ readonly get: GetMaker;
274
+ readonly list: ListMaker;
275
+ readonly update: UpdateMaker;
276
+ readonly delete: DeleteMaker;
277
+ readonly restore: RestoreMaker;
278
+ readonly publish: PublishMaker;
279
+ readonly unpublish: PublishMaker;
280
+ readonly archive: ArchiveMaker;
281
+ readonly unarchive: ArchiveMaker;
282
+ readonly tag: TagMaker;
283
+ readonly untag: TagMaker;
284
+ readonly register: RegisterMaker;
285
+ readonly login: LoginMaker;
286
+ }
287
+ /** The plugins of `StdUseCases`, by name. */
288
+ export type StdUseCasePlugins = {
289
+ readonly [Name in keyof StdUseCaseContext]: IUseCasePlugin<Name, StdUseCaseContext[Name]>;
290
+ };
291
+ export {};
@@ -1,2 +1,4 @@
1
+ export type { MemoryPublisher } from "./memory-publisher.js";
2
+ export { memoryPublisher } from "./memory-publisher.js";
1
3
  export type { ContractRunner, ProviderContractOptions, } from "./provider-contract.js";
2
4
  export { providerContract } from "./provider-contract.js";