@afora/core 0.0.7 → 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.
- package/README.md +34 -6
- package/dist/core/application/start.d.ts +7 -0
- package/dist/core/application/types/application.interface.d.ts +36 -2
- package/dist/core/command/types/command.interface.d.ts +7 -0
- package/dist/core/entity/abstract-entity.d.ts +28 -1
- package/dist/core/entity/entity.d.ts +1 -1
- package/dist/core/entity/event.d.ts +13 -2
- package/dist/core/entity/exceptions.d.ts +8 -0
- package/dist/core/entity/types/entity.interface.d.ts +66 -2
- package/dist/core/entity/version.d.ts +13 -0
- package/dist/core/event-policy/event-policy.d.ts +25 -0
- package/dist/core/event-policy/exceptions.d.ts +11 -0
- package/dist/core/event-policy/publish.d.ts +17 -0
- package/dist/core/event-policy/publishers.d.ts +18 -0
- package/dist/core/event-policy/types/event-policy.interface.d.ts +72 -0
- package/dist/core/output/coerce.d.ts +9 -0
- package/dist/core/output/openapi-sink.d.ts +138 -38
- package/dist/core/output/status.d.ts +1 -1
- package/dist/core/parse/parse.d.ts +10 -0
- package/dist/core/parse/strip.d.ts +13 -0
- package/dist/core/repository/exceptions.d.ts +30 -0
- package/dist/core/repository/in-memory.d.ts +14 -1
- package/dist/core/repository/plan.d.ts +20 -0
- package/dist/core/repository/provider.d.ts +1 -1
- package/dist/core/repository/query.d.ts +9 -2
- package/dist/core/repository/repository.d.ts +40 -8
- package/dist/core/repository/state.d.ts +30 -2
- package/dist/core/repository/types/query.interface.d.ts +106 -5
- package/dist/core/repository/types/repository.interface.d.ts +106 -7
- package/dist/experimental.js +4 -4
- package/dist/{index-r78dsvtc.js → index-qxfkyd6k.js} +612 -612
- package/dist/{index-q6hggpzw.js → index-t5qwtyj5.js} +1807 -280
- package/dist/index.d.ts +22 -11
- package/dist/index.js +62 -14
- package/dist/std/blueprint-plugin.d.ts +6 -2
- package/dist/std/blueprint.d.ts +3 -0
- package/dist/std/entity.d.ts +2 -1
- package/dist/std/event-policies.d.ts +2 -0
- package/dist/std/properties/exceptions.d.ts +11 -0
- package/dist/std/properties/json.d.ts +54 -0
- package/dist/std/properties/time.d.ts +4 -0
- package/dist/std/use-cases/crud.d.ts +6 -4
- package/dist/std/use-cases/shared.d.ts +32 -4
- package/dist/std/use-cases/types.d.ts +100 -21
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +347 -2
- package/dist/testing/memory-publisher.d.ts +16 -0
- package/dist/testing/provider-contract.d.ts +14 -0
- package/package.json +3 -2
|
@@ -22,6 +22,11 @@ export interface RepositoryQuery<Entity = unknown> {
|
|
|
22
22
|
readonly offset?: number;
|
|
23
23
|
/** Include destroyed rows; repository defaults depend on its deletion policy. */
|
|
24
24
|
readonly withDeleted?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Include expired rows, of an entity declared with `expires`; `false` by
|
|
27
|
+
* default.
|
|
28
|
+
*/
|
|
29
|
+
readonly withExpired?: boolean;
|
|
25
30
|
}
|
|
26
31
|
/** A page and the unpaginated number of matching live (or explicitly included) rows. */
|
|
27
32
|
export interface RepositoryPage<Entity> {
|
|
@@ -32,8 +37,8 @@ export interface RepositoryPage<Entity> {
|
|
|
32
37
|
}
|
|
33
38
|
/**
|
|
34
39
|
* The query of `findCursor`: as `RepositoryQuery`, with the `next` of the
|
|
35
|
-
* previous page as `after` in place of `offset`. `where`, `orderBy
|
|
36
|
-
* `withDeleted` must stay the same from one page to the next.
|
|
40
|
+
* previous page as `after` in place of `offset`. `where`, `orderBy`,
|
|
41
|
+
* `withDeleted` and `withExpired` must stay the same from one page to the next.
|
|
37
42
|
*/
|
|
38
43
|
export interface RepositoryCursorQuery<Entity = unknown> extends Omit<RepositoryQuery<Entity>, "offset" | "limit"> {
|
|
39
44
|
/** Positive integer; 20 when left out. */
|
|
@@ -49,13 +54,56 @@ export interface RepositoryCursorPage<Entity> {
|
|
|
49
54
|
readonly next: string | undefined;
|
|
50
55
|
}
|
|
51
56
|
/**
|
|
52
|
-
* What a provider gets
|
|
57
|
+
* What a provider gets. From `findCursor` on `findMany`, `after` holds one
|
|
53
58
|
* value for each order of `orderBy`, those of the last row already read, and
|
|
54
|
-
* the provider gives the rows strictly after it in that order
|
|
55
|
-
* provider with `capabilities.keyset` is given it.
|
|
59
|
+
* the provider gives the rows strictly after it in that order; only a
|
|
60
|
+
* provider with `capabilities.keyset` is given it. For an entity that expires
|
|
61
|
+
* (`context.expiry`), `now` is the current date and time as an ISO 8601
|
|
62
|
+
* string, from the clock of the entity: unless `withExpired`, the provider
|
|
63
|
+
* leaves out the rows whose `context.expiry.key` is at or before it.
|
|
56
64
|
*/
|
|
57
65
|
export interface ProviderQuery extends RepositoryQuery {
|
|
58
66
|
readonly after?: readonly unknown[];
|
|
67
|
+
/**
|
|
68
|
+
* The name of the declared index (`context.indexes`) that serves the
|
|
69
|
+
* query, when one does; a provider without `capabilities.indexes` can
|
|
70
|
+
* ignore it, and the rows must be the same either way.
|
|
71
|
+
*/
|
|
72
|
+
readonly index?: string;
|
|
73
|
+
/** The current date and time (ISO 8601), given for entities that expire. */
|
|
74
|
+
readonly now?: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* An access pattern a repository declares: queries whose `where` holds every
|
|
78
|
+
* key of `where` by equality, and whose first order (if any) is `orderBy`.
|
|
79
|
+
*/
|
|
80
|
+
export interface RepositoryIndex<Key extends string = string> {
|
|
81
|
+
/** The keys the query matches by equality, at least one. */
|
|
82
|
+
readonly where: readonly Key[];
|
|
83
|
+
/** The scalar key the rows are read in order of. */
|
|
84
|
+
readonly orderBy?: Key;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* How a query reaches its rows: by `id`, by another unique key, through a
|
|
88
|
+
* declared index (named by `index`), or by reading every row (`scan`).
|
|
89
|
+
*/
|
|
90
|
+
export interface RepositoryPlan {
|
|
91
|
+
readonly access: "id" | "unique" | "index" | "scan";
|
|
92
|
+
/** The declared index that serves the query, when `access` is `"index"`. */
|
|
93
|
+
readonly index?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* What a repository does with a query that only a scan serves: run it
|
|
97
|
+
* (`"allow"`, the default), log `repository-scan` and run it (`"warn"`), or
|
|
98
|
+
* throw `InvalidRepositoryQuery` before the provider is called (`"reject"`).
|
|
99
|
+
*/
|
|
100
|
+
export type RepositoryScans = "allow" | "warn" | "reject";
|
|
101
|
+
export interface RepositoryExplain<Entity> {
|
|
102
|
+
/**
|
|
103
|
+
* How the query would be read (`{ access, index? }`), without reading
|
|
104
|
+
* anything; takes the query of `findMany` or of `findCursor`.
|
|
105
|
+
*/
|
|
106
|
+
explain(query?: RepositoryQuery<Entity> | RepositoryCursorQuery<Entity>): Promise<RepositoryPlan>;
|
|
59
107
|
}
|
|
60
108
|
export interface RepositoryFindCursor<Entity> {
|
|
61
109
|
/**
|
|
@@ -65,6 +113,48 @@ export interface RepositoryFindCursor<Entity> {
|
|
|
65
113
|
*/
|
|
66
114
|
findCursor(query?: RepositoryCursorQuery<Entity>): Promise<RepositoryCursorPage<Entity>>;
|
|
67
115
|
}
|
|
116
|
+
/** Where `forEachPage` is in its walk, given with each page. */
|
|
117
|
+
export interface RepositoryWalkPage {
|
|
118
|
+
/** The position of the page in this call, from 0. */
|
|
119
|
+
readonly index: number;
|
|
120
|
+
/**
|
|
121
|
+
* The cursor after this page, `undefined` on the last: save it once the
|
|
122
|
+
* page is done to resume from the next one.
|
|
123
|
+
*/
|
|
124
|
+
readonly next?: string;
|
|
125
|
+
}
|
|
126
|
+
/** When `forEachPage` stops before the end. */
|
|
127
|
+
export interface RepositoryWalkOptions {
|
|
128
|
+
/**
|
|
129
|
+
* A deadline (a `Date` or epoch milliseconds) or a function that says when
|
|
130
|
+
* to stop; checked before each page, never while one runs.
|
|
131
|
+
*/
|
|
132
|
+
readonly until?: Date | number | (() => boolean);
|
|
133
|
+
}
|
|
134
|
+
/** What `forEachPage` did. */
|
|
135
|
+
export interface RepositoryWalkResult {
|
|
136
|
+
/** Whether it walked to the last page; `false` when `until` stopped it. */
|
|
137
|
+
readonly done: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* When it stopped early, the `after` to resume from: the `next` of the
|
|
140
|
+
* last page it ran, or the `after` it was given if it ran none.
|
|
141
|
+
*/
|
|
142
|
+
readonly next?: string;
|
|
143
|
+
/** The pages it ran `fn` on. */
|
|
144
|
+
readonly pages: number;
|
|
145
|
+
/** The items of those pages. */
|
|
146
|
+
readonly items: number;
|
|
147
|
+
}
|
|
148
|
+
export interface RepositoryForEachPage<Entity> {
|
|
149
|
+
/**
|
|
150
|
+
* Reads the pages of `query` by cursor, as `findCursor` does, and runs
|
|
151
|
+
* `fn` on each, one after the other, until the last or until `until`
|
|
152
|
+
* says to stop (checked between pages). Rows added or removed between
|
|
153
|
+
* pages, by `fn` too, are neither repeated nor skipped. An error of `fn`
|
|
154
|
+
* stops the walk and rejects; resume from the last `next` saved.
|
|
155
|
+
*/
|
|
156
|
+
forEachPage(query: RepositoryCursorQuery<Entity>, fn: (items: EntityInstanceOf<Entity>[], page: RepositoryWalkPage) => unknown, options?: RepositoryWalkOptions): Promise<RepositoryWalkResult>;
|
|
157
|
+
}
|
|
68
158
|
export interface RepositoryFindMany<Entity> {
|
|
69
159
|
findMany(query?: RepositoryQuery<Entity>): Promise<EntityInstanceOf<Entity>[]>;
|
|
70
160
|
}
|
|
@@ -94,6 +184,17 @@ export interface ProviderCapabilities {
|
|
|
94
184
|
readonly transactions?: boolean;
|
|
95
185
|
/** Whether `findMany` honors `after` (`ProviderQuery`), which `findCursor` needs. */
|
|
96
186
|
readonly keyset?: boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Whether the provider serves the indexes a repository declares
|
|
189
|
+
* (`context.indexes`) from storage, reading `ProviderQuery.index`.
|
|
190
|
+
*/
|
|
191
|
+
readonly indexes?: boolean;
|
|
192
|
+
/** Whether `update` honors an expected `version` (versioned entities, #44). */
|
|
193
|
+
readonly versioning?: boolean;
|
|
194
|
+
/** Whether the provider has an atomic `increment` (#34). */
|
|
195
|
+
readonly atomic?: boolean;
|
|
196
|
+
/** Whether reads leave out expired records (entities with `expires`, #35). */
|
|
197
|
+
readonly expiry?: boolean;
|
|
97
198
|
}
|
|
98
199
|
/** Declaration input for a named provider, implemented by providerOf in T10. */
|
|
99
200
|
export interface ProviderSettings<Options extends ProviderOptions = ProviderOptions, Provider extends IRepositoryProvider = IRepositoryProvider> {
|
|
@@ -3,7 +3,7 @@ import type { AbstractEntity, EntityUniqueKeys } from "../../entity/abstract-ent
|
|
|
3
3
|
import type { AnyEntityClass } from "../../entity/event.js";
|
|
4
4
|
import type { RecordSettings } from "../../record/types/record.interface.js";
|
|
5
5
|
import type { AbstractRepository } from "../repository.js";
|
|
6
|
-
import type { ProviderCapabilities, ProviderQuery, RepositoryExists, RepositoryFindCursor, RepositoryFindMany, RepositoryFindPage, RepositoryQuery } from "./query.interface.js";
|
|
6
|
+
import type { ProviderCapabilities, ProviderQuery, RepositoryExists, RepositoryExplain, RepositoryFindCursor, RepositoryFindMany, RepositoryFindPage, RepositoryForEachPage, RepositoryIndex, RepositoryQuery } from "./query.interface.js";
|
|
7
7
|
/** Any class made by `entityOf`, or extending one, that a repository holds. */
|
|
8
8
|
export type AnyRepositoryEntity = AnyRecordClass & AnyEntityClass & {
|
|
9
9
|
readonly [EntityUniqueKeys]: readonly string[];
|
|
@@ -38,6 +38,38 @@ export interface RepositoryCreate<Entity> {
|
|
|
38
38
|
export interface RepositoryUpdate<Entity> {
|
|
39
39
|
update(entity: EntityInstanceOf<Entity>): Promise<EntityInstanceOf<Entity>>;
|
|
40
40
|
}
|
|
41
|
+
type ChangeKeyOf<Entity> = EntityInstanceOf<Entity> extends {
|
|
42
|
+
readonly change: infer Change;
|
|
43
|
+
} ? keyof Change & string : never;
|
|
44
|
+
/**
|
|
45
|
+
* The keys `increment` takes for `Entity`: those of its `change` list that
|
|
46
|
+
* hold a number.
|
|
47
|
+
*/
|
|
48
|
+
export type EntityIncrementKeyOf<Entity> = {
|
|
49
|
+
[Key in ChangeKeyOf<Entity>]: NonNullable<ValueAt<Entity, Key>> extends number ? Key : never;
|
|
50
|
+
}[ChangeKeyOf<Entity>];
|
|
51
|
+
/** What `increment` adds to each key, e.g. `{ views: 1 }`. */
|
|
52
|
+
export type RepositoryIncrementDeltas<Entity> = {
|
|
53
|
+
readonly [Key in EntityIncrementKeyOf<Entity>]?: number;
|
|
54
|
+
};
|
|
55
|
+
/** The options of `increment`. */
|
|
56
|
+
export interface RepositoryIncrementOptions<Entity> {
|
|
57
|
+
/**
|
|
58
|
+
* The input of the entity to create when the id holds none, without its
|
|
59
|
+
* `id` (the one given) and with the keys of the deltas optional (0 when
|
|
60
|
+
* left out); the deltas are added to it.
|
|
61
|
+
*/
|
|
62
|
+
readonly create?: Omit<Entity extends new (value: infer Input) => unknown ? Input : never, "id" | EntityIncrementKeyOf<Entity>> & {
|
|
63
|
+
readonly [Key in EntityIncrementKeyOf<Entity>]?: number;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* `increment`: adds the deltas to the numeric keys of the entity of the id
|
|
68
|
+
* (or the one given) in one atomic write, and gives the entity as stored.
|
|
69
|
+
*/
|
|
70
|
+
export interface RepositoryIncrement<Entity> {
|
|
71
|
+
increment(entity: EntityInstanceOf<Entity> | string, deltas: RepositoryIncrementDeltas<Entity>, options?: RepositoryIncrementOptions<Entity>): Promise<EntityInstanceOf<Entity>>;
|
|
72
|
+
}
|
|
41
73
|
/** `delete`: destroys the entity (or the one of the id), removes it and gives it. */
|
|
42
74
|
export interface RepositoryDelete<Entity> {
|
|
43
75
|
delete(entity: EntityInstanceOf<Entity> | string): Promise<EntityInstanceOf<Entity>>;
|
|
@@ -74,19 +106,54 @@ export type RepositoryFindManyBy<Entity, Actions extends string = string> = {
|
|
|
74
106
|
* so that a class extending a repository can override them.
|
|
75
107
|
* @internal
|
|
76
108
|
*/
|
|
77
|
-
export type RepositoryMethods<Entity, Actions extends string = string> = RepositoryFindBy<Entity, Actions> & RepositoryFindManyBy<Entity, Actions> & ("create" extends Actions ? RepositoryCreate<Entity> : unknown) & ("update" extends Actions ? RepositoryUpdate<Entity> : unknown) & ("delete" extends Actions ? RepositoryDelete<Entity> : unknown) & ("restore" extends Actions ? RepositoryRestore<Entity> : unknown) & ("count" extends Actions ? RepositoryCount<Entity> : unknown) & ("findMany" extends Actions ? RepositoryFindMany<Entity> : unknown) & ("exists" extends Actions ? RepositoryExists<Entity> : unknown) & ("findPage" extends Actions ? RepositoryFindPage<Entity> : unknown) & ("findCursor" extends Actions ? RepositoryFindCursor<Entity> : unknown);
|
|
109
|
+
export type RepositoryMethods<Entity, Actions extends string = string> = RepositoryFindBy<Entity, Actions> & RepositoryFindManyBy<Entity, Actions> & ("create" extends Actions ? RepositoryCreate<Entity> : unknown) & ("update" extends Actions ? RepositoryUpdate<Entity> : unknown) & ("delete" extends Actions ? RepositoryDelete<Entity> : unknown) & ("restore" extends Actions ? RepositoryRestore<Entity> : unknown) & ("increment" extends Actions ? RepositoryIncrement<Entity> : unknown) & ("count" extends Actions ? RepositoryCount<Entity> : unknown) & ("findMany" extends Actions ? RepositoryFindMany<Entity> : unknown) & ("exists" extends Actions ? RepositoryExists<Entity> : unknown) & ("findPage" extends Actions ? RepositoryFindPage<Entity> : unknown) & ("findCursor" extends Actions ? RepositoryFindCursor<Entity> : unknown) & ("explain" extends Actions ? RepositoryExplain<Entity> : unknown) & ("forEachPage" extends Actions ? RepositoryForEachPage<Entity> : unknown);
|
|
78
110
|
/** A method a repository of `Entity` can have, e.g. `"findByEmail"`. */
|
|
79
|
-
export type RepositoryAction<Entity> = keyof RepositoryFindBy<Entity> | keyof RepositoryFindManyBy<Entity> | "create" | "update" | "delete" | "restore" | "count" | "findMany" | "exists" | "findPage" | "findCursor";
|
|
111
|
+
export type RepositoryAction<Entity> = keyof RepositoryFindBy<Entity> | keyof RepositoryFindManyBy<Entity> | "create" | "update" | "delete" | "restore" | "increment" | "count" | "findMany" | "exists" | "findPage" | "findCursor" | "explain" | "forEachPage";
|
|
112
|
+
/**
|
|
113
|
+
* Whether a repository given `Provider` keeps `findCursor`: `false` when the
|
|
114
|
+
* type of its `capabilities.keyset` cannot be `true` (left out of the
|
|
115
|
+
* capabilities, or `false`), `true` for `true`, for a wide `boolean`, and
|
|
116
|
+
* with no provider (the default in-memory one reads by cursor). `repositoryOf`
|
|
117
|
+
* infers only the `capabilities` of a provider: one without them keeps
|
|
118
|
+
* `findCursor` in the type and is rejected at declaration.
|
|
119
|
+
*/
|
|
120
|
+
export type ProviderKeyset<Provider> = undefined extends Provider ? true : Provider extends {
|
|
121
|
+
readonly capabilities?: infer Capabilities;
|
|
122
|
+
} ? [NonNullable<Capabilities>] extends [{
|
|
123
|
+
readonly keyset?: infer Keyset;
|
|
124
|
+
}] ? true extends Keyset ? true : false : false : false;
|
|
80
125
|
/**
|
|
81
126
|
* A repository of `Entity` with the methods of `Actions`, whose provider gets
|
|
82
127
|
* `Environment` as `context.env`, e.g.
|
|
83
128
|
* `RepositoryOf<typeof User, ["findById", "create"]>`.
|
|
84
129
|
*/
|
|
85
|
-
export type RepositoryOf<Entity extends AnyRepositoryEntity, Actions extends readonly RepositoryAction<Entity>[], Environment = Readonly<Record<never, never
|
|
130
|
+
export type RepositoryOf<Entity extends AnyRepositoryEntity, Actions extends readonly RepositoryAction<Entity>[], Environment = Readonly<Record<never, never>>, Keyset extends boolean = true> = AbstractRepository<Entity, Actions, Environment> & RepositoryMethods<Entity, Keyset extends true ? Actions[number] : Exclude<Actions[number], "findCursor">>;
|
|
86
131
|
/** Any repository, whatever its entity, actions and environment. */
|
|
87
132
|
export type AnyRepository = AbstractRepository<any, any, any>;
|
|
88
133
|
/** A value of an entity as a provider stores it: plain, unmasked. */
|
|
89
134
|
export type RepositoryData = Readonly<Record<string, unknown>>;
|
|
135
|
+
/** What `update` of a provider gets after the data. */
|
|
136
|
+
export interface ProviderUpdateOptions {
|
|
137
|
+
/** The `version` the stored row must hold for the write to happen. */
|
|
138
|
+
readonly expectedVersion?: number;
|
|
139
|
+
}
|
|
140
|
+
/** What `increment` of a provider gets after the deltas. */
|
|
141
|
+
export interface ProviderIncrementOptions {
|
|
142
|
+
/** Values stored as they are by the same write, e.g. `updatedAt`. */
|
|
143
|
+
readonly set?: RepositoryData;
|
|
144
|
+
/**
|
|
145
|
+
* The row to insert when the id holds none, or holds one that expired
|
|
146
|
+
* (which it replaces).
|
|
147
|
+
*/
|
|
148
|
+
readonly create?: RepositoryData;
|
|
149
|
+
/**
|
|
150
|
+
* For an entity that expires (`context.expiry`), the current date and
|
|
151
|
+
* time (ISO 8601) by the clock of the entity: a row whose expiry is at or
|
|
152
|
+
* before it counts as absent. A provider called without it uses the
|
|
153
|
+
* current time.
|
|
154
|
+
*/
|
|
155
|
+
readonly now?: string;
|
|
156
|
+
}
|
|
90
157
|
/** What a provider gets with every call: whose entities, and the environment. */
|
|
91
158
|
export interface RepositoryContext<Environment = unknown> {
|
|
92
159
|
/** The entity class; name a table after `recordNameOf(entity)`, not `entity.name`. */
|
|
@@ -98,6 +165,21 @@ export interface RepositoryContext<Environment = unknown> {
|
|
|
98
165
|
readonly name: string;
|
|
99
166
|
/** The keys no two entities may share, `id` first. */
|
|
100
167
|
readonly unique: readonly string[];
|
|
168
|
+
/**
|
|
169
|
+
* The indexes the repository declares, by name, for a provider to build
|
|
170
|
+
* (a GSI, an SQL index); a repository always gives it, empty when it
|
|
171
|
+
* declares none (optional for contexts built by hand).
|
|
172
|
+
*/
|
|
173
|
+
readonly indexes?: Readonly<Record<string, RepositoryIndex>>;
|
|
174
|
+
/**
|
|
175
|
+
* For an entity declared with `expires`, the key holding the date at which
|
|
176
|
+
* a record expires (`expiresAt`, or the key of `at`): reads leave out the
|
|
177
|
+
* records whose date is at or before `query.now`, unless
|
|
178
|
+
* `query.withExpired`. A record without a date never expires.
|
|
179
|
+
*/
|
|
180
|
+
readonly expiry?: {
|
|
181
|
+
readonly key: string;
|
|
182
|
+
};
|
|
101
183
|
/** The variables of the `environmentDependencies` of the repository. */
|
|
102
184
|
readonly env: Environment;
|
|
103
185
|
}
|
|
@@ -108,13 +190,30 @@ export interface RepositoryContext<Environment = unknown> {
|
|
|
108
190
|
* `RepositoryEntityNotFound` for an unknown id.
|
|
109
191
|
*/
|
|
110
192
|
export interface IRepositoryProvider<Environment = unknown> {
|
|
111
|
-
findOne(context: RepositoryContext<Environment>, query?:
|
|
193
|
+
findOne(context: RepositoryContext<Environment>, query?: ProviderQuery): Promise<RepositoryData | undefined>;
|
|
112
194
|
/** `query.after` is only given to a provider with `capabilities.keyset`. */
|
|
113
195
|
findMany(context: RepositoryContext<Environment>, query?: ProviderQuery): Promise<readonly RepositoryData[]>;
|
|
114
196
|
insert(context: RepositoryContext<Environment>, data: RepositoryData): Promise<void>;
|
|
115
|
-
|
|
197
|
+
/**
|
|
198
|
+
* With `options.expectedVersion`, writes only when the stored `version` is
|
|
199
|
+
* that one, and throws `RepositoryConcurrencyConflict` otherwise; only a
|
|
200
|
+
* provider with `capabilities.versioning` is given it.
|
|
201
|
+
*/
|
|
202
|
+
update(context: RepositoryContext<Environment>, data: RepositoryData, options?: ProviderUpdateOptions): Promise<void>;
|
|
116
203
|
remove(context: RepositoryContext<Environment>, id: string): Promise<void>;
|
|
117
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Adds each of `deltas` to the stored number of its key (a missing one
|
|
206
|
+
* counts as 0) and stores `options.set` in the same atomic write, then
|
|
207
|
+
* gives the row as stored. Only rows that are not soft-deleted, nor expired
|
|
208
|
+
* (`context.expiry`, at `options.now`), match. When the id holds none (or
|
|
209
|
+
* an expired one), inserts `options.create` as it is, replacing the expired
|
|
210
|
+
* row, and gives it, or throws `RepositoryEntityNotFound` without it; a
|
|
211
|
+
* concurrent insert of the same id still gets the deltas added. A
|
|
212
|
+
* soft-deleted row with `create` is a `RepositoryUniqueViolation` on `id`.
|
|
213
|
+
* Advertised by `capabilities.atomic`.
|
|
214
|
+
*/
|
|
215
|
+
increment?(context: RepositoryContext<Environment>, id: string, deltas: Readonly<Record<string, number>>, options?: ProviderIncrementOptions): Promise<RepositoryData>;
|
|
216
|
+
count(context: RepositoryContext<Environment>, query?: ProviderQuery): Promise<number>;
|
|
118
217
|
readonly capabilities?: ProviderCapabilities;
|
|
119
218
|
transaction?<Result>(run: (provider: IRepositoryProvider<Environment>) => Promise<Result>): Promise<Result>;
|
|
120
219
|
/** Releases what the provider holds (connections, files); `app.stop()` calls it. */
|
package/dist/experimental.js
CHANGED
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
listOf2,
|
|
7
7
|
isBlueprintList2,
|
|
8
8
|
AbstractRecord2,
|
|
9
|
-
declareRecord,
|
|
10
|
-
optionalOf2,
|
|
11
9
|
UndeclaredBlueprintProperty2,
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
optionalOf2,
|
|
11
|
+
blueprintFromProperties,
|
|
12
|
+
declareRecord
|
|
13
|
+
} from "./index-qxfkyd6k.js";
|
|
14
14
|
|
|
15
15
|
// src/core/blueprint/slice.ts
|
|
16
16
|
function propertiesOfField(field) {
|