@afora/core 0.0.4 → 0.0.5

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.
@@ -40,6 +40,15 @@ export declare const ApplicationNotStarted: import("../../index.js").DeclaredExc
40
40
  /** The application, or none when `useApplication()` found none started. */
41
41
  readonly application?: string;
42
42
  }>;
43
+ /**
44
+ * A repository read or wrote through a provider of `providersOf` made by
45
+ * `providerFrom` outside an application: an application that registers the
46
+ * storage makes it on start, and its bound repositories use it.
47
+ */
48
+ export declare const ProviderNotBound: import("../../index.js").DeclaredExceptionClass<{
49
+ /** The key of the provider in its storage. */
50
+ readonly provider: string;
51
+ }>;
43
52
  /**
44
53
  * `app.start()` was called while another application is the started one of
45
54
  * the process; `start({ replace: true })` stops it and takes its place.
@@ -0,0 +1,46 @@
1
+ import type { IRepositoryProvider } from "../repository/types/repository.interface.js";
2
+ import { Kind } from "../symbols/kind.js";
3
+ import { type ProviderFactory } from "./start.js";
4
+ /**
5
+ * One provider of a storage made by `providersOf`, e.g. `Providers.audit`:
6
+ * what a repository (`repositoryOf({ provider: Providers.audit })`) or an
7
+ * application (`provider: Providers.main`) names. Each application that
8
+ * registers the storage reads and writes through its own instance of it.
9
+ */
10
+ export type ProviderSlot<Key extends string = string> = IRepositoryProvider & {
11
+ readonly [Kind]: "provider-slot";
12
+ /** Its key in the storage. */
13
+ readonly key: Key;
14
+ };
15
+ /** The providers of `providersOf`, by key. */
16
+ export type ProviderStorage<Keys extends string = string> = {
17
+ readonly [Key in Keys]: ProviderSlot<Key>;
18
+ } & {
19
+ readonly [Kind]: "provider-storage";
20
+ };
21
+ /** What a slot stands for. */
22
+ interface SlotEntry {
23
+ readonly key: string;
24
+ readonly storage: object;
25
+ readonly value: IRepositoryProvider | ProviderFactory;
26
+ }
27
+ /**
28
+ * Named providers, declared once in a module of their own so that
29
+ * repositories can name one before any application exists, e.g.
30
+ * `const Providers = providersOf({ main: providerFrom(Database, ...), audit: auditProvider() })`,
31
+ * then `repositoryOf({ ..., provider: Providers.audit })` and
32
+ * `applicationOf({ providers: Providers, provider: Providers.main, ... })`.
33
+ * Each value is a provider or a factory of `providerFrom`; an application
34
+ * that registers the storage makes each factory on `start()`, its own
35
+ * instance (an application that extends it shares them).
36
+ */
37
+ export declare function providersOf<const Entries extends Readonly<Record<string, IRepositoryProvider | ProviderFactory>>>(entries: Entries): ProviderStorage<keyof Entries & string>;
38
+ /** Whether `value` is a provider of a storage made by `providersOf`. */
39
+ export declare function isProviderSlot(value: unknown): value is ProviderSlot;
40
+ /** Whether `value` is a storage made by `providersOf`. */
41
+ export declare function isProviderStorage(value: unknown): value is ProviderStorage;
42
+ /** The slots of `storage`, in the order of its keys. @internal */
43
+ export declare function slotsOf(storage: ProviderStorage): readonly ProviderSlot[];
44
+ /** What `slot` stands for. @internal */
45
+ export declare function slotEntry(slot: ProviderSlot): SlotEntry;
46
+ export {};
@@ -9,6 +9,7 @@ import type { AnyRepository, IRepositoryProvider } from "../../repository/types/
9
9
  import type { Kind } from "../../symbols/kind.js";
10
10
  import type { UseCaseStepDescription } from "../../use-case/steps/types/steps.interface.js";
11
11
  import type { AnyExceptionClass, AnyUseCaseClass } from "../../use-case/use-case.js";
12
+ import type { ProviderSlot, ProviderStorage } from "../providers.js";
12
13
  import type { LogFactory, ProviderFactory } from "../start.js";
13
14
  type Named<Value> = Readonly<Record<string, Value>>;
14
15
  /** The declarations of an application, by name, one collection for each kind. */
@@ -53,9 +54,18 @@ export interface ApplicationSettings<Name extends string, Extended extends reado
53
54
  * The provider of the repositories that did not declare one; the
54
55
  * repositories of the application read and write through it. With
55
56
  * `providerFrom`, it is made by `app.start()` from the variables of its
56
- * environments, and calls before that throw `ApplicationNotStarted`.
57
+ * environments, and calls before that throw `ApplicationNotStarted`. A
58
+ * provider of `providers` (`Providers.main`) names the instance this
59
+ * application makes of it.
57
60
  */
58
61
  readonly provider?: IRepositoryProvider | ProviderFactory;
62
+ /**
63
+ * Named providers made by `providersOf`, which repositories name
64
+ * (`repositoryOf({ provider: Providers.audit })`). The application makes
65
+ * its own instance of each `providerFrom` on `start()` and binds the
66
+ * repositories to it; an application that extends it shares them.
67
+ */
68
+ readonly providers?: ProviderStorage;
59
69
  /**
60
70
  * How it logs: the providers its lines go to and the lowest level kept.
61
71
  * Use cases, commands and repository calls of the application are logged
@@ -163,6 +173,8 @@ export interface IApplication<Name extends string, Collections extends Applicati
163
173
  get<UseCase extends AnyUseCaseClass>(useCase: UseCase): UseCase;
164
174
  /** The bound version of a repository registered in the application. */
165
175
  get<Repository extends AnyRepository>(repository: Repository): Repository;
176
+ /** The instance this application reads and writes through for a provider of its `providers`. */
177
+ get(provider: ProviderSlot): IRepositoryProvider;
166
178
  /** Whether `start()` completed and `stop()` was not called since. */
167
179
  readonly started: boolean;
168
180
  }
@@ -345,13 +357,22 @@ export interface LogDescription {
345
357
  readonly kind: "opaque";
346
358
  })[];
347
359
  }
360
+ /** How `describe` names a provider of `providersOf`: by its key. */
361
+ export interface ProviderReference {
362
+ readonly kind: "ref";
363
+ readonly key: string;
364
+ }
348
365
  /** The graph `describe` gives: every declaration by name, with its origin in `from`. */
