@headless-lms/core 0.1.0 → 0.3.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/dist/assets/events.d.ts +90 -9
- package/dist/assets/events.js +19 -3
- package/dist/assets/events.js.map +1 -1
- package/dist/assets/file-urls.d.ts +20 -0
- package/dist/assets/file-urls.js +25 -0
- package/dist/assets/file-urls.js.map +1 -0
- package/dist/assets/index.d.ts +5 -4
- package/dist/assets/index.js +3 -2
- package/dist/assets/model.d.ts +2 -2
- package/dist/assets/ports.d.ts +45 -15
- package/dist/assets/service.d.ts +39 -7
- package/dist/assets/service.js +292 -37
- package/dist/assets/service.js.map +1 -1
- package/dist/automations/actions.d.ts +12 -15
- package/dist/automations/actions.js +188 -30
- package/dist/automations/actions.js.map +1 -1
- package/dist/automations/catalog.d.ts +5 -1
- package/dist/automations/catalog.js +514 -197
- package/dist/automations/catalog.js.map +1 -1
- package/dist/automations/community-derivations.d.ts +14 -0
- package/dist/automations/community-derivations.js +439 -0
- package/dist/automations/community-derivations.js.map +1 -0
- package/dist/automations/community-mail.d.ts +112 -0
- package/dist/automations/community-mail.js +90 -0
- package/dist/automations/community-mail.js.map +1 -0
- package/dist/automations/community-notifications.d.ts +16 -0
- package/dist/automations/community-notifications.js +84 -0
- package/dist/automations/community-notifications.js.map +1 -0
- package/dist/automations/events.d.ts +74 -24
- package/dist/automations/events.js +5 -5
- package/dist/automations/events.js.map +1 -1
- package/dist/automations/index.d.ts +7 -5
- package/dist/automations/index.js +3 -2
- package/dist/automations/model.d.ts +20 -3
- package/dist/automations/model.js +36 -3
- package/dist/automations/model.js.map +1 -1
- package/dist/automations/ports.d.ts +27 -8
- package/dist/automations/schedule.d.ts +6 -0
- package/dist/automations/schedule.js +41 -0
- package/dist/automations/schedule.js.map +1 -0
- package/dist/automations/seeds.d.ts +17 -0
- package/dist/automations/seeds.js +235 -0
- package/dist/automations/seeds.js.map +1 -0
- package/dist/automations/service.d.ts +41 -6
- package/dist/automations/service.js +542 -59
- package/dist/automations/service.js.map +1 -1
- package/dist/automations/types.d.ts +2 -2
- package/dist/automations/webhook-signing.d.ts +7 -0
- package/dist/automations/webhook-signing.js +22 -0
- package/dist/automations/webhook-signing.js.map +1 -0
- package/dist/content/events.d.ts +1013 -25
- package/dist/content/events.js +168 -19
- package/dist/content/events.js.map +1 -1
- package/dist/content/index.d.ts +5 -5
- package/dist/content/index.js +2 -2
- package/dist/content/model.d.ts +2 -2
- package/dist/content/ports.d.ts +109 -25
- package/dist/content/service.d.ts +68 -23
- package/dist/content/service.js +647 -60
- package/dist/content/service.js.map +1 -1
- package/dist/content/types.d.ts +2 -2
- package/dist/discussion/authors.d.ts +10 -0
- package/dist/discussion/authors.js +23 -0
- package/dist/discussion/authors.js.map +1 -0
- package/dist/discussion/chats.d.ts +104 -0
- package/dist/discussion/chats.js +798 -0
- package/dist/discussion/chats.js.map +1 -0
- package/dist/discussion/events.d.ts +633 -14
- package/dist/discussion/events.js +134 -5
- package/dist/discussion/events.js.map +1 -1
- package/dist/discussion/index.d.ts +7 -3
- package/dist/discussion/index.js +4 -1
- package/dist/discussion/model.d.ts +1 -2
- package/dist/discussion/ports.d.ts +288 -27
- package/dist/discussion/ports.js +6 -1
- package/dist/discussion/ports.js.map +1 -0
- package/dist/discussion/posts.d.ts +103 -0
- package/dist/discussion/posts.js +723 -0
- package/dist/discussion/posts.js.map +1 -0
- package/dist/discussion/service.d.ts +33 -11
- package/dist/discussion/service.js +297 -81
- package/dist/discussion/service.js.map +1 -1
- package/dist/entitlements/events.d.ts +264 -13
- package/dist/entitlements/events.js +49 -5
- package/dist/entitlements/events.js.map +1 -1
- package/dist/entitlements/index.d.ts +5 -4
- package/dist/entitlements/index.js +2 -1
- package/dist/entitlements/model.d.ts +3 -2
- package/dist/entitlements/ports.d.ts +124 -11
- package/dist/entitlements/rules.d.ts +12 -0
- package/dist/entitlements/rules.js +17 -0
- package/dist/entitlements/rules.js.map +1 -0
- package/dist/entitlements/service.d.ts +54 -3
- package/dist/entitlements/service.js +473 -2
- package/dist/entitlements/service.js.map +1 -1
- package/dist/identity/access.d.ts +6 -0
- package/dist/identity/access.js +7 -0
- package/dist/identity/access.js.map +1 -0
- package/dist/identity/events.d.ts +17 -3
- package/dist/identity/events.js +12 -2
- package/dist/identity/events.js.map +1 -1
- package/dist/identity/index.d.ts +6 -4
- package/dist/identity/index.js +3 -1
- package/dist/identity/model.d.ts +2 -1
- package/dist/identity/notifications.d.ts +27 -0
- package/dist/identity/notifications.js +101 -0
- package/dist/identity/notifications.js.map +1 -0
- package/dist/identity/ports.d.ts +76 -3
- package/dist/identity/service.d.ts +17 -3
- package/dist/identity/service.js +73 -5
- package/dist/identity/service.js.map +1 -1
- package/dist/integrations/events.d.ts +27 -3
- package/dist/integrations/events.js +15 -3
- package/dist/integrations/events.js.map +1 -1
- package/dist/integrations/model.js +1 -1
- package/dist/integrations/model.js.map +1 -1
- package/dist/integrations/service.js +2 -2
- package/dist/integrations/service.js.map +1 -1
- package/dist/organizations/access-scopes.d.ts +19 -0
- package/dist/organizations/access-scopes.js +89 -0
- package/dist/organizations/access-scopes.js.map +1 -0
- package/dist/organizations/events.d.ts +234 -25
- package/dist/organizations/events.js +58 -9
- package/dist/organizations/events.js.map +1 -1
- package/dist/organizations/index.d.ts +8 -7
- package/dist/organizations/index.js +4 -3
- package/dist/organizations/members.d.ts +8 -5
- package/dist/organizations/members.js.map +1 -1
- package/dist/organizations/ports.d.ts +20 -21
- package/dist/organizations/roles.d.ts +6 -10
- package/dist/organizations/roles.js +19 -7
- package/dist/organizations/roles.js.map +1 -1
- package/dist/organizations/service.d.ts +28 -14
- package/dist/organizations/service.js +274 -105
- package/dist/organizations/service.js.map +1 -1
- package/dist/organizations/types.d.ts +2 -11
- package/dist/progress/events.d.ts +34 -2
- package/dist/progress/events.js +15 -2
- package/dist/progress/events.js.map +1 -1
- package/dist/progress/index.d.ts +2 -2
- package/dist/progress/ports.d.ts +6 -1
- package/dist/progress/service.d.ts +5 -3
- package/dist/progress/service.js +9 -3
- package/dist/progress/service.js.map +1 -1
- package/dist/reporting/admin/index.d.ts +4 -0
- package/dist/reporting/admin/index.js +2 -0
- package/dist/reporting/admin/model.d.ts +108 -0
- package/dist/reporting/admin/ports.d.ts +27 -0
- package/dist/reporting/admin/service.d.ts +22 -0
- package/dist/reporting/admin/service.js +38 -0
- package/dist/reporting/admin/service.js.map +1 -0
- package/dist/reporting/member/index.d.ts +5 -0
- package/dist/reporting/member/index.js +2 -0
- package/dist/reporting/member/model.d.ts +124 -0
- package/dist/reporting/member/ports.d.ts +45 -0
- package/dist/reporting/member/service.d.ts +73 -0
- package/dist/reporting/member/service.js +286 -0
- package/dist/reporting/member/service.js.map +1 -0
- package/dist/shared/actor.d.ts +9 -0
- package/dist/shared/errors.d.ts +7 -1
- package/dist/shared/errors.js +10 -1
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/events.d.ts +5 -3
- package/dist/shared/events.js +1 -0
- package/dist/shared/events.js.map +1 -1
- package/dist/shared/id.d.ts +12 -0
- package/dist/shared/id.js +13 -1
- package/dist/shared/id.js.map +1 -1
- package/dist/shared/mailer.d.ts +6 -1
- package/dist/shared/mailer.js.map +1 -1
- package/dist/shared/network.d.ts +10 -0
- package/dist/shared/network.js +211 -0
- package/dist/shared/network.js.map +1 -0
- package/dist/shared/settings.js.map +1 -1
- package/dist/types/assets.d.ts +2 -2
- package/dist/types/automations.d.ts +21 -2
- package/dist/types/content.d.ts +2 -2
- package/dist/types/discussion.d.ts +12 -3
- package/dist/types/email-templates.d.ts +124 -1
- package/dist/types/entitlements.d.ts +2 -2
- package/dist/types/events.d.ts +3 -3
- package/dist/types/identity.d.ts +48 -2
- package/dist/types/index.d.ts +10 -10
- package/dist/types/organizations.d.ts +2 -2
- package/dist/types/ports.d.ts +7 -1
- package/dist/types/schemas/assets.d.ts +67 -36
- package/dist/types/schemas/assets.js +19 -13
- package/dist/types/schemas/assets.js.map +1 -1
- package/dist/types/schemas/automations.d.ts +88 -4
- package/dist/types/schemas/automations.js +46 -6
- package/dist/types/schemas/automations.js.map +1 -1
- package/dist/types/schemas/content.d.ts +385 -20
- package/dist/types/schemas/content.js +178 -15
- package/dist/types/schemas/content.js.map +1 -1
- package/dist/types/schemas/credentials.js.map +1 -1
- package/dist/types/schemas/discussion.d.ts +379 -4
- package/dist/types/schemas/discussion.js +209 -7
- package/dist/types/schemas/discussion.js.map +1 -1
- package/dist/types/schemas/entitlements.d.ts +44 -4
- package/dist/types/schemas/entitlements.js +32 -4
- package/dist/types/schemas/entitlements.js.map +1 -1
- package/dist/types/schemas/identity.d.ts +115 -5
- package/dist/types/schemas/identity.js +59 -6
- package/dist/types/schemas/identity.js.map +1 -1
- package/dist/types/schemas/index.d.ts +9 -9
- package/dist/types/schemas/index.js +9 -9
- package/dist/types/schemas/integrations.js.map +1 -1
- package/dist/types/schemas/organizations.d.ts +27 -5
- package/dist/types/schemas/organizations.js +14 -7
- package/dist/types/schemas/organizations.js.map +1 -1
- package/dist/types/schemas/outbox.d.ts +1 -0
- package/dist/types/schemas/outbox.js +1 -0
- package/dist/types/schemas/outbox.js.map +1 -1
- package/dist/types/schemas/progress.d.ts +1 -0
- package/dist/types/schemas/progress.js +1 -0
- package/dist/types/schemas/progress.js.map +1 -1
- package/dist/types/schemas/settings.js.map +1 -1
- package/dist/types/schemas/shared.d.ts +4 -1
- package/dist/types/schemas/shared.js +7 -1
- package/dist/types/schemas/shared.js.map +1 -1
- package/dist/types/shared.d.ts +1 -1
- package/package.json +2 -2
- package/dist/reporting/dashboard/index.d.ts +0 -4
- package/dist/reporting/dashboard/index.js +0 -2
- package/dist/reporting/dashboard/model.d.ts +0 -14
- package/dist/reporting/dashboard/ports.d.ts +0 -13
- package/dist/reporting/dashboard/service.d.ts +0 -19
- package/dist/reporting/dashboard/service.js +0 -20
- package/dist/reporting/dashboard/service.js.map +0 -1
- package/dist/reporting/learn/index.d.ts +0 -5
- package/dist/reporting/learn/index.js +0 -2
- package/dist/reporting/learn/model.d.ts +0 -23
- package/dist/reporting/learn/ports.d.ts +0 -42
- package/dist/reporting/learn/service.d.ts +0 -48
- package/dist/reporting/learn/service.js +0 -111
- package/dist/reporting/learn/service.js.map +0 -1
- package/dist/reporting/students/index.d.ts +0 -4
- package/dist/reporting/students/index.js +0 -2
- package/dist/reporting/students/model.d.ts +0 -31
- package/dist/reporting/students/ports.d.ts +0 -13
- package/dist/reporting/students/ports.js +0 -1
- package/dist/reporting/students/service.d.ts +0 -19
- package/dist/reporting/students/service.js +0 -20
- package/dist/reporting/students/service.js.map +0 -1
- /package/dist/reporting/{dashboard → admin}/model.js +0 -0
- /package/dist/reporting/{dashboard → admin}/ports.js +0 -0
- /package/dist/reporting/{learn → member}/model.js +0 -0
- /package/dist/reporting/{learn → member}/ports.js +0 -0
- /package/dist/{reporting/students/model.js → shared/actor.js} +0 -0
|
@@ -22,7 +22,7 @@ var ActionInvocationError = class extends Error {
|
|
|
22
22
|
integrationId;
|
|
23
23
|
actionId;
|
|
24
24
|
constructor(integrationId, actionId, cause) {
|
|
25
|
-
super(`action "${integrationId}.${actionId}" failed: ${cause instanceof Error ? cause.message : String(cause)}
|
|
25
|
+
super(`action "${integrationId}.${actionId}" failed: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
26
26
|
this.integrationId = integrationId;
|
|
27
27
|
this.actionId = actionId;
|
|
28
28
|
this.name = "ActionInvocationError";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","names":[],"sources":["../../src/integrations/model.ts"],"sourcesContent":["// integrations context — entities & DTOs are owned by @headless-lms/core/types;\n// the domain errors below are runtime code and stay in core.\nexport type { Connection, ConnectInput, ConfigureInput } from '../types/index.js';\n\n/** An org already has a connection for this integration (one per integration per org). */\nexport class AlreadyConnectedError extends Error {\n constructor(readonly integrationId: string) {\n super(`a connection for \"${integrationId}\" already exists`);\n this.name = 'AlreadyConnectedError';\n }\n}\n\n/** The named integration is not declared in the registry. */\nexport class UnknownIntegrationError extends Error {\n constructor(readonly integrationId: string) {\n super(`unknown integration \"${integrationId}\"`);\n this.name = 'UnknownIntegrationError';\n }\n}\n\n/** An action's external call failed (or the action rejected its input). */\nexport class ActionInvocationError extends Error {\n constructor(\n readonly integrationId: string,\n readonly actionId: string,\n cause: unknown,\n ) {\n super(\n `action \"${integrationId}.${actionId}\" failed: ${\n cause instanceof Error ? cause.message : String(cause)\n }`,\n );\n this.name = 'ActionInvocationError';\n }\n}\n\n/** The config was rejected by the integration's validator. */\nexport class InvalidConfigError extends Error {\n constructor(\n readonly integrationId: string,\n readonly errors: string[],\n ) {\n super(`invalid config for \"${integrationId}\": ${errors.join('; ')}`);\n this.name = 'InvalidConfigError';\n }\n}\n"],"mappings":";;AAKA,IAAa,wBAAb,cAA2C,MAAM;CAC1B;CAArB,YAAY,eAAgC;EAC1C,MAAM,qBAAqB,cAAc,iBAAiB;EADvC,KAAA,gBAAA;EAEnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,0BAAb,cAA6C,MAAM;CAC5B;CAArB,YAAY,eAAgC;EAC1C,MAAM,wBAAwB,cAAc,EAAE;EAD3B,KAAA,gBAAA;EAEnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,wBAAb,cAA2C,MAAM;CAEpC;CACA;CAFX,YACE,eACA,UACA,OACA;EACA,MACE,WAAW,cAAc,GAAG,SAAS,YACnC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"model.js","names":[],"sources":["../../src/integrations/model.ts"],"sourcesContent":["// integrations context — entities & DTOs are owned by @headless-lms/core/types;\n// the domain errors below are runtime code and stay in core.\nexport type { Connection, ConnectInput, ConfigureInput } from '../types/index.js';\n\n/** An org already has a connection for this integration (one per integration per org). */\nexport class AlreadyConnectedError extends Error {\n constructor(readonly integrationId: string) {\n super(`a connection for \"${integrationId}\" already exists`);\n this.name = 'AlreadyConnectedError';\n }\n}\n\n/** The named integration is not declared in the registry. */\nexport class UnknownIntegrationError extends Error {\n constructor(readonly integrationId: string) {\n super(`unknown integration \"${integrationId}\"`);\n this.name = 'UnknownIntegrationError';\n }\n}\n\n/** An action's external call failed (or the action rejected its input). */\nexport class ActionInvocationError extends Error {\n constructor(\n readonly integrationId: string,\n readonly actionId: string,\n cause: unknown,\n ) {\n super(\n `action \"${integrationId}.${actionId}\" failed: ${\n cause instanceof Error ? cause.message : String(cause)\n }`,\n { cause },\n );\n this.name = 'ActionInvocationError';\n }\n}\n\n/** The config was rejected by the integration's validator. */\nexport class InvalidConfigError extends Error {\n constructor(\n readonly integrationId: string,\n readonly errors: string[],\n ) {\n super(`invalid config for \"${integrationId}\": ${errors.join('; ')}`);\n this.name = 'InvalidConfigError';\n }\n}\n"],"mappings":";;AAKA,IAAa,wBAAb,cAA2C,MAAM;CAC1B;CAArB,YAAY,eAAgC;EAC1C,MAAM,qBAAqB,cAAc,iBAAiB;EADvC,KAAA,gBAAA;EAEnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,0BAAb,cAA6C,MAAM;CAC5B;CAArB,YAAY,eAAgC;EAC1C,MAAM,wBAAwB,cAAc,EAAE;EAD3B,KAAA,gBAAA;EAEnB,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,wBAAb,cAA2C,MAAM;CAEpC;CACA;CAFX,YACE,eACA,UACA,OACA;EACA,MACE,WAAW,cAAc,GAAG,SAAS,YACnC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KAEvD,EAAE,MAAM,CACV;EATS,KAAA,gBAAA;EACA,KAAA,WAAA;EAST,KAAK,OAAO;CACd;AACF;;AAGA,IAAa,qBAAb,cAAwC,MAAM;CAEjC;CACA;CAFX,YACE,eACA,QACA;EACA,MAAM,uBAAuB,cAAc,KAAK,OAAO,KAAK,IAAI,GAAG;EAH1D,KAAA,gBAAA;EACA,KAAA,SAAA;EAGT,KAAK,OAAO;CACd;AACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { genId } from "../shared/id.js";
|
|
2
|
-
import { noopLogger } from "../shared/logger.js";
|
|
3
2
|
import { ConflictError, NotFoundError } from "../shared/errors.js";
|
|
3
|
+
import { noopLogger } from "../shared/logger.js";
|
|
4
4
|
import { ActionInvocationError, AlreadyConnectedError, InvalidConfigError, UnknownIntegrationError } from "./model.js";
|
|
5
5
|
import { integrationEvents } from "./events.js";
|
|
6
6
|
//#region src/integrations/service.ts
|
|
@@ -172,7 +172,7 @@ var IntegrationsServiceImpl = class {
|
|
|
172
172
|
connectionId,
|
|
173
173
|
integrationId: connection.integrationId,
|
|
174
174
|
actionId,
|
|
175
|
-
|
|
175
|
+
err
|
|
176
176
|
});
|
|
177
177
|
throw new ActionInvocationError(connection.integrationId, actionId, err);
|
|
178
178
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","names":[],"sources":["../../src/integrations/service.ts"],"sourcesContent":["// integrations context — service implementation (inbound port). Owns the\n// connection lifecycle; credentials live in the shared secure credential store\n// (this service holds only the ref). The integrations the system supports are\n// declared at startup via the IntegrationsRegistry: connect/configure reject\n// unknown integration ids and validate config with the integration's own\n// validator. The domain never calls the external service — consumers take the\n// connection, reveal the credential at point of use, and build their own adapter.\n//\n// Mutations run inside the context's UnitOfWork: credential writes, connection\n// writes, and the outbox append commit in ONE transaction (transactional\n// outbox; this also closed the historical orphan-credential window). The\n// outbox relay — not this service — publishes to the EventBus.\nimport { genId } from '../shared/id.js';\nimport {\n ActionInvocationError,\n AlreadyConnectedError,\n InvalidConfigError,\n UnknownIntegrationError,\n type ConfigureInput,\n type ConnectInput,\n type Connection,\n} from './model.js';\nimport type {\n ConnectionsRepository,\n IntegrationsRegistry,\n IntegrationsService,\n IntegrationsUnitOfWork,\n} from './ports.js';\nimport type { CredentialStore, Logger } from '../shared/ports.js';\nimport { ConflictError, NotFoundError } from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport { integrationEvents } from './events.js';\n\nexport type IntegrationsServiceParams = {\n registry: IntegrationsRegistry;\n /** Read-only access (find/list) — runs outside any transaction. */\n repo: ConnectionsRepository;\n /** Atomic write scope: tx-bound connections repo + credential store + outbox. */\n uow: IntegrationsUnitOfWork;\n /** Point-of-use credential reveal for action invocation — reads only. */\n credentials: CredentialStore;\n logger?: Logger;\n};\n\nexport class IntegrationsServiceImpl implements IntegrationsService {\n private readonly registry: IntegrationsRegistry;\n private readonly repo: ConnectionsRepository;\n private readonly uow: IntegrationsUnitOfWork;\n private readonly credentials: CredentialStore;\n private readonly logger: Logger;\n\n constructor(params: IntegrationsServiceParams) {\n this.registry = params.registry;\n this.repo = params.repo;\n this.uow = params.uow;\n this.credentials = params.credentials;\n this.logger = params.logger ?? noopLogger;\n }\n\n available() {\n return this.registry.list().map((integration) => ({\n id: integration.id,\n configSchema: integration.configSchema(),\n secretsSchema: integration.secretsSchema(),\n actions: integration.actions.map((action) => ({\n id: action.id,\n description: action.description,\n inputSchema: action.inputSchema(),\n outputSchema: action.outputSchema(),\n })),\n }));\n }\n\n private validate(integrationId: string, config: Record<string, unknown>): void {\n const integration = this.registry.get(integrationId);\n if (!integration) {\n this.logger.warn('unknown integration rejected', { integrationId });\n throw new UnknownIntegrationError(integrationId);\n }\n const result = integration.validateConfig(config);\n if (!result.ok) {\n this.logger.warn('invalid integration config rejected', {\n integrationId,\n errors: result.errors,\n });\n throw new InvalidConfigError(integrationId, result.errors);\n }\n }\n\n async connect(orgId: string, input: ConnectInput): Promise<Connection> {\n const config = input.config ?? {};\n this.validate(input.integrationId, config);\n const existing = await this.repo.findByIntegration(orgId, input.integrationId);\n if (existing) {\n this.logger.warn('duplicate connection rejected', {\n orgId,\n integrationId: input.integrationId,\n });\n throw new AlreadyConnectedError(input.integrationId);\n }\n const connection = await this.uow.run(async ({ connections, credentials, outbox }) => {\n const credentialRef = await credentials.store(orgId, input.secrets);\n const at = new Date();\n const created = await connections.insert(orgId, {\n orgId,\n id: genId('connection'),\n integrationId: input.integrationId,\n config,\n active: true,\n credentialRef,\n createdAt: at,\n updatedAt: at,\n });\n await outbox.append([\n integrationEvents.connectionCreated.make({\n orgId,\n data: created,\n }),\n ]);\n return created;\n });\n this.logger.info('integration connected', {\n orgId,\n integrationId: connection.integrationId,\n connectionId: connection.id,\n });\n return connection;\n }\n\n async reconnect(\n orgId: string,\n id: string,\n secrets: Record<string, unknown>,\n ): Promise<Connection | null> {\n const connection = await this.repo.findById(orgId, id);\n if (!connection) {\n return null;\n }\n const updated = await this.uow.run(async ({ connections, credentials, outbox }) => {\n await credentials.update(orgId, connection.credentialRef, secrets);\n const result = await connections.update(orgId, id, { updatedAt: new Date() });\n if (result) {\n await outbox.append([\n integrationEvents.connectionUpdated.make({ orgId, data: result }),\n ]);\n }\n return result;\n });\n this.logger.info('integration credentials rotated', {\n orgId,\n connectionId: id,\n integrationId: connection.integrationId,\n });\n return updated;\n }\n\n async configure(orgId: string, id: string, input: ConfigureInput): Promise<Connection | null> {\n const connection = await this.repo.findById(orgId, id);\n if (!connection) {\n return null;\n }\n if (input.config !== undefined) {\n this.validate(connection.integrationId, input.config);\n }\n const updated = await this.uow.run(async ({ connections, outbox }) => {\n const result = await connections.update(orgId, id, {\n ...(input.config !== undefined ? { config: input.config } : {}),\n ...(input.active !== undefined ? { active: input.active } : {}),\n updatedAt: new Date(),\n });\n if (result) {\n await outbox.append([\n integrationEvents.connectionUpdated.make({ orgId, data: result }),\n ]);\n }\n return result;\n });\n this.logger.info('integration configured', {\n orgId,\n connectionId: id,\n integrationId: connection.integrationId,\n });\n return updated;\n }\n\n async disconnect(orgId: string, id: string): Promise<boolean> {\n const connection = await this.repo.findById(orgId, id);\n if (!connection) {\n return false;\n }\n const deleted = await this.uow.run(async ({ connections, credentials, outbox }) => {\n // Connection first: it holds the FK onto the credential row.\n const ok = await connections.delete(orgId, id);\n await credentials.destroy(orgId, connection.credentialRef);\n await outbox.append([\n integrationEvents.connectionRemoved.make({ orgId, data: connection }),\n ]);\n return ok;\n });\n this.logger.info('integration disconnected', {\n orgId,\n connectionId: id,\n integrationId: connection.integrationId,\n });\n return deleted;\n }\n\n list(orgId: string): Promise<Connection[]> {\n return this.repo.list(orgId);\n }\n\n get(orgId: string, id: string): Promise<Connection | null> {\n return this.repo.findById(orgId, id);\n }\n\n getByIntegration(orgId: string, integrationId: string): Promise<Connection | null> {\n return this.repo.findByIntegration(orgId, integrationId);\n }\n\n async invoke(\n orgId: string,\n connectionId: string,\n actionId: string,\n input: Record<string, unknown>,\n ): Promise<unknown> {\n const connection = await this.repo.findById(orgId, connectionId);\n if (!connection) {\n throw new NotFoundError('Connection', connectionId);\n }\n if (!connection.active) {\n throw new ConflictError(`connection \"${connectionId}\" is inactive`);\n }\n const integration = this.registry.get(connection.integrationId);\n if (!integration) {\n throw new UnknownIntegrationError(connection.integrationId);\n }\n const action = integration.actions.find((a) => a.id === actionId);\n if (!action) {\n throw new NotFoundError('Action', actionId);\n }\n const secrets = await this.credentials.reveal(orgId, connection.credentialRef);\n if (!secrets) {\n throw new NotFoundError('Credential', connectionId);\n }\n try {\n return await action.invoke({ secrets, config: connection.config }, input);\n } catch (err) {\n this.logger.warn('integration action failed', {\n orgId,\n connectionId,\n integrationId: connection.integrationId,\n actionId,\n error: err instanceof Error ? err.message : String(err),\n });\n throw new ActionInvocationError(connection.integrationId, actionId, err);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../../src/integrations/service.ts"],"sourcesContent":["// integrations context — service implementation (inbound port). Owns the\n// connection lifecycle; credentials live in the shared secure credential store\n// (this service holds only the ref). The integrations the system supports are\n// declared at startup via the IntegrationsRegistry: connect/configure reject\n// unknown integration ids and validate config with the integration's own\n// validator. The domain never calls the external service — consumers take the\n// connection, reveal the credential at point of use, and build their own adapter.\n//\n// Mutations run inside the context's UnitOfWork: credential writes, connection\n// writes, and the outbox append commit in ONE transaction (transactional\n// outbox; this also closed the historical orphan-credential window). The\n// outbox relay — not this service — publishes to the EventBus.\nimport { genId } from '../shared/id.js';\nimport {\n ActionInvocationError,\n AlreadyConnectedError,\n InvalidConfigError,\n UnknownIntegrationError,\n type ConfigureInput,\n type ConnectInput,\n type Connection,\n} from './model.js';\nimport type {\n ConnectionsRepository,\n IntegrationsRegistry,\n IntegrationsService,\n IntegrationsUnitOfWork,\n} from './ports.js';\nimport type { CredentialStore, Logger } from '../shared/ports.js';\nimport { ConflictError, NotFoundError } from '../shared/errors.js';\nimport { noopLogger } from '../shared/logger.js';\nimport { integrationEvents } from './events.js';\n\nexport type IntegrationsServiceParams = {\n registry: IntegrationsRegistry;\n /** Read-only access (find/list) — runs outside any transaction. */\n repo: ConnectionsRepository;\n /** Atomic write scope: tx-bound connections repo + credential store + outbox. */\n uow: IntegrationsUnitOfWork;\n /** Point-of-use credential reveal for action invocation — reads only. */\n credentials: CredentialStore;\n logger?: Logger;\n};\n\nexport class IntegrationsServiceImpl implements IntegrationsService {\n private readonly registry: IntegrationsRegistry;\n private readonly repo: ConnectionsRepository;\n private readonly uow: IntegrationsUnitOfWork;\n private readonly credentials: CredentialStore;\n private readonly logger: Logger;\n\n constructor(params: IntegrationsServiceParams) {\n this.registry = params.registry;\n this.repo = params.repo;\n this.uow = params.uow;\n this.credentials = params.credentials;\n this.logger = params.logger ?? noopLogger;\n }\n\n available() {\n return this.registry.list().map((integration) => ({\n id: integration.id,\n configSchema: integration.configSchema(),\n secretsSchema: integration.secretsSchema(),\n actions: integration.actions.map((action) => ({\n id: action.id,\n description: action.description,\n inputSchema: action.inputSchema(),\n outputSchema: action.outputSchema(),\n })),\n }));\n }\n\n private validate(integrationId: string, config: Record<string, unknown>): void {\n const integration = this.registry.get(integrationId);\n if (!integration) {\n this.logger.warn('unknown integration rejected', { integrationId });\n throw new UnknownIntegrationError(integrationId);\n }\n const result = integration.validateConfig(config);\n if (!result.ok) {\n this.logger.warn('invalid integration config rejected', {\n integrationId,\n errors: result.errors,\n });\n throw new InvalidConfigError(integrationId, result.errors);\n }\n }\n\n async connect(orgId: string, input: ConnectInput): Promise<Connection> {\n const config = input.config ?? {};\n this.validate(input.integrationId, config);\n const existing = await this.repo.findByIntegration(orgId, input.integrationId);\n if (existing) {\n this.logger.warn('duplicate connection rejected', {\n orgId,\n integrationId: input.integrationId,\n });\n throw new AlreadyConnectedError(input.integrationId);\n }\n const connection = await this.uow.run(async ({ connections, credentials, outbox }) => {\n const credentialRef = await credentials.store(orgId, input.secrets);\n const at = new Date();\n const created = await connections.insert(orgId, {\n orgId,\n id: genId('connection'),\n integrationId: input.integrationId,\n config,\n active: true,\n credentialRef,\n createdAt: at,\n updatedAt: at,\n });\n await outbox.append([\n integrationEvents.connectionCreated.make({\n orgId,\n data: created,\n }),\n ]);\n return created;\n });\n this.logger.info('integration connected', {\n orgId,\n integrationId: connection.integrationId,\n connectionId: connection.id,\n });\n return connection;\n }\n\n async reconnect(\n orgId: string,\n id: string,\n secrets: Record<string, unknown>,\n ): Promise<Connection | null> {\n const connection = await this.repo.findById(orgId, id);\n if (!connection) {\n return null;\n }\n const updated = await this.uow.run(async ({ connections, credentials, outbox }) => {\n await credentials.update(orgId, connection.credentialRef, secrets);\n const result = await connections.update(orgId, id, { updatedAt: new Date() });\n if (result) {\n await outbox.append([integrationEvents.connectionUpdated.make({ orgId, data: result })]);\n }\n return result;\n });\n this.logger.info('integration credentials rotated', {\n orgId,\n connectionId: id,\n integrationId: connection.integrationId,\n });\n return updated;\n }\n\n async configure(orgId: string, id: string, input: ConfigureInput): Promise<Connection | null> {\n const connection = await this.repo.findById(orgId, id);\n if (!connection) {\n return null;\n }\n if (input.config !== undefined) {\n this.validate(connection.integrationId, input.config);\n }\n const updated = await this.uow.run(async ({ connections, outbox }) => {\n const result = await connections.update(orgId, id, {\n ...(input.config !== undefined ? { config: input.config } : {}),\n ...(input.active !== undefined ? { active: input.active } : {}),\n updatedAt: new Date(),\n });\n if (result) {\n await outbox.append([integrationEvents.connectionUpdated.make({ orgId, data: result })]);\n }\n return result;\n });\n this.logger.info('integration configured', {\n orgId,\n connectionId: id,\n integrationId: connection.integrationId,\n });\n return updated;\n }\n\n async disconnect(orgId: string, id: string): Promise<boolean> {\n const connection = await this.repo.findById(orgId, id);\n if (!connection) {\n return false;\n }\n const deleted = await this.uow.run(async ({ connections, credentials, outbox }) => {\n // Connection first: it holds the FK onto the credential row.\n const ok = await connections.delete(orgId, id);\n await credentials.destroy(orgId, connection.credentialRef);\n await outbox.append([integrationEvents.connectionRemoved.make({ orgId, data: connection })]);\n return ok;\n });\n this.logger.info('integration disconnected', {\n orgId,\n connectionId: id,\n integrationId: connection.integrationId,\n });\n return deleted;\n }\n\n list(orgId: string): Promise<Connection[]> {\n return this.repo.list(orgId);\n }\n\n get(orgId: string, id: string): Promise<Connection | null> {\n return this.repo.findById(orgId, id);\n }\n\n getByIntegration(orgId: string, integrationId: string): Promise<Connection | null> {\n return this.repo.findByIntegration(orgId, integrationId);\n }\n\n async invoke(\n orgId: string,\n connectionId: string,\n actionId: string,\n input: Record<string, unknown>,\n ): Promise<unknown> {\n const connection = await this.repo.findById(orgId, connectionId);\n if (!connection) {\n throw new NotFoundError('Connection', connectionId);\n }\n if (!connection.active) {\n throw new ConflictError(`connection \"${connectionId}\" is inactive`);\n }\n const integration = this.registry.get(connection.integrationId);\n if (!integration) {\n throw new UnknownIntegrationError(connection.integrationId);\n }\n const action = integration.actions.find((a) => a.id === actionId);\n if (!action) {\n throw new NotFoundError('Action', actionId);\n }\n const secrets = await this.credentials.reveal(orgId, connection.credentialRef);\n if (!secrets) {\n throw new NotFoundError('Credential', connectionId);\n }\n try {\n return await action.invoke({ secrets, config: connection.config }, input);\n } catch (err) {\n this.logger.warn('integration action failed', {\n orgId,\n connectionId,\n integrationId: connection.integrationId,\n actionId,\n err,\n });\n throw new ActionInvocationError(connection.integrationId, actionId, err);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Role } from "../types/schemas/organizations.js";
|
|
2
|
+
import { Permission } from "./roles.js";
|
|
3
|
+
//#region src/organizations/access-scopes.d.ts
|
|
4
|
+
declare const ACCESS_SCOPES: readonly ["courses:read", "courses:write", "courses:delete", "downloads:read", "downloads:write", "downloads:delete", "bundles:read", "bundles:write", "bundles:delete", "media:read", "students:read", "students:invite", "access:read", "access:write", "analytics:read", "automations:read", "automations:write", "automations:delete", "comments:read", "comments:moderate", "communities:read", "communities:write", "communities:delete", "community_members:read", "community_members:write", "community_moderation:read", "community_moderation:write"];
|
|
5
|
+
type AccessScope = (typeof ACCESS_SCOPES)[number];
|
|
6
|
+
declare const SCOPE_PERMISSION: Record<AccessScope, Permission | null>;
|
|
7
|
+
type ScopeOption = {
|
|
8
|
+
scope: AccessScope;
|
|
9
|
+
allowed: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare function isAccessScope(value: string): value is AccessScope;
|
|
12
|
+
declare function isDeleteScope(scope: AccessScope): boolean;
|
|
13
|
+
declare function roleHoldsScope(role: Role, scope: AccessScope): boolean;
|
|
14
|
+
declare function scopesForRole(role: Role): AccessScope[];
|
|
15
|
+
declare function scopeOptions(role: Role): ScopeOption[];
|
|
16
|
+
declare function assertRoleHoldsScopes(role: Role, scopes: readonly AccessScope[]): void;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { ACCESS_SCOPES, AccessScope, SCOPE_PERMISSION, ScopeOption, assertRoleHoldsScopes, isAccessScope, isDeleteScope, roleHoldsScope, scopeOptions, scopesForRole };
|
|
19
|
+
//# sourceMappingURL=access-scopes.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ForbiddenError } from "../shared/errors.js";
|
|
2
|
+
import { capability, isStaffRole } from "./roles.js";
|
|
3
|
+
//#region src/organizations/access-scopes.ts
|
|
4
|
+
const ACCESS_SCOPES = [
|
|
5
|
+
"courses:read",
|
|
6
|
+
"courses:write",
|
|
7
|
+
"courses:delete",
|
|
8
|
+
"downloads:read",
|
|
9
|
+
"downloads:write",
|
|
10
|
+
"downloads:delete",
|
|
11
|
+
"bundles:read",
|
|
12
|
+
"bundles:write",
|
|
13
|
+
"bundles:delete",
|
|
14
|
+
"media:read",
|
|
15
|
+
"students:read",
|
|
16
|
+
"students:invite",
|
|
17
|
+
"access:read",
|
|
18
|
+
"access:write",
|
|
19
|
+
"analytics:read",
|
|
20
|
+
"automations:read",
|
|
21
|
+
"automations:write",
|
|
22
|
+
"automations:delete",
|
|
23
|
+
"comments:read",
|
|
24
|
+
"comments:moderate",
|
|
25
|
+
"communities:read",
|
|
26
|
+
"communities:write",
|
|
27
|
+
"communities:delete",
|
|
28
|
+
"community_members:read",
|
|
29
|
+
"community_members:write",
|
|
30
|
+
"community_moderation:read",
|
|
31
|
+
"community_moderation:write"
|
|
32
|
+
];
|
|
33
|
+
const SCOPE_PERMISSION = {
|
|
34
|
+
"courses:read": null,
|
|
35
|
+
"courses:write": "create_course",
|
|
36
|
+
"courses:delete": "create_course",
|
|
37
|
+
"downloads:read": null,
|
|
38
|
+
"downloads:write": "create_course",
|
|
39
|
+
"downloads:delete": "create_course",
|
|
40
|
+
"bundles:read": null,
|
|
41
|
+
"bundles:write": "create_course",
|
|
42
|
+
"bundles:delete": "create_course",
|
|
43
|
+
"media:read": null,
|
|
44
|
+
"students:read": "view_student_progress",
|
|
45
|
+
"students:invite": "manage_users",
|
|
46
|
+
"access:read": "view_student_progress",
|
|
47
|
+
"access:write": "manage_users",
|
|
48
|
+
"analytics:read": "view_student_progress",
|
|
49
|
+
"automations:read": null,
|
|
50
|
+
"automations:write": "manage_org_settings",
|
|
51
|
+
"automations:delete": "manage_org_settings",
|
|
52
|
+
"comments:read": null,
|
|
53
|
+
"comments:moderate": "edit_assigned_course",
|
|
54
|
+
"communities:read": null,
|
|
55
|
+
"communities:write": "create_course",
|
|
56
|
+
"communities:delete": "create_course",
|
|
57
|
+
"community_members:read": null,
|
|
58
|
+
"community_members:write": "moderate",
|
|
59
|
+
"community_moderation:read": null,
|
|
60
|
+
"community_moderation:write": "moderate"
|
|
61
|
+
};
|
|
62
|
+
function isAccessScope(value) {
|
|
63
|
+
return ACCESS_SCOPES.includes(value);
|
|
64
|
+
}
|
|
65
|
+
function isDeleteScope(scope) {
|
|
66
|
+
return scope.endsWith(":delete");
|
|
67
|
+
}
|
|
68
|
+
function roleHoldsScope(role, scope) {
|
|
69
|
+
if (!isStaffRole(role)) return false;
|
|
70
|
+
const permission = SCOPE_PERMISSION[scope];
|
|
71
|
+
return permission === null || capability(role, permission) === true;
|
|
72
|
+
}
|
|
73
|
+
function scopesForRole(role) {
|
|
74
|
+
return ACCESS_SCOPES.filter((scope) => roleHoldsScope(role, scope));
|
|
75
|
+
}
|
|
76
|
+
function scopeOptions(role) {
|
|
77
|
+
return ACCESS_SCOPES.map((scope) => ({
|
|
78
|
+
scope,
|
|
79
|
+
allowed: roleHoldsScope(role, scope)
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
function assertRoleHoldsScopes(role, scopes) {
|
|
83
|
+
const missing = scopes.filter((scope) => !roleHoldsScope(role, scope));
|
|
84
|
+
if (missing.length > 0) throw new ForbiddenError(`Your role cannot grant ${missing.join(", ")}`);
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { ACCESS_SCOPES, SCOPE_PERMISSION, assertRoleHoldsScopes, isAccessScope, isDeleteScope, roleHoldsScope, scopeOptions, scopesForRole };
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=access-scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-scopes.js","names":[],"sources":["../../src/organizations/access-scopes.ts"],"sourcesContent":["import { ForbiddenError } from '../shared/errors.js';\nimport { capability, isStaffRole, type Permission, type Role } from './roles.js';\n\nexport const ACCESS_SCOPES = [\n 'courses:read',\n 'courses:write',\n 'courses:delete',\n 'downloads:read',\n 'downloads:write',\n 'downloads:delete',\n 'bundles:read',\n 'bundles:write',\n 'bundles:delete',\n 'media:read',\n 'students:read',\n 'students:invite',\n 'access:read',\n 'access:write',\n 'analytics:read',\n 'automations:read',\n 'automations:write',\n 'automations:delete',\n 'comments:read',\n 'comments:moderate',\n 'communities:read',\n 'communities:write',\n 'communities:delete',\n 'community_members:read',\n 'community_members:write',\n 'community_moderation:read',\n 'community_moderation:write',\n] as const;\n\nexport type AccessScope = (typeof ACCESS_SCOPES)[number];\n\nexport const SCOPE_PERMISSION: Record<AccessScope, Permission | null> = {\n 'courses:read': null,\n 'courses:write': 'create_course',\n 'courses:delete': 'create_course',\n 'downloads:read': null,\n 'downloads:write': 'create_course',\n 'downloads:delete': 'create_course',\n 'bundles:read': null,\n 'bundles:write': 'create_course',\n 'bundles:delete': 'create_course',\n 'media:read': null,\n 'students:read': 'view_student_progress',\n 'students:invite': 'manage_users',\n 'access:read': 'view_student_progress',\n 'access:write': 'manage_users',\n 'analytics:read': 'view_student_progress',\n 'automations:read': null,\n 'automations:write': 'manage_org_settings',\n 'automations:delete': 'manage_org_settings',\n 'comments:read': null,\n 'comments:moderate': 'edit_assigned_course',\n 'communities:read': null,\n 'communities:write': 'create_course',\n 'communities:delete': 'create_course',\n 'community_members:read': null,\n 'community_members:write': 'moderate',\n 'community_moderation:read': null,\n 'community_moderation:write': 'moderate',\n};\n\nexport type ScopeOption = { scope: AccessScope; allowed: boolean };\n\nexport function isAccessScope(value: string): value is AccessScope {\n return (ACCESS_SCOPES as readonly string[]).includes(value);\n}\n\nexport function isDeleteScope(scope: AccessScope): boolean {\n return scope.endsWith(':delete');\n}\n\nexport function roleHoldsScope(role: Role, scope: AccessScope): boolean {\n if (!isStaffRole(role)) {\n return false;\n }\n const permission = SCOPE_PERMISSION[scope];\n return permission === null || capability(role, permission) === true;\n}\n\nexport function scopesForRole(role: Role): AccessScope[] {\n return ACCESS_SCOPES.filter((scope) => roleHoldsScope(role, scope));\n}\n\nexport function scopeOptions(role: Role): ScopeOption[] {\n return ACCESS_SCOPES.map((scope) => ({ scope, allowed: roleHoldsScope(role, scope) }));\n}\n\nexport function assertRoleHoldsScopes(role: Role, scopes: readonly AccessScope[]): void {\n const missing = scopes.filter((scope) => !roleHoldsScope(role, scope));\n if (missing.length > 0) {\n throw new ForbiddenError(`Your role cannot grant ${missing.join(', ')}`);\n }\n}\n"],"mappings":";;;AAGA,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAIA,MAAa,mBAA2D;CACtE,gBAAgB;CAChB,iBAAiB;CACjB,kBAAkB;CAClB,kBAAkB;CAClB,mBAAmB;CACnB,oBAAoB;CACpB,gBAAgB;CAChB,iBAAiB;CACjB,kBAAkB;CAClB,cAAc;CACd,iBAAiB;CACjB,mBAAmB;CACnB,eAAe;CACf,gBAAgB;CAChB,kBAAkB;CAClB,oBAAoB;CACpB,qBAAqB;CACrB,sBAAsB;CACtB,iBAAiB;CACjB,qBAAqB;CACrB,oBAAoB;CACpB,qBAAqB;CACrB,sBAAsB;CACtB,0BAA0B;CAC1B,2BAA2B;CAC3B,6BAA6B;CAC7B,8BAA8B;AAChC;AAIA,SAAgB,cAAc,OAAqC;CACjE,OAAQ,cAAoC,SAAS,KAAK;AAC5D;AAEA,SAAgB,cAAc,OAA6B;CACzD,OAAO,MAAM,SAAS,SAAS;AACjC;AAEA,SAAgB,eAAe,MAAY,OAA6B;CACtE,IAAI,CAAC,YAAY,IAAI,GACnB,OAAO;CAET,MAAM,aAAa,iBAAiB;CACpC,OAAO,eAAe,QAAQ,WAAW,MAAM,UAAU,MAAM;AACjE;AAEA,SAAgB,cAAc,MAA2B;CACvD,OAAO,cAAc,QAAQ,UAAU,eAAe,MAAM,KAAK,CAAC;AACpE;AAEA,SAAgB,aAAa,MAA2B;CACtD,OAAO,cAAc,KAAK,WAAW;EAAE;EAAO,SAAS,eAAe,MAAM,KAAK;CAAE,EAAE;AACvF;AAEA,SAAgB,sBAAsB,MAAY,QAAsC;CACtF,MAAM,UAAU,OAAO,QAAQ,UAAU,CAAC,eAAe,MAAM,KAAK,CAAC;CACrE,IAAI,QAAQ,SAAS,GACnB,MAAM,IAAI,eAAe,0BAA0B,QAAQ,KAAK,IAAI,GAAG;AAE3E"}
|
|
@@ -18,7 +18,14 @@ declare const organizationEvents: {
|
|
|
18
18
|
ownerId: string;
|
|
19
19
|
createdAt: unknown;
|
|
20
20
|
updatedAt: unknown;
|
|
21
|
-
}
|
|
21
|
+
}, import("zod").ZodObject<{
|
|
22
|
+
id: import("zod").ZodString;
|
|
23
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
24
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
25
|
+
name: import("zod").ZodString;
|
|
26
|
+
slug: import("zod").ZodString;
|
|
27
|
+
ownerId: import("zod").ZodString;
|
|
28
|
+
}, import("zod/v4/core").$strip>>;
|
|
22
29
|
organizationUpdated: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
23
30
|
id: string;
|
|
24
31
|
externalId: string | null;
|
|
@@ -35,7 +42,14 @@ declare const organizationEvents: {
|
|
|
35
42
|
ownerId: string;
|
|
36
43
|
createdAt: unknown;
|
|
37
44
|
updatedAt: unknown;
|
|
38
|
-
}
|
|
45
|
+
}, import("zod").ZodObject<{
|
|
46
|
+
id: import("zod").ZodString;
|
|
47
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
48
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
49
|
+
name: import("zod").ZodString;
|
|
50
|
+
slug: import("zod").ZodString;
|
|
51
|
+
ownerId: import("zod").ZodString;
|
|
52
|
+
}, import("zod/v4/core").$strip>>;
|
|
39
53
|
organizationDeleted: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
40
54
|
id: string;
|
|
41
55
|
externalId: string | null;
|
|
@@ -52,12 +66,19 @@ declare const organizationEvents: {
|
|
|
52
66
|
ownerId: string;
|
|
53
67
|
createdAt: unknown;
|
|
54
68
|
updatedAt: unknown;
|
|
55
|
-
}
|
|
69
|
+
}, import("zod").ZodObject<{
|
|
70
|
+
id: import("zod").ZodString;
|
|
71
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
72
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
73
|
+
name: import("zod").ZodString;
|
|
74
|
+
slug: import("zod").ZodString;
|
|
75
|
+
ownerId: import("zod").ZodString;
|
|
76
|
+
}, import("zod/v4/core").$strip>>;
|
|
56
77
|
orgUserLinked: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
57
78
|
id: string;
|
|
58
79
|
orgId: string;
|
|
59
80
|
userId: string;
|
|
60
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
81
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
61
82
|
status: "active" | "invited";
|
|
62
83
|
createdAt: Date;
|
|
63
84
|
updatedAt: Date;
|
|
@@ -65,16 +86,33 @@ declare const organizationEvents: {
|
|
|
65
86
|
id: string;
|
|
66
87
|
orgId: string;
|
|
67
88
|
userId: string;
|
|
68
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
89
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
69
90
|
status: "active" | "invited";
|
|
70
91
|
createdAt: unknown;
|
|
71
92
|
updatedAt: unknown;
|
|
72
|
-
}
|
|
93
|
+
}, import("zod").ZodObject<{
|
|
94
|
+
orgId: import("zod").ZodString;
|
|
95
|
+
id: import("zod").ZodString;
|
|
96
|
+
status: import("zod").ZodEnum<{
|
|
97
|
+
active: "active";
|
|
98
|
+
invited: "invited";
|
|
99
|
+
}>;
|
|
100
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
101
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
102
|
+
userId: import("zod").ZodString;
|
|
103
|
+
role: import("zod").ZodEnum<{
|
|
104
|
+
owner: "owner";
|
|
105
|
+
admin: "admin";
|
|
106
|
+
instructor: "instructor";
|
|
107
|
+
moderator: "moderator";
|
|
108
|
+
student: "student";
|
|
109
|
+
}>;
|
|
110
|
+
}, import("zod/v4/core").$strip>>;
|
|
73
111
|
orgUserDeleted: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
74
112
|
id: string;
|
|
75
113
|
orgId: string;
|
|
76
114
|
userId: string;
|
|
77
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
115
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
78
116
|
status: "active" | "invited";
|
|
79
117
|
createdAt: Date;
|
|
80
118
|
updatedAt: Date;
|
|
@@ -82,58 +120,176 @@ declare const organizationEvents: {
|
|
|
82
120
|
id: string;
|
|
83
121
|
orgId: string;
|
|
84
122
|
userId: string;
|
|
85
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
123
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
86
124
|
status: "active" | "invited";
|
|
87
125
|
createdAt: unknown;
|
|
88
126
|
updatedAt: unknown;
|
|
89
|
-
}
|
|
127
|
+
}, import("zod").ZodObject<{
|
|
128
|
+
orgId: import("zod").ZodString;
|
|
129
|
+
id: import("zod").ZodString;
|
|
130
|
+
status: import("zod").ZodEnum<{
|
|
131
|
+
active: "active";
|
|
132
|
+
invited: "invited";
|
|
133
|
+
}>;
|
|
134
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
135
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
136
|
+
userId: import("zod").ZodString;
|
|
137
|
+
role: import("zod").ZodEnum<{
|
|
138
|
+
owner: "owner";
|
|
139
|
+
admin: "admin";
|
|
140
|
+
instructor: "instructor";
|
|
141
|
+
moderator: "moderator";
|
|
142
|
+
student: "student";
|
|
143
|
+
}>;
|
|
144
|
+
}, import("zod/v4/core").$strip>>;
|
|
145
|
+
orgUserUpdated: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
146
|
+
id: string;
|
|
147
|
+
orgId: string;
|
|
148
|
+
userId: string;
|
|
149
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
150
|
+
status: "active" | "invited";
|
|
151
|
+
createdAt: Date;
|
|
152
|
+
updatedAt: Date;
|
|
153
|
+
}, "organization.user.updated", 1>, {
|
|
154
|
+
id: string;
|
|
155
|
+
orgId: string;
|
|
156
|
+
userId: string;
|
|
157
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
158
|
+
status: "active" | "invited";
|
|
159
|
+
createdAt: unknown;
|
|
160
|
+
updatedAt: unknown;
|
|
161
|
+
}, import("zod").ZodObject<{
|
|
162
|
+
orgId: import("zod").ZodString;
|
|
163
|
+
id: import("zod").ZodString;
|
|
164
|
+
status: import("zod").ZodEnum<{
|
|
165
|
+
active: "active";
|
|
166
|
+
invited: "invited";
|
|
167
|
+
}>;
|
|
168
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
169
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
170
|
+
userId: import("zod").ZodString;
|
|
171
|
+
role: import("zod").ZodEnum<{
|
|
172
|
+
owner: "owner";
|
|
173
|
+
admin: "admin";
|
|
174
|
+
instructor: "instructor";
|
|
175
|
+
moderator: "moderator";
|
|
176
|
+
student: "student";
|
|
177
|
+
}>;
|
|
178
|
+
}, import("zod/v4/core").$strip>>;
|
|
90
179
|
inviteCreated: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
91
180
|
id: string;
|
|
92
181
|
orgId: string;
|
|
93
182
|
email: string;
|
|
94
|
-
role: "admin" | "instructor" | "student";
|
|
183
|
+
role: "admin" | "instructor" | "moderator" | "student";
|
|
95
184
|
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
96
185
|
invitedBy: string;
|
|
97
186
|
tokenHash: string | null;
|
|
98
187
|
expiresAt: Date | null;
|
|
99
188
|
createdAt: Date;
|
|
189
|
+
updatedAt: Date;
|
|
100
190
|
}, "organization.invite.created", 1>, {
|
|
101
191
|
id: string;
|
|
102
192
|
orgId: string;
|
|
103
193
|
email: string;
|
|
104
|
-
role: "admin" | "instructor" | "student";
|
|
194
|
+
role: "admin" | "instructor" | "moderator" | "student";
|
|
105
195
|
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
106
196
|
invitedBy: string;
|
|
107
197
|
tokenHash: string | null;
|
|
108
198
|
expiresAt: unknown;
|
|
109
199
|
createdAt: unknown;
|
|
110
|
-
|
|
200
|
+
updatedAt: unknown;
|
|
201
|
+
}, import("zod").ZodObject<{
|
|
202
|
+
orgId: import("zod").ZodString;
|
|
203
|
+
id: import("zod").ZodString;
|
|
204
|
+
status: import("zod").ZodEnum<{
|
|
205
|
+
pending: "pending";
|
|
206
|
+
accepted: "accepted";
|
|
207
|
+
rejected: "rejected";
|
|
208
|
+
canceled: "canceled";
|
|
209
|
+
}>;
|
|
210
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
211
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
212
|
+
expiresAt: import("zod").ZodNullable<import("zod").ZodCoercedDate<unknown>>;
|
|
213
|
+
email: import("zod").ZodEmail;
|
|
214
|
+
role: import("zod").ZodEnum<{
|
|
215
|
+
admin: "admin";
|
|
216
|
+
instructor: "instructor";
|
|
217
|
+
moderator: "moderator";
|
|
218
|
+
student: "student";
|
|
219
|
+
}>;
|
|
220
|
+
invitedBy: import("zod").ZodString;
|
|
221
|
+
}, import("zod/v4/core").$strip>>;
|
|
111
222
|
inviteAccepted: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
112
223
|
id: string;
|
|
113
224
|
orgId: string;
|
|
114
225
|
email: string;
|
|
115
|
-
role: "admin" | "instructor" | "student";
|
|
226
|
+
role: "admin" | "instructor" | "moderator" | "student";
|
|
116
227
|
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
117
228
|
invitedBy: string;
|
|
118
229
|
tokenHash: string | null;
|
|
119
230
|
expiresAt: Date | null;
|
|
120
231
|
createdAt: Date;
|
|
232
|
+
updatedAt: Date;
|
|
121
233
|
}, "organization.invite.accepted", 1>, {
|
|
122
234
|
id: string;
|
|
123
235
|
orgId: string;
|
|
124
236
|
email: string;
|
|
125
|
-
role: "admin" | "instructor" | "student";
|
|
237
|
+
role: "admin" | "instructor" | "moderator" | "student";
|
|
238
|
+
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
239
|
+
invitedBy: string;
|
|
240
|
+
tokenHash: string | null;
|
|
241
|
+
expiresAt: unknown;
|
|
242
|
+
createdAt: unknown;
|
|
243
|
+
updatedAt: unknown;
|
|
244
|
+
}, import("zod").ZodObject<{
|
|
245
|
+
orgId: import("zod").ZodString;
|
|
246
|
+
id: import("zod").ZodString;
|
|
247
|
+
status: import("zod").ZodEnum<{
|
|
248
|
+
pending: "pending";
|
|
249
|
+
accepted: "accepted";
|
|
250
|
+
rejected: "rejected";
|
|
251
|
+
canceled: "canceled";
|
|
252
|
+
}>;
|
|
253
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
254
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
255
|
+
expiresAt: import("zod").ZodNullable<import("zod").ZodCoercedDate<unknown>>;
|
|
256
|
+
email: import("zod").ZodEmail;
|
|
257
|
+
role: import("zod").ZodEnum<{
|
|
258
|
+
admin: "admin";
|
|
259
|
+
instructor: "instructor";
|
|
260
|
+
moderator: "moderator";
|
|
261
|
+
student: "student";
|
|
262
|
+
}>;
|
|
263
|
+
invitedBy: import("zod").ZodString;
|
|
264
|
+
}, import("zod/v4/core").$strip>>;
|
|
265
|
+
inviteCanceled: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
266
|
+
id: string;
|
|
267
|
+
orgId: string;
|
|
268
|
+
email: string;
|
|
269
|
+
role: "admin" | "instructor" | "moderator" | "student";
|
|
270
|
+
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
271
|
+
invitedBy: string;
|
|
272
|
+
tokenHash: string | null;
|
|
273
|
+
expiresAt: Date | null;
|
|
274
|
+
createdAt: Date;
|
|
275
|
+
updatedAt: Date;
|
|
276
|
+
}, "organization.invite.canceled", 1>, {
|
|
277
|
+
id: string;
|
|
278
|
+
orgId: string;
|
|
279
|
+
email: string;
|
|
280
|
+
role: "admin" | "instructor" | "moderator" | "student";
|
|
126
281
|
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
127
282
|
invitedBy: string;
|
|
128
283
|
tokenHash: string | null;
|
|
129
284
|
expiresAt: unknown;
|
|
130
285
|
createdAt: unknown;
|
|
131
|
-
|
|
286
|
+
updatedAt: unknown;
|
|
287
|
+
}, undefined>;
|
|
132
288
|
studentCreated: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
133
289
|
id: string;
|
|
134
290
|
orgId: string;
|
|
135
291
|
userId: string;
|
|
136
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
292
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
137
293
|
status: "active" | "invited";
|
|
138
294
|
createdAt: Date;
|
|
139
295
|
updatedAt: Date;
|
|
@@ -141,16 +297,33 @@ declare const organizationEvents: {
|
|
|
141
297
|
id: string;
|
|
142
298
|
orgId: string;
|
|
143
299
|
userId: string;
|
|
144
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
300
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
145
301
|
status: "active" | "invited";
|
|
146
302
|
createdAt: unknown;
|
|
147
303
|
updatedAt: unknown;
|
|
148
|
-
}
|
|
304
|
+
}, import("zod").ZodObject<{
|
|
305
|
+
orgId: import("zod").ZodString;
|
|
306
|
+
id: import("zod").ZodString;
|
|
307
|
+
status: import("zod").ZodEnum<{
|
|
308
|
+
active: "active";
|
|
309
|
+
invited: "invited";
|
|
310
|
+
}>;
|
|
311
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
312
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
313
|
+
userId: import("zod").ZodString;
|
|
314
|
+
role: import("zod").ZodEnum<{
|
|
315
|
+
owner: "owner";
|
|
316
|
+
admin: "admin";
|
|
317
|
+
instructor: "instructor";
|
|
318
|
+
moderator: "moderator";
|
|
319
|
+
student: "student";
|
|
320
|
+
}>;
|
|
321
|
+
}, import("zod/v4/core").$strip>>;
|
|
149
322
|
studentDeleted: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
150
323
|
id: string;
|
|
151
324
|
orgId: string;
|
|
152
325
|
userId: string;
|
|
153
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
326
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
154
327
|
status: "active" | "invited";
|
|
155
328
|
createdAt: Date;
|
|
156
329
|
updatedAt: Date;
|
|
@@ -158,16 +331,33 @@ declare const organizationEvents: {
|
|
|
158
331
|
id: string;
|
|
159
332
|
orgId: string;
|
|
160
333
|
userId: string;
|
|
161
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
334
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
162
335
|
status: "active" | "invited";
|
|
163
336
|
createdAt: unknown;
|
|
164
337
|
updatedAt: unknown;
|
|
165
|
-
}
|
|
338
|
+
}, import("zod").ZodObject<{
|
|
339
|
+
orgId: import("zod").ZodString;
|
|
340
|
+
id: import("zod").ZodString;
|
|
341
|
+
status: import("zod").ZodEnum<{
|
|
342
|
+
active: "active";
|
|
343
|
+
invited: "invited";
|
|
344
|
+
}>;
|
|
345
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
346
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
347
|
+
userId: import("zod").ZodString;
|
|
348
|
+
role: import("zod").ZodEnum<{
|
|
349
|
+
owner: "owner";
|
|
350
|
+
admin: "admin";
|
|
351
|
+
instructor: "instructor";
|
|
352
|
+
moderator: "moderator";
|
|
353
|
+
student: "student";
|
|
354
|
+
}>;
|
|
355
|
+
}, import("zod/v4/core").$strip>>;
|
|
166
356
|
studentLinked: RuntimeEventDefinition<VersionedDomainEvent<{
|
|
167
357
|
id: string;
|
|
168
358
|
orgId: string;
|
|
169
359
|
userId: string;
|
|
170
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
360
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
171
361
|
status: "active" | "invited";
|
|
172
362
|
createdAt: Date;
|
|
173
363
|
updatedAt: Date;
|
|
@@ -175,23 +365,42 @@ declare const organizationEvents: {
|
|
|
175
365
|
id: string;
|
|
176
366
|
orgId: string;
|
|
177
367
|
userId: string;
|
|
178
|
-
role: "owner" | "admin" | "instructor" | "student";
|
|
368
|
+
role: "owner" | "admin" | "instructor" | "moderator" | "student";
|
|
179
369
|
status: "active" | "invited";
|
|
180
370
|
createdAt: unknown;
|
|
181
371
|
updatedAt: unknown;
|
|
182
|
-
}
|
|
372
|
+
}, import("zod").ZodObject<{
|
|
373
|
+
orgId: import("zod").ZodString;
|
|
374
|
+
id: import("zod").ZodString;
|
|
375
|
+
status: import("zod").ZodEnum<{
|
|
376
|
+
active: "active";
|
|
377
|
+
invited: "invited";
|
|
378
|
+
}>;
|
|
379
|
+
createdAt: import("zod").ZodCoercedDate<unknown>;
|
|
380
|
+
updatedAt: import("zod").ZodCoercedDate<unknown>;
|
|
381
|
+
userId: import("zod").ZodString;
|
|
382
|
+
role: import("zod").ZodEnum<{
|
|
383
|
+
owner: "owner";
|
|
384
|
+
admin: "admin";
|
|
385
|
+
instructor: "instructor";
|
|
386
|
+
moderator: "moderator";
|
|
387
|
+
student: "student";
|
|
388
|
+
}>;
|
|
389
|
+
}, import("zod/v4/core").$strip>>;
|
|
183
390
|
};
|
|
184
391
|
type OrganizationCreated = EventOf<typeof organizationEvents.organizationCreated>;
|
|
185
392
|
type OrganizationUpdated = EventOf<typeof organizationEvents.organizationUpdated>;
|
|
186
393
|
type OrganizationDeleted = EventOf<typeof organizationEvents.organizationDeleted>;
|
|
187
394
|
type OrgUserLinked = EventOf<typeof organizationEvents.orgUserLinked>;
|
|
188
395
|
type OrgUserDeleted = EventOf<typeof organizationEvents.orgUserDeleted>;
|
|
396
|
+
type OrgUserUpdated = EventOf<typeof organizationEvents.orgUserUpdated>;
|
|
189
397
|
type InviteCreated = EventOf<typeof organizationEvents.inviteCreated>;
|
|
190
398
|
type InviteAccepted = EventOf<typeof organizationEvents.inviteAccepted>;
|
|
399
|
+
type InviteCanceled = EventOf<typeof organizationEvents.inviteCanceled>;
|
|
191
400
|
type StudentCreated = EventOf<typeof organizationEvents.studentCreated>;
|
|
192
401
|
type StudentDeleted = EventOf<typeof organizationEvents.studentDeleted>;
|
|
193
402
|
type StudentLinked = EventOf<typeof organizationEvents.studentLinked>;
|
|
194
403
|
type OrganizationEvent = EventOfValues<typeof organizationEvents>;
|
|
195
404
|
//#endregion
|
|
196
|
-
export { InviteAccepted, InviteCreated, OrgUserDeleted, OrgUserLinked, OrganizationCreated, OrganizationDeleted, OrganizationEvent, OrganizationUpdated, StudentCreated, StudentDeleted, StudentLinked, organizationEvents };
|
|
405
|
+
export { InviteAccepted, InviteCanceled, InviteCreated, OrgUserDeleted, OrgUserLinked, OrgUserUpdated, OrganizationCreated, OrganizationDeleted, OrganizationEvent, OrganizationUpdated, StudentCreated, StudentDeleted, StudentLinked, organizationEvents };
|
|
197
406
|
//# sourceMappingURL=events.d.ts.map
|