@jskit-ai/kernel 0.1.159 → 0.1.161

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 (102) hide show
  1. package/_testable/index.js +1 -3
  2. package/client/componentRegistry.js +44 -0
  3. package/client/componentRegistry.test.js +16 -0
  4. package/client/moduleBootstrap.js +54 -97
  5. package/client/moduleBootstrap.test.js +47 -32
  6. package/client/vite/clientBootstrapPlugin.test.js +2 -2
  7. package/internal/node/installedPackages.js +2 -7
  8. package/internal/node/installedPackages.test.js +26 -5
  9. package/package.json +3 -5
  10. package/server/actions/actionCatalogue.js +162 -0
  11. package/server/actions/actionEvents.js +66 -0
  12. package/server/actions/actionProvider.js +23 -0
  13. package/server/actions/index.js +3 -6
  14. package/server/features/defineFeature.js +131 -0
  15. package/server/features/defineFeature.test.js +238 -0
  16. package/server/features/index.js +1 -0
  17. package/server/http/HttpProvider.js +23 -0
  18. package/server/http/_testable/index.js +0 -1
  19. package/server/http/capabilityHttpRuntime.js +123 -0
  20. package/server/http/capabilityHttpRuntime.test.js +161 -0
  21. package/server/http/directRequestActionExecutor.js +78 -0
  22. package/server/http/index.js +2 -1
  23. package/server/http/lib/index.js +1 -13
  24. package/server/http/lib/routeRegistration.js +9 -25
  25. package/server/platform/index.js +2 -2
  26. package/server/platform/installedRuntime.js +122 -0
  27. package/server/platform/installedRuntime.test.js +103 -0
  28. package/server/platform/providerRuntime/capabilityProviderLoader.js +100 -0
  29. package/server/platform/providerRuntime/capabilityProviderLoader.test.js +80 -0
  30. package/server/platform/providerRuntime/packageCatalog.js +4 -1
  31. package/server/platform/surfaceRuntime.js +1 -15
  32. package/server/runtime/BootstrapProvider.js +69 -0
  33. package/server/runtime/EventProvider.js +74 -0
  34. package/server/runtime/EventProvider.test.js +32 -0
  35. package/server/runtime/entityChangeEvents.js +7 -7
  36. package/server/runtime/entityChangeEvents.test.js +2 -2
  37. package/server/runtime/fastifyBootstrap.js +0 -40
  38. package/server/runtime/index.js +2 -3
  39. package/server/surface/index.js +0 -1
  40. package/shared/actions/actionDefinitions.js +20 -0
  41. package/shared/actions/pipeline.js +22 -0
  42. package/shared/actions/policies.js +1 -1
  43. package/shared/actions/registry.js +3 -0
  44. package/shared/capabilities/defineProvider.js +99 -0
  45. package/shared/capabilities/index.js +2 -0
  46. package/shared/capabilities/runtime.js +243 -0
  47. package/shared/capabilities/runtime.test.js +170 -0
  48. package/test/barrelExposure.test.js +36 -13
  49. package/test/exportsContract.test.js +8 -3
  50. package/server/actions/ActionRuntimeServiceProvider.js +0 -304
  51. package/server/actions/ActionRuntimeServiceProvider.test.js +0 -558
  52. package/server/container/ContainerCoreServiceProvider.js +0 -27
  53. package/server/container/index.js +0 -10
  54. package/server/http/HttpFastifyServiceProvider.js +0 -25
  55. package/server/http/lib/httpRuntime.js +0 -83
  56. package/server/http/lib/kernel.js +0 -15
  57. package/server/http/lib/kernel.test.js +0 -1565
  58. package/server/http/lib/requestActionExecutor.js +0 -265
  59. package/server/http/lib/requestScope.js +0 -57
  60. package/server/kernel/KernelCoreServiceProvider.js +0 -27
  61. package/server/kernel/index.js +0 -10
  62. package/server/platform/PlatformServerRuntimeServiceProvider.js +0 -30
  63. package/server/platform/providerRuntime/providerLoader.js +0 -283
  64. package/server/platform/providerRuntime.js +0 -146
  65. package/server/platform/providerRuntime.test.js +0 -214
  66. package/server/platform/runtime.js +0 -40
  67. package/server/registries/actionSurfaceSourceRegistry.js +0 -148
  68. package/server/registries/bootstrapPayloadContributorRegistry.js +0 -51
  69. package/server/registries/domainEventListenerRegistry.js +0 -58
  70. package/server/registries/index.js +0 -32
  71. package/server/registries/primitives.js +0 -63
  72. package/server/registries/routeVisibilityResolverRegistry.js +0 -84
  73. package/server/registries/serviceRegistrationRegistry.js +0 -488
  74. package/server/runtime/ServerRuntimeCoreServiceProvider.js +0 -64
  75. package/server/runtime/ServerRuntimeCoreServiceProvider.test.js +0 -53
  76. package/server/runtime/apiRoutePolicyParity.test.js +0 -109
  77. package/server/runtime/apiRouteRegistration.js +0 -65
  78. package/server/runtime/bootBootstrapRoutes.js +0 -29
  79. package/server/runtime/bootBootstrapRoutes.test.js +0 -69
  80. package/server/runtime/bootstrapContributors.test.js +0 -166
  81. package/server/runtime/composition.js +0 -142
  82. package/server/runtime/domainEvents.test.js +0 -114
  83. package/server/runtime/domainRules.js +0 -50
  84. package/server/runtime/domainRules.test.js +0 -87
  85. package/server/runtime/runtimeAssembly.js +0 -113
  86. package/server/runtime/runtimeKernel.js +0 -55
  87. package/server/runtime/serviceRegistration.test.js +0 -251
  88. package/server/support/SupportCoreServiceProvider.js +0 -27
  89. package/server/surface/SurfaceRoutingServiceProvider.js +0 -27
  90. package/shared/actions/index.js +0 -2
  91. package/shared/runtime/application.js +0 -324
  92. package/shared/runtime/container.js +0 -261
  93. package/shared/runtime/containerErrors.js +0 -22
  94. package/shared/runtime/index.js +0 -18
  95. package/shared/runtime/kernelErrors.js +0 -25
  96. package/shared/runtime/kernelErrors.test.js +0 -120
  97. package/shared/runtime/serviceProvider.js +0 -13
  98. package/shared/support/containerToken.js +0 -8
  99. package/shared/support/generatedUiContract.js +0 -542
  100. package/shared/support/generatedUiContract.test.js +0 -218
  101. package/shared/support/tokens.js +0 -1
  102. package/shared/support/tokens.test.js +0 -17