349
366
  export interface ApplicationDescription {
350
367
  readonly name: string;
351
368
  /** The names of the applications it extends directly. */
352
369
  readonly extends: readonly string[];
353
370
  /** The provider of the application (or of the last extended one), present only when configured. */
354
- readonly provider?: ProviderDescription;
371
+ readonly provider?: ProviderDescription | ProviderReference;
372
+ /** Its providers of `providersOf` (inherited ones included), by key; present only when it has some. */
373
+ readonly providers?: Readonly<Record<string, ProviderDescription & {
374
+ readonly from: string;
375
+ }>>;
355
376
  /** Its `log` (or the one of the last extended application), present only when configured. */
356
377
  readonly log?: LogDescription | {
357
378
  readonly kind: "opaque";
@@ -378,8 +399,8 @@ export interface ApplicationDescription {
378
399
  readonly relations: readonly string[];
379
400
  /** The names of its `environmentDependencies`. */
380
401
  readonly environments: readonly string[];
381
- /** Its own provider, present only when it declared one. */
382
- readonly provider?: ProviderDescription;
402
+ /** Its own provider, present only when it declared one; a provider of `providersOf` by its key. */
403
+ readonly provider?: ProviderDescription | ProviderReference;
383
404
  }>>;
384
405
  readonly useCases: Readonly<Record<string, UseCaseDescription>>;
385
406
  readonly commands: Readonly<Record<string, CommandDescription>>;
@@ -39,6 +39,7 @@ export interface RepositoryInspection {
39
39
  export declare function inspectRepository(repository: unknown): RepositoryInspection | undefined;
40
40
  /**
41
41
  * A repository sharing the declaration of `repository` that reads and writes
42
- * through `provider`, unless it declared a provider of its own.
42
+ * through `provider`, unless it declared a provider of its own; a declared
43
+ * provider found in `instances` is replaced by its value.
43
44
  */
44
- export declare function bindRepository<Repository extends object>(repository: Repository, provider: IRepositoryProvider): Repository;
45
+ export declare function bindRepository<Repository extends object>(repository: Repository, provider: IRepositoryProvider | undefined, instances?: ReadonlyMap<object, IRepositoryProvider>): Repository;
@@ -60,6 +60,7 @@ __export(exports_exceptions4, {
60
60
  DuplicateApplicationDeclaration: () => DuplicateApplicationDeclaration2,
61
61
  InvalidApplicationDeclaration: () => InvalidApplicationDeclaration2,
62
62
  InvalidApplicationEnvironment: () => InvalidApplicationEnvironment2,
63
+ ProviderNotBound: () => ProviderNotBound2,
63
64
  UnregisteredApplicationReference: () => UnregisteredApplicationReference2,
64
65
  UnregisteredRepositoryDependency: () => UnregisteredRepositoryDependency2,
65
66
  UnregisteredUseCaseDependency: () => UnregisteredUseCaseDependency2
@@ -268,6 +269,13 @@ var ApplicationNotStarted2 = exceptionOf2({
268
269
  application
269
270
  }) => application === undefined ? "No application is started: call await app.start() first." : `The application "${application}" is not started: call await app.start() first.`
270
271
  });
272
+ var ProviderNotBound2 = exceptionOf2({
273
+ layer: "application" /* Application */,
274
+ name: "ProviderNotBound",
275
+ message: ({
276
+ provider
277
+ }) => `The provider "${provider}" is made by an application: register its storage in applicationOf({ providers }) and call the repository through the application.`
278
+ });
271
279
  var ApplicationAlreadyStarted2 = exceptionOf2({
272
280
  layer: "application" /* Application */,
273
281
  name: "ApplicationAlreadyStarted",
@@ -1083,31 +1091,31 @@ var origins = new WeakMap;
1083
1091
  function declarationOf(state) {
1084
1092
  return origins.get(state) ?? state;
1085
1093
  }
1086
- function bindState(state, provider, bound = new Map) {
1094
+ function bindState(state, provider, instances, bound = new Map) {
1087
1095
  const done = bound.get(state);
1088
1096
  if (done)
1089
1097
  return done;
1090
1098
  const copy = {
1091
1099
  ...state,
1092
- provider: state.explicitProvider ? state.provider : provider,
1100
+ provider: state.explicitProvider ? instances?.get(state.provider) ?? state.provider : provider ?? state.provider,
1093
1101
  context: undefined,
1094
1102
  relations: new Map([...state.relations].map(([target, related]) => [
1095
1103
  target,
1096
- bindState(related, provider, bound)
1104
+ bindState(related, provider, instances, bound)
1097
1105
  ]))
1098
1106
  };
1099
1107
  origins.set(copy, declarationOf(state));
1100
1108
  bound.set(state, copy);
1101
1109
  return copy;
1102
1110
  }
1103
- function bindRepository(repository, provider) {
1111
+ function bindRepository(repository, provider, instances) {
1104
1112
  const state = stateOf(repository);
1105
1113
  const Declared = repository.constructor;
1106
1114
 
1107
1115
  class Bound extends Declared {
1108
1116
  }
1109
1117
  Object.defineProperty(Bound, "name", { value: Declared.name });
1110
- states.set(Bound, bindState(state, provider));
1118
+ states.set(Bound, bindState(state, provider, instances));
1111
1119
  return Object.freeze(new Bound);
1112
1120
  }
1113
1121
 
@@ -2403,7 +2411,7 @@ function commandTransactionProvider(command) {
2403
2411
  return verifiers.get(command)?.();
2404
2412
  }
2405
2413
  var IDENTIFIER2 = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
2406
- function providersOf(useCases, declared) {
2414
+ function repositoryProvidersOf(useCases, declared) {
2407
2415
  const providers = new Map;
2408
2416
  const seen = new Set;
2409
2417
  const add = (state) => {
@@ -2437,7 +2445,7 @@ function providersOf(useCases, declared) {
2437
2445
  return providers;
2438
2446
  }
2439
2447
  function transactionProviderOf(name, useCases, declared = false) {
2440
- const providers = providersOf(useCases, declared);
2448
+ const providers = repositoryProvidersOf(useCases, declared);
2441
2449
  const invalid = (reason, repositories) => {
2442
2450
  throw new InvalidCommandDeclaration2({
2443
2451
  source: name,
@@ -3352,6 +3360,106 @@ function checkTransactions(source, provider, commands) {
3352
3360
  }
3353
3361
  }
3354
3362
 
3363
+ // src/core/application/providers.ts
3364
+ var slots = new WeakMap;
3365
+ var storages = new WeakMap;
3366
+ var METHODS2 = [
3367
+ "findOne",
3368
+ "findMany",
3369
+ "insert",
3370
+ "update",
3371
+ "remove",
3372
+ "count"
3373
+ ];
3374
+ var KEY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
3375
+ var RESERVED = new Set(["inMemory", "__proto__", "constructor", "prototype"]);
3376
+ function invalid6(reason) {
3377
+ throw new InvalidApplicationDeclaration2({
3378
+ source: "providersOf",
3379
+ details: { reason }
3380
+ });
3381
+ }
3382
+ function isProviderObject(value) {
3383
+ return typeof value === "object" && value !== null && !isProviderFactory2(value) && METHODS2.some((method) => typeof value[method] === "function");
3384
+ }
3385
+ function slotOf(key, storage, value) {
3386
+ const slot = {
3387
+ [Kind2]: "provider-slot",
3388
+ key
3389
+ };
3390
+ if (isProviderFactory2(value)) {
3391
+ const unbound = () => {
3392
+ throw new ProviderNotBound2({ source: key, details: { provider: key } });
3393
+ };
3394
+ for (const method of METHODS2)
3395
+ slot[method] = unbound;
3396
+ slot.transaction = unbound;
3397
+ Object.defineProperty(slot, "capabilities", {
3398
+ get: () => {
3399
+ return;
3400
+ },
3401
+ enumerable: true
3402
+ });
3403
+ } else {
3404
+ const target = value;
3405
+ for (const method of [...METHODS2, "transaction", "close"]) {
3406
+ if (typeof target[method] === "function") {
3407
+ slot[method] = (...args) => target[method]?.(...args);
3408
+ }
3409
+ }
3410
+ Object.defineProperty(slot, "capabilities", {
3411
+ get: () => value.capabilities,
3412
+ enumerable: true
3413
+ });
3414
+ }
3415
+ Object.freeze(slot);
3416
+ slots.set(slot, { key, storage, value });
3417
+ return slot;
3418
+ }
3419
+ function providersOf2(entries) {
3420
+ if (typeof entries !== "object" || entries === null || Array.isArray(entries) || Object.keys(entries).length === 0) {
3421
+ invalid6("Expected an object of providers by key.");
3422
+ }
3423
+ const storage = Object.create(null);
3424
+ storage[Kind2] = "provider-storage";
3425
+ const seen = new Map;
3426
+ const list = [];
3427
+ for (const [key, value] of Object.entries(entries)) {
3428
+ if (!KEY.test(key) || RESERVED.has(key)) {
3429
+ invalid6(key === "inMemory" ? `"inMemory" is the built-in provider; choose another key.` : `Expected "${key}" to be an identifier that is not reserved.`);
3430
+ }
3431
+ if (isProviderSlot2(value)) {
3432
+ invalid6(`"${key}" holds a provider of another storage; a storage holds providers, not slots.`);
3433
+ }
3434
+ if (!isProviderFactory2(value) && !isProviderObject(value)) {
3435
+ invalid6(`Expected "${key}" to be a repository provider or a factory of providerFrom.`);
3436
+ }
3437
+ const other = seen.get(value);
3438
+ if (other !== undefined) {
3439
+ invalid6(`"${other}" and "${key}" hold the same provider.`);
3440
+ }
3441
+ seen.set(value, key);
3442
+ const slot = slotOf(key, storage, value);
3443
+ storage[key] = slot;
3444
+ list.push(slot);
3445
+ }
3446
+ Object.freeze(storage);
3447
+ storages.set(storage, Object.freeze(list));
3448
+ return storage;
3449
+ }
3450
+ function isProviderSlot2(value) {
3451
+ return typeof value === "object" && value !== null && slots.has(value);
3452
+ }
3453
+ function isProviderStorage2(value) {
3454
+ return typeof value === "object" && value !== null && storages.has(value);
3455
+ }
3456
+ function slotsOf(storage) {
3457
+ return storages.get(storage) ?? [];
3458
+ }
3459
+ function slotEntry(slot) {
3460
+ return slots.get(slot);
3461
+ }
3462
+
3355
3463
  // src/core/application/application.ts
3356
3464
  var KEYS = [
3357
3465
  "properties",
@@ -3367,6 +3475,11 @@ var KEYS = [
3367
3475
  ];
3368
3476
  var internals = new WeakMap;
3369
3477
  var logSettings = new WeakMap;
3478
+ var namedProviders = new WeakMap;
3479
+ var defaultSlots = new WeakMap;
3480
+ function referenceOf(slot) {
3481
+ return { kind: "ref", key: slotEntry(slot).key };
3482
+ }
3370
3483
  var KIND_OF = {
3371
3484
  properties: "property",
3372
3485
  blueprints: "blueprint",
@@ -3382,7 +3495,7 @@ var KIND_OF = {
3382
3495
  function isApplication2(value) {
3383
3496
  return typeof value === "object" && value !== null && value[Kind2] === "application";
3384
3497
  }
3385
- function invalid6(source, reason) {
3498
+ function invalid7(source, reason) {
3386
3499
  throw new InvalidApplicationDeclaration2({ source, details: { reason } });
3387
3500
  }
3388
3501
  function isOfKind(collection, value) {
@@ -3467,7 +3580,7 @@ function resolve(settings) {
3467
3580
  for (const other of settings.extends ?? []) {
3468
3581
  const resolved = internals.get(other);
3469
3582
  if (!resolved)
3470
- invalid6(source, "Expected `extends` to hold applications.");
3583
+ invalid7(source, "Expected `extends` to hold applications.");
3471
3584
  for (const key of KEYS) {
3472
3585
  for (const entry of resolved[key].values())
3473
3586
  add(entry);
@@ -3478,15 +3591,15 @@ function resolve(settings) {
3478
3591
  if (declared === undefined)
3479
3592
  continue;
3480
3593
  if (typeof declared !== "object" || declared === null || Array.isArray(declared)) {
3481
- invalid6(source, `Expected ${collection} to be an object of declarations.`);
3594
+ invalid7(source, `Expected ${collection} to be an object of declarations.`);
3482
3595
  }
3483
3596
  for (const [name, value] of Object.entries(declared)) {
3484
3597
  if (!isOfKind(collection, value)) {
3485
- invalid6(source, `${collection}.${name} is not a ${KIND_OF[collection]} (${collection} takes ${KIND_OF[collection]} declarations).`);
3598
+ invalid7(source, `${collection}.${name} is not a ${KIND_OF[collection]} (${collection} takes ${KIND_OF[collection]} declarations).`);
3486
3599
  }
3487
3600
  const declaredName = collection === "useCases" ? value.useCaseName : collection === "commands" ? value.commandName : collection === "outputs" ? value.outputName : collection === "exceptions" ? value.name : name;
3488
3601
  if (declaredName !== name) {
3489
- invalid6(source, `${collection}.${name} must be keyed by its name, "${declaredName}".`);
3602
+ invalid7(source, `${collection}.${name} must be keyed by its name, "${declaredName}".`);
3490
3603
  }
3491
3604
  add({
3492
3605
  collection,
@@ -3607,7 +3720,7 @@ function validateOutputs(source, registry) {
3607
3720
  for (const entry of registry.outputs.values()) {
3608
3721
  const output = entry.value;
3609
3722
  if (!output.outputName) {
3610
- invalid6(source, `outputs.${entry.name} has no name (an output made by pipe cannot be registered).`);
3723
+ invalid7(source, `outputs.${entry.name} has no name (an output made by pipe cannot be registered).`);
3611
3724
  }
3612
3725
  for (const command of output.commands) {
3613
3726
  if (commands.has(command))
@@ -3809,7 +3922,7 @@ function recordDescriptionOf(entry, scope) {
3809
3922
  plugins
3810
3923
  };
3811
3924
  }
3812
- function describeRegistry(name, extended, registry, provider, log) {
3925
+ function describeRegistry(name, extended, registry, provider, named, log) {
3813
3926
  const scope = {
3814
3927
  properties: referencesOf(registry, "properties"),
3815
3928
  blueprints: referencesOf(registry, "blueprints"),
@@ -3849,7 +3962,19 @@ function describeRegistry(name, extended, registry, provider, log) {
3849
3962
  return {
3850
3963
  name,
3851
3964
  extends: extended.map((other) => other.name),
3852
- ...provider === undefined ? {} : { provider: providerDescriptionOf2(provider) },
3965
+ ...provider === undefined ? {} : { provider },
3966
+ ...named.size === 0 ? {} : {
3967
+ providers: Object.fromEntries([...named].map(([key, { slot, from }]) => {
3968
+ const { value } = slotEntry(slot);
3969
+ return [
3970
+ key,
3971
+ {
3972
+ from,
3973
+ ...isProviderFactory2(value) ? { kind: "opaque" } : providerDescriptionOf2(value)
3974
+ }
3975
+ ];
3976
+ }))
3977
+ },
3853
3978
  ...log === undefined ? {} : log === "opaque" ? { log: { kind: "opaque" } } : {
3854
3979
  log: {
3855
3980
  level: log.level,
@@ -3882,7 +4007,9 @@ function describeRegistry(name, extended, registry, provider, log) {
3882
4007
  deletion: info.deletion,
3883
4008
  relations: info.relations.map((relation) => repositories.get(relation)),
3884
4009
  environments: info.environments.map((environment) => environmentRefs.get(environment)),
3885
- ...info.provider === undefined ? {} : { provider: providerDescriptionOf2(info.provider) }
4010
+ ...info.provider === undefined ? {} : {
4011
+ provider: isProviderSlot2(info.provider) ? referenceOf(info.provider) : providerDescriptionOf2(info.provider)
4012
+ }
3886
4013
  };
3887
4014
  }),
3888
4015
  useCases: each("useCases", (entry) => {
@@ -3970,35 +4097,101 @@ function describeRegistry(name, extended, registry, provider, log) {
3970
4097
  function applicationOf2(settings) {
3971
4098
  const { name } = settings ?? {};
3972
4099
  if (typeof name !== "string" || name === "") {
3973
- invalid6("applicationOf", "Expected a name.");
4100
+ invalid7("applicationOf", "Expected a name.");
3974
4101
  }
3975
4102
  const extended = settings.extends ?? [];
3976
4103
  if (!Array.isArray(extended) || !extended.every(isApplication2)) {
3977
- invalid6(name, "Expected `extends` to be a list of applications.");
4104
+ invalid7(name, "Expected `extends` to be a list of applications.");
3978
4105
  }
3979
4106
  const registry = resolve(settings);
3980
4107
  validate(name, registry);
3981
4108
  validateUseCases(name, registry);
3982
4109
  validateCommands(name, registry);
3983
4110
  validateOutputs(name, registry);
3984
- const declaredProvider = settings.provider ?? [...extended].reverse().find((other) => other.provider)?.provider;
3985
- if (declaredProvider !== undefined && typeof declaredProvider !== "object") {
3986
- invalid6(name, "Expected `provider` to be a repository provider.");
4111
+ if (settings.providers !== undefined && !isProviderStorage2(settings.providers)) {
4112
+ invalid7(name, "Expected `providers` to be a storage made by providersOf.");
3987
4113
  }
3988
- const provider = isProviderFactory2(declaredProvider) ? deferredProvider(declaredProvider, name) : declaredProvider;
3989
- {
3990
- const registered = new Set([...registry.environments.values()].map((entry) => entry.key));
3991
- for (const environment of deferredEnvironments(provider)) {
3992
- if (registered.has(environment))
3993
- continue;
4114
+ const named = new Map;
4115
+ const addNamed = (entry) => {
4116
+ const { key } = slotEntry(entry.slot);
4117
+ const current = named.get(key);
4118
+ if (current !== undefined && current.slot !== entry.slot) {
4119
+ throw new ApplicationConflict2({
4120
+ source: name,
4121
+ details: {
4122
+ reason: `The provider "${key}" is declared by different storages, in "${current.from}" and "${entry.from}".`,
4123
+ origins: [current.from, entry.from],
4124
+ declarations: [`provider ${key}`, `provider ${key}`]
4125
+ }
4126
+ });
4127
+ }
4128
+ named.set(key, entry);
4129
+ };
4130
+ for (const other of extended) {
4131
+ for (const entry of namedProviders.get(other)?.values() ?? []) {
4132
+ addNamed(entry);
4133
+ }
4134
+ }
4135
+ for (const slot of settings.providers ? slotsOf(settings.providers) : []) {
4136
+ const inherited = named.get(slotEntry(slot).key);
4137
+ if (inherited?.slot === slot)
4138
+ continue;
4139
+ const { value } = slotEntry(slot);
4140
+ addNamed({
4141
+ slot,
4142
+ from: name,
4143
+ instance: isProviderFactory2(value) ? deferredProvider(value, name) : value
4144
+ });
4145
+ }
4146
+ const instances = new Map([...named.values()].map((entry) => [entry.slot, entry.instance]));
4147
+ const instanceOf = (slot, holder) => {
4148
+ const instance = instances.get(slot);
4149
+ if (instance === undefined) {
3994
4150
  throw new UnregisteredApplicationReference2({
3995
4151
  source: name,
3996
4152
  details: {
3997
- holder: "the provider",
3998
- reference: "an environment"
4153
+ holder,
4154
+ reference: `provider "${slotEntry(slot).key}"`
3999
4155
  }
4000
4156
  });
4001
4157
  }
4158
+ return instance;
4159
+ };
4160
+ for (const entry of registry.repositories.values()) {
4161
+ const declared = inspectRepository(entry.value).provider;
4162
+ if (isProviderSlot2(declared)) {
4163
+ instanceOf(declared, `repository "${entry.name}"`);
4164
+ }
4165
+ }
4166
+ const inheritedFrom = settings.provider === undefined ? [...extended].reverse().find((other) => other.provider) : undefined;
4167
+ const declaredProvider = settings.provider ?? inheritedFrom?.provider;
4168
+ if (declaredProvider !== undefined && typeof declaredProvider !== "object") {
4169
+ invalid7(name, "Expected `provider` to be a repository provider.");
4170
+ }
4171
+ const defaultSlot = isProviderSlot2(declaredProvider) ? declaredProvider : inheritedFrom === undefined ? undefined : defaultSlots.get(inheritedFrom);
4172
+ const provider = defaultSlot !== undefined ? instanceOf(defaultSlot, "the application") : isProviderFactory2(declaredProvider) ? deferredProvider(declaredProvider, name) : declaredProvider;
4173
+ const allProviders = [
4174
+ ...new Set([provider, ...instances.values()].filter((value) => value !== undefined))
4175
+ ];
4176
+ {
4177
+ const registered = new Set([...registry.environments.values()].map((entry) => entry.key));
4178
+ const holderOf = (instance) => {
4179
+ const entry = [...named.values()].find((candidate) => candidate.instance === instance);
4180
+ return entry === undefined || instance === provider ? "the provider" : `provider "${slotEntry(entry.slot).key}"`;
4181
+ };
4182
+ for (const instance of allProviders) {
4183
+ for (const environment of deferredEnvironments(instance)) {
4184
+ if (registered.has(environment))
4185
+ continue;
4186
+ throw new UnregisteredApplicationReference2({
4187
+ source: name,
4188
+ details: {
4189
+ holder: holderOf(instance),
4190
+ reference: "an environment"
4191
+ }
4192
+ });
4193
+ }
4194
+ }
4002
4195
  }
4003
4196
  const declaredLog = settings.log ?? [...extended].reverse().map((other) => logSettings.get(other)).find((log) => log !== undefined);
4004
4197
  const log = declaredLog === undefined ? undefined : applicationLogger(name);
@@ -4006,13 +4199,14 @@ function applicationOf2(settings) {
4006
4199
  log?.set(checkLogSettings(declaredLog));
4007
4200
  }
4008
4201
  const logger = log?.logger;
4009
- const rebinds = provider !== undefined || logger !== undefined;
4202
+ const bindsProviders = provider !== undefined || instances.size > 0;
4203
+ const rebinds = bindsProviders || logger !== undefined;
4010
4204
  const collection = (key) => Object.freeze(Object.fromEntries([...registry[key].values()].map((entry) => [entry.name, entry.value])));
4011
4205
  const bound = new Map;
4012
4206
  const boundByState = new Map;
4013
4207
  const repositories = {};
4014
4208
  for (const entry of registry.repositories.values()) {
4015
- const repository = provider === undefined ? entry.value : bindRepository(entry.value, provider);
4209
+ const repository = bindsProviders ? bindRepository(entry.value, provider, instances) : entry.value;
4016
4210
  bound.set(entry.value, repository);
4017
4211
  boundByState.set(entry.key, repository);
4018
4212
  repositories[entry.name] = repository;
@@ -4066,7 +4260,7 @@ function applicationOf2(settings) {
4066
4260
  events: declared.events,
4067
4261
  onEventError: declared.onEventError
4068
4262
  });
4069
- if (provider !== undefined)
4263
+ if (bindsProviders)
4070
4264
  verifyCommand(rebuilt);
4071
4265
  boundCommandOf.set(entry.value, rebuilt);
4072
4266
  commands[entry.name] = rebuilt;
@@ -4127,9 +4321,11 @@ function applicationOf2(settings) {
4127
4321
  if (isLogFactory2(declaredLog)) {
4128
4322
  log?.set(checkLogSettings(await declaredLog.create(context)));
4129
4323
  }
4130
- if (provider !== undefined && isDeferredProvider(provider)) {
4131
- const made = await startDeferred(provider, context);
4132
- checkTransactions(name, made, Object.entries(commands).filter(([, command]) => command.transaction && commandTransactionProvider(command) === provider).map(([key]) => key));
4324
+ for (const instance of allProviders) {
4325
+ if (!isDeferredProvider(instance))
4326
+ continue;
4327
+ const made = await startDeferred(instance, context);
4328
+ checkTransactions(name, made, Object.entries(commands).filter(([, command]) => command.transaction && commandTransactionProvider(command) === instance).map(([key]) => key));
4133
4329
  }
4134
4330
  started = true;
4135
4331
  };
@@ -4153,25 +4349,25 @@ function applicationOf2(settings) {
4153
4349
  exceptions: collection("exceptions"),
4154
4350
  useCase(useCase) {
4155
4351
  if (!boundUseCaseOf.has(useCase)) {
4156
- invalid6(name, "Expected a use case registered in the application.");
4352
+ invalid7(name, "Expected a use case registered in the application.");
4157
4353
  }
4158
4354
  return boundUseCaseOf.get(useCase);
4159
4355
  },
4160
4356
  command(command) {
4161
4357
  if (!boundCommandOf.has(command)) {
4162
- invalid6(name, "Expected a command registered in the application.");
4358
+ invalid7(name, "Expected a command registered in the application.");
4163
4359
  }
4164
4360
  return boundCommandOf.get(command);
4165
4361
  },
4166
4362
  output(output) {
4167
4363
  if (!boundOutputOf.has(output)) {
4168
- invalid6(name, "Expected an output registered in the application.");
4364
+ invalid7(name, "Expected an output registered in the application.");
4169
4365
  }
4170
4366
  return boundOutputOf.get(output);
4171
4367
  },
4172
4368
  repository(repository) {
4173
4369
  if (!bound.has(repository)) {
4174
- invalid6(name, "Expected a repository registered in the application.");
4370
+ invalid7(name, "Expected a repository registered in the application.");
4175
4371
  }
4176
4372
  return bound.get(repository);
4177
4373
  },
@@ -4179,11 +4375,11 @@ function applicationOf2(settings) {
4179
4375
  return applicationOf2({
4180
4376
  name,
4181
4377
  extends: [application, ...others],
4182
- ...provider === undefined ? {} : { provider },
4378
+ ...provider === undefined ? {} : { provider: defaultSlot ?? provider },
4183
4379
  ...declaredLog === undefined ? {} : { log: declaredLog }
4184
4380
  });
4185
4381
  },
4186
- describe: () => describeRegistry(name, extended, registry, provider, isLogFactory2(declaredLog) ? "opaque" : log?.settings),
4382
+ describe: () => describeRegistry(name, extended, registry, defaultSlot !== undefined ? referenceOf(defaultSlot) : provider === undefined ? undefined : providerDescriptionOf2(provider), named, isLogFactory2(declaredLog) ? "opaque" : log?.settings),
4187
4383
  get started() {
4188
4384
  return started;
4189
4385
  },
@@ -4207,8 +4403,9 @@ function applicationOf2(settings) {
4207
4403
  setStartedApplication(application);
4208
4404
  })().then(() => application, async (error) => {
4209
4405
  starting = undefined;
4210
- if (provider !== undefined && isDeferredProvider(provider)) {
4211
- await stopProvider(provider);
4406
+ for (const instance of allProviders) {
4407
+ if (isDeferredProvider(instance))
4408
+ await stopProvider(instance);
4212
4409
  }
4213
4410
  if (isLogFactory2(declaredLog))
4214
4411
  log?.set(undefined);
@@ -4226,8 +4423,8 @@ function applicationOf2(settings) {
4226
4423
  });
4227
4424
  if (startedApplication() === application)
4228
4425
  setStartedApplication(undefined);
4229
- if (provider !== undefined)
4230
- await stopProvider(provider);
4426
+ for (const instance of allProviders)
4427
+ await stopProvider(instance);
4231
4428
  await log?.flush();
4232
4429
  if (isLogFactory2(declaredLog))
4233
4430
  log?.set(undefined);
@@ -4235,7 +4432,7 @@ function applicationOf2(settings) {
4235
4432
  get(declaration) {
4236
4433
  if (isEnvironment2(declaration)) {
4237
4434
  if (!registeredEnvironments.has(declaration)) {
4238
- invalid6(name, "Expected an environment registered in the application.");
4435
+ invalid7(name, "Expected an environment registered in the application.");
4239
4436
  }
4240
4437
  return declaration.load();
4241
4438
  }
@@ -4248,10 +4445,20 @@ function applicationOf2(settings) {
4248
4445
  if (isRepository2(declaration)) {
4249
4446
  return application.repository(declaration);
4250
4447
  }
4251
- return invalid6(name, "Expected a repository, use case, command, output or environment registered in the application.");
4448
+ if (isProviderSlot2(declaration)) {
4449
+ const instance = instances.get(declaration);
4450
+ if (instance === undefined) {
4451
+ invalid7(name, "Expected a provider of a storage registered in the application.");
4452
+ }
4453
+ return instance;
4454
+ }
4455
+ return invalid7(name, "Expected a repository, use case, command, output, environment or provider registered in the application.");
4252
4456
  }
4253
4457
  });
4254
4458
  internals.set(application, registry);
4459
+ namedProviders.set(application, named);
4460
+ if (defaultSlot !== undefined)
4461
+ defaultSlots.set(application, defaultSlot);
4255
4462
  if (declaredLog !== undefined)
4256
4463
  logSettings.set(application, declaredLog);
4257
4464
  return application;
@@ -4337,7 +4544,7 @@ function outputValueOf2(value) {
4337
4544
  }
4338
4545
 
4339
4546
  // src/core/output/openapi-sink.ts
4340
- var METHODS2 = ["get", "post", "put", "patch", "delete"];
4547
+ var METHODS3 = ["get", "post", "put", "patch", "delete"];
4341
4548
  function isObject(value) {
4342
4549
  return typeof value === "object" && value !== null && !Array.isArray(value);
4343
4550
  }
@@ -4363,8 +4570,8 @@ function routeOptionsIssue2(options, where) {
4363
4570
  if (!isObject(entry) || onlyKeys(entry, ["method", "path"], "route")) {
4364
4571
  return `Expected ${where}.route["${id}"] to be { method?, path? }.`;
4365
4572
  }
4366
- if (entry.method !== undefined && !METHODS2.includes(entry.method)) {
4367
- return `Expected ${where}.route["${id}"].method to be one of ${METHODS2.join(", ")}.`;
4573
+ if (entry.method !== undefined && !METHODS3.includes(entry.method)) {
4574
+ return `Expected ${where}.route["${id}"].method to be one of ${METHODS3.join(", ")}.`;
4368
4575
  }
4369
4576
  if (entry.path !== undefined && !isPath(entry.path)) {
4370
4577
  return `Expected ${where}.route["${id}"].path to start with "/" and have no parameters or query.`;
@@ -4402,7 +4609,7 @@ function validate2(options) {
4402
4609
  }
4403
4610
  return routeOptionsIssue2({ basePath, route }, "openapi");
4404
4611
  }
4405
- function invalid7(reason, source = "openapi") {
4612
+ function invalid8(reason, source = "openapi") {
4406
4613
  throw new InvalidOutputStage2({ source, details: { reason } });
4407
4614
  }
4408
4615
  function kebab(text) {
@@ -4414,7 +4621,7 @@ function operationRoutes2(operations, options, source = "openapi") {
4414
4621
  const ids = new Set(operations.map(({ id }) => id));
4415
4622
  for (const id of Object.keys(route)) {
4416
4623
  if (!ids.has(id)) {
4417
- invalid7(`${source}.route names the unknown operation "${id}".`, source);
4624
+ invalid8(`${source}.route names the unknown operation "${id}".`, source);
4418
4625
  }
4419
4626
  }
4420
4627
  const routes = new Map;
@@ -4425,7 +4632,7 @@ function operationRoutes2(operations, options, source = "openapi") {
4425
4632
  const path = base + (chosen.path ?? `/${kebab(operation.command)}/${kebab(operation.name)}`);
4426
4633
  const key = `${method} ${path}`;
4427
4634
  if (taken.has(key)) {
4428
- invalid7(`Two operations are routed to ${method.toUpperCase()} ${path}.`, source);
4635
+ invalid8(`Two operations are routed to ${method.toUpperCase()} ${path}.`, source);
4429
4636
  }
4430
4637
  taken.add(key);
4431
4638
  routes.set(operation.id, { method, path });
@@ -4531,7 +4738,7 @@ function parametersOf(operation, schema) {
4531
4738
  const field = operation.input.properties[name];
4532
4739
  const type = property.type;
4533
4740
  if (!isProperty2(field) || type === "object" || type === "array" || Array.isArray(type) && type.some((t) => t === "object" || t === "array")) {
4534
- invalid7(`${operation.id} uses a ${"get/delete"} route, whose input becomes query parameters, but "${name}" is not a scalar; route it with method "post".`);
4741
+ invalid8(`${operation.id} uses a ${"get/delete"} route, whose input becomes query parameters, but "${name}" is not a scalar; route it with method "post".`);
4535
4742
  }
4536
4743
  const { description, ...rest } = property;
4537
4744
  return {
@@ -4558,10 +4765,10 @@ var openapi2 = sinkOf2({
4558
4765
  for (const record of records) {
4559
4766
  const name = record.name;
4560
4767
  if (!/^[A-Za-z0-9._-]+$/.test(name) || name === "Problem") {
4561
- invalid7(`The record class "${name}" cannot be a component name; give the class a name that is not "Problem".`);
4768
+ invalid8(`The record class "${name}" cannot be a component name; give the class a name that is not "Problem".`);
4562
4769
  }
4563
4770
  if (classes.has(name)) {
4564
- invalid7(`Two record classes are named "${name}"; rename one.`);
4771
+ invalid8(`Two record classes are named "${name}"; rename one.`);
4565
4772
  }
4566
4773
  classes.set(name, record);
4567
4774
  models[name] = record;
@@ -4581,7 +4788,7 @@ var openapi2 = sinkOf2({
4581
4788
  const { method, path } = routes.get(operation.id);
4582
4789
  const operationId = operation.id.replaceAll(".", "_");
4583
4790
  if (operationIds.has(operationId)) {
4584
- invalid7(`The operationId "${operationId}" is produced twice.`);
4791
+ invalid8(`The operationId "${operationId}" is produced twice.`);
4585
4792
  }
4586
4793
  operationIds.add(operationId);
4587
4794
  const slot = paths[path] ?? {};
@@ -5332,4 +5539,4 @@ var entityOf2 = entityBuilderOf2({
5332
5539
  var recordOf2 = recordBuilderOf2(StdRecordPlugins2);
5333
5540
  // src/std/stages.ts
5334
5541
  var StdStages2 = stageCatalogOf2(select2, openapi2);
5335
- export { InvalidEnvironment2, environmentOf2, isEnvironment2, guard2, InvalidApplicationDeclaration2, DuplicateApplicationDeclaration2, ApplicationConflict2, UnregisteredApplicationReference2, UnregisteredRepositoryDependency2, UnregisteredUseCaseDependency2, ApplicationNotStarted2, ApplicationAlreadyStarted2, InvalidApplicationEnvironment2, useApplication2, resetApplication2, InvalidLogDeclaration2, LogLevels2, logProviderOf2, consoleLogProvider2, jsonLogProvider2, memoryLogProvider2, Logger2, ReservedEntityKey2, ImmutableEntityKey2, DeletedEntity2, entityBuilderOf2, isEntityClass2, isEntity2, eventOf2, ENTITY_IDENTITY_KEYS2, RESERVED_ENTITY_KEYS2, EntityUniqueKeys2, AbstractEntity2, InvalidRepositoryQuery2, InvalidRepositoryDeclaration2, InvalidRepositoryEntity2, InvalidRepositoryData2, RepositoryUniqueViolation2, RepositoryEntityNotFound2, providerOf2, providerDescriptionOf2, inMemoryProvider2, AbstractRepository2, repositoryOf2, RepositoryOf2, isRepository2, InvalidUseCaseStep2, InvalidUseCaseDeclaration2, UseCaseAlreadyExecuted2, InvalidUseCaseDependencies2, AbstractUseCase2, useCaseOf2, isUseCaseClass2, isUseCase2, InvalidCommandDeclaration2, UnknownCommandOperation2, InvalidCommandContext2, InvalidCommandEnvironment2, CommandEventFailed2, commandOf2, isCommand2, InvalidOpenAPIModel2, InvalidOutputStage2, DuplicateOperation2, toOpenAPI2, transformOf2, sinkOf2, stageDescriptionOf2, stageKindOf2, stageCatalogOf2, operationOf2, outputOf2, isOutput2, providerFrom2, logFrom2, isLogFactory2, isProviderFactory2, isApplication2, applicationOf2, blueprintPluginOf2, statusOf2, PROBLEM_MEDIA_TYPE2, problemOf2, outputValueOf2, routeOptionsIssue2, operationRoutes2, openapi2, select2, recordPluginCatalogOf2, Email2, Phone2, Url2, Ip2, enumOf2, SchemaProperty2, PasswordHasherRequired2, SyncVerifyUnsupported2, configure2, resetRuntime2, Id2, Slug2, PASSWORD_MIN_LENGTH2, PASSWORD_MAX_LENGTH2, PASSWORD_SPECIAL_CHARACTERS2, isPasswordHash2, passwordIssues2, Password2, StringProperty2, Text2, NumberProperty2, Integer2, BooleanProperty2, DateTime2, DateProperty2, CreatedAt2, UpdatedAt2, DeletedAt2, Std2, blueprintOf2, Publishable2, Archivable2, Taggable2, Ownable2, Authenticatable2, StdRecordPlugins2, entityOf2, recordOf2, StdStages2 };
5542
+ export { InvalidEnvironment2, environmentOf2, isEnvironment2, guard2, InvalidApplicationDeclaration2, DuplicateApplicationDeclaration2, ApplicationConflict2, UnregisteredApplicationReference2, UnregisteredRepositoryDependency2, UnregisteredUseCaseDependency2, ApplicationNotStarted2, ProviderNotBound2, ApplicationAlreadyStarted2, InvalidApplicationEnvironment2, useApplication2, resetApplication2, InvalidLogDeclaration2, LogLevels2, logProviderOf2, consoleLogProvider2, jsonLogProvider2, memoryLogProvider2, Logger2, ReservedEntityKey2, ImmutableEntityKey2, DeletedEntity2, entityBuilderOf2, isEntityClass2, isEntity2, eventOf2, ENTITY_IDENTITY_KEYS2, RESERVED_ENTITY_KEYS2, EntityUniqueKeys2, AbstractEntity2, InvalidRepositoryQuery2, InvalidRepositoryDeclaration2, InvalidRepositoryEntity2, InvalidRepositoryData2, RepositoryUniqueViolation2, RepositoryEntityNotFound2, providerOf2, providerDescriptionOf2, inMemoryProvider2, AbstractRepository2, repositoryOf2, RepositoryOf2, isRepository2, InvalidUseCaseStep2, InvalidUseCaseDeclaration2, UseCaseAlreadyExecuted2, InvalidUseCaseDependencies2, AbstractUseCase2, useCaseOf2, isUseCaseClass2, isUseCase2, InvalidCommandDeclaration2, UnknownCommandOperation2, InvalidCommandContext2, InvalidCommandEnvironment2, CommandEventFailed2, commandOf2, isCommand2, InvalidOpenAPIModel2, InvalidOutputStage2, DuplicateOperation2, toOpenAPI2, transformOf2, sinkOf2, stageDescriptionOf2, stageKindOf2, stageCatalogOf2, operationOf2, outputOf2, isOutput2, providerFrom2, logFrom2, isLogFactory2, isProviderFactory2, providersOf2, isProviderSlot2, isProviderStorage2, isApplication2, applicationOf2, blueprintPluginOf2, statusOf2, PROBLEM_MEDIA_TYPE2, problemOf2, outputValueOf2, routeOptionsIssue2, operationRoutes2, openapi2, select2, recordPluginCatalogOf2, Email2, Phone2, Url2, Ip2, enumOf2, SchemaProperty2, PasswordHasherRequired2, SyncVerifyUnsupported2, configure2, resetRuntime2, Id2, Slug2, PASSWORD_MIN_LENGTH2, PASSWORD_MAX_LENGTH2, PASSWORD_SPECIAL_CHARACTERS2, isPasswordHash2, passwordIssues2, Password2, StringProperty2, Text2, NumberProperty2, Integer2, BooleanProperty2, DateTime2, DateProperty2, CreatedAt2, UpdatedAt2, DeletedAt2, Std2, blueprintOf2, Publishable2, Archivable2, Taggable2, Ownable2, Authenticatable2, StdRecordPlugins2, entityOf2, recordOf2, StdStages2 };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export { applicationOf, isApplication } from "./core/application/application.js";
2
- export { ApplicationAlreadyStarted, ApplicationConflict, ApplicationNotStarted, DuplicateApplicationDeclaration, InvalidApplicationDeclaration, InvalidApplicationEnvironment, UnregisteredApplicationReference, UnregisteredRepositoryDependency, UnregisteredUseCaseDependency, } from "./core/application/exceptions.js";
2
+ export { ApplicationAlreadyStarted, ApplicationConflict, ApplicationNotStarted, DuplicateApplicationDeclaration, InvalidApplicationDeclaration, InvalidApplicationEnvironment, ProviderNotBound, UnregisteredApplicationReference, UnregisteredRepositoryDependency, UnregisteredUseCaseDependency, } from "./core/application/exceptions.js";
3
+ export { isProviderSlot, isProviderStorage, type ProviderSlot, type ProviderStorage, providersOf, } from "./core/application/providers.js";
3
4
  export { type Register, type RegisteredApplication, resetApplication, useApplication, } from "./core/application/registry.js";
4
5
  export { isLogFactory, isProviderFactory, type LogFactory, logFrom, type ProviderFactory, providerFrom, } from "./core/application/start.js";
5
- export type { AnyApplication, ApplicationCollections, ApplicationContext, ApplicationDescription, ApplicationSettings, ApplicationStartOptions, CommandDescription, ExceptionDescription, FieldDescription, FieldsDescription, IApplication, LogDescription, OutputDescription, PropertyDescription, PropertyLineageDescription, PropertyReference, RecordDescription, UseCaseDependencyDescription, UseCaseDescription, } from "./core/application/types/application.interface.js";
6
+ export type { AnyApplication, ApplicationCollections, ApplicationContext, ApplicationDescription, ApplicationSettings, ApplicationStartOptions, CommandDescription, ExceptionDescription, FieldDescription, FieldsDescription, IApplication, LogDescription, OutputDescription, PropertyDescription, PropertyLineageDescription, PropertyReference, ProviderReference, RecordDescription, UseCaseDependencyDescription, UseCaseDescription, } from "./core/application/types/application.interface.js";
6
7
  export { blueprintBuilderOf } from "./core/blueprint/blueprint.js";
7
8
  export { blueprintPluginOf } from "./core/blueprint/blueprint-plugin.js";
8
9
  export { ReservedBlueprintKey, UndeclaredBlueprintProperty, } from "./core/blueprint/exceptions.js";
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  UnregisteredRepositoryDependency2,
11
11
  UnregisteredUseCaseDependency2,
12
12
  ApplicationNotStarted2,
13
+ ProviderNotBound2,
13
14
  ApplicationAlreadyStarted2,
14
15
  InvalidApplicationEnvironment2,
15
16
  useApplication2,
@@ -76,6 +77,9 @@ import {
76
77
  logFrom2,
77
78
  isLogFactory2,
78
79
  isProviderFactory2,
80
+ providersOf2,
81
+ isProviderSlot2,
82
+ isProviderStorage2,
79
83
  isApplication2,
80
84
  applicationOf2,
81
85
  blueprintPluginOf2,
@@ -127,7 +131,7 @@ import {
127
131
  entityOf2,
128
132
  recordOf2,
129
133
  StdStages2
130
- } from "./index-ewm6r4nw.js";
134
+ } from "./index-8m80wjzf.js";
131
135
  import {
132
136
  isProperty2,
133
137
  schemaOf2,
@@ -239,6 +243,7 @@ export {
239
243
  Phone2 as Phone,
240
244
  PropertyRequired2 as PropertyRequired,
241
245
  PropertyStates2 as PropertyStates,
246
+ ProviderNotBound2 as ProviderNotBound,
242
247
  Publishable2 as Publishable,
243
248
  RESERVED_ENTITY_KEYS2 as RESERVED_ENTITY_KEYS,
244
249
  RESERVED_RECORD_KEYS2 as RESERVED_RECORD_KEYS,
@@ -299,6 +304,8 @@ export {
299
304
  isPasswordHash2 as isPasswordHash,
300
305
  isProperty2 as isProperty,
301
306
  isProviderFactory2 as isProviderFactory,
307
+ isProviderSlot2 as isProviderSlot,
308
+ isProviderStorage2 as isProviderStorage,
302
309
  isRecordClass2 as isRecordClass,
303
310
  isRecordPlugin2 as isRecordPlugin,
304
311
  isRepository2 as isRepository,
@@ -323,6 +330,7 @@ export {
323
330
  providerDescriptionOf2 as providerDescriptionOf,
324
331
  providerFrom2 as providerFrom,
325
332
  providerOf2 as providerOf,
333
+ providersOf2 as providersOf,
326
334
  recordBuilderOf2 as recordBuilderOf,
327
335
  recordFieldOf2 as recordFieldOf,
328
336
  recordOf2 as recordOf,
@@ -4,7 +4,7 @@ import {
4
4
  RepositoryEntityNotFound2,
5
5
  blueprintOf2,
6
6
  entityOf2
7
- } from "../index-ewm6r4nw.js";
7
+ } from "../index-8m80wjzf.js";
8
8
 
9
9
  // src/testing/provider-contract.ts
10
10
  function contextOf(name = "Accounts") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afora/core",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Domain modeling on TypeBox: entities with invariants, repositories, use cases, sensitive data masking and layered exceptions, usable by any Standard Schema consumer.",
5
5
  "keywords": [
6
6
  "domain-driven-design",