@owlmeans/server-planning 0.1.18-rc.9 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -19
- package/agent-meta/manifest.json +105 -4
- package/agent-meta/skills/server-planning/SKILL.md +89 -138
- package/agent-meta/skills/server-planning/parts/auxiliary.md +54 -0
- package/agent-meta/skills/server-planning/parts/executor.md +82 -0
- package/agent-meta/skills/server-planning/parts/schemas.md +26 -0
- package/agent-meta/skills/server-planning/parts/serving.md +88 -0
- package/agent-meta/skills/server-planning/parts/stores.md +91 -0
- package/build/actions/apply-schema-request.d.ts +8 -0
- package/build/actions/apply-schema-request.d.ts.map +1 -0
- package/build/actions/apply-schema-request.js +33 -0
- package/build/actions/apply-schema-request.js.map +1 -0
- package/build/actions/commit.d.ts +3 -3
- package/build/actions/commit.d.ts.map +1 -1
- package/build/actions/commit.js +5 -4
- package/build/actions/commit.js.map +1 -1
- package/build/actions/define-schemas.d.ts +13 -0
- package/build/actions/define-schemas.d.ts.map +1 -0
- package/build/actions/define-schemas.js +28 -0
- package/build/actions/define-schemas.js.map +1 -0
- package/build/actions/execute.d.ts +11 -10
- package/build/actions/execute.d.ts.map +1 -1
- package/build/actions/execute.js +17 -27
- package/build/actions/execute.js.map +1 -1
- package/build/actions/execution/types.d.ts +34 -0
- package/build/actions/execution/types.d.ts.map +1 -0
- package/build/actions/execution/types.js +2 -0
- package/build/actions/execution/types.js.map +1 -0
- package/build/actions/execution.d.ts +4 -0
- package/build/actions/execution.d.ts.map +1 -0
- package/build/actions/execution.js +88 -0
- package/build/actions/execution.js.map +1 -0
- package/build/actions/get-card.d.ts +6 -0
- package/build/actions/get-card.d.ts.map +1 -0
- package/build/actions/get-card.js +9 -0
- package/build/actions/get-card.js.map +1 -0
- package/build/actions/get-specification.d.ts +6 -0
- package/build/actions/get-specification.d.ts.map +1 -0
- package/build/actions/get-specification.js +9 -0
- package/build/actions/get-specification.js.map +1 -0
- package/build/actions/index.d.ts +12 -3
- package/build/actions/index.d.ts.map +1 -1
- package/build/actions/index.js +11 -3
- package/build/actions/index.js.map +1 -1
- package/build/actions/links.d.ts +3 -3
- package/build/actions/links.d.ts.map +1 -1
- package/build/actions/links.js +6 -5
- package/build/actions/links.js.map +1 -1
- package/build/actions/list-card-specifications.d.ts +6 -0
- package/build/actions/list-card-specifications.d.ts.map +1 -0
- package/build/actions/list-card-specifications.js +11 -0
- package/build/actions/list-card-specifications.js.map +1 -0
- package/build/actions/list-card-transitions.d.ts +6 -0
- package/build/actions/list-card-transitions.d.ts.map +1 -0
- package/build/actions/list-card-transitions.js +11 -0
- package/build/actions/list-card-transitions.js.map +1 -0
- package/build/actions/list-cards.d.ts +6 -0
- package/build/actions/list-cards.d.ts.map +1 -0
- package/build/actions/list-cards.js +10 -0
- package/build/actions/list-cards.js.map +1 -0
- package/build/actions/list-schemas.d.ts +13 -0
- package/build/actions/list-schemas.d.ts.map +1 -0
- package/build/actions/list-schemas.js +20 -0
- package/build/actions/list-schemas.js.map +1 -0
- package/build/actions/list-specification-revisions.d.ts +6 -0
- package/build/actions/list-specification-revisions.d.ts.map +1 -0
- package/build/actions/list-specification-revisions.js +10 -0
- package/build/actions/list-specification-revisions.js.map +1 -0
- package/build/actions/resources.d.ts +5 -0
- package/build/actions/resources.d.ts.map +1 -0
- package/build/actions/resources.js +111 -0
- package/build/actions/resources.js.map +1 -0
- package/build/actions/summarize-cards.d.ts +6 -0
- package/build/actions/summarize-cards.d.ts.map +1 -0
- package/build/actions/summarize-cards.js +11 -0
- package/build/actions/summarize-cards.js.map +1 -0
- package/build/actions/transitions.d.ts +3 -3
- package/build/actions/transitions.d.ts.map +1 -1
- package/build/actions/transitions.js +4 -3
- package/build/actions/transitions.js.map +1 -1
- package/build/actions/types.d.ts +6 -0
- package/build/actions/types.d.ts.map +1 -0
- package/build/actions/types.js +2 -0
- package/build/actions/types.js.map +1 -0
- package/build/actions/watch.d.ts +2 -2
- package/build/actions/watch.d.ts.map +1 -1
- package/build/actions/watch.js +8 -6
- package/build/actions/watch.js.map +1 -1
- package/build/conformance/assert/types.d.ts +19 -0
- package/build/conformance/assert/types.d.ts.map +1 -0
- package/build/conformance/assert/types.js +2 -0
- package/build/conformance/assert/types.js.map +1 -0
- package/build/conformance/assert.d.ts +15 -0
- package/build/conformance/assert.d.ts.map +1 -0
- package/build/conformance/assert.js +52 -0
- package/build/conformance/assert.js.map +1 -0
- package/build/conformance/cases.d.ts +7 -0
- package/build/conformance/cases.d.ts.map +1 -0
- package/build/conformance/cases.js +544 -0
- package/build/conformance/cases.js.map +1 -0
- package/build/conformance/clock.d.ts +6 -0
- package/build/conformance/clock.d.ts.map +1 -0
- package/build/conformance/clock.js +12 -0
- package/build/conformance/clock.js.map +1 -0
- package/build/conformance/consts.d.ts +30 -0
- package/build/conformance/consts.d.ts.map +1 -0
- package/build/conformance/consts.js +159 -0
- package/build/conformance/consts.js.map +1 -0
- package/build/conformance/errors.d.ts +5 -0
- package/build/conformance/errors.d.ts.map +1 -0
- package/build/conformance/errors.js +8 -0
- package/build/conformance/errors.js.map +1 -0
- package/build/conformance/fixtures/types.d.ts +13 -0
- package/build/conformance/fixtures/types.d.ts.map +1 -0
- package/build/conformance/fixtures/types.js +2 -0
- package/build/conformance/fixtures/types.js.map +1 -0
- package/build/conformance/fixtures.d.ts +14 -0
- package/build/conformance/fixtures.d.ts.map +1 -0
- package/build/conformance/fixtures.js +26 -0
- package/build/conformance/fixtures.js.map +1 -0
- package/build/conformance/index.d.ts +15 -0
- package/build/conformance/index.d.ts.map +1 -0
- package/build/conformance/index.js +12 -0
- package/build/conformance/index.js.map +1 -0
- package/build/conformance/resources.d.ts +4 -0
- package/build/conformance/resources.d.ts.map +1 -0
- package/build/conformance/resources.js +228 -0
- package/build/conformance/resources.js.map +1 -0
- package/build/conformance/types.d.ts +18 -0
- package/build/conformance/types.d.ts.map +1 -0
- package/build/conformance/types.js +2 -0
- package/build/conformance/types.js.map +1 -0
- package/build/consts.d.ts +5 -0
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +5 -0
- package/build/consts.js.map +1 -1
- package/build/definitions.d.ts +18 -0
- package/build/definitions.d.ts.map +1 -0
- package/build/definitions.js +225 -0
- package/build/definitions.js.map +1 -0
- package/build/executor/changes/types.d.ts +36 -0
- package/build/executor/changes/types.d.ts.map +1 -0
- package/build/executor/changes/types.js +2 -0
- package/build/executor/changes/types.js.map +1 -0
- package/build/executor/changes.d.ts +3 -30
- package/build/executor/changes.d.ts.map +1 -1
- package/build/executor/changes.js +42 -51
- package/build/executor/changes.js.map +1 -1
- package/build/executor/code/types.d.ts +17 -0
- package/build/executor/code/types.d.ts.map +1 -0
- package/build/executor/code/types.js +2 -0
- package/build/executor/code/types.js.map +1 -0
- package/build/executor/code.d.ts +3 -14
- package/build/executor/code.d.ts.map +1 -1
- package/build/executor/code.js +50 -54
- package/build/executor/code.js.map +1 -1
- package/build/executor/consts.local.d.ts +5 -0
- package/build/executor/consts.local.d.ts.map +1 -0
- package/build/executor/consts.local.js +6 -0
- package/build/executor/consts.local.js.map +1 -0
- package/build/executor/creator/types.d.ts +33 -0
- package/build/executor/creator/types.d.ts.map +1 -0
- package/build/executor/creator/types.js +2 -0
- package/build/executor/creator/types.js.map +1 -0
- package/build/executor/creator.d.ts +11 -0
- package/build/executor/creator.d.ts.map +1 -0
- package/build/executor/creator.js +32 -0
- package/build/executor/creator.js.map +1 -0
- package/build/executor/resolve/types.d.ts +30 -0
- package/build/executor/resolve/types.d.ts.map +1 -0
- package/build/executor/resolve/types.js +2 -0
- package/build/executor/resolve/types.js.map +1 -0
- package/build/executor/resolve.d.ts +5 -34
- package/build/executor/resolve.d.ts.map +1 -1
- package/build/executor/resolve.js +169 -110
- package/build/executor/resolve.js.map +1 -1
- package/build/executor/types.d.ts +23 -0
- package/build/executor/types.d.ts.map +1 -0
- package/build/executor/types.js +2 -0
- package/build/executor/types.js.map +1 -0
- package/build/executor/validate.d.ts +6 -5
- package/build/executor/validate.d.ts.map +1 -1
- package/build/executor/validate.js +38 -27
- package/build/executor/validate.js.map +1 -1
- package/build/executor.d.ts +11 -7
- package/build/executor.d.ts.map +1 -1
- package/build/executor.js +27 -21
- package/build/executor.js.map +1 -1
- package/build/facade.d.ts +20 -2
- package/build/facade.d.ts.map +1 -1
- package/build/facade.js +144 -22
- package/build/facade.js.map +1 -1
- package/build/helper.d.ts +5 -9
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +12 -11
- package/build/helper.js.map +1 -1
- package/build/hierarchy/types.d.ts +20 -0
- package/build/hierarchy/types.d.ts.map +1 -0
- package/build/hierarchy/types.js +2 -0
- package/build/hierarchy/types.js.map +1 -0
- package/build/hierarchy.d.ts +5 -0
- package/build/hierarchy.d.ts.map +1 -0
- package/build/hierarchy.js +133 -0
- package/build/hierarchy.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/invariants/types.d.ts +6 -0
- package/build/invariants/types.d.ts.map +1 -0
- package/build/invariants/types.js +2 -0
- package/build/invariants/types.js.map +1 -0
- package/build/invariants.d.ts +5 -0
- package/build/invariants.d.ts.map +1 -0
- package/build/invariants.js +126 -0
- package/build/invariants.js.map +1 -0
- package/build/projection.d.ts +4 -10
- package/build/projection.d.ts.map +1 -1
- package/build/projection.js +7 -5
- package/build/projection.js.map +1 -1
- package/build/queue/consts.d.ts +5 -0
- package/build/queue/consts.d.ts.map +1 -0
- package/build/queue/consts.js +5 -0
- package/build/queue/consts.js.map +1 -0
- package/build/queue/declare.d.ts +5 -0
- package/build/queue/declare.d.ts.map +1 -0
- package/build/queue/declare.js +5 -0
- package/build/queue/declare.js.map +1 -0
- package/build/queue/index.d.ts +3 -18
- package/build/queue/index.d.ts.map +1 -1
- package/build/queue/index.js +2 -7
- package/build/queue/index.js.map +1 -1
- package/build/queue/types.d.ts +13 -0
- package/build/queue/types.d.ts.map +1 -0
- package/build/queue/types.js +2 -0
- package/build/queue/types.js.map +1 -0
- package/build/registry.d.ts +5 -22
- package/build/registry.d.ts.map +1 -1
- package/build/registry.js +16 -10
- package/build/registry.js.map +1 -1
- package/build/resources.d.ts +5 -0
- package/build/resources.d.ts.map +1 -0
- package/build/resources.js +287 -0
- package/build/resources.js.map +1 -0
- package/build/service.d.ts +3 -16
- package/build/service.d.ts.map +1 -1
- package/build/service.js +12 -0
- package/build/service.js.map +1 -1
- package/build/store/commits.d.ts.map +1 -1
- package/build/store/commits.js +3 -1
- package/build/store/commits.js.map +1 -1
- package/build/store/composite.d.ts +1 -0
- package/build/store/composite.d.ts.map +1 -1
- package/build/store/composite.js +7 -2
- package/build/store/composite.js.map +1 -1
- package/build/store/consts.local.d.ts +2 -0
- package/build/store/consts.local.d.ts.map +1 -0
- package/build/store/consts.local.js +2 -0
- package/build/store/consts.local.js.map +1 -0
- package/build/store/fold/types.d.ts +43 -0
- package/build/store/fold/types.d.ts.map +1 -0
- package/build/store/fold/types.js +2 -0
- package/build/store/fold/types.js.map +1 -0
- package/build/store/fold.d.ts +8 -30
- package/build/store/fold.d.ts.map +1 -1
- package/build/store/fold.js +190 -198
- package/build/store/fold.js.map +1 -1
- package/build/store/index.d.ts +1 -0
- package/build/store/index.d.ts.map +1 -1
- package/build/store/index.js.map +1 -1
- package/build/store/memory.d.ts +12 -0
- package/build/store/memory.d.ts.map +1 -1
- package/build/store/memory.js +0 -0
- package/build/store/memory.js.map +1 -1
- package/build/store/types.d.ts +15 -1
- package/build/store/types.d.ts.map +1 -1
- package/build/store/types.local.d.ts +5 -0
- package/build/store/types.local.d.ts.map +1 -0
- package/build/store/types.local.js +2 -0
- package/build/store/types.local.js.map +1 -0
- package/build/types.d.ts +126 -2
- package/build/types.d.ts.map +1 -1
- package/build/types.local.d.ts +7 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/build/utils/access/types.d.ts +30 -0
- package/build/utils/access/types.d.ts.map +1 -0
- package/build/utils/access/types.js +2 -0
- package/build/utils/access/types.js.map +1 -0
- package/build/utils/access.d.ts +4 -0
- package/build/utils/access.d.ts.map +1 -0
- package/build/utils/access.js +28 -0
- package/build/utils/access.js.map +1 -0
- package/build/utils/guard/types.d.ts +23 -0
- package/build/utils/guard/types.d.ts.map +1 -0
- package/build/utils/guard/types.js +2 -0
- package/build/utils/guard/types.js.map +1 -0
- package/build/utils/guard.d.ts +7 -10
- package/build/utils/guard.d.ts.map +1 -1
- package/build/utils/guard.js +36 -32
- package/build/utils/guard.js.map +1 -1
- package/build/utils/handler/types.d.ts +26 -0
- package/build/utils/handler/types.d.ts.map +1 -0
- package/build/utils/handler/types.js +2 -0
- package/build/utils/handler/types.js.map +1 -0
- package/build/utils/handler.d.ts +6 -0
- package/build/utils/handler.d.ts.map +1 -0
- package/build/utils/handler.js +21 -0
- package/build/utils/handler.js.map +1 -0
- package/build/utils/index.d.ts +8 -0
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +3 -0
- package/build/utils/index.js.map +1 -1
- package/build/utils/request/types.d.ts +23 -0
- package/build/utils/request/types.d.ts.map +1 -0
- package/build/utils/request/types.js +2 -0
- package/build/utils/request/types.js.map +1 -0
- package/build/utils/request.d.ts +4 -0
- package/build/utils/request.d.ts.map +1 -0
- package/build/utils/request.js +27 -0
- package/build/utils/request.js.map +1 -0
- package/build/utils/scope.d.ts +17 -13
- package/build/utils/scope.d.ts.map +1 -1
- package/build/utils/scope.js +21 -35
- package/build/utils/scope.js.map +1 -1
- package/build/utils/types.d.ts +8 -0
- package/build/utils/types.d.ts.map +1 -0
- package/build/utils/types.js +2 -0
- package/build/utils/types.js.map +1 -0
- package/package.json +30 -22
- package/src/actions/apply-schema-request.ts +36 -0
- package/src/actions/commit.ts +7 -5
- package/src/actions/define-schemas.ts +34 -0
- package/src/actions/execute.ts +32 -34
- package/src/actions/execution/types.ts +34 -0
- package/src/actions/execution.ts +100 -0
- package/src/actions/get-card.ts +14 -0
- package/src/actions/get-specification.ts +14 -0
- package/src/actions/index.ts +13 -3
- package/src/actions/links.ts +8 -6
- package/src/actions/list-card-specifications.ts +15 -0
- package/src/actions/list-card-transitions.ts +15 -0
- package/src/actions/list-cards.ts +14 -0
- package/src/actions/list-schemas.ts +29 -0
- package/src/actions/list-specification-revisions.ts +15 -0
- package/src/actions/resources.ts +79 -0
- package/src/actions/summarize-cards.ts +15 -0
- package/src/actions/transitions.ts +6 -4
- package/src/actions/types.ts +5 -0
- package/src/actions/watch.ts +11 -7
- package/src/conformance/assert/types.ts +16 -0
- package/src/conformance/assert.ts +67 -0
- package/src/conformance/cases.ts +631 -0
- package/src/conformance/clock.ts +11 -0
- package/src/conformance/consts.ts +165 -0
- package/src/conformance/errors.ts +7 -0
- package/src/conformance/fixtures/types.ts +11 -0
- package/src/conformance/fixtures.ts +46 -0
- package/src/conformance/index.ts +14 -0
- package/src/conformance/resources.ts +227 -0
- package/src/conformance/types.ts +20 -0
- package/src/consts.ts +6 -0
- package/src/definitions.ts +264 -0
- package/src/executor/changes/types.ts +38 -0
- package/src/executor/changes.ts +49 -68
- package/src/executor/code/types.ts +23 -0
- package/src/executor/code.ts +62 -69
- package/src/executor/consts.local.ts +8 -0
- package/src/executor/creator/types.ts +33 -0
- package/src/executor/creator.ts +43 -0
- package/src/executor/resolve/types.ts +30 -0
- package/src/executor/resolve.ts +181 -139
- package/src/executor/types.ts +23 -0
- package/src/executor/validate.ts +40 -38
- package/src/executor.ts +33 -27
- package/src/facade.ts +132 -29
- package/src/helper.ts +12 -11
- package/src/hierarchy/types.ts +20 -0
- package/src/hierarchy.ts +113 -0
- package/src/index.ts +1 -0
- package/src/invariants/types.ts +6 -0
- package/src/invariants.ts +106 -0
- package/src/projection.ts +12 -18
- package/src/queue/consts.ts +5 -0
- package/src/queue/declare.ts +7 -0
- package/src/queue/index.ts +3 -25
- package/src/queue/types.ts +14 -0
- package/src/registry.ts +18 -36
- package/src/resources.ts +256 -0
- package/src/service.ts +16 -20
- package/src/store/commits.ts +5 -4
- package/src/store/composite.ts +7 -2
- package/src/store/consts.local.ts +1 -0
- package/src/store/fold/types.ts +44 -0
- package/src/store/fold.ts +214 -212
- package/src/store/index.ts +1 -0
- package/src/store/memory.ts +0 -0
- package/src/store/types.local.ts +3 -0
- package/src/store/types.ts +16 -1
- package/src/types.local.ts +7 -0
- package/src/types.ts +139 -6
- package/src/utils/access/types.ts +30 -0
- package/src/utils/access.ts +33 -0
- package/src/utils/guard/types.ts +21 -0
- package/src/utils/guard.ts +44 -31
- package/src/utils/handler/types.ts +28 -0
- package/src/utils/handler.ts +35 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/request/types.ts +23 -0
- package/src/utils/request.ts +40 -0
- package/src/utils/scope.ts +39 -42
- package/src/utils/types.ts +8 -0
- package/tests/access.spec.ts +160 -0
- package/tests/app.spec.ts +112 -0
- package/tests/conformance.spec.ts +47 -0
- package/tests/create-example.spec.ts +202 -0
- package/tests/creator.spec.ts +257 -0
- package/tests/entrypoints.spec.ts +5 -0
- package/tests/memory-store.spec.ts +52 -0
- package/tests/narrowing.spec.ts +94 -0
- package/tests/plugins.spec.ts +4 -3
- package/tests/writes.spec.ts +140 -0
- package/build/actions/cards.d.ts +0 -16
- package/build/actions/cards.d.ts.map +0 -1
- package/build/actions/cards.js +0 -32
- package/build/actions/cards.js.map +0 -1
- package/build/actions/schemas.d.ts +0 -6
- package/build/actions/schemas.d.ts.map +0 -1
- package/build/actions/schemas.js +0 -9
- package/build/actions/schemas.js.map +0 -1
- package/build/actions/specs.d.ts +0 -10
- package/build/actions/specs.d.ts.map +0 -1
- package/build/actions/specs.js +0 -14
- package/build/actions/specs.js.map +0 -1
- package/src/actions/cards.ts +0 -52
- package/src/actions/schemas.ts +0 -15
- package/src/actions/specs.ts +0 -23
package/src/store/commits.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
1
|
+
import { logger } from '@owlmeans/log'
|
|
2
|
+
import { CommitFailed, CommitState, CommitTimeout, DEFAULT_COMMIT_TIMEOUT, WorkcardNotFound, type CommitEvent, type CommitFilter, type CommitStatus, type Unsubscribe, type Workcard } from '@owlmeans/planning'
|
|
3
3
|
import { COMMIT_POLL_LADDER, DEFAULT_COMMIT_MEMORY } from '../consts.js'
|
|
4
4
|
import type { CommitHub, CommitHubOptions } from './types.js'
|
|
5
|
+
import type { Listener } from './types.local.js'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
const log = logger('planning:store')
|
|
7
8
|
|
|
8
9
|
const matches = (event: CommitEvent, filter?: CommitFilter): boolean =>
|
|
9
10
|
filter == null || (
|
|
@@ -58,7 +59,7 @@ export const makeCommitHub = (options: CommitHubOptions): CommitHub => {
|
|
|
58
59
|
const results = await Promise.allSettled(targets.map(async entry => await entry.listener(event)))
|
|
59
60
|
results.forEach(result => {
|
|
60
61
|
if (result.status === 'rejected') {
|
|
61
|
-
|
|
62
|
+
log.error('Planning commit listener failed', { transition: event.transition, error: result.reason })
|
|
62
63
|
}
|
|
63
64
|
})
|
|
64
65
|
},
|
package/src/store/composite.ts
CHANGED
|
@@ -3,9 +3,9 @@ import type {
|
|
|
3
3
|
CommitSource, PlanningStore, ProjectionStore, Relationship, RelationshipStore, SpecificationStore,
|
|
4
4
|
TransitionStore, Unsubscribe, Workcard,
|
|
5
5
|
} from '@owlmeans/planning'
|
|
6
|
-
import { applyQuery } from '@owlmeans/resource'
|
|
7
6
|
import type { Criteria, ListResult } from '@owlmeans/resource'
|
|
8
7
|
import type { CommitHub, StoreRoute } from './types.js'
|
|
8
|
+
import { recordQueryHelper } from '@owlmeans/resource'
|
|
9
9
|
|
|
10
10
|
const firstOf = async <S, T>(
|
|
11
11
|
stores: S[], read: (store: S) => Promise<T | null | undefined> | undefined
|
|
@@ -29,6 +29,7 @@ const sum = async <S>(stores: S[], run: (store: S) => Promise<number>): Promise<
|
|
|
29
29
|
* then each owner; a list whose criteria names one owned type (or several owned by one store) goes
|
|
30
30
|
* there, and every other list is the default store's — a cross-type query is answered by the
|
|
31
31
|
* default store alone, never merged. Relationship lists and commit subscriptions span every store.
|
|
32
|
+
* The data-defined schema port is the default store's.
|
|
32
33
|
*/
|
|
33
34
|
export const makeCompositeStore = (routes: StoreRoute[], fallback: PlanningStore): PlanningStore => {
|
|
34
35
|
const all = [...new Set([fallback, ...routes.map(route => route.store)])]
|
|
@@ -121,7 +122,7 @@ export const makeCompositeStore = (routes: StoreRoute[], fallback: PlanningStore
|
|
|
121
122
|
list: async (where, opts) => {
|
|
122
123
|
const results = await Promise.all(linked.map(store => store.links!.list(where, { size: 0 })))
|
|
123
124
|
const items = results.flatMap((result: ListResult<Relationship>) => result.items)
|
|
124
|
-
return applyQuery(items, undefined, opts)
|
|
125
|
+
return recordQueryHelper.applyQuery(items, undefined, opts)
|
|
125
126
|
},
|
|
126
127
|
put: link => (fallback.links ?? linked[0].links!).put(link),
|
|
127
128
|
drop: where => sum(linked, store => store.links!.drop(where)),
|
|
@@ -162,10 +163,14 @@ export const makeCompositeStore = (routes: StoreRoute[], fallback: PlanningStore
|
|
|
162
163
|
return {
|
|
163
164
|
alias: `composite:${fallback.alias ?? 'default'}`,
|
|
164
165
|
newId: fallback.newId,
|
|
166
|
+
unit: fallback.unit,
|
|
167
|
+
assignees: fallback.assignees, teams: fallback.teams, comments: fallback.comments, mentions: fallback.mentions,
|
|
165
168
|
cards,
|
|
166
169
|
...(transitions != null ? { transitions } : {}),
|
|
167
170
|
...(specs != null ? { specs } : {}),
|
|
168
171
|
...(links != null ? { links } : {}),
|
|
169
172
|
...(commits != null ? { commits } : {}),
|
|
173
|
+
// Data-defined schemas are the default store's alone: a layer describes the whole organization.
|
|
174
|
+
...(fallback.schemas != null ? { schemas: fallback.schemas } : {}),
|
|
170
175
|
}
|
|
171
176
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CONTENT_KEYS = ['body', 'ref', 'format', 'version'] as const
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CommitEvent, CommitState, PlanningStore, SpecificationRevision, Transition, Workcard } from '@owlmeans/planning'
|
|
2
|
+
import type { FoldOptions, FoldResult } from '../types.js'
|
|
3
|
+
|
|
4
|
+
/** The projection body every store reuses: the fold of a card's pending log, and what it publishes. */
|
|
5
|
+
export interface FoldHelper {
|
|
6
|
+
/** The event a settled transition publishes. `record` is in-process only — strip it before a bus. */
|
|
7
|
+
commitEventOf: (
|
|
8
|
+
transition: Transition, state: CommitState, at: string, extra?: { error?: string, record?: Workcard | null }
|
|
9
|
+
) => CommitEvent
|
|
10
|
+
/**
|
|
11
|
+
* Fold every pending transition of one card — the projection body every store reuses.
|
|
12
|
+
*
|
|
13
|
+
* Transitions are read in `seq` order past the card's own `seq`, and only `pending` ones are
|
|
14
|
+
* applied, each with `applyHelper.applyTransition` and nothing else. Per transition: write the
|
|
15
|
+
* record (a `delete` drops it with its own documents, a project `delete` purges everything under it), fold its
|
|
16
|
+
* relationships, mark it `committed`, `publish` the event, then run `onCommitted` — so the `after`
|
|
17
|
+
* chain runs in THIS process, exactly once per committed transition. A transition that cannot be
|
|
18
|
+
* folded is marked `failed` with the reason and a failed event is published, and the fold goes PAST
|
|
19
|
+
* it: the card's `seq` advances to the failed transition with every other value as it was, so the
|
|
20
|
+
* next transition applies normally. Nothing is removed from the log. A create that fails leaves no
|
|
21
|
+
* card to advance, so what follows it fails too; a store that refuses the advancing write itself
|
|
22
|
+
* stops the fold there and reports `followUp`, leaving the rest pending for a retry.
|
|
23
|
+
*
|
|
24
|
+
* The caller owns single flight: two folds of one card running at once would both publish. A
|
|
25
|
+
* transactional store passes `unit`, which wraps each transition's writes (a savepoint), so a write
|
|
26
|
+
* the database refuses is undone whole before the fold marks the transition failed.
|
|
27
|
+
*
|
|
28
|
+
* @throws {PlanningUnsupported} for a store without a transition log
|
|
29
|
+
*/
|
|
30
|
+
foldPending: (store: PlanningStore, cardId: string, entityId: string, opts?: FoldOptions) => Promise<FoldResult>
|
|
31
|
+
/**
|
|
32
|
+
* Mark every pending transition of a card `failed` and publish a failed event for each — what a
|
|
33
|
+
* queued store does when its projection job is dead, or waiters hang until their timeout.
|
|
34
|
+
*/
|
|
35
|
+
failPending: (
|
|
36
|
+
store: PlanningStore, cardId: string, entityId: string, reason: string, opts?: Pick<FoldOptions, 'publish' | 'now'>
|
|
37
|
+
) => Promise<number>
|
|
38
|
+
/**
|
|
39
|
+
* A specification's history, replayed from its log: one entry per create and per committed
|
|
40
|
+
* content change, newest first. The fold is `applyHelper.applyTransition` itself, so an entry's
|
|
41
|
+
* `body` is the body AT that revision even when the transition changed only `ref`.
|
|
42
|
+
*/
|
|
43
|
+
revisionsFromLog: (log: Transition[], limit?: number) => SpecificationRevision[]
|
|
44
|
+
}
|
package/src/store/fold.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from '
|
|
4
|
-
import type {
|
|
5
|
-
CommitEvent, PlanningStore, Relationship, SpecificationRevision, Transition, Workcard,
|
|
6
|
-
} from '@owlmeans/planning'
|
|
1
|
+
import { logger } from '@owlmeans/log'
|
|
2
|
+
import { applyHelper, cardHelper, CommitState, PlanningUnsupported, TransitionAction, type CommitEvent, type PlanningStore, type Relationship, type SpecificationRevision, type Transition, type Workcard } from '@owlmeans/planning'
|
|
3
|
+
import type { FoldHelper } from './fold/types.js'
|
|
7
4
|
import type { FoldOptions, FoldResult } from './types.js'
|
|
5
|
+
import { CONTENT_KEYS } from './consts.local.js'
|
|
6
|
+
|
|
7
|
+
const log = logger('planning:store')
|
|
8
8
|
|
|
9
9
|
const isoNow = (): string => new Date().toISOString()
|
|
10
10
|
|
|
@@ -14,244 +14,246 @@ const clean = <T extends object>(record: T): T =>
|
|
|
14
14
|
const errorText = (error: unknown): string =>
|
|
15
15
|
error instanceof Error ? error.message : `${error}`
|
|
16
16
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
export const createFoldHelper = (): FoldHelper => {
|
|
18
|
+
const safely = async (label: string, run: () => Promise<void> | void | undefined): Promise<void> => {
|
|
19
|
+
try {
|
|
20
|
+
await run()
|
|
21
|
+
} catch (error) {
|
|
22
|
+
log.error('Planning store step failed', { step: label, error })
|
|
23
|
+
}
|
|
22
24
|
}
|
|
23
|
-
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
})
|
|
26
|
+
const commitEventOf = (
|
|
27
|
+
transition: Transition, state: CommitState, at: string, extra?: { error?: string, record?: Workcard | null }
|
|
28
|
+
): CommitEvent => clean({
|
|
29
|
+
transition: transition.id!,
|
|
30
|
+
card: transition.card,
|
|
31
|
+
entityId: transition.entityId,
|
|
32
|
+
project: transition.project,
|
|
33
|
+
kind: transition.kind,
|
|
34
|
+
type: transition.type,
|
|
35
|
+
seq: transition.seq,
|
|
36
|
+
action: transition.action,
|
|
37
|
+
state,
|
|
38
|
+
at,
|
|
39
|
+
error: extra?.error,
|
|
40
|
+
record: extra?.record,
|
|
41
|
+
})
|
|
42
42
|
|
|
43
|
-
const bearsRelationships = (transition: Transition): boolean =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
const bearsRelationships = (transition: Transition): boolean =>
|
|
44
|
+
transition.action === TransitionAction.Link
|
|
45
|
+
|| transition.action === TransitionAction.Unlink
|
|
46
|
+
|| transition.action === TransitionAction.Delete
|
|
47
|
+
|| (transition.action === TransitionAction.Create && (transition.links?.length ?? 0) > 0)
|
|
48
48
|
|
|
49
|
-
const foldRelationships = async (store: PlanningStore, transition: Transition): Promise<void> => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
const foldRelationships = async (store: PlanningStore, transition: Transition): Promise<void> => {
|
|
50
|
+
const links = store.links
|
|
51
|
+
if (links == null || !bearsRelationships(transition)) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
const where = { entityId: transition.entityId }
|
|
55
|
+
const [outgoing, incoming] = await Promise.all([
|
|
56
|
+
links.list({ ...where, from: transition.card }, { size: 0 }),
|
|
57
|
+
links.list({ ...where, to: transition.card }, { size: 0 }),
|
|
58
|
+
])
|
|
59
|
+
const before = [...new Map([...outgoing.items, ...incoming.items].map(link => [link.id, link])).values()]
|
|
60
|
+
const after = applyHelper.applyRelationship(before, transition)
|
|
61
|
+
const kept = new Set(after.filter(link => link.id != null).map(link => link.id))
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
for (const link of before) {
|
|
64
|
+
if (link.id != null && !kept.has(link.id)) {
|
|
65
|
+
await links.drop({ entityId: transition.entityId, id: link.id })
|
|
66
|
+
}
|
|
66
67
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
for (const link of after) {
|
|
69
|
+
if (link.id == null) {
|
|
70
|
+
await links.put(link as Relationship)
|
|
71
|
+
}
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
|
-
}
|
|
74
74
|
|
|
75
|
-
const writeFold = async (
|
|
76
|
-
|
|
77
|
-
): Promise<void> => {
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
const writeFold = async (
|
|
76
|
+
store: PlanningStore, before: Workcard | null, after: Workcard | null, transition: Transition
|
|
77
|
+
): Promise<void> => {
|
|
78
|
+
await store.validateProjection?.(before, after, transition)
|
|
79
|
+
if (transition.action === TransitionAction.Delete) {
|
|
80
|
+
if (before != null && cardHelper.isProject(before)) {
|
|
81
|
+
// A project takes everything under it, its own log included — the hub remembers the commit.
|
|
82
|
+
await store.cards.purge(transition.card, transition.entityId)
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
await foldRelationships(store, transition)
|
|
86
|
+
await store.cards.drop(transition.card, transition.entityId)
|
|
82
87
|
return
|
|
83
88
|
}
|
|
89
|
+
if (after != null) {
|
|
90
|
+
await store.cards.put(after)
|
|
91
|
+
await store.projectReferences?.(after, transition)
|
|
92
|
+
}
|
|
84
93
|
await foldRelationships(store, transition)
|
|
85
|
-
await store.cards.drop(transition.card, transition.entityId)
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
if (after != null) {
|
|
89
|
-
await store.cards.put(after)
|
|
90
94
|
}
|
|
91
|
-
await foldRelationships(store, transition)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Fold every pending transition of one card — the projection body every store reuses.
|
|
96
|
-
*
|
|
97
|
-
* Transitions are read in `seq` order past the card's own `seq`, and only `pending` ones are
|
|
98
|
-
* applied, each with `applyTransition` and nothing else. Per transition: write the record (a
|
|
99
|
-
* `delete` drops it, a project `delete` purges everything under it), fold its relationships, mark
|
|
100
|
-
* it `committed`, `publish` the event, then run `onCommitted` — so the `after` chain runs in THIS
|
|
101
|
-
* process, exactly once per committed transition. A transition that cannot be folded is marked
|
|
102
|
-
* `failed` with the reason and a failed event is published, and the fold goes PAST it: the card's
|
|
103
|
-
* `seq` advances to the failed transition with every other value as it was, so the next
|
|
104
|
-
* transition applies normally. Nothing is removed from the log. A create that fails leaves no card
|
|
105
|
-
* to advance, so what follows it fails too; a store that refuses the advancing write itself stops
|
|
106
|
-
* the fold there and reports `followUp`, leaving the rest pending for a retry.
|
|
107
|
-
*
|
|
108
|
-
* The caller owns single flight: two folds of one card running at once would both publish.
|
|
109
|
-
*
|
|
110
|
-
* @throws {PlanningUnsupported} for a store without a transition log
|
|
111
|
-
*/
|
|
112
|
-
export const foldPending = async (
|
|
113
|
-
store: PlanningStore, cardId: string, entityId: string, opts: FoldOptions = {}
|
|
114
|
-
): Promise<FoldResult> => {
|
|
115
|
-
const transitions = store.transitions
|
|
116
|
-
if (transitions == null) {
|
|
117
|
-
throw new PlanningUnsupported(`fold:${store.alias ?? 'store'}`)
|
|
118
|
-
}
|
|
119
|
-
const now = opts.now ?? isoNow
|
|
120
|
-
|
|
121
|
-
let card = await store.cards.get(cardId, entityId)
|
|
122
|
-
const listed = await transitions.list(
|
|
123
|
-
{ entityId, card: cardId, sinceSeq: card?.seq ?? 0, state: CommitState.Pending },
|
|
124
|
-
{ sort: ['seq'], size: opts.limit ?? 0 }
|
|
125
|
-
)
|
|
126
95
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
96
|
+
const foldPending = async (
|
|
97
|
+
store: PlanningStore, cardId: string, entityId: string, opts: FoldOptions = {}
|
|
98
|
+
): Promise<FoldResult> => {
|
|
99
|
+
const transitions = store.transitions
|
|
100
|
+
if (transitions == null) {
|
|
101
|
+
throw new PlanningUnsupported(`fold:${store.alias ?? 'store'}`)
|
|
132
102
|
}
|
|
133
|
-
|
|
134
|
-
const at = now()
|
|
103
|
+
const now = opts.now ?? isoNow
|
|
135
104
|
|
|
136
|
-
let
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
105
|
+
let card = await store.cards.get(cardId, entityId)
|
|
106
|
+
const listed = await transitions.list(
|
|
107
|
+
{ entityId, card: cardId, sinceSeq: card?.seq ?? 0, state: CommitState.Pending },
|
|
108
|
+
{ sort: ['seq'], size: opts.limit ?? 0 }
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
let folded = 0
|
|
112
|
+
let failed = 0
|
|
113
|
+
for (const transition of listed.items) {
|
|
114
|
+
if (transition.commit.state !== CommitState.Pending || transition.id == null) {
|
|
141
115
|
continue
|
|
142
116
|
}
|
|
143
|
-
await
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
await store.cards.put(skipped)
|
|
154
|
-
card = skipped
|
|
155
|
-
} catch (advance) {
|
|
156
|
-
// The store itself refuses writes: leave the rest pending for a retry rather than
|
|
157
|
-
// failing every later transition as out of order.
|
|
158
|
-
console.error(`planning: cannot advance ${cardId} past failed seq ${transition.seq}:`, advance)
|
|
159
|
-
await safely('commit failure', () => transitions.commit(transition.id!, { state: CommitState.Failed, at, error: message }))
|
|
160
|
-
await safely('publish', () => opts.publish?.(commitEventOf(transition, CommitState.Failed, at, { error: message })))
|
|
161
|
-
return { card, folded, failed, followUp: true }
|
|
117
|
+
await opts.touch?.()
|
|
118
|
+
const at = now()
|
|
119
|
+
|
|
120
|
+
let next: Workcard | null
|
|
121
|
+
try {
|
|
122
|
+
next = applyHelper.applyTransition(card, transition)
|
|
123
|
+
if (card != null && next === card) {
|
|
124
|
+
// Already applied by another folder, which owns its commit and its event.
|
|
125
|
+
continue
|
|
162
126
|
}
|
|
127
|
+
const before = card
|
|
128
|
+
const after = next
|
|
129
|
+
await (opts.unit != null
|
|
130
|
+
? opts.unit(async () => { await writeFold(store, before, after, transition) })
|
|
131
|
+
: writeFold(store, before, after, transition))
|
|
132
|
+
} catch (error) {
|
|
133
|
+
failed++
|
|
134
|
+
const message = errorText(error)
|
|
135
|
+
if (card != null && transition.seq > card.seq) {
|
|
136
|
+
// Fold PAST it: the record keeps its previous values and only its cursor moves, so the
|
|
137
|
+
// next transition still applies. The card is re-written whole, which also undoes a write
|
|
138
|
+
// that got half way before it threw.
|
|
139
|
+
const skipped: Workcard = { ...card, seq: transition.seq, head: Math.max(card.head ?? card.seq, transition.seq) }
|
|
140
|
+
try {
|
|
141
|
+
await store.cards.put(skipped)
|
|
142
|
+
card = skipped
|
|
143
|
+
} catch (advance) {
|
|
144
|
+
// The store itself refuses writes: leave the rest pending for a retry rather than
|
|
145
|
+
// failing every later transition as out of order.
|
|
146
|
+
log.error('Planning cannot advance a card past a failed transition', { cardId, seq: transition.seq, error: advance })
|
|
147
|
+
await safely('commit failure', () => transitions.commit(transition.id!, { state: CommitState.Failed, at, error: message }))
|
|
148
|
+
await safely('publish', () => opts.publish?.(commitEventOf(transition, CommitState.Failed, at, { error: message })))
|
|
149
|
+
return { card, folded, failed, followUp: true }
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
await safely('commit failure', () => transitions.commit(transition.id!, { state: CommitState.Failed, at, error: message }))
|
|
153
|
+
const event = commitEventOf(transition, CommitState.Failed, at, { error: message })
|
|
154
|
+
await safely('publish', () => opts.publish?.(event))
|
|
155
|
+
continue
|
|
163
156
|
}
|
|
164
|
-
|
|
165
|
-
|
|
157
|
+
|
|
158
|
+
card = next
|
|
159
|
+
folded++
|
|
160
|
+
await safely('commit', () => transitions.commit(transition.id!, { state: CommitState.Committed, at }))
|
|
161
|
+
const event = commitEventOf(transition, CommitState.Committed, at, { record: next })
|
|
166
162
|
await safely('publish', () => opts.publish?.(event))
|
|
167
|
-
|
|
163
|
+
await safely('onCommitted', () => opts.onCommitted?.(event))
|
|
168
164
|
}
|
|
169
165
|
|
|
170
|
-
card
|
|
171
|
-
folded++
|
|
172
|
-
await safely('commit', () => transitions.commit(transition.id!, { state: CommitState.Committed, at }))
|
|
173
|
-
const event = commitEventOf(transition, CommitState.Committed, at, { record: next })
|
|
174
|
-
await safely('publish', () => opts.publish?.(event))
|
|
175
|
-
await safely('onCommitted', () => opts.onCommitted?.(event))
|
|
166
|
+
return { card, folded, failed, followUp: listed.total > listed.items.length }
|
|
176
167
|
}
|
|
177
168
|
|
|
178
|
-
|
|
179
|
-
|
|
169
|
+
const failPending = async (
|
|
170
|
+
store: PlanningStore, cardId: string, entityId: string, reason: string,
|
|
171
|
+
opts: Pick<FoldOptions, 'publish' | 'now'> = {}
|
|
172
|
+
): Promise<number> => {
|
|
173
|
+
const transitions = store.transitions
|
|
174
|
+
if (transitions == null) {
|
|
175
|
+
return 0
|
|
176
|
+
}
|
|
177
|
+
const at = (opts.now ?? isoNow)()
|
|
178
|
+
const pending = await transitions.list({ entityId, card: cardId, state: CommitState.Pending }, { sort: ['seq'], size: 0 })
|
|
179
|
+
for (const transition of pending.items) {
|
|
180
|
+
if (transition.id == null) {
|
|
181
|
+
continue
|
|
182
|
+
}
|
|
183
|
+
await transitions.commit(transition.id, { state: CommitState.Failed, at, error: reason })
|
|
184
|
+
const event = commitEventOf(transition, CommitState.Failed, at, { error: reason })
|
|
185
|
+
await safely('publish', () => opts.publish?.(event))
|
|
186
|
+
}
|
|
180
187
|
|
|
181
|
-
|
|
182
|
-
* Mark every pending transition of a card `failed` and publish a failed event for each — what a
|
|
183
|
-
* queued store does when its projection job is dead, or waiters hang until their timeout.
|
|
184
|
-
*/
|
|
185
|
-
export const failPending = async (
|
|
186
|
-
store: PlanningStore, cardId: string, entityId: string, reason: string,
|
|
187
|
-
opts: Pick<FoldOptions, 'publish' | 'now'> = {}
|
|
188
|
-
): Promise<number> => {
|
|
189
|
-
const transitions = store.transitions
|
|
190
|
-
if (transitions == null) {
|
|
191
|
-
return 0
|
|
188
|
+
return pending.items.length
|
|
192
189
|
}
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
190
|
+
|
|
191
|
+
const revisionsFromLog = (log: Transition[], limit?: number): SpecificationRevision[] => {
|
|
192
|
+
const ordered = log.filter(transition => transition.commit.state !== CommitState.Pending)
|
|
193
|
+
.sort((left, right) => left.seq - right.seq)
|
|
194
|
+
|
|
195
|
+
const entries: SpecificationRevision[] = []
|
|
196
|
+
let state: Workcard | null = null
|
|
197
|
+
for (const transition of ordered) {
|
|
198
|
+
if (transition.commit.state === CommitState.Failed) {
|
|
199
|
+
// The fold went past it; so does the replay.
|
|
200
|
+
if (state != null && transition.seq > state.seq) {
|
|
201
|
+
state = { ...(state as Workcard), seq: transition.seq }
|
|
202
|
+
}
|
|
203
|
+
continue
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
state = applyHelper.applyTransition(state, transition)
|
|
207
|
+
} catch {
|
|
208
|
+
break
|
|
209
|
+
}
|
|
210
|
+
if (state == null) {
|
|
211
|
+
break
|
|
212
|
+
}
|
|
213
|
+
const changed = transition.action === TransitionAction.Create
|
|
214
|
+
|| CONTENT_KEYS.some(key => (transition.changes as Record<string, unknown>)[key] !== undefined
|
|
215
|
+
|| transition.unset?.includes(key) === true)
|
|
216
|
+
if (!changed) {
|
|
217
|
+
continue
|
|
218
|
+
}
|
|
219
|
+
const spec = state as Workcard & { body?: string, ref?: string, bodyChars?: number, version?: number, revision?: number }
|
|
220
|
+
entries.push(clean({
|
|
221
|
+
revision: spec.revision ?? entries.length + 1,
|
|
222
|
+
body: spec.body,
|
|
223
|
+
ref: spec.ref,
|
|
224
|
+
bodyChars: spec.bodyChars,
|
|
225
|
+
version: spec.version,
|
|
226
|
+
at: transition.at,
|
|
227
|
+
by: transition.actor,
|
|
228
|
+
transition: transition.id!,
|
|
229
|
+
}))
|
|
198
230
|
}
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
231
|
+
|
|
232
|
+
const newest = entries.reverse()
|
|
233
|
+
return limit != null && limit > 0 ? newest.slice(0, limit) : newest
|
|
202
234
|
}
|
|
203
235
|
|
|
204
|
-
return
|
|
236
|
+
return { commitEventOf, foldPending, failPending, revisionsFromLog }
|
|
205
237
|
}
|
|
206
238
|
|
|
207
|
-
const
|
|
239
|
+
export const foldHelper = createFoldHelper()
|
|
208
240
|
|
|
209
|
-
/**
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
*/
|
|
214
|
-
export const revisionsFromLog = (log: Transition[], limit?: number): SpecificationRevision[] => {
|
|
215
|
-
const ordered = log.filter(transition => transition.commit.state !== CommitState.Pending)
|
|
216
|
-
.sort((left, right) => left.seq - right.seq)
|
|
241
|
+
/** @deprecated compat:factory-refactor — use `foldHelper.commitEventOf(…)` */
|
|
242
|
+
export const commitEventOf = (
|
|
243
|
+
transition: Transition, state: CommitState, at: string, extra?: { error?: string, record?: Workcard | null }
|
|
244
|
+
): CommitEvent => foldHelper.commitEventOf(transition, state, at, extra)
|
|
217
245
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
// The fold went past it; so does the replay.
|
|
223
|
-
if (state != null && transition.seq > state.seq) {
|
|
224
|
-
state = { ...(state as Workcard), seq: transition.seq }
|
|
225
|
-
}
|
|
226
|
-
continue
|
|
227
|
-
}
|
|
228
|
-
try {
|
|
229
|
-
state = applyTransition(state, transition)
|
|
230
|
-
} catch {
|
|
231
|
-
break
|
|
232
|
-
}
|
|
233
|
-
if (state == null) {
|
|
234
|
-
break
|
|
235
|
-
}
|
|
236
|
-
const changed = transition.action === TransitionAction.Create
|
|
237
|
-
|| CONTENT_KEYS.some(key => (transition.changes as Record<string, unknown>)[key] !== undefined
|
|
238
|
-
|| transition.unset?.includes(key) === true)
|
|
239
|
-
if (!changed) {
|
|
240
|
-
continue
|
|
241
|
-
}
|
|
242
|
-
const spec = state as Workcard & { body?: string, ref?: string, bodyChars?: number, version?: number, revision?: number }
|
|
243
|
-
entries.push(clean({
|
|
244
|
-
revision: spec.revision ?? entries.length + 1,
|
|
245
|
-
body: spec.body,
|
|
246
|
-
ref: spec.ref,
|
|
247
|
-
bodyChars: spec.bodyChars,
|
|
248
|
-
version: spec.version,
|
|
249
|
-
at: transition.at,
|
|
250
|
-
by: transition.actor,
|
|
251
|
-
transition: transition.id!,
|
|
252
|
-
}))
|
|
253
|
-
}
|
|
246
|
+
/** @deprecated compat:factory-refactor — use `foldHelper.foldPending(…)` */
|
|
247
|
+
export const foldPending = async (
|
|
248
|
+
store: PlanningStore, cardId: string, entityId: string, opts: FoldOptions = {}
|
|
249
|
+
): Promise<FoldResult> => await foldHelper.foldPending(store, cardId, entityId, opts)
|
|
254
250
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
251
|
+
/** @deprecated compat:factory-refactor — use `foldHelper.failPending(…)` */
|
|
252
|
+
export const failPending = async (
|
|
253
|
+
store: PlanningStore, cardId: string, entityId: string, reason: string,
|
|
254
|
+
opts: Pick<FoldOptions, 'publish' | 'now'> = {}
|
|
255
|
+
): Promise<number> => await foldHelper.failPending(store, cardId, entityId, reason, opts)
|
|
256
|
+
|
|
257
|
+
/** @deprecated compat:factory-refactor — use `foldHelper.revisionsFromLog(…)` */
|
|
258
|
+
export const revisionsFromLog = (log: Transition[], limit?: number): SpecificationRevision[] =>
|
|
259
|
+
foldHelper.revisionsFromLog(log, limit)
|
package/src/store/index.ts
CHANGED
package/src/store/memory.ts
CHANGED
|
Binary file
|
package/src/store/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CommitEvent, CommitSource, CommitStatus, PlanningStore, ProjectionStore, Relationship,
|
|
3
|
-
RelationshipStore, SpecificationStore, Transition, TransitionStore,
|
|
3
|
+
RelationshipStore, SchemaStore, ScopedSchemaRecord, SpecificationStore, Transition, TransitionStore,
|
|
4
|
+
Workcard,
|
|
4
5
|
} from '@owlmeans/planning'
|
|
5
6
|
|
|
6
7
|
/** What a folding store calls for every committed transition — the service's `committed`. */
|
|
@@ -49,6 +50,11 @@ export interface FoldOptions {
|
|
|
49
50
|
limit?: number
|
|
50
51
|
/** Called between transitions — a queue processor renews its lock here. */
|
|
51
52
|
touch?: () => Promise<void>
|
|
53
|
+
/**
|
|
54
|
+
* Runs one transition's store writes as a unit — a transactional store opens a savepoint here, so
|
|
55
|
+
* a write the database refuses leaves nothing of that transition behind and the fold goes past it.
|
|
56
|
+
*/
|
|
57
|
+
unit?: <R>(run: () => Promise<R>) => Promise<R>
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
export interface FoldResult {
|
|
@@ -63,6 +69,8 @@ export interface MemoryPlanningStoreSeed {
|
|
|
63
69
|
cards?: Workcard[]
|
|
64
70
|
links?: Relationship[]
|
|
65
71
|
transitions?: Transition[]
|
|
72
|
+
/** Data-defined type and flow records — kept only by a store built with `schemas: true`. */
|
|
73
|
+
schemas?: ScopedSchemaRecord[]
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
export interface MemoryPlanningStoreOptions {
|
|
@@ -74,6 +82,11 @@ export interface MemoryPlanningStoreOptions {
|
|
|
74
82
|
/** The commit listener used until a service binds its own. */
|
|
75
83
|
onCommitted?: CommitListener
|
|
76
84
|
alias?: string
|
|
85
|
+
/**
|
|
86
|
+
* Hold data-defined types and flows (the `schemas` port). Off by default: a store without it
|
|
87
|
+
* resolves every type and flow from the code registry, exactly as before.
|
|
88
|
+
*/
|
|
89
|
+
schemas?: boolean
|
|
77
90
|
}
|
|
78
91
|
|
|
79
92
|
export interface MemoryPlanningStore extends BindablePlanningStore {
|
|
@@ -82,6 +95,8 @@ export interface MemoryPlanningStore extends BindablePlanningStore {
|
|
|
82
95
|
specs: SpecificationStore
|
|
83
96
|
links: RelationshipStore
|
|
84
97
|
commits: CommitHub
|
|
98
|
+
/** Present when the store was built with `schemas: true`. */
|
|
99
|
+
schemas?: SchemaStore
|
|
85
100
|
bind: (committed: CommitListener) => void
|
|
86
101
|
/** Fold what is pending — for one card, or for every card with a pending transition. */
|
|
87
102
|
flush: (card?: string) => Promise<void>
|