@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,114 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { createContainer } from "../container/index.js";
4
- import {
5
- registerDomainEventListener,
6
- resolveDomainEventListeners,
7
- createDomainEvents
8
- } from "../registries/domainEventListenerRegistry.js";
9
-
10
- test("registerDomainEventListener + resolveDomainEventListeners resolve canonical listeners", () => {
11
- const app = createContainer();
12
-
13
- registerDomainEventListener(app, "test.domainEvents.alpha", () => ({
14
- listenerId: "alpha",
15
- async handle() {}
16
- }));
17
- registerDomainEventListener(app, "test.domainEvents.zeta", () => ({
18
- listenerId: "zeta",
19
- async handle() {}
20
- }));
21
-
22
- const listeners = resolveDomainEventListeners(app);
23
- assert.deepEqual(
24
- listeners.map((listener) => listener.listenerId),
25
- ["alpha", "zeta"]
26
- );
27
- assert.equal(typeof listeners[0].handle, "function");
28
- assert.equal(typeof listeners[1].handle, "function");
29
- });
30
-
31
- test("createDomainEvents.publish dispatches listeners and applies matches filter", async () => {
32
- const app = createContainer();
33
- const calls = [];
34
-
35
- registerDomainEventListener(app, "test.domainEvents.alpha", () => ({
36
- listenerId: "alpha",
37
- matches(event) {
38
- return event.entity === "record";
39
- },
40
- async handle(event) {
41
- calls.push({
42
- listenerId: "alpha",
43
- event
44
- });
45
- }
46
- }));
47
- registerDomainEventListener(app, "test.domainEvents.beta", () => ({
48
- listenerId: "beta",
49
- async handle(event) {
50
- calls.push({
51
- listenerId: "beta",
52
- event
53
- });
54
- }
55
- }));
56
-
57
- const domainEvents = createDomainEvents(app);
58
- await domainEvents.publish({
59
- entity: "record",
60
- operation: "created"
61
- });
62
- await domainEvents.publish({
63
- entity: "other",
64
- operation: "created"
65
- });
66
-
67
- assert.deepEqual(calls, [
68
- {
69
- listenerId: "alpha",
70
- event: {
71
- entity: "record",
72
- operation: "created"
73
- }
74
- },
75
- {
76
- listenerId: "beta",
77
- event: {
78
- entity: "record",
79
- operation: "created"
80
- }
81
- },
82
- {
83
- listenerId: "beta",
84
- event: {
85
- entity: "other",
86
- operation: "created"
87
- }
88
- }
89
- ]);
90
- });
91
-
92
- test("createDomainEvents.publish ignores non-listener tag entries", async () => {
93
- const app = createContainer();
94
-
95
- registerDomainEventListener(app, "test.domainEvents.invalid", () => ({
96
- listenerId: "invalid"
97
- }));
98
- registerDomainEventListener(app, "test.domainEvents.valid", () => ({
99
- listenerId: "valid",
100
- async handle() {}
101
- }));
102
-
103
- const listeners = resolveDomainEventListeners(app);
104
- assert.deepEqual(
105
- listeners.map((listener) => listener.listenerId),
106
- ["valid"]
107
- );
108
-
109
- const domainEvents = createDomainEvents(app);
110
- const result = await domainEvents.publish({
111
- entity: "record"
112
- });
113
- assert.equal(result, null);
114
- });
@@ -1,50 +0,0 @@
1
- import { DomainValidationError } from "./errors.js";
2
-
3
- function collectDomainFieldErrors(rules) {
4
- const fieldErrors = {};
5
-
6
- for (const rule of Array.isArray(rules) ? rules : []) {
7
- if (rule?.when && !rule.when()) {
8
- continue;
9
- }
10
-
11
- const outcome = rule?.check ? rule.check() : null;
12
- if (!outcome) {
13
- continue;
14
- }
15
-
16
- if (typeof outcome === "string") {
17
- fieldErrors[rule.field] = outcome;
18
- continue;
19
- }
20
-
21
- if (typeof outcome === "object") {
22
- fieldErrors[rule.field] = outcome?.message || "domain rule failed";
23
- }
24
- }
25
-
26
- return fieldErrors;
27
- }
28
-
29
- function assertNoDomainRuleFailures(
30
- rules,
31
- {
32
- message = "Domain validation failed.",
33
- code = "domain_validation_failed"
34
- } = {}
35
- ) {
36
- const fieldErrors = collectDomainFieldErrors(rules);
37
- if (Object.keys(fieldErrors).length > 0) {
38
- throw new DomainValidationError(
39
- {
40
- fieldErrors
41
- },
42
- {
43
- message,
44
- code
45
- }
46
- );
47
- }
48
- }
49
-
50
- export { collectDomainFieldErrors, assertNoDomainRuleFailures };
@@ -1,87 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
-
4
- import { DomainValidationError } from "./errors.js";
5
- import { assertNoDomainRuleFailures, collectDomainFieldErrors } from "./domainRules.js";
6
-
7
- test("collectDomainFieldErrors collects string and object rule outcomes", () => {
8
- const fieldErrors = collectDomainFieldErrors([
9
- {
10
- field: "name",
11
- check: () => "name is required"
12
- },
13
- {
14
- field: "email",
15
- check: () => ({
16
- message: "invalid email"
17
- })
18
- },
19
- {
20
- field: "country",
21
- when: () => false,
22
- check: () => "country not allowed"
23
- }
24
- ]);
25
-
26
- assert.deepEqual(fieldErrors, {
27
- name: "name is required",
28
- email: "invalid email"
29
- });
30
- });
31
-
32
- test("assertNoDomainRuleFailures does not throw when rules pass", () => {
33
- assert.doesNotThrow(() =>
34
- assertNoDomainRuleFailures([
35
- {
36
- field: "name",
37
- check: () => null
38
- }
39
- ])
40
- );
41
- });
42
-
43
- test("assertNoDomainRuleFailures throws DomainValidationError with fieldErrors", () => {
44
- assert.throws(
45
- () =>
46
- assertNoDomainRuleFailures([
47
- {
48
- field: "plan",
49
- check: () => "starter plan supports up to 200 employees"
50
- }
51
- ]),
52
- (error) => {
53
- assert.equal(error instanceof DomainValidationError, true);
54
- assert.equal(error.code, "domain_validation_failed");
55
- assert.deepEqual(error.details, {
56
- fieldErrors: {
57
- plan: "starter plan supports up to 200 employees"
58
- }
59
- });
60
- return true;
61
- }
62
- );
63
- });
64
-
65
- test("assertNoDomainRuleFailures applies custom message and code", () => {
66
- assert.throws(
67
- () =>
68
- assertNoDomainRuleFailures(
69
- [
70
- {
71
- field: "email",
72
- check: () => "email must include @"
73
- }
74
- ],
75
- {
76
- message: "Contact domain validation failed.",
77
- code: "contact_domain_invalid"
78
- }
79
- ),
80
- (error) => {
81
- assert.equal(error instanceof DomainValidationError, true);
82
- assert.equal(error.message, "Contact domain validation failed.");
83
- assert.equal(error.code, "contact_domain_invalid");
84
- return true;
85
- }
86
- );
87
- });
@@ -1,113 +0,0 @@
1
- import { createRuntimeKernel } from "./runtimeKernel.js";
2
-
3
- function normalizeRuntimeBundles(bundles) {
4
- const source = Array.isArray(bundles) ? bundles : [];
5
- return source.filter((entry) => entry && typeof entry === "object");
6
- }
7
-
8
- function mergeRuntimeBundles(bundles = []) {
9
- const normalizedBundles = normalizeRuntimeBundles(bundles);
10
-
11
- return normalizedBundles.reduce(
12
- (accumulator, bundle) => ({
13
- repositoryDefinitions: accumulator.repositoryDefinitions.concat(
14
- Array.isArray(bundle.repositoryDefinitions) ? bundle.repositoryDefinitions : []
15
- ),
16
- serviceDefinitions: accumulator.serviceDefinitions.concat(
17
- Array.isArray(bundle.serviceDefinitions) ? bundle.serviceDefinitions : []
18
- ),
19
- controllerDefinitions: accumulator.controllerDefinitions.concat(
20
- Array.isArray(bundle.controllerDefinitions) ? bundle.controllerDefinitions : []
21
- ),
22
- runtimeServiceIds: accumulator.runtimeServiceIds.concat(
23
- Array.isArray(bundle.runtimeServiceIds) ? bundle.runtimeServiceIds : []
24
- )
25
- }),
26
- {
27
- repositoryDefinitions: [],
28
- serviceDefinitions: [],
29
- controllerDefinitions: [],
30
- runtimeServiceIds: []
31
- }
32
- );
33
- }
34
-
35
- function createRuntimeAssembly({
36
- bundles = [],
37
- dependencies = {},
38
- repositoryDependencies = {},
39
- serviceDependencies = {},
40
- controllerDependencies = {}
41
- } = {}) {
42
- const runtimeBundle = mergeRuntimeBundles(bundles);
43
-
44
- return createRuntimeKernel({
45
- runtimeBundle,
46
- dependencies,
47
- repositoryDependencies,
48
- serviceDependencies,
49
- controllerDependencies
50
- });
51
- }
52
-
53
- function normalizeRouteModuleDefinitions(definitions) {
54
- const source = Array.isArray(definitions) ? definitions : [];
55
- const normalized = [];
56
- const seenIds = new Set();
57
-
58
- for (const entry of source) {
59
- const id = String(entry?.id || "").trim();
60
- const buildRoutes = entry?.buildRoutes;
61
- const resolveOptions = entry?.resolveOptions;
62
-
63
- if (!id) {
64
- throw new TypeError("Route module definition id is required.");
65
- }
66
- if (seenIds.has(id)) {
67
- throw new TypeError(`Route module definition "${id}" is duplicated.`);
68
- }
69
- if (typeof buildRoutes !== "function") {
70
- throw new TypeError(`Route module definition "${id}" buildRoutes must be a function.`);
71
- }
72
- if (resolveOptions != null && typeof resolveOptions !== "function") {
73
- throw new TypeError(`Route module definition "${id}" resolveOptions must be a function when provided.`);
74
- }
75
-
76
- seenIds.add(id);
77
- normalized.push({
78
- id,
79
- buildRoutes,
80
- resolveOptions
81
- });
82
- }
83
-
84
- return normalized;
85
- }
86
-
87
- function buildRoutesFromManifest({ definitions = [], controllers = {}, routeConfig = {}, missingHandler } = {}) {
88
- const normalizedDefinitions = normalizeRouteModuleDefinitions(definitions);
89
- const routeList = [];
90
-
91
- for (const definition of normalizedDefinitions) {
92
- const resolvedOptions = definition.resolveOptions ? definition.resolveOptions(routeConfig || {}) : {};
93
- const routes = definition.buildRoutes(controllers || {}, {
94
- ...(resolvedOptions && typeof resolvedOptions === "object" ? resolvedOptions : {}),
95
- ...(missingHandler ? { missingHandler } : {})
96
- });
97
-
98
- if (!Array.isArray(routes)) {
99
- throw new TypeError(`Route module definition "${definition.id}" must return an array.`);
100
- }
101
-
102
- routeList.push(...routes);
103
- }
104
-
105
- return routeList;
106
- }
107
-
108
- const __testables = {
109
- normalizeRuntimeBundles,
110
- normalizeRouteModuleDefinitions
111
- };
112
-
113
- export { mergeRuntimeBundles, createRuntimeAssembly, buildRoutesFromManifest, __testables };
@@ -1,55 +0,0 @@
1
- import { createRuntimeComposition } from "./composition.js";
2
-
3
- function normalizeDefinitions(value) {
4
- return Array.isArray(value) ? value : [];
5
- }
6
-
7
- function normalizeRuntimeServiceIds(value) {
8
- return Array.isArray(value) ? value : [];
9
- }
10
-
11
- function normalizeRuntimeBundle(bundle = {}) {
12
- const source = bundle && typeof bundle === "object" ? bundle : {};
13
-
14
- return {
15
- repositoryDefinitions: normalizeDefinitions(source.repositoryDefinitions),
16
- serviceDefinitions: normalizeDefinitions(source.serviceDefinitions),
17
- controllerDefinitions: normalizeDefinitions(source.controllerDefinitions),
18
- runtimeServiceIds: normalizeRuntimeServiceIds(source.runtimeServiceIds)
19
- };
20
- }
21
-
22
- function createRuntimeKernel({
23
- runtimeBundle,
24
- dependencies = {},
25
- repositoryDependencies = {},
26
- serviceDependencies = {},
27
- controllerDependencies = {}
28
- } = {}) {
29
- const sharedDependencies = dependencies && typeof dependencies === "object" ? dependencies : {};
30
- const normalizedBundle = normalizeRuntimeBundle(runtimeBundle);
31
-
32
- return createRuntimeComposition({
33
- ...normalizedBundle,
34
- repositoryDependencies: {
35
- ...sharedDependencies,
36
- ...(repositoryDependencies || {})
37
- },
38
- serviceDependencies: {
39
- ...sharedDependencies,
40
- ...(serviceDependencies || {})
41
- },
42
- controllerDependencies: {
43
- ...sharedDependencies,
44
- ...(controllerDependencies || {})
45
- }
46
- });
47
- }
48
-
49
- const __testables = {
50
- normalizeDefinitions,
51
- normalizeRuntimeServiceIds,
52
- normalizeRuntimeBundle
53
- };
54
-
55
- export { normalizeRuntimeBundle, createRuntimeKernel, __testables };
@@ -1,251 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import test from "node:test";
3
- import { createContainer } from "../container/index.js";
4
- import {
5
- installServiceRegistrationApi,
6
- resolveServiceRegistrations
7
- } from "../registries/serviceRegistrationRegistry.js";
8
-
9
- test("installServiceRegistrationApi exposes app.service and publishes declared events", async () => {
10
- const app = createContainer();
11
- const published = [];
12
- app.singleton("domainEvents", () => ({
13
- async publish(payload) {
14
- published.push(payload);
15
- return null;
16
- }
17
- }));
18
-
19
- installServiceRegistrationApi(app);
20
- assert.equal(typeof app.service, "function");
21
-
22
- app.service(
23
- "test.customers.service",
24
- () => ({
25
- async createRecord() {
26
- return { id: 41 };
27
- }
28
- }),
29
- {
30
- events: {
31
- createRecord: [
32
- {
33
- type: "entity.changed",
34
- source: "crud",
35
- entity: "record",
36
- operation: "created",
37
- realtime: {
38
- event: "customers.record.changed"
39
- }
40
- }
41
- ]
42
- }
43
- }
44
- );
45
-
46
- const service = app.make("test.customers.service");
47
- const result = await service.createRecord({
48
- context: {
49
- actor: { id: 7 },
50
- visibilityContext: {
51
- scopeOwnerId: 13
52
- }
53
- }
54
- });
55
-
56
- assert.equal(result.id, 41);
57
- assert.equal(service.serviceEvents.createRecord[0].realtime.audience, "event_scope");
58
- assert.equal(published.length, 1);
59
- assert.equal(published[0].source, "crud");
60
- assert.equal(published[0].operation, "created");
61
- assert.equal(published[0].meta?.service?.token, "test.customers.service");
62
- assert.equal(published[0].meta?.service?.method, "createRecord");
63
- assert.equal(published[0].meta?.realtime?.event, "customers.record.changed");
64
- });
65
-
66
- test("app.service rejects unknown metadata fields", () => {
67
- const app = createContainer();
68
- app.singleton("domainEvents", () => ({
69
- async publish() {
70
- return null;
71
- }
72
- }));
73
- installServiceRegistrationApi(app);
74
-
75
- assert.throws(
76
- () =>
77
- app.service(
78
- "test.secure.service",
79
- () => ({
80
- async listRecords() {
81
- return [];
82
- }
83
- }),
84
- {
85
- unexpected: true
86
- }
87
- ),
88
- /metadata supports only events.*unexpected/
89
- );
90
- });
91
-
92
- test("app.service publishes lifecycle action, reason, and realtime payload metadata", async () => {
93
- const app = createContainer();
94
- const published = [];
95
- app.singleton("domainEvents", () => ({
96
- async publish(payload) {
97
- published.push(payload);
98
- return null;
99
- }
100
- }));
101
- installServiceRegistrationApi(app);
102
-
103
- app.service(
104
- "test.projects.service",
105
- () => ({
106
- async closeRuntime() {
107
- return {
108
- id: "project_acme",
109
- action: "runtime-closed",
110
- message: "Project is closed."
111
- };
112
- }
113
- }),
114
- {
115
- events: {
116
- closeRuntime: [
117
- {
118
- type: "entity.changed",
119
- source: "vibe64",
120
- entity: "project",
121
- operation: "updated",
122
- action: ({ result }) => result?.action,
123
- reason: "user-request",
124
- realtime: {
125
- event: "vibe64.project.changed",
126
- payload: ({ result }) => ({
127
- message: result?.message || ""
128
- })
129
- }
130
- }
131
- ]
132
- }
133
- }
134
- );
135
-
136
- const service = app.make("test.projects.service");
137
- await service.closeRuntime();
138
-
139
- assert.equal(service.serviceEvents.closeRuntime[0].reason, "user-request");
140
- assert.equal(typeof service.serviceEvents.closeRuntime[0].action, "function");
141
- assert.equal(published.length, 1);
142
- assert.equal(published[0].meta?.action, "runtime-closed");
143
- assert.equal(published[0].meta?.reason, "user-request");
144
- assert.equal(published[0].meta?.realtime?.event, "vibe64.project.changed");
145
- assert.deepEqual(published[0].meta?.realtime?.payload, {
146
- message: "Project is closed."
147
- });
148
- });
149
-
150
- test("resolveServiceRegistrations returns declared service metadata", () => {
151
- const app = createContainer();
152
- app.singleton("domainEvents", () => ({
153
- async publish() {
154
- return null;
155
- }
156
- }));
157
- installServiceRegistrationApi(app);
158
-
159
- app.service(
160
- "test.registry.service",
161
- () => ({
162
- async createRecord() {
163
- return { id: 1 };
164
- }
165
- })
166
- );
167
-
168
- const entries = resolveServiceRegistrations(app);
169
- assert.equal(entries.length, 1);
170
- assert.equal(entries[0].serviceToken, "test.registry.service");
171
- assert.deepEqual(entries[0].metadata, {
172
- events: {}
173
- });
174
- });
175
-
176
- test("app.service keeps realtime audience callbacks", () => {
177
- const app = createContainer();
178
- app.singleton("domainEvents", () => ({
179
- async publish() {
180
- return null;
181
- }
182
- }));
183
- installServiceRegistrationApi(app);
184
-
185
- const audience = () => ({ userId: 7 });
186
- app.service(
187
- "test.audience.service",
188
- () => ({
189
- async updateRecord() {
190
- return { id: 2 };
191
- }
192
- }),
193
- {
194
- events: {
195
- updateRecord: [
196
- {
197
- type: "entity.changed",
198
- source: "crud",
199
- entity: "record",
200
- operation: "updated",
201
- realtime: {
202
- event: "customers.record.changed",
203
- audience
204
- }
205
- }
206
- ]
207
- }
208
- }
209
- );
210
-
211
- const service = app.make("test.audience.service");
212
- assert.equal(typeof service.serviceEvents.updateRecord[0].realtime.audience, "function");
213
- });
214
-
215
- test("app.service accepts opaque realtime audience string presets", () => {
216
- const app = createContainer();
217
- app.singleton("domainEvents", () => ({
218
- async publish() {
219
- return null;
220
- }
221
- }));
222
- installServiceRegistrationApi(app);
223
-
224
- app.service(
225
- "test.opaque.audience.service",
226
- () => ({
227
- async updateRecord() {
228
- return { id: 2 };
229
- }
230
- }),
231
- {
232
- events: {
233
- updateRecord: [
234
- {
235
- type: "entity.changed",
236
- source: "crud",
237
- entity: "record",
238
- operation: "updated",
239
- realtime: {
240
- event: "customers.record.changed",
241
- audience: "workspace_member"
242
- }
243
- }
244
- ]
245
- }
246
- }
247
- );
248
-
249
- const service = app.make("test.opaque.audience.service");
250
- assert.equal(service.serviceEvents.updateRecord[0].realtime.audience, "workspace_member");
251
- });
@@ -1,27 +0,0 @@
1
- import * as normalize from "../../shared/support/normalize.js";
2
- import * as sorting from "../../shared/support/sorting.js";
3
- import { isContainerToken } from "../../shared/support/containerToken.js";
4
-
5
- const SUPPORT_CORE_API = Object.freeze({
6
- normalize: Object.freeze({ ...normalize }),
7
- sorting: Object.freeze({ ...sorting }),
8
- tokens: Object.freeze({
9
- isContainerToken
10
- })
11
- });
12
-
13
- class SupportCoreServiceProvider {
14
- static id = "runtime.support";
15
-
16
- register(app) {
17
- if (!app || typeof app.singleton !== "function") {
18
- throw new Error("SupportCoreServiceProvider requires application singleton().");
19
- }
20
-
21
- app.singleton("runtime.support", () => SUPPORT_CORE_API);
22
- }
23
-
24
- boot() {}
25
- }
26
-
27
- export { SupportCoreServiceProvider };