@aeolus-fleet/core 0.19.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/prisma/generated/browser.d.ts +25 -0
- package/dist/adapters/prisma/generated/client.d.ts +25 -0
- package/dist/adapters/prisma/generated/internal/class.d.ts +44 -0
- package/dist/adapters/prisma/generated/internal/class.js +4 -4
- package/dist/adapters/prisma/generated/internal/class.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +338 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js +34 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +37 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +34 -1
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/adapters/prisma/generated/models/CrewRequest.d.ts +103 -1
- package/dist/adapters/prisma/generated/models/Fleet.d.ts +860 -0
- package/dist/adapters/prisma/generated/models/Label.d.ts +1475 -0
- package/dist/adapters/prisma/generated/models/Label.js +2 -0
- package/dist/adapters/prisma/generated/models/Label.js.map +1 -0
- package/dist/adapters/prisma/generated/models/LabelValue.d.ts +1454 -0
- package/dist/adapters/prisma/generated/models/LabelValue.js +2 -0
- package/dist/adapters/prisma/generated/models/LabelValue.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Ship.d.ts +1225 -70
- package/dist/adapters/prisma/generated/models/ShipLabel.d.ts +1431 -0
- package/dist/adapters/prisma/generated/models/ShipLabel.js +2 -0
- package/dist/adapters/prisma/generated/models/ShipLabel.js.map +1 -0
- package/dist/adapters/prisma/generated/models/WorktreeClearRequest.d.ts +1539 -0
- package/dist/adapters/prisma/generated/models/WorktreeClearRequest.js +2 -0
- package/dist/adapters/prisma/generated/models/WorktreeClearRequest.js.map +1 -0
- package/dist/adapters/prisma/generated/models.d.ts +4 -0
- package/dist/adapters/prisma/registry.d.ts +3 -1
- package/dist/adapters/prisma/registry.js +129 -9
- package/dist/adapters/prisma/registry.js.map +1 -1
- package/dist/adapters/prisma/rows.d.ts +10 -0
- package/dist/adapters/prisma/rows.js +41 -2
- package/dist/adapters/prisma/rows.js.map +1 -1
- package/dist/adapters/prisma/unit-of-work.d.ts +3 -1
- package/dist/adapters/prisma/unit-of-work.js +3 -1
- package/dist/adapters/prisma/unit-of-work.js.map +1 -1
- package/dist/adapters/trpc/console.d.ts +1 -1
- package/dist/adapters/trpc/context.d.ts +20 -0
- package/dist/adapters/trpc/fleet.d.ts +144 -8
- package/dist/adapters/trpc/fleet.js +143 -6
- package/dist/adapters/trpc/fleet.js.map +1 -1
- package/dist/adapters/trpc/router.d.ts +134 -8
- package/dist/adapters/trpc/ship-contract.js +10 -0
- package/dist/adapters/trpc/ship-contract.js.map +1 -1
- package/dist/adapters/trpc/trpc.js +14 -0
- package/dist/adapters/trpc/trpc.js.map +1 -1
- package/dist/domain/registry/assign-label.d.ts +32 -0
- package/dist/domain/registry/assign-label.js +39 -0
- package/dist/domain/registry/assign-label.js.map +1 -0
- package/dist/domain/registry/change-label-values.d.ts +33 -0
- package/dist/domain/registry/change-label-values.js +34 -0
- package/dist/domain/registry/change-label-values.js.map +1 -0
- package/dist/domain/registry/clear-request.d.ts +69 -0
- package/dist/domain/registry/clear-request.js +51 -0
- package/dist/domain/registry/clear-request.js.map +1 -0
- package/dist/domain/registry/confirm-worktree-cleared.d.ts +31 -0
- package/dist/domain/registry/confirm-worktree-cleared.js +30 -0
- package/dist/domain/registry/confirm-worktree-cleared.js.map +1 -0
- package/dist/domain/registry/crew-request.d.ts +9 -3
- package/dist/domain/registry/crew-request.js +9 -6
- package/dist/domain/registry/crew-request.js.map +1 -1
- package/dist/domain/registry/define-label.d.ts +33 -0
- package/dist/domain/registry/define-label.js +33 -0
- package/dist/domain/registry/define-label.js.map +1 -0
- package/dist/domain/registry/delete-label.d.ts +30 -0
- package/dist/domain/registry/delete-label.js +32 -0
- package/dist/domain/registry/delete-label.js.map +1 -0
- package/dist/domain/registry/find-label-value.d.ts +22 -0
- package/dist/domain/registry/find-label-value.js +19 -0
- package/dist/domain/registry/find-label-value.js.map +1 -0
- package/dist/domain/registry/label.d.ts +197 -0
- package/dist/domain/registry/label.js +263 -0
- package/dist/domain/registry/label.js.map +1 -0
- package/dist/domain/registry/list-fleet.d.ts +13 -7
- package/dist/domain/registry/list-fleet.js +10 -5
- package/dist/domain/registry/list-fleet.js.map +1 -1
- package/dist/domain/registry/list-labels.d.ts +12 -0
- package/dist/domain/registry/list-labels.js +9 -0
- package/dist/domain/registry/list-labels.js.map +1 -0
- package/dist/domain/registry/ports.d.ts +59 -1
- package/dist/domain/registry/read-clear-requests.d.ts +15 -0
- package/dist/domain/registry/read-clear-requests.js +16 -0
- package/dist/domain/registry/read-clear-requests.js.map +1 -0
- package/dist/domain/registry/report-crew-status.d.ts +6 -3
- package/dist/domain/registry/report-crew-status.js +11 -4
- package/dist/domain/registry/report-crew-status.js.map +1 -1
- package/dist/domain/registry/request-worktree-clear.d.ts +31 -0
- package/dist/domain/registry/request-worktree-clear.js +35 -0
- package/dist/domain/registry/request-worktree-clear.js.map +1 -0
- package/dist/domain/registry/retire-ship.d.ts +9 -3
- package/dist/domain/registry/retire-ship.js +27 -2
- package/dist/domain/registry/retire-ship.js.map +1 -1
- package/dist/domain/registry/unassign-label.d.ts +30 -0
- package/dist/domain/registry/unassign-label.js +37 -0
- package/dist/domain/registry/unassign-label.js.map +1 -0
- package/dist/domain/shared/errors.d.ts +1 -1
- package/dist/domain/shared/errors.js.map +1 -1
- package/dist/wiring.d.ts +20 -0
- package/dist/wiring.js +21 -1
- package/dist/wiring.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/prisma/migrations/20261007100000_labels/migration.sql +87 -0
- package/src/adapters/prisma/migrations/20261007110000_foreign_key_indexes/migration.sql +42 -0
- package/src/adapters/prisma/migrations/20261007120000_crew_status_attempt/migration.sql +4 -0
- package/src/adapters/prisma/migrations/20261007140000_worktree_clear_requests/migration.sql +32 -0
- package/src/adapters/prisma/schema.prisma +120 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CLEAR_REQUESTS_PER_TRIERARCH_MAX } from '@aeolus-fleet/common';
|
|
2
|
+
import { refuse } from '../shared/errors.js';
|
|
3
|
+
import { ok } from '../shared/result.js';
|
|
4
|
+
/** The type of the ship a trierarch crews (docs/trierarch.md). */
|
|
5
|
+
export const TRIERARCH_SHIP_TYPE = 'trierarch';
|
|
6
|
+
function event(trierarch, change) {
|
|
7
|
+
const { at, actor, ...what } = change;
|
|
8
|
+
return { fleetId: trierarch.fleetId, occurredAt: at, actor, shipId: trierarch.id, ...what };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A ship asks a trierarch to clear the worktree it kept for a ship in a
|
|
12
|
+
* repository: the request, and WorktreeClearRequested on the trierarch's
|
|
13
|
+
* ship. Only a trierarch that is not retired; at most
|
|
14
|
+
* CLEAR_REQUESTS_PER_TRIERARCH_MAX pending at once. A request it holds
|
|
15
|
+
* already changes nothing: no request and no event.
|
|
16
|
+
*/
|
|
17
|
+
export function requestWorktreeClear({ trierarch, current, pending }, input) {
|
|
18
|
+
if (trierarch.type !== TRIERARCH_SHIP_TYPE) {
|
|
19
|
+
return refuse('NOT_A_TRIERARCH', `${trierarch.name} is no trierarch: only a trierarch clears a worktree it kept`);
|
|
20
|
+
}
|
|
21
|
+
if (trierarch.retiredAt !== null) {
|
|
22
|
+
return refuse('SHIP_ALREADY_RETIRED', `${trierarch.name} is retired: a retired trierarch clears nothing`);
|
|
23
|
+
}
|
|
24
|
+
if (current) {
|
|
25
|
+
return ok({ request: null, events: [] });
|
|
26
|
+
}
|
|
27
|
+
if (pending >= CLEAR_REQUESTS_PER_TRIERARCH_MAX) {
|
|
28
|
+
return refuse('CLEAR_REQUEST_LIMIT_REACHED', `${trierarch.name} holds ${String(CLEAR_REQUESTS_PER_TRIERARCH_MAX)} clear requests already, the most a trierarch may hold (decision 0032): ask again once it confirms some`);
|
|
29
|
+
}
|
|
30
|
+
const { shipId, repository, requestedBy, at, actor } = input;
|
|
31
|
+
return ok({
|
|
32
|
+
request: { fleetId: trierarch.fleetId, trierarchShipId: trierarch.id, shipId, repository, requestedBy, requestedAt: at },
|
|
33
|
+
events: [event(trierarch, { type: 'WorktreeClearRequested', details: { worktreeShipId: shipId, repository }, at, actor })],
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The trierarch confirms a clear request it holds, saying how it came out:
|
|
38
|
+
* the request goes, with WorktreeCleared and the outcome.
|
|
39
|
+
*/
|
|
40
|
+
export function confirmWorktreeCleared({ trierarch, worktreeShipName, current }, input) {
|
|
41
|
+
const { repository, outcome, at, actor } = input;
|
|
42
|
+
if (!current) {
|
|
43
|
+
return refuse('CLEAR_REQUEST_NOT_FOUND', `${trierarch.name} holds no clear request for the ${repository} worktree of ${worktreeShipName}`);
|
|
44
|
+
}
|
|
45
|
+
return ok({ events: [event(trierarch, { type: 'WorktreeCleared', details: { worktreeShipId: current.shipId, repository, outcome }, at, actor })] });
|
|
46
|
+
}
|
|
47
|
+
/** A retired trierarch clears nothing: its pending requests go, one WorktreeClearRemoved each. */
|
|
48
|
+
export function removeClearRequestsOf({ trierarch, requests }, change) {
|
|
49
|
+
return requests.map(({ shipId, repository }) => event(trierarch, { type: 'WorktreeClearRemoved', details: { worktreeShipId: shipId, repository }, ...change }));
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=clear-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clear-request.js","sourceRoot":"","sources":["../../../src/domain/registry/clear-request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ClearOutcome, IdGenerator, ShipId } from '@aeolus-fleet/common';
|
|
2
|
+
import type { Caller } from '../shared/caller.js';
|
|
3
|
+
import type { Clock } from '../shared/clock.js';
|
|
4
|
+
import { type DomainError } from '../shared/errors.js';
|
|
5
|
+
import { type EventLog } from '../shared/events.js';
|
|
6
|
+
import { type Result } from '../shared/result.js';
|
|
7
|
+
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
8
|
+
import { type ConfirmWorktreeClearedRefusal } from './clear-request.js';
|
|
9
|
+
import type { ClearRequestRepository, ShipRepository } from './ports.js';
|
|
10
|
+
export interface ConfirmWorktreeClearedTx {
|
|
11
|
+
ships: Pick<ShipRepository, 'find' | 'findForUpdate'>;
|
|
12
|
+
clearRequests: ClearRequestRepository;
|
|
13
|
+
events: EventLog;
|
|
14
|
+
}
|
|
15
|
+
export type ConfirmWorktreeClearedUseCaseRefusal = DomainError<'SHIP_NOT_FOUND'> | ConfirmWorktreeClearedRefusal;
|
|
16
|
+
export type ConfirmWorktreeCleared = (caller: Caller, input: {
|
|
17
|
+
shipId: ShipId;
|
|
18
|
+
repository: string;
|
|
19
|
+
outcome: ClearOutcome;
|
|
20
|
+
}) => Promise<Result<undefined, ConfirmWorktreeClearedUseCaseRefusal>>;
|
|
21
|
+
/**
|
|
22
|
+
* Use case: a trierarch confirms a clear request to its own ship, saying it
|
|
23
|
+
* removed the worktree or kept none (decision 0032). Its scope (crew:run) is
|
|
24
|
+
* checked before this runs. In one unit of work, locking its ship first: the
|
|
25
|
+
* request goes, with WorktreeCleared.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createConfirmWorktreeCleared(deps: {
|
|
28
|
+
uow: UnitOfWork<ConfirmWorktreeClearedTx>;
|
|
29
|
+
clock: Clock;
|
|
30
|
+
ids: IdGenerator;
|
|
31
|
+
}): ConfirmWorktreeCleared;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { refuse } from '../shared/errors.js';
|
|
2
|
+
import { recordEvent, shipActor } from '../shared/events.js';
|
|
3
|
+
import { ok } from '../shared/result.js';
|
|
4
|
+
import { confirmWorktreeCleared } from './clear-request.js';
|
|
5
|
+
/**
|
|
6
|
+
* Use case: a trierarch confirms a clear request to its own ship, saying it
|
|
7
|
+
* removed the worktree or kept none (decision 0032). Its scope (crew:run) is
|
|
8
|
+
* checked before this runs. In one unit of work, locking its ship first: the
|
|
9
|
+
* request goes, with WorktreeCleared.
|
|
10
|
+
*/
|
|
11
|
+
export function createConfirmWorktreeCleared(deps) {
|
|
12
|
+
return (caller, input) => deps.uow.run(async (tx) => {
|
|
13
|
+
const { fleetId } = caller;
|
|
14
|
+
const trierarch = await tx.ships.findForUpdate(fleetId, caller.shipId);
|
|
15
|
+
if (!trierarch) {
|
|
16
|
+
return refuse('SHIP_NOT_FOUND', `Ship ${caller.shipId} does not exist`);
|
|
17
|
+
}
|
|
18
|
+
const key = { trierarchShipId: trierarch.id, shipId: input.shipId, repository: input.repository };
|
|
19
|
+
const confirmed = confirmWorktreeCleared({ trierarch, worktreeShipName: (await tx.ships.find(fleetId, input.shipId))?.name ?? input.shipId, current: await tx.clearRequests.find(fleetId, key) }, { repository: input.repository, outcome: input.outcome, at: deps.clock.now(), actor: shipActor(caller.shipId) });
|
|
20
|
+
if (!confirmed.isOk) {
|
|
21
|
+
return confirmed;
|
|
22
|
+
}
|
|
23
|
+
await tx.clearRequests.remove(fleetId, key);
|
|
24
|
+
for (const event of confirmed.value.events) {
|
|
25
|
+
await recordEvent({ events: tx.events, ids: deps.ids }, event);
|
|
26
|
+
}
|
|
27
|
+
return ok(undefined);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=confirm-worktree-cleared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm-worktree-cleared.js","sourceRoot":"","sources":["../../../src/domain/registry/confirm-worktree-cleared.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAsC,MAAM,oBAAoB,CAAC;AAgBhG;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAmF;IAC9H,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAoE,EAAE;QAC1F,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACvE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,gBAAgB,EAAE,QAAQ,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,GAAG,GAAG,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QAClG,MAAM,SAAS,GAAG,sBAAsB,CACtC,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,EACvJ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAChH,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YACpB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -28,6 +28,10 @@ export interface CrewRequest {
|
|
|
28
28
|
status: CrewStatus | null;
|
|
29
29
|
/** Why no trierarch can take it, written by the assigner while unassigned; null when none. */
|
|
30
30
|
reason: string | null;
|
|
31
|
+
/** How many times its trierarch restarted the session within its restart window, written with the status: 0 on its first start (#332). */
|
|
32
|
+
attempt: number;
|
|
33
|
+
/** When the session its trierarch runs now started, written with the status; null while none runs. */
|
|
34
|
+
sessionStartedAt: Date | null;
|
|
31
35
|
}
|
|
32
36
|
type NotFound = DomainError<'CREW_REQUEST_NOT_FOUND'>;
|
|
33
37
|
type Releasing = DomainError<'CREW_REQUEST_RELEASING'>;
|
|
@@ -105,9 +109,9 @@ export declare function explainCrewRequest({ ship, current }: {
|
|
|
105
109
|
events: NewEvent[];
|
|
106
110
|
}, ExplainCrewRequestRefusal>;
|
|
107
111
|
/**
|
|
108
|
-
* The assigned trierarch writes how its crew of the ship stands, with
|
|
109
|
-
*
|
|
110
|
-
* releasing.
|
|
112
|
+
* The assigned trierarch writes how its crew of the ship stands, with the
|
|
113
|
+
* restart attempt and when the session started (#332), and CrewStatusChanged
|
|
114
|
+
* when any of them changes. Once the request is releasing, only releasing.
|
|
111
115
|
*/
|
|
112
116
|
export declare function reportCrewStatus({ ship, current, trierarchShipId }: {
|
|
113
117
|
ship: Ship;
|
|
@@ -115,6 +119,8 @@ export declare function reportCrewStatus({ ship, current, trierarchShipId }: {
|
|
|
115
119
|
trierarchShipId: ShipId;
|
|
116
120
|
}, input: {
|
|
117
121
|
status: CrewStatus;
|
|
122
|
+
attempt: number;
|
|
123
|
+
sessionStartedAt: Date | null;
|
|
118
124
|
at: Date;
|
|
119
125
|
actor: Actor;
|
|
120
126
|
}): Result<{
|
|
@@ -38,6 +38,8 @@ export function requestCrew({ ship, current }, input) {
|
|
|
38
38
|
assignedTo: current?.assignedTo ?? null,
|
|
39
39
|
status: current?.status ?? null,
|
|
40
40
|
reason: current?.reason ?? null,
|
|
41
|
+
attempt: current?.attempt ?? 0,
|
|
42
|
+
sessionStartedAt: current?.sessionStartedAt ?? null,
|
|
41
43
|
};
|
|
42
44
|
return ok({ request, events: [event(ship, { at: input.at, actor: input.actor, type: 'CrewRequested', details: { settingsVersion: request.settingsVersion } })] });
|
|
43
45
|
}
|
|
@@ -119,9 +121,9 @@ function checkAssignedTo({ ship, current, trierarchShipId }) {
|
|
|
119
121
|
: refuse('CREW_REQUEST_NOT_ASSIGNED_TO_CALLER', `${ship.name}'s crew request is not assigned to your ship`);
|
|
120
122
|
}
|
|
121
123
|
/**
|
|
122
|
-
* The assigned trierarch writes how its crew of the ship stands, with
|
|
123
|
-
*
|
|
124
|
-
* releasing.
|
|
124
|
+
* The assigned trierarch writes how its crew of the ship stands, with the
|
|
125
|
+
* restart attempt and when the session started (#332), and CrewStatusChanged
|
|
126
|
+
* when any of them changes. Once the request is releasing, only releasing.
|
|
125
127
|
*/
|
|
126
128
|
export function reportCrewStatus({ ship, current, trierarchShipId }, input) {
|
|
127
129
|
if (!current) {
|
|
@@ -134,12 +136,13 @@ export function reportCrewStatus({ ship, current, trierarchShipId }, input) {
|
|
|
134
136
|
if (current.status === 'releasing' && input.status !== 'releasing') {
|
|
135
137
|
return refuse('CREW_REQUEST_RELEASING', `${ship.name}'s crew request is releasing: stop its session, end its lease and confirm`);
|
|
136
138
|
}
|
|
137
|
-
|
|
139
|
+
const isSameStart = (current.sessionStartedAt?.getTime() ?? null) === (input.sessionStartedAt?.getTime() ?? null);
|
|
140
|
+
if (current.status === input.status && current.attempt === input.attempt && isSameStart) {
|
|
138
141
|
return ok({ request: current, events: [] });
|
|
139
142
|
}
|
|
140
143
|
return ok({
|
|
141
|
-
request: { ...current, status: input.status },
|
|
142
|
-
events: [event(ship, { at: input.at, actor: input.actor, type: 'CrewStatusChanged', details: { status: input.status } })],
|
|
144
|
+
request: { ...current, status: input.status, attempt: input.attempt, sessionStartedAt: input.sessionStartedAt },
|
|
145
|
+
events: [event(ship, { at: input.at, actor: input.actor, type: 'CrewStatusChanged', details: { status: input.status, attempt: input.attempt } })],
|
|
143
146
|
});
|
|
144
147
|
}
|
|
145
148
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crew-request.js","sourceRoot":"","sources":["../../../src/domain/registry/crew-request.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,+BAA+B,EAC/B,SAAS,EACT,wBAAwB,GAKzB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAe,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAA0C,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"crew-request.js","sourceRoot":"","sources":["../../../src/domain/registry/crew-request.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,+BAA+B,EAC/B,SAAS,EACT,wBAAwB,GAKzB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAe,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAA0C,MAAM,WAAW,CAAC;AAqC5F,SAAS,QAAQ,CAAC,IAAU;IAC1B,OAAO,MAAM,CAAC,wBAAwB,EAAE,GAAG,IAAI,CAAC,IAAI,sBAAsB,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,KAAK,CAAC,IAAU,EAAE,MAAuE;IAChG,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IACtC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC;AACpF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,EAAE,IAAI,EAAE,OAAO,EAAoD,EACnE,KAAuD;IAEvD,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACtB,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,MAAM,CAAC,wBAAwB,EAAE,GAAG,IAAI,CAAC,IAAI,yEAAyE,CAAC,CAAC;IACjI,CAAC;IACD,MAAM,KAAK,GAAG,wBAAwB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,KAAK,GAAG,+BAA+B,EAAE,CAAC;QAC5C,OAAO,MAAM,CACX,iCAAiC,EACjC,eAAe,MAAM,CAAC,KAAK,CAAC,wBAAwB,MAAM,CAAC,+BAA+B,CAAC,kBAAkB,CAC9G,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAgB;QAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC;QACpD,WAAW,EAAE,KAAK,CAAC,EAAE;QACrB,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,IAAI;QACvC,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;QAC/B,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;QAC/B,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,CAAC;QAC9B,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,IAAI,IAAI;KACpD,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACpK,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAE,IAAI,EAAE,OAAO,EAAoD,EACnE,KAAiC;IAEjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACnC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,CAAC;QACR,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE;QAC5C,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;KACjG,CAAC,CAAC;AACL,CAAC;AAMD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAmG,EACtI,KAAiC;IAEjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,+BAA+B,EAAE,GAAG,IAAI,CAAC,IAAI,qCAAqC,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,MAAM,CAAC,wBAAwB,EAAE,GAAG,IAAI,CAAC,IAAI,oDAAoD,CAAC,CAAC;IAC5G,CAAC;IACD,IAAI,QAAQ,EAAE,SAAS,KAAK,IAAI,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,qBAAqB,EAAE,gEAAgE,CAAC,CAAC;IACzG,CAAC;IACD,OAAO,EAAE,CAAC;QACR,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAC9D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;KAChG,CAAC,CAAC;AACL,CAAC;AAID;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,EAAE,IAAI,EAAE,OAAO,EAAoD,EACnE,KAAwD;IAExD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,+BAA+B,EAAE,GAAG,IAAI,CAAC,IAAI,iDAAiD,CAAC,CAAC;IAChH,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1C,IAAI,MAAM,CAAC,MAAM,GAAG,8BAA8B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACzE,OAAO,MAAM,CAAC,6BAA6B,EAAE,mCAAmC,MAAM,CAAC,8BAA8B,CAAC,aAAa,CAAC,CAAC;IACvI,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC3C,IAAI,IAAI,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,CAAC;QACR,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;QACrC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;KACrH,CAAC,CAAC;AACL,CAAC;AAED,+FAA+F;AAC/F,SAAS,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAiE;IACxH,OAAO,OAAO,CAAC,UAAU,KAAK,eAAe;QAC3C,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC;QACf,CAAC,CAAC,MAAM,CAAC,qCAAqC,EAAE,GAAG,IAAI,CAAC,IAAI,8CAA8C,CAAC,CAAC;AAChH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAA6E,EAC7G,KAAqG;IAErG,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACnE,OAAO,MAAM,CAAC,wBAAwB,EAAE,GAAG,IAAI,CAAC,IAAI,2EAA2E,CAAC,CAAC;IACnI,CAAC;IACD,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC;IAClH,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO,IAAI,WAAW,EAAE,CAAC;QACxF,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,CAAC;QACR,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE;QAC/G,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;KAClJ,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAA6E,EAC7G,KAAiC;IAEjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC,4BAA4B,EAAE,GAAG,IAAI,CAAC,IAAI,sDAAsD,CAAC,CAAC;IAClH,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACjF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAA0F;IAEtH,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;QACzD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM;QAC1C,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC;QACf,CAAC,CAAC,MAAM,CAAC,qCAAqC,EAAE,GAAG,IAAI,CAAC,IAAI,8CAA8C,CAAC,CAAC;AAChH,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { IdGenerator, LabelId } from '@aeolus-fleet/common';
|
|
2
|
+
import type { Caller } from '../shared/caller.js';
|
|
3
|
+
import type { Clock } from '../shared/clock.js';
|
|
4
|
+
import { type EventLog } from '../shared/events.js';
|
|
5
|
+
import { type Result } from '../shared/result.js';
|
|
6
|
+
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
7
|
+
import { type DefineLabelRefusal, type LabelValue } from './label.js';
|
|
8
|
+
import type { LabelRepository, ShipRepository } from './ports.js';
|
|
9
|
+
export interface DefineLabelTx {
|
|
10
|
+
ships: Pick<ShipRepository, 'find'>;
|
|
11
|
+
labels: Pick<LabelRepository, 'lockKey' | 'findByKey' | 'save'>;
|
|
12
|
+
events: EventLog;
|
|
13
|
+
}
|
|
14
|
+
/** The new label's id, and its values with their ids. */
|
|
15
|
+
export interface DefinedLabel {
|
|
16
|
+
labelId: LabelId;
|
|
17
|
+
values: readonly LabelValue[];
|
|
18
|
+
}
|
|
19
|
+
export type DefineLabel = (caller: Caller, input: {
|
|
20
|
+
key: string;
|
|
21
|
+
values: readonly string[];
|
|
22
|
+
}) => Promise<Result<DefinedLabel, DefineLabelRefusal>>;
|
|
23
|
+
/**
|
|
24
|
+
* Use case: the caller's ship defines a label it then owns (decision 0031).
|
|
25
|
+
* Its scope (labels:define) is checked before this runs. In one unit of work,
|
|
26
|
+
* holding the key's lock so two definitions of one key never both find it
|
|
27
|
+
* free: the label, a new id for it and each of its values, and LabelDefined.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createDefineLabel(deps: {
|
|
30
|
+
uow: UnitOfWork<DefineLabelTx>;
|
|
31
|
+
clock: Clock;
|
|
32
|
+
ids: IdGenerator;
|
|
33
|
+
}): DefineLabel;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { recordEvent, shipActor } from '../shared/events.js';
|
|
2
|
+
import { ok } from '../shared/result.js';
|
|
3
|
+
import { defineLabel } from './label.js';
|
|
4
|
+
/**
|
|
5
|
+
* Use case: the caller's ship defines a label it then owns (decision 0031).
|
|
6
|
+
* Its scope (labels:define) is checked before this runs. In one unit of work,
|
|
7
|
+
* holding the key's lock so two definitions of one key never both find it
|
|
8
|
+
* free: the label, a new id for it and each of its values, and LabelDefined.
|
|
9
|
+
*/
|
|
10
|
+
export function createDefineLabel(deps) {
|
|
11
|
+
return (caller, input) => deps.uow.run(async (tx) => {
|
|
12
|
+
const { fleetId } = caller;
|
|
13
|
+
await tx.labels.lockKey(fleetId, input.key);
|
|
14
|
+
const label = await tx.labels.findByKey(fleetId, input.key);
|
|
15
|
+
const owner = label && (await tx.ships.find(fleetId, label.ownerShipId));
|
|
16
|
+
const defined = defineLabel({ owner: { fleetId, id: caller.shipId }, existing: label && { label, ownerName: owner?.name ?? label.ownerShipId } }, {
|
|
17
|
+
id: deps.ids('label'),
|
|
18
|
+
key: input.key,
|
|
19
|
+
values: input.values.map((value) => ({ value, newId: deps.ids('labelValue') })),
|
|
20
|
+
at: deps.clock.now(),
|
|
21
|
+
actor: shipActor(caller.shipId),
|
|
22
|
+
});
|
|
23
|
+
if (!defined.isOk) {
|
|
24
|
+
return defined;
|
|
25
|
+
}
|
|
26
|
+
await tx.labels.save(defined.value.label);
|
|
27
|
+
for (const event of defined.value.events) {
|
|
28
|
+
await recordEvent({ events: tx.events, ids: deps.ids }, event);
|
|
29
|
+
}
|
|
30
|
+
return ok({ labelId: defined.value.label.id, values: defined.value.label.values });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=define-label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-label.js","sourceRoot":"","sources":["../../../src/domain/registry/define-label.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAA4C,MAAM,YAAY,CAAC;AAiBnF;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAwE;IACxG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAqD,EAAE;QAC3E,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,WAAW,CACzB,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,EACpH;YACE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;YACrB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC/E,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;SAChC,CACF,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACzC,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { IdGenerator, LabelId } from '@aeolus-fleet/common';
|
|
2
|
+
import type { Caller } from '../shared/caller.js';
|
|
3
|
+
import type { Clock } from '../shared/clock.js';
|
|
4
|
+
import { type DomainError } from '../shared/errors.js';
|
|
5
|
+
import { type EventLog } from '../shared/events.js';
|
|
6
|
+
import { type Result } from '../shared/result.js';
|
|
7
|
+
import type { UnitOfWork } from '../shared/unit-of-work.js';
|
|
8
|
+
import { type DeleteLabelRefusal } from './label.js';
|
|
9
|
+
import type { LabelRepository, ShipRepository } from './ports.js';
|
|
10
|
+
export interface DeleteLabelTx {
|
|
11
|
+
ships: Pick<ShipRepository, 'find'>;
|
|
12
|
+
labels: Pick<LabelRepository, 'findForUpdate' | 'carriersOf' | 'remove'>;
|
|
13
|
+
events: EventLog;
|
|
14
|
+
}
|
|
15
|
+
export type DeleteLabelFailure = DomainError<'LABEL_NOT_FOUND'> | DeleteLabelRefusal;
|
|
16
|
+
export type DeleteLabel = (caller: Caller, input: {
|
|
17
|
+
labelId: LabelId;
|
|
18
|
+
}) => Promise<Result<undefined, DeleteLabelFailure>>;
|
|
19
|
+
/**
|
|
20
|
+
* Use case: a label's owner deletes it, freeing its key (decision 0031). Its
|
|
21
|
+
* scope (labels:define) is checked before this runs. In one unit of work,
|
|
22
|
+
* locking the label first, as a change of values does, so an assignment
|
|
23
|
+
* either comes before and is seen here, or waits and finds the label gone:
|
|
24
|
+
* the label goes with its values, with LabelDeleted.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createDeleteLabel(deps: {
|
|
27
|
+
uow: UnitOfWork<DeleteLabelTx>;
|
|
28
|
+
clock: Clock;
|
|
29
|
+
ids: IdGenerator;
|
|
30
|
+
}): DeleteLabel;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { refuse } from '../shared/errors.js';
|
|
2
|
+
import { recordEvent, shipActor } from '../shared/events.js';
|
|
3
|
+
import { ok } from '../shared/result.js';
|
|
4
|
+
import { deleteLabel } from './label.js';
|
|
5
|
+
/**
|
|
6
|
+
* Use case: a label's owner deletes it, freeing its key (decision 0031). Its
|
|
7
|
+
* scope (labels:define) is checked before this runs. In one unit of work,
|
|
8
|
+
* locking the label first, as a change of values does, so an assignment
|
|
9
|
+
* either comes before and is seen here, or waits and finds the label gone:
|
|
10
|
+
* the label goes with its values, with LabelDeleted.
|
|
11
|
+
*/
|
|
12
|
+
export function createDeleteLabel(deps) {
|
|
13
|
+
return (caller, input) => deps.uow.run(async (tx) => {
|
|
14
|
+
const { fleetId } = caller;
|
|
15
|
+
const label = await tx.labels.findForUpdate(fleetId, input.labelId);
|
|
16
|
+
if (!label) {
|
|
17
|
+
return refuse('LABEL_NOT_FOUND', `The fleet has no label ${input.labelId}`);
|
|
18
|
+
}
|
|
19
|
+
const nameOf = async (shipId) => (await tx.ships.find(fleetId, shipId))?.name ?? shipId;
|
|
20
|
+
const carrierNames = await Promise.all((await tx.labels.carriersOf(fleetId, label.id)).map((carried) => nameOf(carried.shipId)));
|
|
21
|
+
const deleted = deleteLabel({ label, ownerName: await nameOf(label.ownerShipId), carrierNames }, { callerShipId: caller.shipId, at: deps.clock.now(), actor: shipActor(caller.shipId) });
|
|
22
|
+
if (!deleted.isOk) {
|
|
23
|
+
return deleted;
|
|
24
|
+
}
|
|
25
|
+
await tx.labels.remove(fleetId, label.id);
|
|
26
|
+
for (const event of deleted.value.events) {
|
|
27
|
+
await recordEvent({ events: tx.events, ids: deps.ids }, event);
|
|
28
|
+
}
|
|
29
|
+
return ok(undefined);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=delete-label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-label.js","sourceRoot":"","sources":["../../../src/domain/registry/delete-label.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAA2B,MAAM,YAAY,CAAC;AAalE;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAwE;IACxG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAkD,EAAE;QACxE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACpE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,MAAM,CAAC,iBAAiB,EAAE,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,EAAE,MAAwB,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,IAAI,MAAM,CAAC;QAC1G,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjI,MAAM,OAAO,GAAG,WAAW,CACzB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,YAAY,EAAE,EACnE,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CACvF,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACzC,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { LabelId, LabelValueId } from '@aeolus-fleet/common';
|
|
2
|
+
import type { Caller } from '../shared/caller.js';
|
|
3
|
+
import { type DomainError } from '../shared/errors.js';
|
|
4
|
+
import { type Result } from '../shared/result.js';
|
|
5
|
+
import type { FleetListing } from './ports.js';
|
|
6
|
+
export type FindLabelValue = (caller: Caller, input: {
|
|
7
|
+
key: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}) => Promise<Result<{
|
|
10
|
+
labelId: LabelId;
|
|
11
|
+
valueId: LabelValueId;
|
|
12
|
+
}, DomainError<'LABEL_VALUE_NOT_FOUND'>>>;
|
|
13
|
+
/**
|
|
14
|
+
* Use case: the ids of a label and one of its values, by the texts people
|
|
15
|
+
* write, so a caller that knows `os=macos` can assign and select by id
|
|
16
|
+
* (decision 0031). Keys and values are lowercase, so both texts are
|
|
17
|
+
* lowercased, then matched exactly. The caller's scope (fleet:read) is
|
|
18
|
+
* checked before this runs.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createFindLabelValue(deps: {
|
|
21
|
+
listing: Pick<FleetListing, 'labels'>;
|
|
22
|
+
}): FindLabelValue;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { refuse } from '../shared/errors.js';
|
|
2
|
+
import { ok } from '../shared/result.js';
|
|
3
|
+
/**
|
|
4
|
+
* Use case: the ids of a label and one of its values, by the texts people
|
|
5
|
+
* write, so a caller that knows `os=macos` can assign and select by id
|
|
6
|
+
* (decision 0031). Keys and values are lowercase, so both texts are
|
|
7
|
+
* lowercased, then matched exactly. The caller's scope (fleet:read) is
|
|
8
|
+
* checked before this runs.
|
|
9
|
+
*/
|
|
10
|
+
export function createFindLabelValue(deps) {
|
|
11
|
+
return async (caller, input) => {
|
|
12
|
+
const key = input.key.toLowerCase();
|
|
13
|
+
const value = input.value.toLowerCase();
|
|
14
|
+
const label = (await deps.listing.labels(caller.fleetId)).find((listed) => listed.key === key);
|
|
15
|
+
const found = label?.values.find((held) => held.value === value);
|
|
16
|
+
return label && found ? ok({ labelId: label.id, valueId: found.id }) : refuse('LABEL_VALUE_NOT_FOUND', `The fleet has no label value ${input.key}=${input.value}`);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=find-label-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-label-value.js","sourceRoot":"","sources":["../../../src/domain/registry/find-label-value.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAoB,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,EAAE,EAAe,MAAM,qBAAqB,CAAC;AAQtD;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAA+C;IAClF,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC/F,MAAM,KAAK,GAAG,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACjE,OAAO,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,uBAAuB,EAAE,gCAAgC,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACrK,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { type FleetId, type LabelId, type LabelValueId, type ShipId } from '@aeolus-fleet/common';
|
|
2
|
+
import { type DomainError } from '../shared/errors.js';
|
|
3
|
+
import type { Actor, NewEvent } from '../shared/events.js';
|
|
4
|
+
import { type Result } from '../shared/result.js';
|
|
5
|
+
import type { Ship } from './ship.js';
|
|
6
|
+
/** One value of a label: its own id, and its text for people. */
|
|
7
|
+
export interface LabelValue {
|
|
8
|
+
id: LabelValueId;
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A label (docs/blueprint.md, "Label"; decision 0031): a key with a defined
|
|
13
|
+
* set of values, each with its own id, owned by the ship that defined it.
|
|
14
|
+
* Ids are for machines, key and value texts for people. Only its owner
|
|
15
|
+
* changes its values and assigns them, never to itself. It retires with its
|
|
16
|
+
* owner.
|
|
17
|
+
*/
|
|
18
|
+
export interface Label {
|
|
19
|
+
fleetId: FleetId;
|
|
20
|
+
id: LabelId;
|
|
21
|
+
/** Unique among the fleet's labels. */
|
|
22
|
+
key: string;
|
|
23
|
+
/** In the order the owner gave them, each once. */
|
|
24
|
+
values: readonly LabelValue[];
|
|
25
|
+
ownerShipId: ShipId;
|
|
26
|
+
}
|
|
27
|
+
/** A label as the fleet lists it: its id, key and values, and its owner by id and name. */
|
|
28
|
+
export interface ListedLabel {
|
|
29
|
+
id: LabelId;
|
|
30
|
+
key: string;
|
|
31
|
+
values: readonly LabelValue[];
|
|
32
|
+
owner: {
|
|
33
|
+
id: ShipId;
|
|
34
|
+
name: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** One value a ship carries, with its label: ids and texts. */
|
|
38
|
+
export interface CarriedLabel {
|
|
39
|
+
labelId: LabelId;
|
|
40
|
+
key: string;
|
|
41
|
+
valueId: LabelValueId;
|
|
42
|
+
value: string;
|
|
43
|
+
}
|
|
44
|
+
/** One value a ship carries. A ship holds a set of values, of one label or several. */
|
|
45
|
+
export interface ShipLabel {
|
|
46
|
+
fleetId: FleetId;
|
|
47
|
+
shipId: ShipId;
|
|
48
|
+
labelId: LabelId;
|
|
49
|
+
valueId: LabelValueId;
|
|
50
|
+
}
|
|
51
|
+
/** A value text as a definition or a change gives it, with the id it gets if the label does not have it yet. */
|
|
52
|
+
export interface NewLabelValue {
|
|
53
|
+
value: string;
|
|
54
|
+
newId: LabelValueId;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Whether a ship carries every value of the selector: exact matches by id,
|
|
58
|
+
* combined with AND (decision 0031). No selector, or an empty one, selects
|
|
59
|
+
* every ship.
|
|
60
|
+
*/
|
|
61
|
+
export declare function carriesEvery(carried: readonly CarriedLabel[], valueIds: readonly LabelValueId[] | undefined): boolean;
|
|
62
|
+
type InvalidKey = DomainError<'INVALID_LABEL_KEY'>;
|
|
63
|
+
type InvalidValue = DomainError<'INVALID_LABEL_VALUE'>;
|
|
64
|
+
type InvalidValues = DomainError<'INVALID_LABEL_VALUES'>;
|
|
65
|
+
/** A label's key, checked against the limits. */
|
|
66
|
+
export declare function labelKey(key: string): Result<string, InvalidKey>;
|
|
67
|
+
export type DefineLabelRefusal = InvalidKey | InvalidValue | InvalidValues | DomainError<'LABEL_KEY_TAKEN'>;
|
|
68
|
+
/**
|
|
69
|
+
* A ship defines a label, owning it: a key unique in the fleet and its values,
|
|
70
|
+
* the label and each value with its new id. A key the fleet has is refused,
|
|
71
|
+
* naming its owner. LabelDefined names the owner, with the label and its
|
|
72
|
+
* values.
|
|
73
|
+
*/
|
|
74
|
+
export declare function defineLabel({ owner, existing, }: {
|
|
75
|
+
owner: Pick<Ship, 'fleetId' | 'id'>;
|
|
76
|
+
existing: {
|
|
77
|
+
label: Label;
|
|
78
|
+
ownerName: string;
|
|
79
|
+
} | undefined;
|
|
80
|
+
}, input: {
|
|
81
|
+
id: LabelId;
|
|
82
|
+
key: string;
|
|
83
|
+
values: readonly NewLabelValue[];
|
|
84
|
+
at: Date;
|
|
85
|
+
actor: Actor;
|
|
86
|
+
}): Result<{
|
|
87
|
+
label: Label;
|
|
88
|
+
events: NewEvent[];
|
|
89
|
+
}, DefineLabelRefusal>;
|
|
90
|
+
type NotTheOwner = DomainError<'NOT_THE_LABEL_OWNER'>;
|
|
91
|
+
export type ChangeLabelValuesRefusal = NotTheOwner | InvalidValue | InvalidValues | DomainError<'LABEL_VALUE_CARRIED'>;
|
|
92
|
+
/**
|
|
93
|
+
* The owner gives its label the values it has from now on, adding and
|
|
94
|
+
* removing at once: a value it has keeps its id, a new one gets its new id.
|
|
95
|
+
* A value ships carry is never removed: the refusal names them. The values
|
|
96
|
+
* it has already, in any order, change nothing.
|
|
97
|
+
*/
|
|
98
|
+
export declare function changeLabelValues({ label, ownerName, carriers, }: {
|
|
99
|
+
label: Label;
|
|
100
|
+
ownerName: string;
|
|
101
|
+
carriers: readonly {
|
|
102
|
+
valueId: LabelValueId;
|
|
103
|
+
shipName: string;
|
|
104
|
+
}[];
|
|
105
|
+
}, input: {
|
|
106
|
+
callerShipId: ShipId;
|
|
107
|
+
values: readonly NewLabelValue[];
|
|
108
|
+
at: Date;
|
|
109
|
+
actor: Actor;
|
|
110
|
+
}): Result<{
|
|
111
|
+
label: Label;
|
|
112
|
+
events: NewEvent[];
|
|
113
|
+
}, ChangeLabelValuesRefusal>;
|
|
114
|
+
export type DeleteLabelRefusal = NotTheOwner | DomainError<'LABEL_CARRIED'>;
|
|
115
|
+
/**
|
|
116
|
+
* The owner deletes its label with its values, freeing its key. A label any
|
|
117
|
+
* ship carries a value of is never deleted: the refusal names the ships.
|
|
118
|
+
* LabelDeleted names the owner, with the label.
|
|
119
|
+
*/
|
|
120
|
+
export declare function deleteLabel({ label, ownerName, carrierNames }: {
|
|
121
|
+
label: Label;
|
|
122
|
+
ownerName: string;
|
|
123
|
+
carrierNames: readonly string[];
|
|
124
|
+
}, input: {
|
|
125
|
+
callerShipId: ShipId;
|
|
126
|
+
at: Date;
|
|
127
|
+
actor: Actor;
|
|
128
|
+
}): Result<{
|
|
129
|
+
events: NewEvent[];
|
|
130
|
+
}, DeleteLabelRefusal>;
|
|
131
|
+
type OwnShip = DomainError<'LABEL_ON_OWN_SHIP'>;
|
|
132
|
+
export type AssignLabelRefusal = NotTheOwner | OwnShip | DomainError<'SHIP_ALREADY_RETIRED' | 'SHIP_LABEL_LIMIT_REACHED'>;
|
|
133
|
+
/**
|
|
134
|
+
* The owner gives a ship one of its label's values, by its id: the ship
|
|
135
|
+
* holds a set of values, so it may carry several of one label. A value it
|
|
136
|
+
* carries changes nothing. Never the owner's own ship or a retired ship;
|
|
137
|
+
* argo and the viewer ship as any other (decision 0016). A ship carries at
|
|
138
|
+
* most 20 values. LabelAssigned names the ship, with the label and the value.
|
|
139
|
+
*/
|
|
140
|
+
export declare function assignLabel({ label, ownerName, ship, carried, }: {
|
|
141
|
+
label: Label;
|
|
142
|
+
ownerName: string;
|
|
143
|
+
ship: Ship;
|
|
144
|
+
carried: readonly ShipLabel[];
|
|
145
|
+
}, input: {
|
|
146
|
+
callerShipId: ShipId;
|
|
147
|
+
valueId: LabelValueId;
|
|
148
|
+
at: Date;
|
|
149
|
+
actor: Actor;
|
|
150
|
+
}): Result<{
|
|
151
|
+
assignment: ShipLabel | undefined;
|
|
152
|
+
events: NewEvent[];
|
|
153
|
+
}, AssignLabelRefusal>;
|
|
154
|
+
export type UnassignLabelRefusal = NotTheOwner | OwnShip;
|
|
155
|
+
/**
|
|
156
|
+
* The owner takes one value of its label off a ship. A ship that does not
|
|
157
|
+
* carry it changes nothing. LabelUnassigned names the ship, with the label
|
|
158
|
+
* and the value it carried.
|
|
159
|
+
*/
|
|
160
|
+
export declare function unassignLabel({ label, ownerName, ship, carried, }: {
|
|
161
|
+
label: Label;
|
|
162
|
+
ownerName: string;
|
|
163
|
+
ship: Ship;
|
|
164
|
+
carried: readonly ShipLabel[];
|
|
165
|
+
}, input: {
|
|
166
|
+
callerShipId: ShipId;
|
|
167
|
+
valueId: LabelValueId;
|
|
168
|
+
at: Date;
|
|
169
|
+
actor: Actor;
|
|
170
|
+
}): Result<{
|
|
171
|
+
unassigned: ShipLabel | undefined;
|
|
172
|
+
events: NewEvent[];
|
|
173
|
+
}, UnassignLabelRefusal>;
|
|
174
|
+
/**
|
|
175
|
+
* A ship is retired: the labels it owns retire with it (their meaning
|
|
176
|
+
* retires with their owner), each after every assignment of it goes, and
|
|
177
|
+
* the values it carries go. LabelUnassigned for every assignment that goes,
|
|
178
|
+
* LabelRetired for every label.
|
|
179
|
+
*/
|
|
180
|
+
export declare function retireLabelsWith({ owned, carried, }: {
|
|
181
|
+
owned: readonly {
|
|
182
|
+
label: Label;
|
|
183
|
+
carriers: readonly ShipLabel[];
|
|
184
|
+
}[];
|
|
185
|
+
carried: readonly {
|
|
186
|
+
label: Label;
|
|
187
|
+
assignment: ShipLabel;
|
|
188
|
+
}[];
|
|
189
|
+
}, input: {
|
|
190
|
+
at: Date;
|
|
191
|
+
actor: Actor;
|
|
192
|
+
}): {
|
|
193
|
+
unassigned: ShipLabel[];
|
|
194
|
+
retired: Label[];
|
|
195
|
+
events: NewEvent[];
|
|
196
|
+
};
|
|
197
|
+
export {};
|