@@ -1,63 +0,0 @@
1
- function normalizeNestedEntries(value) {
2
- const queue = Array.isArray(value) ? [...value] : [value];
3
- const entries = [];
4
-
5
- while (queue.length > 0) {
6
- const entry = queue.shift();
7
- if (Array.isArray(entry)) {
8
- queue.push(...entry);
9
- continue;
10
- }
11
- if (entry == null) {
12
- continue;
13
- }
14
- entries.push(entry);
15
- }
16
-
17
- return entries;
18
- }
19
-
20
- function assertTaggableApp(app, { context = "registry", ErrorType = Error } = {}) {
21
- if (!app || typeof app.singleton !== "function" || typeof app.tag !== "function") {
22
- throw new ErrorType(`${context} requires application singleton()/tag().`);
23
- }
24
- }
25
-
26
- function registerTaggedSingleton(app, token, factory, tag, { context = "registry", ErrorType = Error } = {}) {
27
- assertTaggableApp(app, { context, ErrorType });
28
- app.singleton(token, factory);
29
- app.tag(token, tag);
30
- }
31
-
32
- function resolveTaggedEntries(scope, tag) {
33
- if (!scope || typeof scope.resolveTag !== "function") {
34
- return [];
35
- }
36
- return normalizeNestedEntries(scope.resolveTag(tag));
37
- }
38
-
39
- function normalizeContributorEntry(entry) {
40
- if (typeof entry === "function") {
41
- return {
42
- contributorId: String(entry.name || "anonymous"),
43
- contribute: entry
44
- };
45
- }
46
-
47
- if (entry && typeof entry === "object" && typeof entry.contribute === "function") {
48
- return {
49
- ...entry,
50
- contributorId: String(entry.contributorId || "anonymous")
51
- };
52
- }
53
-
54
- return null;
55
- }
56
-
57
- export {
58
- normalizeNestedEntries,
59
- assertTaggableApp,
60
- registerTaggedSingleton,
61
- resolveTaggedEntries,
62
- normalizeContributorEntry
63
- };
@@ -1,84 +0,0 @@
1
- import { normalizeRouteVisibility, normalizeRouteVisibilityToken, normalizeVisibilityContext } from "../../shared/support/visibility.js";
2
- import { normalizeText } from "../../shared/support/normalize.js";
3
- import { ROUTE_VISIBILITY_PUBLIC } from "../../shared/support/policies.js";
4
- import { RouteRegistrationError } from "../http/lib/errors.js";
5
- import { registerTaggedSingleton, resolveTaggedEntries } from "./primitives.js";
6
-
7
- function normalizeRouteVisibilityResolver(entry) {
8
- if (typeof entry === "function") {
9
- return {
10
- resolverId: normalizeText(entry.name) || "anonymous",
11
- resolve: entry
12
- };
13
- }
14
-
15
- if (!entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.resolve !== "function") {
16
- return null;
17
- }
18
-
19
- return {
20
- resolverId: normalizeText(entry.resolverId) || "anonymous",
21
- resolve: entry.resolve
22
- };
23
- }
24
-
25
- function resolveRouteVisibilityResolvers(scope) {
26
- return resolveTaggedEntries(scope, "jskit.runtime.http.visibilityResolvers")
27
- .map((entry) => normalizeRouteVisibilityResolver(entry))
28
- .filter(Boolean);
29
- }
30
-
31
- function registerRouteVisibilityResolver(app, token, factory) {
32
- registerTaggedSingleton(app, token, factory, "jskit.runtime.http.visibilityResolvers", {
33
- context: "registerRouteVisibilityResolver",
34
- ErrorType: RouteRegistrationError
35
- });
36
- }
37
-
38
- async function resolveRouteVisibilityContext({
39
- resolutionScope = null,
40
- request = null,
41
- routeVisibility = ROUTE_VISIBILITY_PUBLIC,
42
- context = {},
43
- input = {},
44
- deps = {},
45
- actionId = "",
46
- version = null,
47
- channel = "api"
48
- } = {}) {
49
- const normalizedRouteVisibility = normalizeRouteVisibilityToken(routeVisibility);
50
- const normalizedCoreVisibility = normalizeRouteVisibility(normalizedRouteVisibility);
51
- const resolvers = resolveRouteVisibilityResolvers(resolutionScope);
52
- const patch = {};
53
-
54
- for (const resolver of resolvers) {
55
- const contribution = await resolver.resolve({
56
- request,
57
- visibility: normalizedRouteVisibility,
58
- context,
59
- input,
60
- deps,
61
- actionId: normalizeText(actionId),
62
- version: version == null ? null : version,
63
- channel: normalizeText(channel).toLowerCase() || "api"
64
- });
65
-
66
- if (!contribution || typeof contribution !== "object" || Array.isArray(contribution)) {
67
- continue;
68
- }
69
-
70
- Object.assign(patch, contribution);
71
- }
72
-
73
- return normalizeVisibilityContext({
74
- ...patch,
75
- visibility: normalizedRouteVisibility,
76
- requiresActorScope: patch.requiresActorScope === true || normalizedCoreVisibility === "user"
77
- });
78
- }
79
-
80
- export {
81
- resolveRouteVisibilityResolvers,
82
- registerRouteVisibilityResolver,
83
- resolveRouteVisibilityContext
84
- };
@@ -1,488 +0,0 @@
1
- import { normalizeObject, normalizePositiveInteger, normalizeText } from "../../shared/support/normalize.js";
2
- import { isContainerToken } from "../../shared/support/containerToken.js";
3
- import { createEntityChangePublisher } from "../runtime/entityChangeEvents.js";
4
- import {
5
- assertTaggableApp,
6
- normalizeNestedEntries,
7
- registerTaggedSingleton,
8
- resolveTaggedEntries
9
- } from "./primitives.js";
10
-
11
- const DEFAULT_REALTIME_AUDIENCE = "event_scope";
12
- let SERVICE_REGISTRATION_INDEX = 0;
13
-
14
- function normalizeMethodName(value, { context = "service method" } = {}) {
15
- const methodName = String(value || "").trim();
16
- if (!methodName) {
17
- throw new TypeError(`${context} must be a non-empty string.`);
18
- }
19
- return methodName;
20
- }
21
-
22
- function createServiceRegistrationToken() {
23
- SERVICE_REGISTRATION_INDEX += 1;
24
- return Symbol(`jskit.runtime.services.registration.${SERVICE_REGISTRATION_INDEX}`);
25
- }
26
-
27
- function normalizeServiceEventType(value, { context = "service event" } = {}) {
28
- const normalizedType = normalizeText(value).toLowerCase();
29
- if (normalizedType !== "entity.changed") {
30
- throw new TypeError(`${context}.type must be "entity.changed".`);
31
- }
32
- return normalizedType;
33
- }
34
-
35
- function normalizeServiceEventOperation(value, { context = "service event" } = {}) {
36
- if (typeof value === "function") {
37
- return value;
38
- }
39
-
40
- const normalizedOperation = normalizeText(value).toLowerCase();
41
- if (!normalizedOperation) {
42
- throw new TypeError(`${context}.operation is required.`);
43
- }
44
- if (normalizedOperation !== "created" && normalizedOperation !== "updated" && normalizedOperation !== "deleted") {
45
- throw new TypeError(`${context}.operation must be one of: created, updated, deleted.`);
46
- }
47
- return normalizedOperation;
48
- }
49
-
50
- function normalizeServiceEventEntityId(value) {
51
- if (typeof value === "function" || typeof value === "string") {
52
- return value;
53
- }
54
-
55
- const parsed = normalizePositiveInteger(value);
56
- if (parsed > 0) {
57
- return parsed;
58
- }
59
-
60
- return null;
61
- }
62
-
63
- function normalizeServiceEventMetaField(value, { context = "service event meta field" } = {}) {
64
- if (value == null) {
65
- return null;
66
- }
67
-
68
- if (typeof value === "function") {
69
- return value;
70
- }
71
- if (typeof value !== "string") {
72
- throw new TypeError(`${context} must be a non-empty string or function.`);
73
- }
74
-
75
- const normalized = normalizeText(value);
76
- if (!normalized) {
77
- throw new TypeError(`${context} must be a non-empty string or function.`);
78
- }
79
- return normalized;
80
- }
81
-
82
- function normalizeRealtimeDispatch(value, { context = "service event.realtime" } = {}) {
83
- const source = normalizeObject(value);
84
- if (Object.keys(source).length < 1) {
85
- return null;
86
- }
87
-
88
- const event = normalizeText(source.event);
89
- if (!event) {
90
- throw new TypeError(`${context}.event is required.`);
91
- }
92
-
93
- const payload = typeof source.payload === "function" ? source.payload : null;
94
- const audience = normalizeRealtimeAudience(source.audience, {
95
- context: `${context}.audience`
96
- });
97
-
98
- return Object.freeze({
99
- event,
100
- payload,
101
- audience
102
- });
103
- }
104
-
105
- function normalizeRealtimeAudience(value, { context = "service event.realtime.audience" } = {}) {
106
- if (typeof value === "undefined") {
107
- return DEFAULT_REALTIME_AUDIENCE;
108
- }
109
-
110
- if (typeof value === "function") {
111
- return value;
112
- }
113
-
114
- if (typeof value === "string") {
115
- const preset = normalizeText(value).toLowerCase();
116
- if (!preset) {
117
- throw new TypeError(`${context} must be a non-empty string, function, or object.`);
118
- }
119
- return preset;
120
- }
121
-
122
- if (value && typeof value === "object" && !Array.isArray(value)) {
123
- return Object.freeze({
124
- ...value
125
- });
126
- }
127
-
128
- throw new TypeError(`${context} must be a string, function, or object.`);
129
- }
130
-
131
- function normalizeServiceEventSpec(entry, { context = "service event" } = {}) {
132
- const source = normalizeObject(entry);
133
-
134
- return Object.freeze({
135
- type: normalizeServiceEventType(source.type, { context }),
136
- source: normalizeText(source.source),
137
- entity: normalizeText(source.entity),
138
- operation: normalizeServiceEventOperation(source.operation, { context }),
139
- entityId: normalizeServiceEventEntityId(source.entityId),
140
- action: normalizeServiceEventMetaField(source.action, { context: `${context}.action` }),
141
- reason: normalizeServiceEventMetaField(source.reason, { context: `${context}.reason` }),
142
- realtime: normalizeRealtimeDispatch(source.realtime, { context: `${context}.realtime` })
143
- });
144
- }
145
-
146
- function normalizeServiceMetadata(value = {}) {
147
- const source = normalizeObject(value);
148
- const unsupportedFields = Object.keys(source).filter((key) => key !== "events");
149
- if (unsupportedFields.length > 0) {
150
- throw new TypeError(`service metadata supports only events. Received: ${unsupportedFields.sort().join(", ")}.`);
151
- }
152
- const eventsSource = normalizeObject(source.events);
153
- const events = {};
154
-
155
- for (const [methodName, eventEntries] of Object.entries(eventsSource)) {
156
- const normalizedMethodName = normalizeMethodName(methodName, {
157
- context: "service metadata.events method"
158
- });
159
- const normalizedEventEntries = normalizeNestedEntries(eventEntries).map((entry, index) =>
160
- normalizeServiceEventSpec(entry, {
161
- context: `service metadata.events.${normalizedMethodName}[${index}]`
162
- })
163
- );
164
- events[normalizedMethodName] = Object.freeze(normalizedEventEntries);
165
- }
166
-
167
- return Object.freeze({
168
- events: Object.freeze(events)
169
- });
170
- }
171
-
172
- function normalizeServiceEventsForDefinition(serviceDefinition, serviceMetadata) {
173
- const service = normalizeObject(serviceDefinition);
174
- const methodNameSet = new Set(
175
- Object.entries(service)
176
- .filter(([, value]) => typeof value === "function")
177
- .map(([name]) => name)
178
- );
179
- const declaredEvents = normalizeObject(serviceMetadata.events);
180
- const normalizedEvents = {};
181
-
182
- for (const [methodName, events] of Object.entries(declaredEvents)) {
183
- if (!methodNameSet.has(methodName)) {
184
- throw new TypeError(`service metadata.events.${methodName} does not match a service method.`);
185
- }
186
-
187
- const normalizedEntries = normalizeNestedEntries(events).map((entry, index) =>
188
- normalizeServiceEventSpec(entry, {
189
- context: `service metadata.events.${methodName}[${index}]`
190
- })
191
- );
192
-
193
- for (const [index, entry] of normalizedEntries.entries()) {
194
- if (!entry.source || !entry.entity) {
195
- throw new TypeError(
196
- `service metadata.events.${methodName}[${index}] requires source and entity for "entity.changed".`
197
- );
198
- }
199
- }
200
-
201
- normalizedEvents[methodName] = Object.freeze(normalizedEntries);
202
- }
203
-
204
- return Object.freeze(normalizedEvents);
205
- }
206
-
207
- function resolveMethodOptions(args = []) {
208
- if (!Array.isArray(args) || args.length < 1) {
209
- return {};
210
- }
211
-
212
- const candidate = args[args.length - 1];
213
- if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) {
214
- return candidate;
215
- }
216
-
217
- return {};
218
- }
219
-
220
- function resolveEventOperation(spec, state) {
221
- if (typeof spec.operation === "function") {
222
- return spec.operation({
223
- result: state.result,
224
- args: state.args,
225
- options: state.options,
226
- methodName: state.methodName,
227
- serviceToken: state.serviceToken
228
- });
229
- }
230
- return spec.operation;
231
- }
232
-
233
- function resolveEventEntityId(spec, state) {
234
- if (typeof spec.entityId === "function") {
235
- return spec.entityId({
236
- result: state.result,
237
- args: state.args,
238
- options: state.options,
239
- methodName: state.methodName,
240
- serviceToken: state.serviceToken
241
- });
242
- }
243
-
244
- if (typeof spec.entityId === "string") {
245
- return state?.result?.[spec.entityId];
246
- }
247
-
248
- if (Number.isInteger(spec.entityId) && spec.entityId > 0) {
249
- return spec.entityId;
250
- }
251
-
252
- return state?.result?.id;
253
- }
254
-
255
- function resolveEventMetaField(value, state) {
256
- const context = `service metadata.events.${state.methodName}.meta`;
257
- if (typeof value === "function") {
258
- const resolved = value({
259
- result: state.result,
260
- args: state.args,
261
- options: state.options,
262
- methodName: state.methodName,
263
- serviceToken: state.serviceToken,
264
- event: state.event
265
- });
266
- if (resolved == null) {
267
- return "";
268
- }
269
- if (typeof resolved !== "string") {
270
- throw new TypeError(`${context} field resolver must return a string.`);
271
- }
272
- return normalizeText(resolved);
273
- }
274
- return normalizeText(value);
275
- }
276
-
277
- function resolveEventMeta(spec, state) {
278
- const meta = {
279
- service: Object.freeze({
280
- token: state.serviceToken,
281
- method: state.methodName
282
- })
283
- };
284
-
285
- const action = resolveEventMetaField(spec.action, {
286
- ...state,
287
- event: spec
288
- });
289
- if (action) {
290
- meta.action = action;
291
- }
292
-
293
- const reason = resolveEventMetaField(spec.reason, {
294
- ...state,
295
- event: spec
296
- });
297
- if (reason) {
298
- meta.reason = reason;
299
- }
300
-
301
- if (spec.realtime) {
302
- meta.realtime = spec.realtime.payload
303
- ? Object.freeze({
304
- event: spec.realtime.event,
305
- payload: spec.realtime.payload({
306
- event: state.event,
307
- result: state.result,
308
- args: state.args,
309
- options: state.options,
310
- methodName: state.methodName,
311
- serviceToken: state.serviceToken
312
- })
313
- })
314
- : Object.freeze({
315
- event: spec.realtime.event
316
- });
317
- }
318
-
319
- return Object.freeze(meta);
320
- }
321
-
322
- function createServiceMethodEventPublisher(scope, serviceToken, methodName, specs = []) {
323
- if (!scope || typeof scope.make !== "function" || typeof scope.has !== "function") {
324
- throw new TypeError("service event publisher requires a scope with has()/make().");
325
- }
326
- if (specs.length < 1) {
327
- return async function publishNoop() {
328
- return null;
329
- };
330
- }
331
- if (!scope.has("domainEvents")) {
332
- throw new Error(`app.service(${String(serviceToken)}) requires "domainEvents" binding to emit service events.`);
333
- }
334
-
335
- const domainEvents = scope.make("domainEvents");
336
- const publishers = specs.map((spec) =>
337
- createEntityChangePublisher({
338
- domainEvents,
339
- source: spec.source,
340
- entity: spec.entity
341
- })
342
- );
343
-
344
- return async function publishServiceMethodEvents(state) {
345
- for (const [index, spec] of specs.entries()) {
346
- const publisher = publishers[index];
347
- const operation = resolveEventOperation(spec, state);
348
- const entityId = resolveEventEntityId(spec, state);
349
- const eventMeta = resolveEventMeta(spec, {
350
- ...state,
351
- event: spec
352
- });
353
- await publisher(operation, entityId, state.options, eventMeta);
354
- }
355
- return null;
356
- };
357
- }
358
-
359
- function materializeServiceRegistration(scope, registrationSpec) {
360
- const service = registrationSpec.factory(scope);
361
- const normalizedService = normalizeObject(service);
362
- const events = normalizeServiceEventsForDefinition(normalizedService, registrationSpec.metadata);
363
- const wrappedService = {};
364
-
365
- for (const [methodName, method] of Object.entries(normalizedService)) {
366
- if (typeof method !== "function") {
367
- continue;
368
- }
369
-
370
- const methodEvents = events[methodName] || [];
371
- const eventPublisher = createServiceMethodEventPublisher(
372
- scope,
373
- registrationSpec.serviceToken,
374
- methodName,
375
- methodEvents
376
- );
377
-
378
- wrappedService[methodName] = function registeredServiceMethod(...args) {
379
- if (methodEvents.length < 1) {
380
- return method(...args);
381
- }
382
-
383
- const options = resolveMethodOptions(args);
384
- const result = method(...args);
385
- const publish = (resolvedResult) =>
386
- eventPublisher({
387
- result: resolvedResult,
388
- args,
389
- options,
390
- methodName,
391
- serviceToken: registrationSpec.serviceToken
392
- }).then(() => resolvedResult);
393
-
394
- if (result && typeof result.then === "function") {
395
- return result.then((resolvedResult) => publish(resolvedResult));
396
- }
397
-
398
- return publish(result);
399
- };
400
- }
401
-
402
- Object.defineProperty(wrappedService, "serviceEvents", {
403
- enumerable: false,
404
- configurable: false,
405
- writable: false,
406
- value: events
407
- });
408
- Object.defineProperty(wrappedService, "serviceToken", {
409
- enumerable: false,
410
- configurable: false,
411
- writable: false,
412
- value: registrationSpec.serviceToken
413
- });
414
-
415
- return Object.freeze(wrappedService);
416
- }
417
-
418
- function normalizeServiceRegistration(value = {}) {
419
- const source = normalizeObject(value);
420
- if (!isContainerToken(source.serviceToken)) {
421
- throw new TypeError("app.service requires a valid service token.");
422
- }
423
- if (typeof source.factory !== "function") {
424
- throw new TypeError("app.service requires a factory function.");
425
- }
426
-
427
- return Object.freeze({
428
- serviceToken: source.serviceToken,
429
- factory: source.factory,
430
- metadata: normalizeServiceMetadata(source.metadata)
431
- });
432
- }
433
-
434
- function registerServiceRegistration(app, token, factory) {
435
- registerTaggedSingleton(app, token, factory, "jskit.runtime.services.registrations", {
436
- context: "registerServiceRegistration"
437
- });
438
- }
439
-
440
- function resolveServiceRegistrations(scope) {
441
- return resolveTaggedEntries(scope, "jskit.runtime.services.registrations")
442
- .map((entry) => normalizeObject(entry))
443
- .filter((entry) => Object.keys(entry).length > 0)
444
- .sort((left, right) => String(left.serviceToken || "").localeCompare(String(right.serviceToken || "")));
445
- }
446
-
447
- function installServiceRegistrationApi(app) {
448
- assertTaggableApp(app, {
449
- context: "installServiceRegistrationApi"
450
- });
451
- if (typeof app.service === "function") {
452
- return;
453
- }
454
-
455
- const registerService = function registerService(serviceToken, factory, metadata = {}) {
456
- const registration = normalizeServiceRegistration({
457
- serviceToken,
458
- factory,
459
- metadata
460
- });
461
-
462
- this.singleton(registration.serviceToken, (scope) => materializeServiceRegistration(scope, registration));
463
-
464
- const registrationToken = createServiceRegistrationToken();
465
- registerServiceRegistration(this, registrationToken, () =>
466
- Object.freeze({
467
- serviceToken: registration.serviceToken,
468
- metadata: registration.metadata
469
- })
470
- );
471
-
472
- return this;
473
- };
474
-
475
- Object.defineProperty(app, "service", {
476
- configurable: true,
477
- writable: true,
478
- value: registerService
479
- });
480
- }
481
-
482
- export {
483
- normalizeServiceRegistration,
484
- materializeServiceRegistration,
485
- registerServiceRegistration,
486
- resolveServiceRegistrations,
487
- installServiceRegistrationApi
488
- };
@@ -1,64 +0,0 @@
1
- import * as apiRouteRegistration from "./apiRouteRegistration.js";
2
- import * as bootstrapContributors from "../registries/bootstrapPayloadContributorRegistry.js";
3
- import * as bootstrapRoutes from "./bootBootstrapRoutes.js";
4
- import * as canonicalJson from "./canonicalJson.js";
5
- import * as composition from "./composition.js";
6
- import * as domainEvents from "../registries/domainEventListenerRegistry.js";
7
- import * as errors from "./errors.js";
8
- import * as fastifyBootstrap from "./fastifyBootstrap.js";
9
- import * as integers from "./integers.js";
10
- import * as pagination from "./pagination.js";
11
- import * as realtimeNormalization from "./realtimeNormalization.js";
12
- import * as requestUrl from "./requestUrl.js";
13
- import * as routeUtils from "./routeUtils.js";
14
- import * as runtimeAssembly from "./runtimeAssembly.js";
15
- import * as runtimeKernel from "./runtimeKernel.js";
16
- import * as serviceAuthorization from "./serviceAuthorization.js";
17
- import * as serviceRegistration from "../registries/serviceRegistrationRegistry.js";
18
- import * as entityChangeEvents from "./entityChangeEvents.js";
19
- import * as securityAudit from "./securityAudit.js";
20
-
21
- const SERVER_RUNTIME_CORE_API = Object.freeze({
22
- apiRouteRegistration: Object.freeze({ ...apiRouteRegistration }),
23
- bootstrapContributors: Object.freeze({ ...bootstrapContributors }),
24
- bootstrapRoutes: Object.freeze({ ...bootstrapRoutes }),
25
- canonicalJson: Object.freeze({ ...canonicalJson }),
26
- composition: Object.freeze({ ...composition }),
27
- domainEvents: Object.freeze({ ...domainEvents }),
28
- errors: Object.freeze({ ...errors }),
29
- fastifyBootstrap: Object.freeze({ ...fastifyBootstrap }),
30
- integers: Object.freeze({ ...integers }),
31
- pagination: Object.freeze({ ...pagination }),
32
- realtimeNormalization: Object.freeze({ ...realtimeNormalization }),
33
- requestUrl: Object.freeze({ ...requestUrl }),
34
- routeUtils: Object.freeze({ ...routeUtils }),
35
- runtimeAssembly: Object.freeze({ ...runtimeAssembly }),
36
- runtimeKernel: Object.freeze({ ...runtimeKernel }),
37
- serviceAuthorization: Object.freeze({ ...serviceAuthorization }),
38
- serviceRegistration: Object.freeze({ ...serviceRegistration }),
39
- entityChangeEvents: Object.freeze({ ...entityChangeEvents }),
40
- securityAudit: Object.freeze({ ...securityAudit })
41
- });
42
-
43
- class ServerRuntimeCoreServiceProvider {
44
- static id = "runtime.server";
45
-
46
- register(app) {
47
- if (!app || typeof app.singleton !== "function" || typeof app.has !== "function") {
48
- throw new Error("ServerRuntimeCoreServiceProvider requires application singleton()/has().");
49
- }
50
-
51
- serviceRegistration.installServiceRegistrationApi(app);
52
-
53
- app.singleton("runtime.server", () => SERVER_RUNTIME_CORE_API);
54
- app.singleton("domainEvents", (scope) => domainEvents.createDomainEvents(scope));
55
- }
56
-
57
- boot(app) {
58
- if (app.has("jskit.http.router")) {
59
- bootstrapRoutes.bootBootstrapRoutes(app);
60
- }
61
- }
62
- }
63
-
64
- export { ServerRuntimeCoreServiceProvider };