@kelpie/server 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/index.d.ts +17 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/actor.d.ts +9 -1
- package/dist/lib/actor.d.ts.map +1 -1
- package/dist/lib/actor.js +13 -0
- package/dist/lib/actor.js.map +1 -1
- package/dist/lib/config.d.ts +44 -6
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +9 -5
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/email.d.ts +15 -63
- package/dist/lib/email.d.ts.map +1 -1
- package/dist/lib/email.js +13 -65
- package/dist/lib/email.js.map +1 -1
- package/dist/lib/fromEnv.d.ts +60 -0
- package/dist/lib/fromEnv.d.ts.map +1 -0
- package/dist/lib/fromEnv.js +94 -0
- package/dist/lib/fromEnv.js.map +1 -0
- package/dist/lib/ids.d.ts +6 -0
- package/dist/lib/ids.d.ts.map +1 -1
- package/dist/lib/ids.js +6 -0
- package/dist/lib/ids.js.map +1 -1
- package/dist/lib/kelpieConfigFile.d.ts +123 -0
- package/dist/lib/kelpieConfigFile.d.ts.map +1 -0
- package/dist/lib/kelpieConfigFile.js +111 -0
- package/dist/lib/kelpieConfigFile.js.map +1 -0
- package/dist/lib/logger.d.ts +38 -7
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +58 -20
- package/dist/lib/logger.js.map +1 -1
- package/dist/modules/agent-tasks/index.d.ts.map +1 -1
- package/dist/modules/agent-tasks/index.js +4 -1
- package/dist/modules/agent-tasks/index.js.map +1 -1
- package/dist/modules/agent-tasks/prompt.d.ts +36 -6
- package/dist/modules/agent-tasks/prompt.d.ts.map +1 -1
- package/dist/modules/agent-tasks/prompt.js +33 -4
- package/dist/modules/agent-tasks/prompt.js.map +1 -1
- package/dist/modules/agent-tasks/service.d.ts.map +1 -1
- package/dist/modules/agent-tasks/service.js +3 -2
- package/dist/modules/agent-tasks/service.js.map +1 -1
- package/dist/modules/agent-tasks/wire.d.ts +11 -0
- package/dist/modules/agent-tasks/wire.d.ts.map +1 -1
- package/dist/modules/agent-tasks/wire.js +1 -0
- package/dist/modules/agent-tasks/wire.js.map +1 -1
- package/dist/modules/auth/index.d.ts.map +1 -1
- package/dist/modules/auth/index.js +8 -7
- package/dist/modules/auth/index.js.map +1 -1
- package/dist/modules/companies/events.d.ts +22 -0
- package/dist/modules/companies/events.d.ts.map +1 -0
- package/dist/modules/companies/events.js +8 -0
- package/dist/modules/companies/events.js.map +1 -0
- package/dist/modules/companies/index.d.ts.map +1 -1
- package/dist/modules/companies/index.js +2 -0
- package/dist/modules/companies/index.js.map +1 -1
- package/dist/modules/companies/service.d.ts +1 -0
- package/dist/modules/companies/service.d.ts.map +1 -1
- package/dist/modules/companies/service.js +8 -11
- package/dist/modules/companies/service.js.map +1 -1
- package/dist/modules/core.d.ts.map +1 -1
- package/dist/modules/core.js +4 -0
- package/dist/modules/core.js.map +1 -1
- package/dist/modules/deals/events.d.ts +31 -0
- package/dist/modules/deals/events.d.ts.map +1 -0
- package/dist/modules/deals/events.js +12 -0
- package/dist/modules/deals/events.js.map +1 -0
- package/dist/modules/deals/index.d.ts.map +1 -1
- package/dist/modules/deals/index.js +2 -0
- package/dist/modules/deals/index.js.map +1 -1
- package/dist/modules/deals/service.d.ts +1 -0
- package/dist/modules/deals/service.d.ts.map +1 -1
- package/dist/modules/deals/service.js +9 -18
- package/dist/modules/deals/service.js.map +1 -1
- package/dist/modules/decisions/events.d.ts +21 -0
- package/dist/modules/decisions/events.d.ts.map +1 -0
- package/dist/modules/decisions/events.js +11 -0
- package/dist/modules/decisions/events.js.map +1 -0
- package/dist/modules/decisions/index.d.ts.map +1 -1
- package/dist/modules/decisions/index.js +2 -0
- package/dist/modules/decisions/index.js.map +1 -1
- package/dist/modules/decisions/service.d.ts +1 -0
- package/dist/modules/decisions/service.d.ts.map +1 -1
- package/dist/modules/decisions/service.js +4 -7
- package/dist/modules/decisions/service.js.map +1 -1
- package/dist/modules/forms/events.d.ts +37 -0
- package/dist/modules/forms/events.d.ts.map +1 -0
- package/dist/modules/forms/events.js +15 -0
- package/dist/modules/forms/events.js.map +1 -0
- package/dist/modules/forms/index.d.ts.map +1 -1
- package/dist/modules/forms/index.js +2 -0
- package/dist/modules/forms/index.js.map +1 -1
- package/dist/modules/forms/service.d.ts +1 -0
- package/dist/modules/forms/service.d.ts.map +1 -1
- package/dist/modules/forms/service.js +8 -11
- package/dist/modules/forms/service.js.map +1 -1
- package/dist/modules/forms/submission.d.ts +5 -0
- package/dist/modules/forms/submission.d.ts.map +1 -1
- package/dist/modules/forms/submission.js +54 -28
- package/dist/modules/forms/submission.js.map +1 -1
- package/dist/modules/handbook/events.d.ts +28 -0
- package/dist/modules/handbook/events.d.ts.map +1 -0
- package/dist/modules/handbook/events.js +14 -0
- package/dist/modules/handbook/events.js.map +1 -0
- package/dist/modules/handbook/index.d.ts.map +1 -1
- package/dist/modules/handbook/index.js +2 -0
- package/dist/modules/handbook/index.js.map +1 -1
- package/dist/modules/handbook/service.d.ts +1 -0
- package/dist/modules/handbook/service.d.ts.map +1 -1
- package/dist/modules/handbook/service.js +8 -15
- package/dist/modules/handbook/service.js.map +1 -1
- package/dist/modules/hiring/candidates.d.ts +1 -0
- package/dist/modules/hiring/candidates.d.ts.map +1 -1
- package/dist/modules/hiring/candidates.js +8 -11
- package/dist/modules/hiring/candidates.js.map +1 -1
- package/dist/modules/hiring/events.d.ts +35 -0
- package/dist/modules/hiring/events.d.ts.map +1 -0
- package/dist/modules/hiring/events.js +11 -0
- package/dist/modules/hiring/events.js.map +1 -0
- package/dist/modules/hiring/index.d.ts.map +1 -1
- package/dist/modules/hiring/index.js +2 -0
- package/dist/modules/hiring/index.js.map +1 -1
- package/dist/modules/hiring/roles.d.ts +1 -0
- package/dist/modules/hiring/roles.d.ts.map +1 -1
- package/dist/modules/hiring/roles.js +8 -11
- package/dist/modules/hiring/roles.js.map +1 -1
- package/dist/modules/import-export/events.d.ts +22 -0
- package/dist/modules/import-export/events.d.ts.map +1 -0
- package/dist/modules/import-export/events.js +12 -0
- package/dist/modules/import-export/events.js.map +1 -0
- package/dist/modules/import-export/index.d.ts.map +1 -1
- package/dist/modules/import-export/index.js +2 -0
- package/dist/modules/import-export/index.js.map +1 -1
- package/dist/modules/import-export/service.d.ts +5 -0
- package/dist/modules/import-export/service.d.ts.map +1 -1
- package/dist/modules/import-export/service.js +53 -14
- package/dist/modules/import-export/service.js.map +1 -1
- package/dist/modules/notes/events.d.ts +22 -0
- package/dist/modules/notes/events.d.ts.map +1 -0
- package/dist/modules/notes/events.js +12 -0
- package/dist/modules/notes/events.js.map +1 -0
- package/dist/modules/notes/index.d.ts.map +1 -1
- package/dist/modules/notes/index.js +2 -0
- package/dist/modules/notes/index.js.map +1 -1
- package/dist/modules/notes/service.d.ts +1 -0
- package/dist/modules/notes/service.d.ts.map +1 -1
- package/dist/modules/notes/service.js +4 -7
- package/dist/modules/notes/service.js.map +1 -1
- package/dist/modules/opportunities/events.d.ts +31 -0
- package/dist/modules/opportunities/events.d.ts.map +1 -0
- package/dist/modules/opportunities/events.js +12 -0
- package/dist/modules/opportunities/events.js.map +1 -0
- package/dist/modules/opportunities/index.d.ts.map +1 -1
- package/dist/modules/opportunities/index.js +2 -0
- package/dist/modules/opportunities/index.js.map +1 -1
- package/dist/modules/opportunities/service.d.ts +1 -0
- package/dist/modules/opportunities/service.d.ts.map +1 -1
- package/dist/modules/opportunities/service.js +9 -18
- package/dist/modules/opportunities/service.js.map +1 -1
- package/dist/modules/partnerships/events.d.ts +31 -0
- package/dist/modules/partnerships/events.d.ts.map +1 -0
- package/dist/modules/partnerships/events.js +12 -0
- package/dist/modules/partnerships/events.js.map +1 -0
- package/dist/modules/partnerships/index.d.ts.map +1 -1
- package/dist/modules/partnerships/index.js +2 -0
- package/dist/modules/partnerships/index.js.map +1 -1
- package/dist/modules/partnerships/service.d.ts +1 -0
- package/dist/modules/partnerships/service.d.ts.map +1 -1
- package/dist/modules/partnerships/service.js +9 -18
- package/dist/modules/partnerships/service.js.map +1 -1
- package/dist/modules/people/events.d.ts +28 -0
- package/dist/modules/people/events.d.ts.map +1 -0
- package/dist/modules/people/events.js +18 -0
- package/dist/modules/people/events.js.map +1 -0
- package/dist/modules/people/index.d.ts.map +1 -1
- package/dist/modules/people/index.js +2 -0
- package/dist/modules/people/index.js.map +1 -1
- package/dist/modules/people/service.d.ts +1 -0
- package/dist/modules/people/service.d.ts.map +1 -1
- package/dist/modules/people/service.js +8 -11
- package/dist/modules/people/service.js.map +1 -1
- package/dist/modules/pipelines/service.d.ts +4 -0
- package/dist/modules/pipelines/service.d.ts.map +1 -1
- package/dist/modules/pipelines/service.js +31 -8
- package/dist/modules/pipelines/service.js.map +1 -1
- package/dist/modules/plans/events.d.ts +21 -0
- package/dist/modules/plans/events.d.ts.map +1 -0
- package/dist/modules/plans/events.js +11 -0
- package/dist/modules/plans/events.js.map +1 -0
- package/dist/modules/plans/index.d.ts.map +1 -1
- package/dist/modules/plans/index.js +2 -0
- package/dist/modules/plans/index.js.map +1 -1
- package/dist/modules/plans/service.d.ts +1 -0
- package/dist/modules/plans/service.d.ts.map +1 -1
- package/dist/modules/plans/service.js +6 -14
- package/dist/modules/plans/service.js.map +1 -1
- package/dist/modules/positions/events.d.ts +22 -0
- package/dist/modules/positions/events.d.ts.map +1 -0
- package/dist/modules/positions/events.js +8 -0
- package/dist/modules/positions/events.js.map +1 -0
- package/dist/modules/positions/index.d.ts.map +1 -1
- package/dist/modules/positions/index.js +2 -0
- package/dist/modules/positions/index.js.map +1 -1
- package/dist/modules/positions/service.d.ts +1 -0
- package/dist/modules/positions/service.d.ts.map +1 -1
- package/dist/modules/positions/service.js +8 -11
- package/dist/modules/positions/service.js.map +1 -1
- package/dist/modules/raises/events.d.ts +31 -0
- package/dist/modules/raises/events.d.ts.map +1 -0
- package/dist/modules/raises/events.js +12 -0
- package/dist/modules/raises/events.js.map +1 -0
- package/dist/modules/raises/index.d.ts.map +1 -1
- package/dist/modules/raises/index.js +2 -0
- package/dist/modules/raises/index.js.map +1 -1
- package/dist/modules/raises/service.d.ts +1 -0
- package/dist/modules/raises/service.d.ts.map +1 -1
- package/dist/modules/raises/service.js +9 -18
- package/dist/modules/raises/service.js.map +1 -1
- package/dist/modules/reseal.d.ts +55 -0
- package/dist/modules/reseal.d.ts.map +1 -1
- package/dist/modules/reseal.js +90 -1
- package/dist/modules/reseal.js.map +1 -1
- package/dist/modules/smtp-email/index.d.ts +69 -0
- package/dist/modules/smtp-email/index.d.ts.map +1 -0
- package/dist/modules/smtp-email/index.js +82 -0
- package/dist/modules/smtp-email/index.js.map +1 -0
- package/dist/modules/webhooks/index.d.ts.map +1 -1
- package/dist/modules/webhooks/index.js +5 -1
- package/dist/modules/webhooks/index.js.map +1 -1
- package/dist/modules/webhooks/payloads.d.ts +22 -7
- package/dist/modules/webhooks/payloads.d.ts.map +1 -1
- package/dist/modules/webhooks/payloads.js +63 -44
- package/dist/modules/webhooks/payloads.js.map +1 -1
- package/dist/modules/workspace/events.d.ts +52 -0
- package/dist/modules/workspace/events.d.ts.map +1 -0
- package/dist/modules/workspace/events.js +16 -0
- package/dist/modules/workspace/events.js.map +1 -0
- package/dist/modules/workspace/index.d.ts.map +1 -1
- package/dist/modules/workspace/index.js +6 -2
- package/dist/modules/workspace/index.js.map +1 -1
- package/dist/modules/workspace/service.d.ts +1 -0
- package/dist/modules/workspace/service.d.ts.map +1 -1
- package/dist/modules/workspace/service.js +13 -15
- package/dist/modules/workspace/service.js.map +1 -1
- package/dist/modules/workspace/workspaceAccessMiddleware.d.ts.map +1 -1
- package/dist/modules/workspace/workspaceAccessMiddleware.js +11 -3
- package/dist/modules/workspace/workspaceAccessMiddleware.js.map +1 -1
- package/dist/runtime/events.d.ts +86 -108
- package/dist/runtime/events.d.ts.map +1 -1
- package/dist/runtime/events.js +123 -52
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/module.d.ts +54 -2
- package/dist/runtime/module.d.ts.map +1 -1
- package/dist/runtime/registry.d.ts +23 -0
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/runtime/registry.js +102 -2
- package/dist/runtime/registry.js.map +1 -1
- package/dist/runtime/transaction.d.ts +29 -4
- package/dist/runtime/transaction.d.ts.map +1 -1
- package/dist/runtime/transaction.js +48 -7
- package/dist/runtime/transaction.js.map +1 -1
- package/dist/testing/app.d.ts.map +1 -1
- package/dist/testing/app.js +11 -3
- package/dist/testing/app.js.map +1 -1
- package/dist/testing/database.d.ts.map +1 -1
- package/dist/testing/database.js +6 -3
- package/dist/testing/database.js.map +1 -1
- package/dist/testing/services.d.ts +21 -1
- package/dist/testing/services.d.ts.map +1 -1
- package/dist/testing/services.js +20 -5
- package/dist/testing/services.js.map +1 -1
- package/package.json +5 -2
- package/src/index.ts +44 -9
- package/src/lib/actor.ts +15 -1
- package/src/lib/config.ts +56 -7
- package/src/lib/email.ts +22 -92
- package/src/lib/fromEnv.ts +143 -0
- package/src/lib/ids.ts +6 -0
- package/src/lib/kelpieConfigFile.ts +283 -0
- package/src/lib/logger.ts +92 -34
- package/src/modules/agent-tasks/index.ts +4 -1
- package/src/modules/agent-tasks/prompt.ts +57 -9
- package/src/modules/agent-tasks/service.ts +3 -2
- package/src/modules/agent-tasks/wire.ts +12 -0
- package/src/modules/auth/index.ts +11 -9
- package/src/modules/companies/events.ts +25 -0
- package/src/modules/companies/index.ts +2 -0
- package/src/modules/companies/service.ts +8 -11
- package/src/modules/core.ts +4 -0
- package/src/modules/deals/events.ts +34 -0
- package/src/modules/deals/index.ts +2 -0
- package/src/modules/deals/service.ts +17 -18
- package/src/modules/decisions/events.ts +24 -0
- package/src/modules/decisions/index.ts +2 -0
- package/src/modules/decisions/service.ts +8 -7
- package/src/modules/forms/events.ts +37 -0
- package/src/modules/forms/index.ts +2 -0
- package/src/modules/forms/service.ts +12 -11
- package/src/modules/forms/submission.ts +80 -29
- package/src/modules/handbook/events.ts +31 -0
- package/src/modules/handbook/index.ts +2 -0
- package/src/modules/handbook/service.ts +8 -15
- package/src/modules/hiring/candidates.ts +8 -11
- package/src/modules/hiring/events.ts +36 -0
- package/src/modules/hiring/index.ts +2 -0
- package/src/modules/hiring/roles.ts +8 -11
- package/src/modules/import-export/events.ts +25 -0
- package/src/modules/import-export/index.ts +2 -0
- package/src/modules/import-export/service.ts +83 -15
- package/src/modules/notes/events.ts +25 -0
- package/src/modules/notes/index.ts +2 -0
- package/src/modules/notes/service.ts +8 -7
- package/src/modules/opportunities/events.ts +34 -0
- package/src/modules/opportunities/index.ts +2 -0
- package/src/modules/opportunities/service.ts +17 -18
- package/src/modules/partnerships/events.ts +34 -0
- package/src/modules/partnerships/index.ts +2 -0
- package/src/modules/partnerships/service.ts +17 -18
- package/src/modules/people/events.ts +36 -0
- package/src/modules/people/index.ts +2 -0
- package/src/modules/people/service.ts +97 -87
- package/src/modules/pipelines/service.ts +47 -8
- package/src/modules/plans/events.ts +24 -0
- package/src/modules/plans/index.ts +2 -0
- package/src/modules/plans/service.ts +14 -14
- package/src/modules/positions/events.ts +25 -0
- package/src/modules/positions/index.ts +2 -0
- package/src/modules/positions/service.ts +8 -11
- package/src/modules/raises/events.ts +34 -0
- package/src/modules/raises/index.ts +2 -0
- package/src/modules/raises/service.ts +17 -18
- package/src/modules/reseal.ts +144 -1
- package/src/modules/smtp-email/index.ts +119 -0
- package/src/modules/webhooks/index.ts +5 -1
- package/src/modules/webhooks/payloads.ts +94 -48
- package/src/modules/workspace/events.ts +46 -0
- package/src/modules/workspace/index.ts +6 -2
- package/src/modules/workspace/service.ts +37 -15
- package/src/modules/workspace/workspaceAccessMiddleware.ts +12 -3
- package/src/runtime/events.ts +268 -107
- package/src/runtime/module.ts +55 -2
- package/src/runtime/registry.ts +169 -1
- package/src/runtime/transaction.ts +94 -17
- package/src/testing/app.ts +11 -3
- package/src/testing/database.ts +6 -3
- package/src/testing/services.ts +34 -5
package/dist/runtime/registry.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { requireWorkspaceId } from '../lib/actor.js';
|
|
3
|
+
import { createLogEmailSender } from '../lib/email.js';
|
|
3
4
|
import { AppError, describeThrown, describeValidationIssue, toErrorDetails } from '../lib/errors.js';
|
|
4
5
|
import { createEntitlementRegistry, requireCapability } from './entitlements.js';
|
|
5
6
|
import { createEventBus } from './events.js';
|
|
@@ -24,9 +25,47 @@ function assertMountablePath(moduleId, kind, path) {
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
/**
|
|
29
|
+
* The email sender every module writes through. `target` is set once, after
|
|
30
|
+
* all modules have registered, from the provider `email.provider` picked. Until
|
|
31
|
+
* then a `.send()` throws: consumer modules capture the proxy at register time
|
|
32
|
+
* but only reach it at request time, so this is unreachable in normal flow.
|
|
33
|
+
*/
|
|
34
|
+
class EmailSenderProxy {
|
|
35
|
+
target = undefined;
|
|
36
|
+
setTarget(sender) {
|
|
37
|
+
this.target = sender;
|
|
38
|
+
}
|
|
39
|
+
send(message) {
|
|
40
|
+
if (this.target === undefined) {
|
|
41
|
+
return Promise.reject(new Error('email sender used before boot resolved a provider. Set email.provider in kelpie.config.ts.'));
|
|
42
|
+
}
|
|
43
|
+
return this.target.send(message);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The name the runtime uses for its built-in log sender. Reserved: a module
|
|
48
|
+
* that tries to register under this name fails boot.
|
|
49
|
+
*/
|
|
50
|
+
const LOG_PROVIDER_NAME = 'log';
|
|
51
|
+
function createModuleContext(module, accumulator, options, events, entitlements, moduleCatalog, emailProxy, providers) {
|
|
28
52
|
return {
|
|
29
53
|
...options.services,
|
|
54
|
+
email: emailProxy,
|
|
55
|
+
provideEmailSender(name, build) {
|
|
56
|
+
if (name === LOG_PROVIDER_NAME) {
|
|
57
|
+
throw new ModuleBootError([
|
|
58
|
+
`module "${module.id}" registers email provider "${name}", which is reserved by the runtime`,
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
const existing = providers.get(name);
|
|
62
|
+
if (existing !== undefined) {
|
|
63
|
+
throw new ModuleBootError([
|
|
64
|
+
`module "${module.id}" registers email provider "${name}", but module "${existing.registeredBy}" already did`,
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
providers.set(name, { build, registeredBy: module.id });
|
|
68
|
+
},
|
|
30
69
|
routes(mount) {
|
|
31
70
|
const router = new Hono();
|
|
32
71
|
// Gate first, so it runs before anything `mount` adds: Hono composes a
|
|
@@ -119,6 +158,28 @@ export async function registerModules(options) {
|
|
|
119
158
|
}
|
|
120
159
|
const events = options.events ?? createEventBus(options.logger);
|
|
121
160
|
const entitlements = options.entitlements ?? createEntitlementRegistry();
|
|
161
|
+
const emailProxy = new EmailSenderProxy();
|
|
162
|
+
const emailProviders = new Map();
|
|
163
|
+
// The built-in log provider is always available, no module required. Named
|
|
164
|
+
// 'log' in kelpie.config.ts's email.provider picks this one. Built eagerly
|
|
165
|
+
// because it has no env to parse and never fails.
|
|
166
|
+
const logSender = createLogEmailSender(options.logger, options.email.from);
|
|
167
|
+
emailProviders.set(LOG_PROVIDER_NAME, {
|
|
168
|
+
build: () => logSender,
|
|
169
|
+
registeredBy: '<runtime>',
|
|
170
|
+
});
|
|
171
|
+
// Seed test-supplied providers before any module registers, so a module
|
|
172
|
+
// collision with one of them fails boot the same way two modules would.
|
|
173
|
+
if (options.additionalEmailProviders !== undefined) {
|
|
174
|
+
for (const [name, sender] of options.additionalEmailProviders) {
|
|
175
|
+
if (emailProviders.has(name)) {
|
|
176
|
+
throw new ModuleBootError([
|
|
177
|
+
`additionalEmailProviders names "${name}", which is already registered by the runtime`,
|
|
178
|
+
]);
|
|
179
|
+
}
|
|
180
|
+
emailProviders.set(name, { build: () => sender, registeredBy: '<additionalEmailProviders>' });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
122
183
|
const accumulator = {
|
|
123
184
|
routers: [],
|
|
124
185
|
publicRouters: [],
|
|
@@ -149,8 +210,21 @@ export async function registerModules(options) {
|
|
|
149
210
|
if (options.moduleConfig !== undefined) {
|
|
150
211
|
entitlements.provide(createModuleConfigProvider(options.moduleConfig));
|
|
151
212
|
}
|
|
213
|
+
// Register every module's event catalog before any `register` runs, so a
|
|
214
|
+
// module that subscribes to another module's event during its own registration
|
|
215
|
+
// finds a validated name.
|
|
216
|
+
for (const module of ordered) {
|
|
217
|
+
if (module.events !== undefined) {
|
|
218
|
+
try {
|
|
219
|
+
events.registerCatalog({ moduleId: module.id, events: module.events });
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
throw new ModuleBootError([describeThrown(error)], { cause: error });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
152
226
|
for (const module of ordered) {
|
|
153
|
-
const context = createModuleContext(module, accumulator, options, events, entitlements, moduleCatalog);
|
|
227
|
+
const context = createModuleContext(module, accumulator, options, events, entitlements, moduleCatalog, emailProxy, emailProviders);
|
|
154
228
|
try {
|
|
155
229
|
await module.register(context);
|
|
156
230
|
}
|
|
@@ -164,9 +238,35 @@ export async function registerModules(options) {
|
|
|
164
238
|
}
|
|
165
239
|
context.log.debug('module registered');
|
|
166
240
|
}
|
|
241
|
+
// Resolve the configured provider. The lookup happens after every module has
|
|
242
|
+
// registered, so a module registering a provider late in the list still wins
|
|
243
|
+
// if the config names it. An unknown name is a boot error whose message lists
|
|
244
|
+
// every registered name, so a self-hoster sees what they had to pick from.
|
|
245
|
+
const chosen = emailProviders.get(options.email.provider);
|
|
246
|
+
if (chosen === undefined) {
|
|
247
|
+
const available = [...emailProviders.keys()].sort();
|
|
248
|
+
throw new ModuleBootError([
|
|
249
|
+
`email.provider is "${options.email.provider}", which no module registered. Available: ${available.join(', ')}`,
|
|
250
|
+
]);
|
|
251
|
+
}
|
|
252
|
+
// Only the chosen provider is built. A registered-but-unused provider never
|
|
253
|
+
// runs its factory, so a self-hoster who leaves a module in `modules:` but
|
|
254
|
+
// picks a different provider is not asked for the unused module's env.
|
|
255
|
+
let chosenSender;
|
|
256
|
+
try {
|
|
257
|
+
chosenSender = chosen.build();
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
if (error instanceof ModuleBootError) {
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
throw new ModuleBootError([`email provider "${options.email.provider}" (${chosen.registeredBy}) failed to build: ${describeThrown(error)}`], { cause: error });
|
|
264
|
+
}
|
|
265
|
+
emailProxy.setTarget(chosenSender);
|
|
167
266
|
options.logger.info('modules registered', {
|
|
168
267
|
count: ordered.length,
|
|
169
268
|
ids: ordered.map((module) => module.id),
|
|
269
|
+
emailProvider: options.email.provider,
|
|
170
270
|
});
|
|
171
271
|
return {
|
|
172
272
|
routers: accumulator.routers,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAI3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEpD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEpG,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAEhF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAU5C,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAC1G,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAyC1D;;;;;GAKG;AACH,MAAM,kBAAkB,GAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAA;AAEzE,SAAS,mBAAmB,CAAC,QAAgB,EAAE,IAAY,EAAE,IAAY;IACvE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,eAAe,CAAC,CAAC,WAAW,QAAQ,cAAc,IAAI,KAAK,IAAI,8BAA8B,CAAC,CAAC,CAAA;IAC3G,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,kBAAkB,EAAE,CAAC;QAC1C,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,eAAe,CAAC;gBACxB,WAAW,QAAQ,cAAc,IAAI,KAAK,IAAI,YAAY,QAAQ,4BAA4B;aAC/F,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;AACH,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { EventActor, EventTarget } from '@kelpie/schemas';
|
|
1
2
|
import type { Database } from '../lib/database.ts';
|
|
3
|
+
import type { IdFactory } from '../lib/ids.ts';
|
|
2
4
|
import type { Logger } from '../lib/logger.ts';
|
|
3
|
-
import type {
|
|
5
|
+
import type { EventBus, EventName, KelpieEventMap } from './events.ts';
|
|
4
6
|
/**
|
|
5
7
|
* One service call, one transaction, per `architecture.md`.
|
|
6
8
|
*
|
|
@@ -15,20 +17,43 @@ export type Transaction = Parameters<Parameters<Database['transaction']>[0]>[0];
|
|
|
15
17
|
* transaction when a service is composing several writes.
|
|
16
18
|
*/
|
|
17
19
|
export type Queryable = Database | Transaction;
|
|
18
|
-
|
|
20
|
+
type EventMapFor<Name extends EventName> = keyof KelpieEventMap extends never ? unknown : Name extends keyof KelpieEventMap ? KelpieEventMap[Name] : unknown;
|
|
21
|
+
/**
|
|
22
|
+
* Collects events during the transaction. Nothing leaves until commit.
|
|
23
|
+
*
|
|
24
|
+
* `emit` stamps the envelope (id, workspaceId, actor, occurredAt, causedBy) so
|
|
25
|
+
* services pass only what they know: the name, the target the event refers to,
|
|
26
|
+
* and the module-defined payload.
|
|
27
|
+
*/
|
|
19
28
|
export interface BufferedEvents {
|
|
20
|
-
emit<Name extends
|
|
29
|
+
emit<Name extends EventName>(name: Name, target: EventTarget, data: EventMapFor<Name>): void;
|
|
21
30
|
}
|
|
22
31
|
export interface TransactionContext {
|
|
23
32
|
readonly tx: Transaction;
|
|
24
33
|
readonly events: BufferedEvents;
|
|
25
34
|
}
|
|
35
|
+
export interface TransactionOptions {
|
|
36
|
+
/**
|
|
37
|
+
* The tenant this work belongs to. Every event emitted from the scope stamps
|
|
38
|
+
* it into the envelope. Required when any event is emitted; a scope that
|
|
39
|
+
* emits nothing may omit it.
|
|
40
|
+
*/
|
|
41
|
+
readonly workspaceId?: string;
|
|
42
|
+
/** Who caused this work. Defaults to `system`. */
|
|
43
|
+
readonly actor?: EventActor;
|
|
44
|
+
}
|
|
26
45
|
/** Runs `work` in one transaction and publishes its events after commit. */
|
|
27
|
-
export type TransactionScope = <Result>(work: (context: TransactionContext) => Promise<Result
|
|
46
|
+
export type TransactionScope = <Result>(work: (context: TransactionContext) => Promise<Result>, options?: TransactionOptions) => Promise<Result>;
|
|
28
47
|
export interface TransactionScopeDependencies {
|
|
29
48
|
readonly db: Database;
|
|
30
49
|
readonly bus: EventBus;
|
|
31
50
|
readonly logger: Logger;
|
|
51
|
+
readonly createId: IdFactory;
|
|
52
|
+
/** Injected so a test can pin timestamps. Defaults to `Date.now`. */
|
|
53
|
+
readonly now?: () => Date;
|
|
54
|
+
/** Chain-depth cap. Reads `KELPIE_EVENT_MAX_DEPTH`; otherwise 8. */
|
|
55
|
+
readonly maxDepth?: number;
|
|
32
56
|
}
|
|
33
57
|
export declare function createTransactionScope(dependencies: TransactionScopeDependencies): TransactionScope;
|
|
58
|
+
export {};
|
|
34
59
|
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/runtime/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/runtime/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAe,MAAM,iBAAiB,CAAA;AAE3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEtE;;;;;;GAMG;AAEH,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAE/E;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;AAE9C,KAAK,WAAW,CAAC,IAAI,SAAS,SAAS,IAAI,MAAM,cAAc,SAAS,KAAK,GACzE,OAAO,GACP,IAAI,SAAS,MAAM,cAAc,GAC/B,cAAc,CAAC,IAAI,CAAC,GACpB,OAAO,CAAA;AAEb;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,IAAI,SAAS,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAC7F;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAC5B;AAED,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EACpC,IAAI,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,MAAM,CAAC,EACtD,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,MAAM,CAAC,CAAA;AASpB,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,4BAA4B,GAAG,gBAAgB,CAiEnG"}
|
|
@@ -1,24 +1,65 @@
|
|
|
1
|
+
import { checkEventCycle, currentEventChain } from './events.js';
|
|
2
|
+
const SYSTEM_ACTOR = { kind: 'system' };
|
|
1
3
|
export function createTransactionScope(dependencies) {
|
|
2
|
-
|
|
4
|
+
const now = dependencies.now ?? (() => new Date());
|
|
5
|
+
const maxDepth = dependencies.maxDepth ?? readMaxDepthFromEnv() ?? 8;
|
|
6
|
+
return async function runInTransaction(work, options) {
|
|
7
|
+
const actor = options?.actor ?? SYSTEM_ACTOR;
|
|
8
|
+
const workspaceId = options?.workspaceId;
|
|
3
9
|
const buffered = [];
|
|
4
10
|
const result = await dependencies.db.transaction((tx) => work({
|
|
5
11
|
tx,
|
|
6
12
|
events: {
|
|
7
|
-
emit(name,
|
|
8
|
-
|
|
13
|
+
emit(name, target, data) {
|
|
14
|
+
if (workspaceId === undefined || workspaceId.length === 0) {
|
|
15
|
+
throw new Error(`event "${name}" was emitted without a workspaceId: pass it via TransactionOptions`);
|
|
16
|
+
}
|
|
17
|
+
const chain = currentEventChain();
|
|
18
|
+
const outcome = checkEventCycle(chain, name, target, maxDepth);
|
|
19
|
+
if (outcome.kind !== 'ok') {
|
|
20
|
+
dependencies.logger.error('event cycle guard dropped emit', {
|
|
21
|
+
event: name,
|
|
22
|
+
target,
|
|
23
|
+
reason: outcome.kind,
|
|
24
|
+
chain: chain.map((entry) => ({
|
|
25
|
+
id: entry.id,
|
|
26
|
+
name: entry.name,
|
|
27
|
+
target: { type: entry.targetType, id: entry.targetId },
|
|
28
|
+
})),
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const envelope = {
|
|
33
|
+
id: dependencies.createId('event'),
|
|
34
|
+
name,
|
|
35
|
+
workspaceId,
|
|
36
|
+
actor,
|
|
37
|
+
occurredAt: now().toISOString(),
|
|
38
|
+
target,
|
|
39
|
+
...(chain.length > 0 ? { causedBy: chain[chain.length - 1].id } : {}),
|
|
40
|
+
data: data,
|
|
41
|
+
};
|
|
42
|
+
buffered.push({ name, envelope });
|
|
9
43
|
},
|
|
10
44
|
},
|
|
11
45
|
}));
|
|
12
46
|
// Past this line the transaction has committed. Publishing is deliberately
|
|
13
|
-
// not awaited:
|
|
14
|
-
//
|
|
15
|
-
// graceful shutdown wait via `bus.drain()`.
|
|
47
|
+
// not awaited: an outbound HTTP delivery must not sit inside the request
|
|
48
|
+
// that triggered it. Tests and graceful shutdown wait via `bus.drain()`.
|
|
16
49
|
for (const event of buffered) {
|
|
17
|
-
void
|
|
50
|
+
void dependencies.bus.publish(event.envelope).catch((error) => {
|
|
18
51
|
dependencies.logger.error('event publication failed', { event: event.name, error });
|
|
19
52
|
});
|
|
20
53
|
}
|
|
21
54
|
return result;
|
|
22
55
|
};
|
|
23
56
|
}
|
|
57
|
+
function readMaxDepthFromEnv() {
|
|
58
|
+
const raw = process.env.KELPIE_EVENT_MAX_DEPTH;
|
|
59
|
+
if (raw === undefined || raw === '') {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
const parsed = Number.parseInt(raw, 10);
|
|
63
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
64
|
+
}
|
|
24
65
|
//# sourceMappingURL=transaction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/runtime/transaction.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/runtime/transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/testing/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAIrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAejD;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC1C,wFAAwF;IACxF,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAA;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IACrD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAA;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAC3C,sFAAsF;IACtF,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACzD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,CAAA;IAC5D,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAA;IACpC,sFAAsF;IACtF,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAA;CACxD;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAA;IAC3C,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAID,wBAAsB,aAAa,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/testing/app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAGzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAIrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAejD;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAC1C,wFAAwF;IACxF,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAA;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAA;IACrD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAA;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAC3C,sFAAsF;IACtF,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACzD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,CAAA;IAC5D,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAA;IACpC,sFAAsF;IACtF,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAA;CACxD;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAA;IAC3C,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAID,wBAAsB,aAAa,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAoClF"}
|
package/dist/testing/app.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createApp } from '../app.js';
|
|
2
|
-
import { createLogger } from '../lib/logger.js';
|
|
2
|
+
import { createCaptureTransport, createLogger } from '../lib/logger.js';
|
|
3
3
|
import { rateLimitConfigFrom, rateLimitConfigSchema } from '../lib/rateLimit.js';
|
|
4
4
|
import { registerModules } from '../runtime/registry.js';
|
|
5
5
|
import { TEST_ENVIRONMENT } from './environment.js';
|
|
6
|
-
import { createTestServices } from './services.js';
|
|
6
|
+
import { TEST_EMAIL_FROM, TEST_EMAIL_PROVIDER, createTestServices } from './services.js';
|
|
7
7
|
/** The same defaults `loadConfig` produces from an empty environment: one source of numbers for both. */
|
|
8
8
|
const DEFAULT_TEST_RATE_LIMIT = rateLimitConfigFrom(rateLimitConfigSchema.parse({}));
|
|
9
9
|
/**
|
|
@@ -18,13 +18,21 @@ function testClientIp(context) {
|
|
|
18
18
|
const reachableDatabase = () => Promise.resolve({ reachable: true });
|
|
19
19
|
export async function createTestApp(options = {}) {
|
|
20
20
|
const logLines = [];
|
|
21
|
-
const logger = createLogger(
|
|
21
|
+
const logger = createLogger({
|
|
22
|
+
level: 'debug',
|
|
23
|
+
transports: [createCaptureTransport((line) => logLines.push(line))],
|
|
24
|
+
});
|
|
22
25
|
const services = options.services ?? createTestServices();
|
|
26
|
+
// Seed the test collecting sender under a stable name and point the email
|
|
27
|
+
// config at it. A test that wants a real provider module in the mix registers
|
|
28
|
+
// it as usual; picking that name in `email.provider` overrides this default.
|
|
23
29
|
const contributions = await registerModules({
|
|
24
30
|
modules: options.modules ?? [],
|
|
25
31
|
environment: options.environment ?? TEST_ENVIRONMENT,
|
|
26
32
|
logger,
|
|
27
33
|
events: services.events,
|
|
34
|
+
email: { provider: TEST_EMAIL_PROVIDER, from: TEST_EMAIL_FROM },
|
|
35
|
+
additionalEmailProviders: new Map([[TEST_EMAIL_PROVIDER, services.emailSender]]),
|
|
28
36
|
...(options.entitlements === undefined ? {} : { entitlements: options.entitlements }),
|
|
29
37
|
...(options.moduleConfig === undefined ? {} : { moduleConfig: options.moduleConfig }),
|
|
30
38
|
...(options.resolveActor === undefined ? {} : { resolveActor: options.resolveActor }),
|
package/dist/testing/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/testing/app.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAKrC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/testing/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/testing/database.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAmB5D,MAAM,WAAW,YAAa,SAAQ,kBAAkB;IACtD,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAE5E;AA+BD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/testing/database.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAmB5D,MAAM,WAAW,YAAa,SAAQ,kBAAkB;IACtD,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAE5E;AA+BD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAsCzF"}
|
package/dist/testing/database.js
CHANGED
|
@@ -6,7 +6,7 @@ import { coreModules } from '../modules/core.js';
|
|
|
6
6
|
import { runMigrations } from '../runtime/migrate.js';
|
|
7
7
|
import { registerModules } from '../runtime/registry.js';
|
|
8
8
|
import { TEST_ENVIRONMENT } from './environment.js';
|
|
9
|
-
import { createTestServices } from './services.js';
|
|
9
|
+
import { TEST_EMAIL_FROM, TEST_EMAIL_PROVIDER, createTestServices } from './services.js';
|
|
10
10
|
/**
|
|
11
11
|
* A migrated database for integration tests.
|
|
12
12
|
*
|
|
@@ -15,7 +15,7 @@ import { createTestServices } from './services.js';
|
|
|
15
15
|
* `truncateAll` empties the tables rather than re-migrating, which is an order of
|
|
16
16
|
* magnitude faster and just as isolated.
|
|
17
17
|
*/
|
|
18
|
-
const silentLogger = createLogger('error',
|
|
18
|
+
const silentLogger = createLogger({ level: 'error', transports: [] });
|
|
19
19
|
/**
|
|
20
20
|
* Reads the test database location. Integration tests are skipped rather than
|
|
21
21
|
* failed when it is absent, so `npm test` still works without Postgres running.
|
|
@@ -55,12 +55,15 @@ async function ensureDatabaseExists(connectionString) {
|
|
|
55
55
|
export async function connectTestDatabase(connectionString) {
|
|
56
56
|
await ensureDatabaseExists(connectionString);
|
|
57
57
|
const connection = connectDatabase(connectionString, silentLogger);
|
|
58
|
+
const services = createTestServices({ db: connection.db });
|
|
58
59
|
const contributions = await registerModules({
|
|
59
60
|
modules: coreModules,
|
|
60
61
|
// Enough for core modules to configure themselves; no test reads it further.
|
|
61
62
|
environment: TEST_ENVIRONMENT,
|
|
62
63
|
logger: silentLogger,
|
|
63
|
-
services
|
|
64
|
+
services,
|
|
65
|
+
email: { provider: TEST_EMAIL_PROVIDER, from: TEST_EMAIL_FROM },
|
|
66
|
+
additionalEmailProviders: new Map([[TEST_EMAIL_PROVIDER, services.emailSender]]),
|
|
64
67
|
});
|
|
65
68
|
await runMigrations(connection.db, contributions.schemas, silentLogger);
|
|
66
69
|
async function truncateAll() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/testing/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,QAAQ,MAAM,UAAU,CAAA;AAG/B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/testing/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
import type { Database } from '../lib/database.ts';
|
|
2
|
-
import type { EmailMessage } from '../lib/email.ts';
|
|
2
|
+
import type { EmailMessage, EmailSender } from '../lib/email.ts';
|
|
3
3
|
import type { IdFactory } from '../lib/ids.ts';
|
|
4
|
+
import type { SecretEncryptionConfig } from '../lib/secrets.ts';
|
|
4
5
|
import type { EventBus } from '../runtime/events.ts';
|
|
5
6
|
import type { ModuleServices } from '../runtime/module.ts';
|
|
7
|
+
/**
|
|
8
|
+
* The provider name `createTestApp` seeds and points `email.provider` at.
|
|
9
|
+
* Exported so a test spawning `registerModules` directly can pass the same
|
|
10
|
+
* name and reach the same collecting sender.
|
|
11
|
+
*/
|
|
12
|
+
export declare const TEST_EMAIL_PROVIDER = "test";
|
|
13
|
+
/** The from address the test email config uses. Arbitrary but real. */
|
|
14
|
+
export declare const TEST_EMAIL_FROM = "kelpie-test@example.com";
|
|
6
15
|
export interface TestServicesOptions {
|
|
7
16
|
readonly db?: Database;
|
|
8
17
|
readonly now?: () => Date;
|
|
9
18
|
readonly createId?: IdFactory;
|
|
10
19
|
readonly events?: EventBus;
|
|
20
|
+
/** Threaded through to `ModuleServices.appBaseUrl`, so a test exercises the preferred path. */
|
|
21
|
+
readonly appBaseUrl?: string;
|
|
22
|
+
/** Threaded through to `ModuleServices.secretEncryption`, so a test exercises the preferred path. */
|
|
23
|
+
readonly secretEncryption?: SecretEncryptionConfig;
|
|
11
24
|
}
|
|
12
25
|
export interface TestServices extends ModuleServices {
|
|
26
|
+
/**
|
|
27
|
+
* The collecting sender `createTestApp` seeds under `TEST_EMAIL_PROVIDER`.
|
|
28
|
+
* `services.emailSender` (this field) is what actually receives calls; a
|
|
29
|
+
* consumer module reaches it through `context.email`, which the runtime's
|
|
30
|
+
* proxy points at whichever provider `email.provider` picked.
|
|
31
|
+
*/
|
|
32
|
+
readonly emailSender: EmailSender;
|
|
13
33
|
/** Everything the email port was asked to send, in order. */
|
|
14
34
|
readonly sentEmails: readonly EmailMessage[];
|
|
15
35
|
readonly events: EventBus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/testing/services.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../src/testing/services.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAEhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAc1D;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,SAAS,CAAA;AAEzC,uEAAuE;AACvE,eAAO,MAAM,eAAe,4BAA4B,CAAA;AAExD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAA;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;IAC1B,+FAA+F;IAC/F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,qGAAqG;IACrG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,sBAAsB,CAAA;CACnD;AAED,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAA;IAC5C,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;CAC1B;AAkBD,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,YAAY,CAsBlF"}
|
package/dist/testing/services.js
CHANGED
|
@@ -12,6 +12,14 @@ import { createTransactionScope } from '../runtime/transaction.js';
|
|
|
12
12
|
*/
|
|
13
13
|
/** Never queried. A unit test that reaches the database fails here, loudly. */
|
|
14
14
|
const UNUSED_DATABASE_URL = 'postgres://unused:unused@127.0.0.1:1/unused';
|
|
15
|
+
/**
|
|
16
|
+
* The provider name `createTestApp` seeds and points `email.provider` at.
|
|
17
|
+
* Exported so a test spawning `registerModules` directly can pass the same
|
|
18
|
+
* name and reach the same collecting sender.
|
|
19
|
+
*/
|
|
20
|
+
export const TEST_EMAIL_PROVIDER = 'test';
|
|
21
|
+
/** The from address the test email config uses. Arbitrary but real. */
|
|
22
|
+
export const TEST_EMAIL_FROM = 'kelpie-test@example.com';
|
|
15
23
|
/** Collects messages instead of sending them, so a test can read the reset link. */
|
|
16
24
|
function createCollectingEmailSender() {
|
|
17
25
|
const sent = [];
|
|
@@ -26,18 +34,25 @@ function createCollectingEmailSender() {
|
|
|
26
34
|
};
|
|
27
35
|
}
|
|
28
36
|
export function createTestServices(options = {}) {
|
|
29
|
-
const logger = createLogger('error',
|
|
37
|
+
const logger = createLogger({ level: 'error', transports: [] });
|
|
30
38
|
const db = options.db ?? connectDatabase(UNUSED_DATABASE_URL, logger).db;
|
|
31
39
|
const events = options.events ?? createEventBus(logger);
|
|
40
|
+
const createId = options.createId ?? createIdFactory();
|
|
41
|
+
const now = options.now ?? (() => new Date());
|
|
32
42
|
const { sender, sent } = createCollectingEmailSender();
|
|
33
43
|
return {
|
|
34
44
|
db,
|
|
35
|
-
transaction: createTransactionScope({ db, bus: events, logger }),
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
transaction: createTransactionScope({ db, bus: events, logger, createId, now }),
|
|
46
|
+
createId,
|
|
47
|
+
now,
|
|
48
|
+
emailSender: sender,
|
|
39
49
|
sentEmails: sent,
|
|
40
50
|
events,
|
|
51
|
+
// Spread conditionally so the field is absent (not `undefined`) when the
|
|
52
|
+
// caller does not opt in, keeping the fallback path (context.config) live
|
|
53
|
+
// for the many suites that never touch these fields.
|
|
54
|
+
...(options.appBaseUrl === undefined ? {} : { appBaseUrl: options.appBaseUrl }),
|
|
55
|
+
...(options.secretEncryption === undefined ? {} : { secretEncryption: options.secretEncryption }),
|
|
41
56
|
};
|
|
42
57
|
}
|
|
43
58
|
//# sourceMappingURL=services.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.js","sourceRoot":"","sources":["../../src/testing/services.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"services.js","sourceRoot":"","sources":["../../src/testing/services.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGpD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAGrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAElE;;;;;;GAMG;AAEH,+EAA+E;AAC/E,MAAM,mBAAmB,GAAG,6CAA6C,CAAA;AAEzE;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAA;AAEzC,uEAAuE;AACvE,MAAM,CAAC,MAAM,eAAe,GAAG,yBAAyB,CAAA;AA0BxD,oFAAoF;AACpF,SAAS,2BAA2B;IAClC,MAAM,IAAI,GAAmB,EAAE,CAAA;IAE/B,OAAO;QACL,IAAI;QACJ,MAAM,EAAE;YACN,IAAI,CAAC,OAAO;gBACV,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAElB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;YAC1B,CAAC;SACF;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAO,GAAwB,EAAE;IAClE,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAA;IAC/D,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,eAAe,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAA;IACxE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM,CAAC,CAAA;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,eAAe,EAAE,CAAA;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAS,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;IACnD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,2BAA2B,EAAE,CAAA;IAEtD,OAAO;QACL,EAAE;QACF,WAAW,EAAE,sBAAsB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QAC/E,QAAQ;QACR,GAAG;QACH,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,IAAI;QAChB,MAAM;QACN,yEAAyE;QACzE,0EAA0E;QAC1E,qDAAqD;QACrD,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;QAC/E,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;KAClG,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kelpie/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "The Kelpie service as a library: module runtime, core CRM modules, REST API, MCP surface, and the shared migration pipeline.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"kelpie",
|
|
@@ -52,13 +52,16 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@hono/node-server": "^2.0.12",
|
|
55
|
-
"@kelpie/schemas": "^0.
|
|
55
|
+
"@kelpie/schemas": "^0.6.0",
|
|
56
56
|
"@node-rs/argon2": "^2.0.2",
|
|
57
57
|
"drizzle-orm": "^0.45.2",
|
|
58
|
+
"emittery": "^2.0.0",
|
|
58
59
|
"hono": "^4.12.32",
|
|
59
60
|
"nodemailer": "^9.0.5",
|
|
60
61
|
"postgres": "^3.4.9",
|
|
61
62
|
"ulid": "^3.0.2",
|
|
63
|
+
"winston": "^3.19.0",
|
|
64
|
+
"winston-transport": "^4.9.0",
|
|
62
65
|
"zod": "^4.4.3"
|
|
63
66
|
},
|
|
64
67
|
"devDependencies": {
|