@cosmicdrift/kumiko-framework 0.382.0 → 0.383.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/examples/api-worker-split.md +57 -0
- package/agents/examples/record-detail-layout.md +20 -18
- package/agents/examples/screens-nav.md +3 -2
- package/agents/examples/writeform-section.md +2 -1
- package/dist/api/api-constants.d.ts +1 -0
- package/dist/api/api-constants.js +2 -0
- package/dist/api/auth-middleware.d.ts +1 -0
- package/dist/api/auth-middleware.js +17 -0
- package/dist/api/auth-routes.d.ts +1 -0
- package/dist/api/auth-routes.js +14 -4
- package/dist/api/client-error-route.d.ts +12 -0
- package/dist/api/client-error-route.js +113 -0
- package/dist/api/request-context.d.ts +6 -0
- package/dist/api/request-context.js +9 -0
- package/dist/api/routes.js +7 -4
- package/dist/api/server.js +11 -1
- package/dist/db/connection.d.ts +7 -0
- package/dist/db/connection.js +40 -0
- package/dist/db/index.d.ts +2 -1
- package/dist/db/index.js +2 -1
- package/dist/db/migrate-runner.js +4 -0
- package/dist/db/queries/backfill-pii.js +5 -1
- package/dist/db/queries/event-store.js +9 -2
- package/dist/db/statement-timeout.d.ts +2 -0
- package/dist/db/statement-timeout.js +18 -0
- package/dist/db/tenant-db.js +5 -12
- package/dist/engine/boot-validator/access-declarations.js +17 -18
- package/dist/engine/boot-validator/query-output-columns.js +1 -2
- package/dist/engine/boot-validator/screens.js +12 -16
- package/dist/engine/boot-validator/url-prefill-fields.js +1 -3
- package/dist/engine/build-config-feature-schema.js +4 -4
- package/dist/engine/entity-handlers.js +5 -7
- package/dist/engine/escape-hatch-declaration.d.ts +1 -1
- package/dist/engine/escape-hatch-declaration.js +5 -2
- package/dist/engine/escape-hatch-reason.d.ts +2 -0
- package/dist/engine/escape-hatch-reason.js +35 -0
- package/dist/engine/extensions/escape-hatch-usage.js +2 -1
- package/dist/engine/feature-config-events-jobs.js +6 -4
- package/dist/engine/feature-ui-extensions.js +12 -6
- package/dist/engine/iban.d.ts +2 -0
- package/dist/engine/iban.js +19 -0
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/project-app-schema-for-roles.js +1 -1
- package/dist/engine/registry-validate.d.ts +1 -0
- package/dist/engine/registry-validate.js +8 -0
- package/dist/engine/registry.js +2 -1
- package/dist/engine/schema-builder.js +9 -0
- package/dist/engine/screen-helpers.d.ts +3 -3
- package/dist/engine/screen-helpers.js +1 -2
- package/dist/engine/steps/_read-source.js +2 -0
- package/dist/engine/types/index.d.ts +2 -2
- package/dist/engine/types/index.js +1 -1
- package/dist/engine/types/screen.d.ts +1 -1
- package/dist/engine/types/screen.js +1 -1
- package/dist/entrypoint/index.d.ts +1 -0
- package/dist/entrypoint/index.js +1 -0
- package/dist/event-store/event-store.d.ts +0 -3
- package/dist/event-store/event-store.js +1 -26
- package/dist/event-store/index.d.ts +1 -1
- package/dist/event-store/index.js +1 -1
- package/dist/event-store/snapshot.js +6 -1
- package/dist/files/file-ref-entity.d.ts +6 -6
- package/dist/files/file-ref-table.d.ts +6 -6
- package/dist/i18n/required-surface-keys.js +0 -1
- package/dist/jobs/job-runner.d.ts +1 -0
- package/dist/jobs/job-runner.js +74 -7
- package/dist/logging/index.d.ts +2 -1
- package/dist/logging/index.js +2 -1
- package/dist/logging/pino-logger.d.ts +1 -0
- package/dist/logging/pino-logger.js +35 -0
- package/dist/logging/request-log-fields.d.ts +1 -0
- package/dist/logging/request-log-fields.js +21 -0
- package/dist/logging/scrub.d.ts +2 -0
- package/dist/logging/scrub.js +21 -0
- package/dist/logging/utils.d.ts +1 -0
- package/dist/logging/utils.js +40 -6
- package/dist/migrations/pii-event-backfill.js +5 -1
- package/dist/observability/standard-metrics.d.ts +1 -0
- package/dist/observability/standard-metrics.js +9 -0
- package/dist/pipeline/msp-rebuild.js +5 -1
- package/dist/pipeline/projection-rebuild.js +5 -1
- package/dist/rate-limit/middleware.d.ts +8 -3
- package/dist/rate-limit/middleware.js +28 -10
- package/dist/rate-limit/resolver.js +10 -0
- package/dist/redis/client.d.ts +2 -0
- package/dist/redis/client.js +20 -0
- package/dist/redis/index.d.ts +1 -1
- package/dist/redis/index.js +1 -1
- package/dist/search/purge-subject.js +6 -8
- package/dist/search/reindex-entity.js +11 -10
- package/dist/ui-types/index.d.ts +1 -1
- package/dist/ui-types/index.js +1 -1
- package/package.json +3 -3
- package/src/changes.json +64 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const IBAN_SHAPE = /^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$/;
|
|
2
|
+
const MOD_97_RESIDUE = 1;
|
|
3
|
+
export function normalizeIban(value) {
|
|
4
|
+
return value.replace(/\s+/g, "").toUpperCase();
|
|
5
|
+
}
|
|
6
|
+
// Digit-wise reduction keeps every intermediate below 2^31, so no BigInt is needed for up to 34 characters.
|
|
7
|
+
export function isValidIban(value) {
|
|
8
|
+
const iban = normalizeIban(value);
|
|
9
|
+
if (!IBAN_SHAPE.test(iban))
|
|
10
|
+
return false;
|
|
11
|
+
const rearranged = iban.slice(4) + iban.slice(0, 4);
|
|
12
|
+
let remainder = 0;
|
|
13
|
+
for (const char of rearranged) {
|
|
14
|
+
const digits = char >= "A" ? String(char.charCodeAt(0) - 55) : char;
|
|
15
|
+
for (const digit of digits)
|
|
16
|
+
remainder = (remainder * 10 + Number(digit)) % 97;
|
|
17
|
+
}
|
|
18
|
+
return remainder === MOD_97_RESIDUE;
|
|
19
|
+
}
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export { assertNotificationVariables, templateVariable, templateVariablesToZod,
|
|
|
87
87
|
export { type EffectiveFeaturesResolver, findTierResolverUsage, isTierResolverPlugin, requireTierResolverPlugin, TENANT_TIER_RESOLVER_EXT, type TierResolverPlugin, type TrialGate, } from "./tier-resolver-extension.ts";
|
|
88
88
|
export { findOverDeepTransferChain, resolveTransferAdjacency as resolveEntityTransferAdjacency, type TransferAdjacency, type TransferEdge, type TransferEdgeLink, } from "./transfer-adjacency.ts";
|
|
89
89
|
export { isSystemTenant, isUuid, parseTenantId, SYSTEM_TENANT_ID } from "./types/identifiers.ts";
|
|
90
|
-
export type { AccessRule, ActionFormScreenDefinition, ActiveMembership, ActiveMembershipRejection, ActiveMembershipResult, AgentExposure, AgentHandlerHints, AgentRisk, AppContext, AppendEventArgs, AppendEventFn, AuthClaimsContext, AuthClaimsFn, AuthClaimsHookDef, BeforeTransactionPhase, BeforeTransactionResult, BelongsToRelation, BigIntFieldDef, BooleanFieldDef, BootOptionName, CamelToKebab, ChatSendFailureCode, ClaimKeyDefinition, ClaimKeyHandle, ClaimKeyJsType, ClaimKeyType, ConcurrencyMode, ConfigAccessor, ConfigAccessorFactory, ConfigBacking, ConfigCascade, ConfigCascadeLevel, ConfigDefinition, ConfigEditScreenDefinition, ConfigKeyAccess, ConfigKeyDefinition, ConfigKeyHandle, ConfigKeyType, ConfigMask, ConfigResolver, ConfigScope, ConfigSecretsReader, ConfigSeedDef, ConfigStoredRow, ConfigStoredRowWithSource, ConfigValidateContext, ConfigValidateFn, ConfigValue, ConfigValueSource, ConfigValueWithSource, ContentCollectionDefinition, CreateSeedOptions, CreateTenantSeedOptions, CreateUserSeedOptions, CustomScreenDefinition, CustomScreenRoute, DashboardChartPanel, DashboardCurrencyFormat, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListPanel, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelVisibility, DashboardProgressListPanel, DashboardProgressTone, DashboardRecordBinding, DashboardRefresh, DashboardRelativeTimeFormat, DashboardRelativeTimeParam, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupPanel, DashboardStatPanel, DashboardText, DashboardTextBlock, DashboardTextPanel, DashboardTextParam, DashboardValueFormat, DateFieldDef, DecimalFieldDef, DeleteContext, DeliveryErrorCode, DeliveryFailureCode, DeliverySkipReason, DeriveContext, DerivedFieldDef, DerivedFieldsMap, DerivedValueType, EditExtensionSection, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EmbeddedListEditSpec, EntityDefinition, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityId, EntityListExpandableRow, EntityListScreenDefinition, EntityObjectDefinition, EntityRef, EntityRelations, EscapeHatchAuditSink, EscapeHatchDeclaration, EscapeHatchKind, EscapeHatchReporter, EscapeHatchTarget, EscapeHatchUseEvent, EventDef, ExtensionOptionsArgs, ExtensionOptionsFor, FeatureDefinition, FeatureRegistrar, FieldAccess, FieldCondition, FieldDefinition, FieldFormatRegistry, FieldIconKey, FieldRenderer, FileFieldDef, FilesFieldDef, Findability, FormatSpec, FormWidth, HandlerContext, HasManyRelation, HookDefinition, HookMap, ImageFieldDef, ImagesFieldDef, JobBackoff, JobBackoffStrategy, JobContext, JobDefinition, JobHandlerFn, JobTrigger, JobTriggerEvent, JsonbFieldDef, KumikoEntityTypeMap, KumikoEventTypeMap, KumikoExtensionOptionsMap, KumikoHandlerPayloadMap, KumikoHandlerResultMap, LifecycleHookType, ListColumnSpec, ListFacetSpec, ListPaginationMode, ListSortDir, ListSortSpec, LongTextFindability, ManyToManyRelation, MaxPerTenantOptions, MemberReader, MetricNavigate, MetricSpec, MspErrorMode, MspErrorPolicy, MultiSelectFieldDef, MultiStreamApplyFn, MultiStreamProjectionDefinition, NameOrRef, NavDefinition, NavIconKey, NotificationDataFn, NotificationDefinition, NotificationLocalizedTemplate, NotificationRecipientFn, NotificationRecordMapping, NotificationTemplateBody, NotificationTemplateFn, NotificationTemplateMeta, NotifyDeferred, NotifyDelivery, NotifyDeliveryStatus, NotifyDispatched, NotifyFactory, NotifyFn, NotifyJobDispatcher, NotifyOptions, NotifyPriority, NotifyResult, NumberFieldDef, OnDeleteStrategy, OpenToAllAccessRule, OpenToAllDeclaration, OpenToAllPersonalData, ParentRefDef, PersonalAnnotations, PersonalAnnotationsLongText, PersonalAnnotationsNoFind, PersonalSubject, PlatformComponent, PluralForms, PostDeleteHookFn, PostSaveHookFn, PreDeleteHookFn, PreparedWriteEvent, PreQueryHookFn, PreSaveHookFn, ProjectionDefinition, ProjectionDetailScreenDefinition, ProjectionListScreenDefinition, ProjectionTable, ProviderPluginContext, QualifiedEventName, QueryEvent, QueryHandlerDef, QueryHandlerFn, RateLimitPer, RecordHeaderSpec, RecordHeaderSubtitlePart, ReferenceDataDef, Registry, RelationDefinition, ResolvedPiiFlags, RetentionDef, RoleAccessPersonalData, RoleAccessRule, RowAction, RowActionNavigate, RowActionNavigateBase, RowActionWriteHandler, RowFieldExtractor, SaveContext, ScreenDefinition, ScreenFilter, ScreenFilterOp, ScreenNavSugar, ScreenSlots, SecretKeyDefinition, SecretKeyHandle, SecretMintConfirmStep, SecretMintScreenDefinition, SecretNamespaceDefinition, SecretNamespaceHandle, SecretNamespaceOptions, SecretReveal, SecretRevealField, SecretsEditScreenDefinition, SecretsEditSection, SelectFieldDef, SessionUser, SessionUserOrigin, StackBootRequirement, StreamHandlerDef, StreamHandlerFn, Subscribe, TargetRef, TemplateImagesVariableDef, TemplateListVariableDef, TemplateScalarVariableDef, TemplateVariableDef, TemplateVariables, TenantId, TenantWriteTarget, TextFieldDef, ToolbarAction, TranslationEntry, TranslationKeys, TranslationsDef, TranslationValue, TreeAction, TreeActionDef, TreeActionsHandle, TreeChildrenSubscribe, TreeNode, TreeNodeState, UnitKey, UnsafeAppendEventFn, ValidationError, ValidationHookFn, WorkspaceDefinition, WriteEvent, WriteHandlerDef, WriteHandlerFn, WriteResult, } from "./types/index.ts";
|
|
90
|
+
export type { AccessRule, ActionFormScreenDefinition, ActiveMembership, ActiveMembershipRejection, ActiveMembershipResult, AgentExposure, AgentHandlerHints, AgentRisk, AppContext, AppendEventArgs, AppendEventFn, AuthClaimsContext, AuthClaimsFn, AuthClaimsHookDef, BeforeTransactionPhase, BeforeTransactionResult, BelongsToRelation, BigIntFieldDef, BooleanFieldDef, BootOptionName, CamelToKebab, ChatSendFailureCode, ClaimKeyDefinition, ClaimKeyHandle, ClaimKeyJsType, ClaimKeyType, ConcurrencyMode, ConfigAccessor, ConfigAccessorFactory, ConfigBacking, ConfigCascade, ConfigCascadeLevel, ConfigDefinition, ConfigEditScreenDefinition, ConfigKeyAccess, ConfigKeyDefinition, ConfigKeyHandle, ConfigKeyType, ConfigMask, ConfigResolver, ConfigScope, ConfigSecretsReader, ConfigSeedDef, ConfigStoredRow, ConfigStoredRowWithSource, ConfigValidateContext, ConfigValidateFn, ConfigValue, ConfigValueSource, ConfigValueWithSource, ContentCollectionDefinition, CreateSeedOptions, CreateTenantSeedOptions, CreateUserSeedOptions, CustomScreenDefinition, CustomScreenRoute, DashboardChartPanel, DashboardCurrencyFormat, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListPanel, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelVisibility, DashboardProgressListPanel, DashboardProgressTone, DashboardRecordBinding, DashboardRefresh, DashboardRelativeTimeFormat, DashboardRelativeTimeParam, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupPanel, DashboardStatPanel, DashboardText, DashboardTextBlock, DashboardTextPanel, DashboardTextParam, DashboardValueFormat, DateFieldDef, DecimalFieldDef, DeleteContext, DeliveryErrorCode, DeliveryFailureCode, DeliverySkipReason, DeriveContext, DerivedFieldDef, DerivedFieldsMap, DerivedValueType, EditExtensionSection, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EmbeddedListEditSpec, EntityDefinition, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityId, EntityListExpandableRow, EntityListScreenDefinition, EntityObjectDefinition, EntityRef, EntityRelations, EscapeHatchAuditSink, EscapeHatchDeclaration, EscapeHatchKind, EscapeHatchReporter, EscapeHatchTarget, EscapeHatchUseEvent, EventDef, ExtensionOptionsArgs, ExtensionOptionsFor, FeatureDefinition, FeatureRegistrar, FieldAccess, FieldCondition, FieldDefinition, FieldFormatRegistry, FieldIconKey, FieldRenderer, FileFieldDef, FilesFieldDef, Findability, FormatSpec, FormWidth, HandlerContext, HasManyRelation, HookDefinition, HookMap, ImageFieldDef, ImagesFieldDef, JobBackoff, JobBackoffStrategy, JobContext, JobDeferral, JobDefinition, JobHandlerFn, JobTrigger, JobTriggerEvent, JsonbFieldDef, KumikoEntityTypeMap, KumikoEventTypeMap, KumikoExtensionOptionsMap, KumikoHandlerPayloadMap, KumikoHandlerResultMap, LifecycleHookType, ListColumnSpec, ListFacetSpec, ListPaginationMode, ListSortDir, ListSortSpec, LongTextFindability, ManyToManyRelation, MaxPerTenantOptions, MemberReader, MetricNavigate, MetricSpec, MspErrorMode, MspErrorPolicy, MultiSelectFieldDef, MultiStreamApplyFn, MultiStreamProjectionDefinition, NameOrRef, NavDefinition, NavIconKey, NotificationDataFn, NotificationDefinition, NotificationLocalizedTemplate, NotificationRecipientFn, NotificationRecordMapping, NotificationTemplateBody, NotificationTemplateFn, NotificationTemplateMeta, NotifyDeferred, NotifyDelivery, NotifyDeliveryStatus, NotifyDispatched, NotifyFactory, NotifyFn, NotifyJobDispatcher, NotifyOptions, NotifyPriority, NotifyResult, NumberFieldDef, OnDeleteStrategy, OpenToAllAccessRule, OpenToAllDeclaration, OpenToAllPersonalData, ParentRefDef, PersonalAnnotations, PersonalAnnotationsLongText, PersonalAnnotationsNoFind, PersonalSubject, PlatformComponent, PluralForms, PostDeleteHookFn, PostSaveHookFn, PreDeleteHookFn, PreparedWriteEvent, PreQueryHookFn, PreSaveHookFn, ProjectionDefinition, ProjectionDetailScreenDefinition, ProjectionListScreenDefinition, ProjectionTable, ProviderPluginContext, QualifiedEventName, QueryEvent, QueryHandlerDef, QueryHandlerFn, RateLimitPer, RecordHeaderSpec, RecordHeaderSubtitlePart, ReferenceDataDef, Registry, RelationDefinition, ResolvedPiiFlags, RetentionDef, RoleAccessPersonalData, RoleAccessRule, RowAction, RowActionNavigate, RowActionNavigateBase, RowActionWriteHandler, RowFieldExtractor, SaveContext, ScreenDefinition, ScreenFilter, ScreenFilterOp, ScreenNavSugar, ScreenSlots, SecretKeyDefinition, SecretKeyHandle, SecretMintConfirmStep, SecretMintScreenDefinition, SecretNamespaceDefinition, SecretNamespaceHandle, SecretNamespaceOptions, SecretReveal, SecretRevealField, SecretsEditScreenDefinition, SecretsEditSection, SelectFieldDef, SessionUser, SessionUserOrigin, StackBootRequirement, StreamHandlerDef, StreamHandlerFn, Subscribe, TargetRef, TemplateImagesVariableDef, TemplateListVariableDef, TemplateScalarVariableDef, TemplateVariableDef, TemplateVariables, TenantId, TenantWriteTarget, TextFieldDef, ToolbarAction, TranslationEntry, TranslationKeys, TranslationsDef, TranslationValue, TreeAction, TreeActionDef, TreeActionsHandle, TreeChildrenSubscribe, TreeNode, TreeNodeState, UnitKey, UnsafeAppendEventFn, ValidationError, ValidationHookFn, WorkspaceDefinition, WriteEvent, WriteHandlerDef, WriteHandlerFn, WriteResult, } from "./types/index.ts";
|
|
91
91
|
export { DEFAULT_CURRENCIES, DEFAULT_LOCALES, DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, HookPhases, HTTP_ERROR_CODE_PATTERN, isAgentVisibleScreen, isDeliveryErrorCode, isOpenToAllGranted, resolveAgentExposure, } from "./types/index.ts";
|
|
92
92
|
export type { AwaitedEventType, PipelineBuildCtx, PipelineCtx, PipelineDef, StepBuilder, StepDef, StepFailureStrategy, StepInstance, StepKind, StepNamespace, StepResolver, } from "./types/step.ts";
|
|
93
93
|
export { runValidation } from "./validation.ts";
|
|
@@ -391,7 +391,7 @@ function projectMetrics(metrics, indices, keptScreenQns) {
|
|
|
391
391
|
return undefined;
|
|
392
392
|
let changed = false;
|
|
393
393
|
const next = metrics.map((m) => {
|
|
394
|
-
if (
|
|
394
|
+
if (m.navigate === undefined)
|
|
395
395
|
return m;
|
|
396
396
|
if (keepMetricNavigate(m.navigate, indices, keptScreenQns))
|
|
397
397
|
return m;
|
|
@@ -27,6 +27,7 @@ export declare function resolveJobTriggers(state: RegistryState): void;
|
|
|
27
27
|
export declare function validateLiveEntities(state: RegistryState): void;
|
|
28
28
|
export declare function validateBootGates(state: RegistryState): void;
|
|
29
29
|
export declare function validateJobBackoff(state: RegistryState): void;
|
|
30
|
+
export declare function validateMaxDefers(state: RegistryState): void;
|
|
30
31
|
export declare function validateMaxPerTenant(state: RegistryState): void;
|
|
31
32
|
export declare function validateExtensionUsageTargets(state: RegistryState): void;
|
|
32
33
|
export declare function computeHasRateLimitedHandler(state: RegistryState): void;
|
|
@@ -767,6 +767,14 @@ export function validateJobBackoff(state) {
|
|
|
767
767
|
}
|
|
768
768
|
}
|
|
769
769
|
}
|
|
770
|
+
export function validateMaxDefers(state) {
|
|
771
|
+
for (const [jobName, jobDef] of state.jobMap) {
|
|
772
|
+
const { maxDefers } = jobDef;
|
|
773
|
+
if (maxDefers !== undefined && (!Number.isInteger(maxDefers) || maxDefers <= 0)) {
|
|
774
|
+
throw new Error(`Job "${jobName}" maxDefers must be a positive integer (got ${maxDefers})`);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
770
778
|
export function validateMaxPerTenant(state) {
|
|
771
779
|
for (const [jobName, jobDef] of state.jobMap) {
|
|
772
780
|
const resolved = resolveMaxPerTenant(jobDef);
|
package/dist/engine/registry.js
CHANGED
|
@@ -3,7 +3,7 @@ import { dedupeFeatures } from "./dedupe-features.js";
|
|
|
3
3
|
import { buildRegistryFacade } from "./registry-facade.js";
|
|
4
4
|
import { populateClaimsAndAuth, populateConfigKeys, populateEvents, populateExtensionsAndSeeds, populateFeatureCore, populateHandlers, populateHooks, populateJobsAndNotifications, populateMetricsAndSecrets, populateProjectionsAndTables, populateScreensNavWorkspaces, populateSystemEvents, populateTranslations, } from "./registry-ingest.js";
|
|
5
5
|
import { createInitialState } from "./registry-state.js";
|
|
6
|
-
import { applyExtensionUsages, autoWireSoftDeleteJobs, buildEntityEventUpcasterChains, buildEventUpcasterChains, buildImplicitProjections, buildIncomingRelations, buildSearchableSortableCaches, computeHasRateLimitedHandler, finalizeWorkspaceNavMembership, populateHandlerEntityMappings, publishEventPiiCatalog, resolveJobTriggers, resolveNotificationTriggersAndRegisterHooks, validateBootGates, validateEntityHookTargets, validateEventMigrationVersions, validateExtensionSelectors, validateExtensionUsageTargets, validateFieldAccessHandlersAreEntityMapped, validateJobBackoff, validateLifecycleHookTargets, validateLiveEntities, validateMaxPerTenant, validateNotificationRecordMappings, validateNotificationRenamedFrom, validateProjectionApplyKeys, validateRelationTargetsExist, validateRequiredFeatures, } from "./registry-validate.js";
|
|
6
|
+
import { applyExtensionUsages, autoWireSoftDeleteJobs, buildEntityEventUpcasterChains, buildEventUpcasterChains, buildImplicitProjections, buildIncomingRelations, buildSearchableSortableCaches, computeHasRateLimitedHandler, finalizeWorkspaceNavMembership, populateHandlerEntityMappings, publishEventPiiCatalog, resolveJobTriggers, resolveNotificationTriggersAndRegisterHooks, validateBootGates, validateEntityHookTargets, validateEventMigrationVersions, validateExtensionSelectors, validateExtensionUsageTargets, validateFieldAccessHandlersAreEntityMapped, validateJobBackoff, validateLifecycleHookTargets, validateLiveEntities, validateMaxDefers, validateMaxPerTenant, validateNotificationRecordMappings, validateNotificationRenamedFrom, validateProjectionApplyKeys, validateRelationTargetsExist, validateRequiredFeatures, } from "./registry-validate.js";
|
|
7
7
|
// This is where the magic happens. By "magic" I mean: precomputed maps.
|
|
8
8
|
// I build everything once at boot (hooks, relations, searchable fields, ...)
|
|
9
9
|
// so nothing has to iterate over objects at runtime. O(1) instead of O(n*m).
|
|
@@ -49,6 +49,7 @@ export function createRegistry(rawFeatures) {
|
|
|
49
49
|
validateBootGates(state);
|
|
50
50
|
validateLiveEntities(state);
|
|
51
51
|
validateJobBackoff(state);
|
|
52
|
+
validateMaxDefers(state);
|
|
52
53
|
validateMaxPerTenant(state);
|
|
53
54
|
validateExtensionUsageTargets(state);
|
|
54
55
|
computeHasRateLimitedHandler(state);
|
|
@@ -3,6 +3,7 @@ import { moneyPayloadToMinorUnits } from "../db/money.js";
|
|
|
3
3
|
import { isValidIanaTimeZone } from "../time/index.js";
|
|
4
4
|
import { assertUnreachable } from "../utils/index.js";
|
|
5
5
|
import { withDerivedCells } from "./embedded-derived.js";
|
|
6
|
+
import { isValidIban } from "./iban.js";
|
|
6
7
|
import { DEFAULT_CURRENCIES } from "./types/index.js";
|
|
7
8
|
const MONTH_PATTERN = /^\d{4}-(0[1-9]|1[0-2])$/;
|
|
8
9
|
// True if `n` carries at most `scale` decimal places. A relative epsilon
|
|
@@ -107,6 +108,14 @@ export function fieldToZod(field, currencies, opts = {}) {
|
|
|
107
108
|
schema = schema.email();
|
|
108
109
|
if (field.format === "url")
|
|
109
110
|
schema = schema.url();
|
|
111
|
+
if (field.format === "iban") {
|
|
112
|
+
// "" stays valid for an optional field; `required` rejects it via min(1) below.
|
|
113
|
+
schema = schema.superRefine((value, ctx) => {
|
|
114
|
+
if (value !== "" && !isValidIban(value)) {
|
|
115
|
+
ctx.addIssue({ code: "invalid_format", format: "iban", input: value });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
110
119
|
if (field.format === "month") {
|
|
111
120
|
// "" stays valid for an optional field; `required` rejects it via min(1) below.
|
|
112
121
|
schema = schema.refine((value) => value === "" || MONTH_PATTERN.test(value), {
|
|
@@ -8,10 +8,10 @@ export declare function isEditLayoutScreen(screen: ScreenDefinition): screen is
|
|
|
8
8
|
export declare function isExtensionEditSection(section: EditSectionSpec): section is EditExtensionSection;
|
|
9
9
|
export declare function isFieldsEditSection(section: EditSectionSpec): section is EditFieldsSection;
|
|
10
10
|
export declare function isWriteFormEditSection(section: EditSectionSpec): section is EditWriteFormSection;
|
|
11
|
-
/** Structural
|
|
12
|
-
*
|
|
11
|
+
/** Structural reader contract for every section that can carry `fields` and/or `groups`: the
|
|
12
|
+
* `EditFieldsSection` union members and `EditWriteFormSection` all assign without narrowing. */
|
|
13
13
|
export type FieldsOrGroupsSection = {
|
|
14
|
-
readonly fields
|
|
14
|
+
readonly fields?: readonly EditFieldSpec[];
|
|
15
15
|
readonly groups?: readonly {
|
|
16
16
|
readonly title: string;
|
|
17
17
|
readonly fields: readonly EditFieldSpec[];
|
|
@@ -73,8 +73,7 @@ export function isWriteFormEditSection(section) {
|
|
|
73
73
|
// one runs after the fields-XOR-groups check, collectors run without it and must
|
|
74
74
|
// not drop a source (fw#2986).
|
|
75
75
|
export function sectionFieldSpecs(section) {
|
|
76
|
-
|
|
77
|
-
return [...section.fields, ...(section.groups?.flatMap((group) => group.fields) ?? [])];
|
|
76
|
+
return [...(section.fields ?? []), ...(section.groups?.flatMap((group) => group.fields) ?? [])];
|
|
78
77
|
}
|
|
79
78
|
// Type guard — narrows FieldRenderer to FormatSpec. Useful for renderer
|
|
80
79
|
// authors who branch on the three FieldRenderer variants without manual
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { requestedTenantIds, unsafeRawForDeclaredStep } from "../../db/tenant-db.js";
|
|
2
2
|
import { InternalError } from "../../errors/classes.js";
|
|
3
|
+
import { assertReason } from "../escape-hatch-reason.js";
|
|
3
4
|
import { SYSTEM_TENANT_ID } from "../types/identifiers.js";
|
|
4
5
|
// unsafeRaw fails closed without the handler's escapeHatch (or systemScope) and reports the use.
|
|
5
6
|
export function readSourceFor(ctx, unsafeAllTenants) {
|
|
@@ -12,6 +13,7 @@ export function readSourceFor(ctx, unsafeAllTenants) {
|
|
|
12
13
|
message: "unsafeAllTenants on a read step must be { reason: string }",
|
|
13
14
|
});
|
|
14
15
|
}
|
|
16
|
+
assertReason("unsafeAllTenants", unsafeAllTenants.reason);
|
|
15
17
|
return unsafeRawForDeclaredStep(ctx.systemDb ?? ctx.db, unsafeAllTenants.reason);
|
|
16
18
|
}
|
|
17
19
|
// TenantDb silently narrows a foreign where.tenantId to the caller's scope; the step keeps that
|
|
@@ -7,7 +7,7 @@ export type { ExtensionOptionsArgs, ExtensionOptionsFor, KumikoExtensionOptionsM
|
|
|
7
7
|
export type { BootCheckContext, BootCheckFn, BootOptionName, EntityObjectDefinition, FeatureDefinition, FeatureMetricDef, FeatureMetricType, FeatureRegistrar, HookDefinition, MetricOptions, Registry, SecretKeyDefinition, SecretKeyHandle, SecretNamespaceDefinition, SecretNamespaceHandle, SecretNamespaceOptions, SecretOptions, StackBootRequirement, StoreTableDef, StoreTableEntry, StoreTableOptions, UiHintOption, UiHints, } from "@cosmicdrift/kumiko-types/feature";
|
|
8
8
|
export type { FieldIconKey } from "@cosmicdrift/kumiko-types/field-icon";
|
|
9
9
|
export type { AnyFileFieldDef, BigIntFieldDef, BooleanFieldDef, ClientDerivedFieldDef, DateFieldDef, DecimalFieldDef, DefaultCurrency, DeriveContext, DerivedFieldDef, DerivedFieldsMap, DerivedValueType, EmbeddedDerivedCellDef, EmbeddedFieldDef, EmbeddedSubFieldDef, EntityDefinition, EntityEventMigration, EntityIndexDef, FieldAccess, FieldDefinition, FieldsMap, FileFieldDef, FilesFieldDef, Findability, ImageFieldDef, ImagesFieldDef, JsonbFieldDef, LocatedTimestampFieldDef, LongTextFieldDef, LongTextFindability, MoneyCurrencySource, MoneyFieldDef, MultiSelectFieldDef, NumberFieldDef, OptionsQueryPayload, OptionsQueryPayloadValue, ParentRefDef, PersonalAnnotations, PersonalAnnotationsLongText, PersonalAnnotationsNoFind, PersonalSubject, ReferenceFieldDef, ResolvedPiiFlags, RetentionDef, SelectFieldDef, SelectOptionTone, TextFieldDef, TimestampFieldDef, TransitionMap, TzFieldDef, } from "@cosmicdrift/kumiko-types/fields";
|
|
10
|
-
export type { AccessRule, ActiveMembership, ActiveMembershipRejection, ActiveMembershipResult, AgentExposure, AgentHandlerHints, AgentRisk, AggregateStreamHandle, AppContext, AppendEventArgs, AppendEventFn, AuthClaimsContext, AuthClaimsFn, AuthClaimsHookDef, BeforeTransactionPhase, BeforeTransactionResult, CamelToKebab, ChatSendFailureCode, ClaimKeyDefinition, ClaimKeyHandle, ClaimKeyJsType, ClaimKeyType, DeclarativeEventMigration, DeliveryErrorCode, DeliveryFailureCode, DeliverySkipReason, DispatchWriteRef, EntityRef, EscapeHatchAuditSink, EscapeHatchDeclaration, EscapeHatchKind, EscapeHatchReporter, EscapeHatchTarget, EscapeHatchUseEvent, EventDef, EventMigrationDef, EventPiiFields, EventPiiStance, EventUpcastCtx, EventUpcastFn, FetchForWritingArgs, HandlerContext, HandlerRef, JobContext, JobRunnerRef, JobTriggerEvent, MemberReader, NameOrRef, NotifyDeferred, NotifyDelivery, NotifyDeliveryStatus, NotifyDispatched, NotifyFactory, NotifyFn, NotifyJobDispatcher, NotifyOptions, NotifyPriority, NotifyResult, OpenToAllAccessRule, OpenToAllDeclaration, OpenToAllPersonalData, PayloadBucketNormalization, PayloadRateLimitOption, PreparedWriteEvent, ProviderPluginContext, QualifiedEventName, QueryEvent, QueryHandlerDef, QueryHandlerFn, RateLimitDeclaration, RateLimitDisabled, RateLimitOption, RateLimitOptions, RateLimitPer, RoleAccessPersonalData, RoleAccessRule, SessionUser, SessionUserOrigin, StreamHandlerDef, StreamHandlerFn, TenantWriteTarget, TryAppendEventFn, TryAppendEventResult, UnsafeAppendEventFn, WriteEvent, WriteHandlerDef, WriteHandlerFn, WriteResult, } from "@cosmicdrift/kumiko-types/handlers";
|
|
10
|
+
export type { AccessRule, ActiveMembership, ActiveMembershipRejection, ActiveMembershipResult, AgentExposure, AgentHandlerHints, AgentRisk, AggregateStreamHandle, AppContext, AppendEventArgs, AppendEventFn, AuthClaimsContext, AuthClaimsFn, AuthClaimsHookDef, BeforeTransactionPhase, BeforeTransactionResult, CamelToKebab, ChatSendFailureCode, ClaimKeyDefinition, ClaimKeyHandle, ClaimKeyJsType, ClaimKeyType, DeclarativeEventMigration, DeliveryErrorCode, DeliveryFailureCode, DeliverySkipReason, DispatchWriteRef, EntityRef, EscapeHatchAuditSink, EscapeHatchDeclaration, EscapeHatchKind, EscapeHatchReporter, EscapeHatchTarget, EscapeHatchUseEvent, EventDef, EventMigrationDef, EventPiiFields, EventPiiStance, EventUpcastCtx, EventUpcastFn, FetchForWritingArgs, HandlerContext, HandlerRef, JobContext, JobDeferral, JobRunnerRef, JobTriggerEvent, MemberReader, NameOrRef, NotifyDeferred, NotifyDelivery, NotifyDeliveryStatus, NotifyDispatched, NotifyFactory, NotifyFn, NotifyJobDispatcher, NotifyOptions, NotifyPriority, NotifyResult, OpenToAllAccessRule, OpenToAllDeclaration, OpenToAllPersonalData, PayloadBucketNormalization, PayloadRateLimitOption, PreparedWriteEvent, ProviderPluginContext, QualifiedEventName, QueryEvent, QueryHandlerDef, QueryHandlerFn, RateLimitDeclaration, RateLimitDisabled, RateLimitOption, RateLimitOptions, RateLimitPer, RoleAccessPersonalData, RoleAccessRule, SessionUser, SessionUserOrigin, StreamHandlerDef, StreamHandlerFn, TenantWriteTarget, TryAppendEventFn, TryAppendEventResult, UnsafeAppendEventFn, WriteEvent, WriteHandlerDef, WriteHandlerFn, WriteResult, } from "@cosmicdrift/kumiko-types/handlers";
|
|
11
11
|
export { DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, declaredRateLimitOptions, HTTP_ERROR_CODE_PATTERN, isDeliveryErrorCode, isOpenToAllGranted, isRateLimitDisabled, isRateLimitOption, isUiAccessGranted, } from "@cosmicdrift/kumiko-types/handlers";
|
|
12
12
|
export type { DeleteContext, EntityHookMap, HookMap, HookOwner, HookPhase, LifecycleHookFn, LifecycleResult, OwnedFn, PhasedHook, PostDeleteBatchHookFn, PostDeleteHookFn, PostQueryHookFn, PostSaveBatchHookFn, PostSaveHookFn, PreDeleteHookFn, PreQueryHookFn, PreSaveHookFn, SaveContext, SearchPayloadContributorFn, ValidationError, ValidationHookFn, } from "@cosmicdrift/kumiko-types/hooks";
|
|
13
13
|
export type { HttpRouteDefinition, HttpRouteHandler, HttpRouteHandlerDeps, HttpRouteMethod, } from "@cosmicdrift/kumiko-types/http-route";
|
|
@@ -18,7 +18,7 @@ export type { FromRule, FromRuleKind, OwnershipClause, OwnershipMap, OwnershipRe
|
|
|
18
18
|
export type { EntityProjectionExtension, MspErrorMode, MspErrorPolicy, MultiStreamApplyFn, MultiStreamProjectionDefinition, ProjectionDefinition, ProjectionRowIdOf, ProjectionTable, SingleStreamApplyFn, } from "@cosmicdrift/kumiko-types/projection";
|
|
19
19
|
export type { BelongsToRelation, EntityRelations, HasManyRelation, ManyToManyRelation, RelationDefinition, } from "@cosmicdrift/kumiko-types/relations";
|
|
20
20
|
export type { ActionFormScreenDefinition, ConfigEditScreenDefinition, CustomScreenDefinition, CustomScreenRoute, DashboardChartMarkerKind, DashboardChartPanel, DashboardChartRangeOption, DashboardChartRanges, DashboardCurrencyFormat, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListPanel, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelGate, DashboardPanelVisibility, DashboardProgressListPanel, DashboardProgressTone, DashboardRecordBinding, DashboardRefresh, DashboardRelativeTimeFormat, DashboardRelativeTimeParam, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupPanel, DashboardStatPanel, DashboardText, DashboardTextBlock, DashboardTextPanel, DashboardTextParam, DashboardValueFormat, EditExtensionSection, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EditWriteFormSection, EmbeddedListEditSpec, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityListExpandableRow, EntityListScreenDefinition, FieldCondition, FieldFormatRegistry, FieldRenderer, FormatSpec, FormFieldDerivation, FormWidth, ListColumnSpec, ListEmptyStateSpec, ListFacetSpec, ListPaginationMode, ListSortDir, ListSortSpec, MetricNavigate, MetricSpec, PlatformComponent, ProjectionDetailScreenDefinition, ProjectionListScreenDefinition, RecordHeaderSpec, RecordHeaderSubtitlePart, RowAction, RowActionNavigate, RowActionNavigateBase, RowActionWriteHandler, RowFieldExtractor, ScreenDefinition, ScreenFilter, ScreenFilterOp, ScreenNavSugar, ScreenSlots, SecretMintConfirmStep, SecretMintScreenDefinition, SecretReveal, SecretRevealField, SecretsEditScreenDefinition, SecretsEditSection, ToolbarAction, UnitKey, } from "@cosmicdrift/kumiko-types/screen";
|
|
21
|
-
export {
|
|
21
|
+
export { relatedListGroupHeaderLabel, relatedListGroupKey, } from "@cosmicdrift/kumiko-types/screen";
|
|
22
22
|
export type { TargetRef } from "@cosmicdrift/kumiko-types/target-ref";
|
|
23
23
|
export type { Subscribe, TreeAction, TreeActionDef, TreeActionsHandle, TreeChildrenSubscribe, TreeNode, TreeNodeState, } from "@cosmicdrift/kumiko-types/tree-node";
|
|
24
24
|
export type { WebSocketConnection, WebSocketMessageData, WebSocketRouteConnectDeps, WebSocketRouteDefinition, WebSocketSessionHandlers, } from "@cosmicdrift/kumiko-types/websocket-route";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export { isAgentVisibleScreen, resolveAgentExposure, } from "@cosmicdrift/kumiko-types/agent-exposure";
|
|
4
4
|
export { DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, declaredRateLimitOptions, HTTP_ERROR_CODE_PATTERN, isDeliveryErrorCode, isOpenToAllGranted, isRateLimitDisabled, isRateLimitOption, isUiAccessGranted, } from "@cosmicdrift/kumiko-types/handlers";
|
|
5
5
|
export { isSystemTenant, isUuid, parseTenantId, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-types/identifiers";
|
|
6
|
-
export {
|
|
6
|
+
export { relatedListGroupHeaderLabel, relatedListGroupKey, } from "@cosmicdrift/kumiko-types/screen";
|
|
7
7
|
export { DEFAULT_CURRENCIES, DEFAULT_LOCALES, isFileField } from "../field-helpers.js";
|
|
8
8
|
export { resolveName, withResponseData } from "../handler-helpers.js";
|
|
9
9
|
export { HookPhases } from "../hook-helpers.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type * from "@cosmicdrift/kumiko-types/screen";
|
|
2
|
-
export {
|
|
2
|
+
export { relatedListGroupHeaderLabel, relatedListGroupKey, } from "@cosmicdrift/kumiko-types/screen";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { relatedListGroupHeaderLabel, relatedListGroupKey, } from "@cosmicdrift/kumiko-types/screen";
|
|
@@ -29,6 +29,7 @@ type JobsBlock = {
|
|
|
29
29
|
readonly onJobStart?: JobRunnerOptions["onJobStart"];
|
|
30
30
|
readonly onJobComplete?: JobRunnerOptions["onJobComplete"];
|
|
31
31
|
readonly onJobFailed?: JobRunnerOptions["onJobFailed"];
|
|
32
|
+
readonly onJobDeferred?: JobRunnerOptions["onJobDeferred"];
|
|
32
33
|
readonly onJobQueued?: JobRunnerOptions["onJobQueued"];
|
|
33
34
|
readonly onJobDropped?: JobRunnerOptions["onJobDropped"];
|
|
34
35
|
};
|
package/dist/entrypoint/index.js
CHANGED
|
@@ -174,6 +174,7 @@ function buildJobRunnerWithHook(registry, context, jobs, consumerLane, lifecycle
|
|
|
174
174
|
onJobStart: jobs.onJobStart,
|
|
175
175
|
onJobComplete: jobs.onJobComplete,
|
|
176
176
|
onJobFailed: jobs.onJobFailed,
|
|
177
|
+
onJobDeferred: jobs.onJobDeferred,
|
|
177
178
|
onJobQueued: jobs.onJobQueued,
|
|
178
179
|
onJobDropped: jobs.onJobDropped,
|
|
179
180
|
});
|
|
@@ -41,7 +41,4 @@ export declare function getUnscopedAggregateStreamMaxVersion(db: DbRunner, aggre
|
|
|
41
41
|
export declare function getUnscopedStreamMaxVersionForSeed(...args: Parameters<typeof getUnscopedAggregateStreamMaxVersion>): ReturnType<typeof getUnscopedAggregateStreamMaxVersion>;
|
|
42
42
|
export declare function getEventsHighWaterMark(db: DbRunner): Promise<bigint>;
|
|
43
43
|
export declare function loadEventsAfterVersion(db: DbRunner, aggregateId: string, tenantId: TenantId, afterVersion: number): Promise<readonly StoredEvent[]>;
|
|
44
|
-
export declare const LOAD_ALL_EVENTS_ROW_LIMIT = 100000;
|
|
45
|
-
/** Buffers ALL matching events in memory — a memory cliff for large stores. Use `streamAllEventsByType` (yields batchwise) for production reads; this is test-only in practice. */
|
|
46
|
-
export declare function loadAllEventsByType(db: DbRunner, aggregateType: string, rowLimit?: number): Promise<readonly StoredEvent[]>;
|
|
47
44
|
export declare function streamAllEventsByType(db: DbRunner, aggregateType: string, batchSize?: number, signal?: AbortSignal): AsyncIterable<StoredEvent>;
|
|
@@ -284,30 +284,6 @@ export async function loadEventsAfterVersion(db, aggregateId, tenantId, afterVer
|
|
|
284
284
|
const rows = await selectMany(db, eventsTable, { aggregateId, tenantId, version: { gt: afterVersion } }, { orderBy: { col: "version", direction: "asc" } });
|
|
285
285
|
return rows.map(toStoredEvent);
|
|
286
286
|
}
|
|
287
|
-
// Load every event for an aggregate_type across all tenants. Ordered by
|
|
288
|
-
// (created_at, id) — chronological replay order for projection rebuilds.
|
|
289
|
-
// Mostly called from tests today — production rebuild goes through
|
|
290
|
-
// projection-rebuild's own streaming path.
|
|
291
|
-
//
|
|
292
|
-
// Fails loud past LOAD_ALL_EVENTS_ROW_LIMIT rather than silently buffering
|
|
293
|
-
// an unbounded result set — that's the memory cliff this guard exists to
|
|
294
|
-
// prevent.
|
|
295
|
-
export const LOAD_ALL_EVENTS_ROW_LIMIT = 100_000;
|
|
296
|
-
/** Buffers ALL matching events in memory — a memory cliff for large stores. Use `streamAllEventsByType` (yields batchwise) for production reads; this is test-only in practice. */
|
|
297
|
-
export async function loadAllEventsByType(db, aggregateType, rowLimit = LOAD_ALL_EVENTS_ROW_LIMIT) {
|
|
298
|
-
const rows = await selectMany(db, eventsTable, { aggregateType }, {
|
|
299
|
-
orderBy: [
|
|
300
|
-
{ col: "createdAt", direction: "asc" },
|
|
301
|
-
{ col: "id", direction: "asc" },
|
|
302
|
-
],
|
|
303
|
-
limit: rowLimit + 1,
|
|
304
|
-
});
|
|
305
|
-
if (rows.length > rowLimit) {
|
|
306
|
-
throw new Error(`loadAllEventsByType("${aggregateType}") exceeds ${rowLimit} rows — ` +
|
|
307
|
-
"use streamAllEventsByType instead of buffering the full result set in memory.");
|
|
308
|
-
}
|
|
309
|
-
return rows.map(toStoredEvent);
|
|
310
|
-
}
|
|
311
287
|
// Stream every event for an aggregate_type across all tenants, batchwise
|
|
312
288
|
// instead of buffered. Memory-bounded: never more than `batchSize` rows
|
|
313
289
|
// resident. Cursor walks `events.id` (bigserial monotonic, but ids are
|
|
@@ -317,8 +293,7 @@ export async function loadAllEventsByType(db, aggregateType, rowLimit = LOAD_ALL
|
|
|
317
293
|
// (projection-rebuild, tests) that don't need live, just-committed rows.
|
|
318
294
|
//
|
|
319
295
|
// Use case: projection-rebuild on a large event log (>100k events per
|
|
320
|
-
// aggregate-type)
|
|
321
|
-
// in batches and the caller accumulates only what it needs.
|
|
296
|
+
// aggregate-type); the caller accumulates only what it needs.
|
|
322
297
|
//
|
|
323
298
|
// Default batchSize 1000 — trade-off between DB round-trips (smaller =
|
|
324
299
|
// more queries) and memory (larger = more resident).
|
|
@@ -3,7 +3,7 @@ export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch, type PiiBa
|
|
|
3
3
|
export { type DeleteRowsWithoutReplayableStreamArgs, deleteRowsWithoutReplayableStream, } from "../db/queries/event-store-orphan-rows.ts";
|
|
4
4
|
export { type ArchiveStreamArgs, archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, restoreStream, } from "./archive.ts";
|
|
5
5
|
export { ArchivedStreamError, IdempotentAppendConflictError, SeedTimeOrderError, VersionConflictError, } from "./errors.ts";
|
|
6
|
-
export { append, EVENTS_PUBSUB_CHANNEL, type EventMetadata, type EventToAppend, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed,
|
|
6
|
+
export { append, EVENTS_PUBSUB_CHANNEL, type EventMetadata, type EventToAppend, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, loadAggregateAsOf, loadEventsAfterVersion, type StoredEvent, streamAllEventsByType, } from "./event-store.ts";
|
|
7
7
|
export { createEventsTable, eventsTable } from "./events-schema.ts";
|
|
8
8
|
export { appendProvenanceEvent, type ProvenanceEventInput } from "./provenance-append.ts";
|
|
9
9
|
export { createRebuildDeadLetterTable, listRebuildDeadLetters, type RebuildDeadLetterRow, rebuildDeadLetterTable, recordRebuildDeadLetters, type SkippedApply, } from "./rebuild-dead-letter.ts";
|
|
@@ -3,7 +3,7 @@ export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch, } from "..
|
|
|
3
3
|
export { deleteRowsWithoutReplayableStream, } from "../db/queries/event-store-orphan-rows.js";
|
|
4
4
|
export { archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, restoreStream, } from "./archive.js";
|
|
5
5
|
export { ArchivedStreamError, IdempotentAppendConflictError, SeedTimeOrderError, VersionConflictError, } from "./errors.js";
|
|
6
|
-
export { append, EVENTS_PUBSUB_CHANNEL, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed,
|
|
6
|
+
export { append, EVENTS_PUBSUB_CHANNEL, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, loadAggregateAsOf, loadEventsAfterVersion, streamAllEventsByType, } from "./event-store.js";
|
|
7
7
|
export { createEventsTable, eventsTable } from "./events-schema.js";
|
|
8
8
|
export { appendProvenanceEvent } from "./provenance-append.js";
|
|
9
9
|
export { createRebuildDeadLetterTable, listRebuildDeadLetters, rebuildDeadLetterTable, recordRebuildDeadLetters, } from "./rebuild-dead-letter.js";
|
|
@@ -5,6 +5,7 @@ import { ensureSnapshotVersionColumn, upsertSnapshot } from "../db/queries/event
|
|
|
5
5
|
import { selectMany } from "../db/query.js";
|
|
6
6
|
import { tableExists } from "../db/schema-inspection.js";
|
|
7
7
|
import { unsafePushTables } from "../db/table-push.js";
|
|
8
|
+
import { createFallbackLogger, scrubLogText } from "../logging/index.js";
|
|
8
9
|
import { isStreamArchived } from "./archive.js";
|
|
9
10
|
import { loadEventsAfterVersion } from "./event-store.js";
|
|
10
11
|
// Marten-aligned snapshot store. A snapshot is a point-in-time materialised
|
|
@@ -153,8 +154,12 @@ export async function loadAggregateWithSnapshot(db, aggregateId, tenantId, reduc
|
|
|
153
154
|
snapshotVersion: generationFor(lastDelta.aggregateType),
|
|
154
155
|
});
|
|
155
156
|
}
|
|
156
|
-
catch {
|
|
157
|
+
catch (err) {
|
|
157
158
|
// Best-effort cache write — losing it only costs the next load a replay.
|
|
159
|
+
createFallbackLogger("snapshot").warn("snapshot save failed", {
|
|
160
|
+
aggregateType: lastDelta.aggregateType,
|
|
161
|
+
error: scrubLogText(err instanceof Error ? err.message : String(err)),
|
|
162
|
+
});
|
|
158
163
|
}
|
|
159
164
|
}
|
|
160
165
|
return {
|
|
@@ -14,7 +14,7 @@ export declare const fileRefEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
14
14
|
readonly sensitive?: boolean;
|
|
15
15
|
readonly writeOnly?: boolean;
|
|
16
16
|
readonly readAsInstruction?: boolean;
|
|
17
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
17
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
18
18
|
readonly default?: string;
|
|
19
19
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
20
20
|
readonly multiline?: boolean | {
|
|
@@ -37,7 +37,7 @@ export declare const fileRefEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
37
37
|
readonly sensitive?: boolean;
|
|
38
38
|
readonly writeOnly?: boolean;
|
|
39
39
|
readonly readAsInstruction?: boolean;
|
|
40
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
40
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
41
41
|
readonly default?: string;
|
|
42
42
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
43
43
|
readonly multiline?: boolean | {
|
|
@@ -60,7 +60,7 @@ export declare const fileRefEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
60
60
|
readonly sensitive?: boolean;
|
|
61
61
|
readonly writeOnly?: boolean;
|
|
62
62
|
readonly readAsInstruction?: boolean;
|
|
63
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
63
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
64
64
|
readonly default?: string;
|
|
65
65
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
66
66
|
readonly multiline?: boolean | {
|
|
@@ -95,7 +95,7 @@ export declare const fileRefEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
95
95
|
readonly sensitive?: boolean;
|
|
96
96
|
readonly writeOnly?: boolean;
|
|
97
97
|
readonly readAsInstruction?: boolean;
|
|
98
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
98
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
99
99
|
readonly default?: string;
|
|
100
100
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
101
101
|
readonly multiline?: boolean | {
|
|
@@ -118,7 +118,7 @@ export declare const fileRefEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
118
118
|
readonly sensitive?: boolean;
|
|
119
119
|
readonly writeOnly?: boolean;
|
|
120
120
|
readonly readAsInstruction?: boolean;
|
|
121
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
121
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
122
122
|
readonly default?: string;
|
|
123
123
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
124
124
|
readonly multiline?: boolean | {
|
|
@@ -141,7 +141,7 @@ export declare const fileRefEntity: import("@cosmicdrift/kumiko-types/fields").E
|
|
|
141
141
|
readonly sensitive?: boolean;
|
|
142
142
|
readonly writeOnly?: boolean;
|
|
143
143
|
readonly readAsInstruction?: boolean;
|
|
144
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
144
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
145
145
|
readonly default?: string;
|
|
146
146
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
147
147
|
readonly multiline?: boolean | {
|
|
@@ -13,7 +13,7 @@ export declare const fileRefsTable: import("../db/table-builder.ts").EntityTable
|
|
|
13
13
|
readonly sensitive?: boolean;
|
|
14
14
|
readonly writeOnly?: boolean;
|
|
15
15
|
readonly readAsInstruction?: boolean;
|
|
16
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
16
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
17
17
|
readonly default?: string;
|
|
18
18
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
19
19
|
readonly multiline?: boolean | {
|
|
@@ -36,7 +36,7 @@ export declare const fileRefsTable: import("../db/table-builder.ts").EntityTable
|
|
|
36
36
|
readonly sensitive?: boolean;
|
|
37
37
|
readonly writeOnly?: boolean;
|
|
38
38
|
readonly readAsInstruction?: boolean;
|
|
39
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
39
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
40
40
|
readonly default?: string;
|
|
41
41
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
42
42
|
readonly multiline?: boolean | {
|
|
@@ -59,7 +59,7 @@ export declare const fileRefsTable: import("../db/table-builder.ts").EntityTable
|
|
|
59
59
|
readonly sensitive?: boolean;
|
|
60
60
|
readonly writeOnly?: boolean;
|
|
61
61
|
readonly readAsInstruction?: boolean;
|
|
62
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
62
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
63
63
|
readonly default?: string;
|
|
64
64
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
65
65
|
readonly multiline?: boolean | {
|
|
@@ -94,7 +94,7 @@ export declare const fileRefsTable: import("../db/table-builder.ts").EntityTable
|
|
|
94
94
|
readonly sensitive?: boolean;
|
|
95
95
|
readonly writeOnly?: boolean;
|
|
96
96
|
readonly readAsInstruction?: boolean;
|
|
97
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
97
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
98
98
|
readonly default?: string;
|
|
99
99
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
100
100
|
readonly multiline?: boolean | {
|
|
@@ -117,7 +117,7 @@ export declare const fileRefsTable: import("../db/table-builder.ts").EntityTable
|
|
|
117
117
|
readonly sensitive?: boolean;
|
|
118
118
|
readonly writeOnly?: boolean;
|
|
119
119
|
readonly readAsInstruction?: boolean;
|
|
120
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
120
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
121
121
|
readonly default?: string;
|
|
122
122
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
123
123
|
readonly multiline?: boolean | {
|
|
@@ -140,7 +140,7 @@ export declare const fileRefsTable: import("../db/table-builder.ts").EntityTable
|
|
|
140
140
|
readonly sensitive?: boolean;
|
|
141
141
|
readonly writeOnly?: boolean;
|
|
142
142
|
readonly readAsInstruction?: boolean;
|
|
143
|
-
readonly format?: "email" | "url" | "phone" | "password" | "month";
|
|
143
|
+
readonly format?: "email" | "url" | "phone" | "password" | "month" | "iban";
|
|
144
144
|
readonly default?: string;
|
|
145
145
|
readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
|
|
146
146
|
readonly multiline?: boolean | {
|
|
@@ -412,7 +412,6 @@ export function requiredKeysFromScreen(featureName, screen, options = {}) {
|
|
|
412
412
|
pushKey(out, section.title);
|
|
413
413
|
pushKey(out, section.description);
|
|
414
414
|
pushKey(out, section.submitLabel);
|
|
415
|
-
// kumiko-lint-ignore section-fields-raw writeForm sections carry no groups (EditWriteFormSection)
|
|
416
415
|
for (const f of section.fields) {
|
|
417
416
|
pushEditFieldTextKeys(out, f);
|
|
418
417
|
const fieldName = editFieldName(f);
|
|
@@ -70,6 +70,7 @@ export type JobRunnerOptions = {
|
|
|
70
70
|
onJobStart?: (jobName: string, jobId: string, meta: JobMeta) => void;
|
|
71
71
|
onJobComplete?: (jobName: string, jobId: string, duration: number, logs: JobLogEntry[], outcome?: JobOutcomeMeta) => void;
|
|
72
72
|
onJobFailed?: (jobName: string, jobId: string, error: string, logs: JobLogEntry[], outcome?: JobOutcomeMeta) => void;
|
|
73
|
+
onJobDeferred?: (jobName: string, jobId: string, meta: JobMeta) => void;
|
|
73
74
|
onJobQueued?: (jobName: string, jobId: string, meta: JobQueuedMeta) => void;
|
|
74
75
|
onJobDropped?: (jobName: string, jobId: string, meta: JobDroppedMeta) => void;
|
|
75
76
|
};
|