@chidchanun/bcp 0.3.0 → 0.3.1

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.
@@ -1,3 +1,12 @@
1
+ import {
2
+ createServiceContainer,
3
+
4
+ type ServiceContainer,
5
+ type ServiceProvider,
6
+ type ServiceScope,
7
+ type ServiceScopeOptions,
8
+ } from "./container.js";
9
+
1
10
  import {
2
11
  createDeploymentRuntime,
3
12
 
@@ -52,6 +61,7 @@ export interface ApplicationContext<TConfig = unknown> {
52
61
  readonly name: string;
53
62
  readonly version?: string;
54
63
  readonly config: TConfig;
64
+ readonly container: ServiceContainer;
55
65
  readonly services: PluginServiceRegistry;
56
66
  readonly hooks: PluginHookBus;
57
67
  readonly plugins: PluginHost;
@@ -65,6 +75,7 @@ export interface ApplicationDefinition<TConfig = unknown> {
65
75
  version?: string;
66
76
  config?: unknown;
67
77
  schema?: ApplicationConfigParser<TConfig>;
78
+ providers?: readonly ServiceProvider<unknown>[];
68
79
  plugins?: readonly PluginDefinition<any>[];
69
80
  modules?: readonly PluginModule[];
70
81
  pluginConfigs?: Record<string, unknown>;
@@ -96,6 +107,7 @@ export interface Application<TConfig = unknown> {
96
107
  readonly state: ApplicationState;
97
108
  readonly config: TConfig;
98
109
  readonly context: ApplicationContext<TConfig>;
110
+ readonly container: ServiceContainer;
99
111
  readonly services: PluginServiceRegistry;
100
112
  readonly hooks: PluginHookBus;
101
113
  readonly plugins: PluginHost;
@@ -112,6 +124,15 @@ export interface Application<TConfig = unknown> {
112
124
  replace?: boolean;
113
125
  }
114
126
  ): Application<TConfig>;
127
+ register<T>(
128
+ provider: ServiceProvider<T>,
129
+ options?: {
130
+ replace?: boolean;
131
+ }
132
+ ): Application<TConfig>;
133
+ createScope(
134
+ options?: ServiceScopeOptions
135
+ ): ServiceScope;
115
136
  addResource(
116
137
  resource: DeploymentResource
117
138
  ): Application<TConfig>;
@@ -180,6 +201,13 @@ export function createApp<TConfig = unknown>(
180
201
  definition.schema,
181
202
  definition.config
182
203
  );
204
+ const container =
205
+ createServiceContainer({
206
+ name:
207
+ `${name}:container`,
208
+ providers:
209
+ definition.providers,
210
+ });
183
211
  const plugins =
184
212
  createPluginHost({
185
213
  plugins:
@@ -229,6 +257,7 @@ export function createApp<TConfig = unknown>(
229
257
  }
230
258
  : {}),
231
259
  config,
260
+ container,
232
261
  services:
233
262
  plugins.services,
234
263
  hooks:
@@ -243,6 +272,38 @@ export function createApp<TConfig = unknown>(
243
272
  },
244
273
  };
245
274
 
275
+ deployment.addResource({
276
+ name:
277
+ "bcp:container",
278
+ ready() {
279
+ return {
280
+ ok:
281
+ container.state ===
282
+ "active",
283
+ detail:
284
+ `Service container is ${container.state}.`,
285
+ };
286
+ },
287
+ async stop() {
288
+ await container.dispose();
289
+ },
290
+ diagnostics() {
291
+ return {
292
+ state:
293
+ container.state,
294
+ providers:
295
+ container.graph().map(
296
+ node => ({
297
+ token:
298
+ node.description,
299
+ lifetime:
300
+ node.lifetime,
301
+ })
302
+ ),
303
+ };
304
+ },
305
+ });
306
+
246
307
  deployment.addResource({
247
308
  name:
248
309
  "bcp:plugins",
@@ -284,11 +345,12 @@ export function createApp<TConfig = unknown>(
284
345
  name,
285
346
  ...(version
286
347
  ? {
287
- version,
288
- }
348
+ version,
349
+ }
289
350
  : {}),
290
351
  config,
291
352
  context,
353
+ container,
292
354
  services:
293
355
  plugins.services,
294
356
  hooks:
@@ -322,6 +384,26 @@ export function createApp<TConfig = unknown>(
322
384
  return app;
323
385
  },
324
386
 
387
+ register<T>(
388
+ provider: ServiceProvider<T>,
389
+ options: {
390
+ replace?: boolean;
391
+ } = {}
392
+ ) {
393
+ assertMutable();
394
+ container.register(
395
+ provider,
396
+ options
397
+ );
398
+ return app;
399
+ },
400
+
401
+ createScope(options = {}) {
402
+ return container.createScope(
403
+ options
404
+ );
405
+ },
406
+
325
407
  addResource(resource) {
326
408
  assertMutable();
327
409
  deployment.addResource(
@@ -562,6 +644,14 @@ export function createApp<TConfig = unknown>(
562
644
  }
563
645
  }
564
646
 
647
+ if (container.state !== "disposed") {
648
+ try {
649
+ await container.dispose();
650
+ } catch (error) {
651
+ errors.push(error);
652
+ }
653
+ }
654
+
565
655
  try {
566
656
  await disposeApplication();
567
657
  } catch (error) {
@@ -612,8 +702,8 @@ export function createApp<TConfig = unknown>(
612
702
  name,
613
703
  ...(version
614
704
  ? {
615
- version,
616
- }
705
+ version,
706
+ }
617
707
  : {}),
618
708
  state,
619
709
  services:
@@ -622,6 +712,11 @@ export function createApp<TConfig = unknown>(
622
712
  .map(
623
713
  formatServiceKey
624
714
  ),
715
+ containerProviders:
716
+ container.graph().map(
717
+ node =>
718
+ node.description
719
+ ),
625
720
  pluginCount:
626
721
  plugins.plugins().length,
627
722
  };
@@ -654,6 +749,14 @@ export function createApp<TConfig = unknown>(
654
749
  // Preserve the original startup failure.
655
750
  }
656
751
 
752
+ if (container.state !== "disposed") {
753
+ try {
754
+ await container.dispose();
755
+ } catch {
756
+ // Preserve the original startup failure.
757
+ }
758
+ }
759
+
657
760
  try {
658
761
  await disposeApplication();
659
762
  } catch {
@@ -697,7 +800,7 @@ export function createApp<TConfig = unknown>(
697
800
  function assertMutable(): void {
698
801
  if (state !== "created") {
699
802
  throw new Error(
700
- "BCP Application: plugins, services and resources must be registered before start()."
803
+ "BCP Application: plugins, services, providers and resources must be registered before start()."
701
804
  );
702
805
  }
703
806
  }
@@ -747,6 +850,14 @@ function validateDefinition<TConfig>(
747
850
  definition.version
748
851
  );
749
852
 
853
+ if (
854
+ definition.providers !== undefined &&
855
+ !Array.isArray(definition.providers)
856
+ ) {
857
+ throw new TypeError(
858
+ "BCP Application: providers must be an array."
859
+ );
860
+ }
750
861
  if (
751
862
  definition.plugins !== undefined &&
752
863
  !Array.isArray(definition.plugins)