@cosmicdrift/kumiko-framework 0.254.0 → 0.255.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -116,12 +116,15 @@ function invalidateTenantTimezoneCache(
116
116
  // Runs lifecycle hooks for a handler result. inTransaction hooks fire NOW
117
117
  // (they see the tx via ctx.db when batch/write opens a transaction).
118
118
  // afterCommit hooks are queued into `afterCommitHooks` for the caller to
119
- // flush after commit.
119
+ // flush after commit. Their context is built lazily, without `tx`: by the
120
+ // time they fire the transaction has already committed, so `handlerContext`
121
+ // (built around it) would hand them a dead handle.
120
122
  async function runLifecycle(
121
123
  ctx: DispatchContext,
122
124
  type: string,
123
125
  data: unknown,
124
126
  handlerContext: HandlerContext,
127
+ user: SessionUser,
125
128
  afterCommitHooks: AfterCommitHook[],
126
129
  ): Promise<void> {
127
130
  const { lifecycle } = ctx;
@@ -143,15 +146,29 @@ async function runLifecycle(
143
146
 
144
147
  if (result.kind === "save") {
145
148
  await lifecycle.runPostSave(type, result, handlerContext, HookPhases.inTransaction);
146
- afterCommitHooks.push(() =>
147
- lifecycle.runPostSave(type, result, handlerContext, HookPhases.afterCommit),
148
- );
149
+ afterCommitHooks.push(async () => {
150
+ const afterCommitContext = await buildHandlerContext(
151
+ ctx,
152
+ type,
153
+ user,
154
+ undefined,
155
+ afterCommitHooks,
156
+ );
157
+ await lifecycle.runPostSave(type, result, afterCommitContext, HookPhases.afterCommit);
158
+ });
149
159
  } else if (result.kind === "delete") {
150
160
  await lifecycle.runPreDelete(type, result, handlerContext);
151
161
  await lifecycle.runPostDelete(type, result, handlerContext, HookPhases.inTransaction);
152
- afterCommitHooks.push(() =>
153
- lifecycle.runPostDelete(type, result, handlerContext, HookPhases.afterCommit),
154
- );
162
+ afterCommitHooks.push(async () => {
163
+ const afterCommitContext = await buildHandlerContext(
164
+ ctx,
165
+ type,
166
+ user,
167
+ undefined,
168
+ afterCommitHooks,
169
+ );
170
+ await lifecycle.runPostDelete(type, result, afterCommitContext, HookPhases.afterCommit);
171
+ });
155
172
  }
156
173
  }
157
174
 
@@ -159,8 +176,9 @@ async function runLifecycle(
159
176
  // Used by runBatch (which opens a transaction and flushes afterCommitHooks on commit).
160
177
  //
161
178
  // Contract:
162
- // - `tx` is the active Drizzle transaction handle (or undefined for the no-DB
163
- // fallback path used by tests without a Postgres connection).
179
+ // - `tx` is the active Drizzle transaction handle, or undefined for "no
180
+ // surrounding transaction" — either no Postgres is configured, or the
181
+ // transaction already committed (afterCommit phase).
164
182
  // - `afterCommitHooks` collects deferred side-effects that must only fire
165
183
  // after the transaction commits. The caller flushes them on commit, drops
166
184
  // them on rollback. executeWrite never fires them directly.
@@ -479,7 +497,7 @@ async function executeWriteInner(
479
497
 
480
498
  if (result.isSuccess) {
481
499
  try {
482
- await runLifecycle(ctx, type, result.data, handlerContext, afterCommitHooks);
500
+ await runLifecycle(ctx, type, result.data, handlerContext, user, afterCommitHooks);
483
501
  } catch (e) {
484
502
  return writeFailure(wrapToKumiko(e));
485
503
  }
@@ -86,6 +86,8 @@ export type {
86
86
  ListColumnSpec,
87
87
  ListFacetSpec,
88
88
  ListSortSpec,
89
+ MetricNavigate,
90
+ MetricSpec,
89
91
  PlatformComponent,
90
92
  ProjectionDetailScreenDefinition,
91
93
  ProjectionListScreenDefinition,
@@ -102,6 +104,7 @@ export type {
102
104
  SecretsEditSection,
103
105
  ToolbarAction,
104
106
  } from "../engine/types/screen";
107
+ export { metricField } from "../engine/types/screen";
105
108
  export type { TargetRef } from "../engine/types/target-ref";
106
109
  export type { TreeAction, TreeNode, TreeNodeState } from "../engine/types/tree-node";
107
110
  export type { WorkspaceDefinition } from "../engine/types/workspace";