@cosmicdrift/kumiko-framework 0.372.0 → 0.374.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.
Files changed (38) hide show
  1. package/agents/examples/rate-limiting.md +65 -1
  2. package/agents/widgets.md +1 -0
  3. package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
  4. package/dist/engine/boot-validator/entity-handler.js +47 -16
  5. package/dist/engine/boot-validator/projection-list-screens.js +28 -37
  6. package/dist/engine/boot-validator/query-refs.js +26 -8
  7. package/dist/engine/boot-validator/screens.d.ts +1 -1
  8. package/dist/engine/boot-validator/screens.js +327 -41
  9. package/dist/engine/boot-validator/url-prefill-fields.js +3 -0
  10. package/dist/engine/build-app-schema.js +7 -3
  11. package/dist/engine/entity-list-searchability.d.ts +5 -0
  12. package/dist/engine/entity-list-searchability.js +35 -0
  13. package/dist/engine/feature-ast/extractors/handlers.js +1 -1
  14. package/dist/engine/feature-ast/extractors/hooks.js +8 -8
  15. package/dist/engine/feature-ast/pattern-change-schema.d.ts +150 -6
  16. package/dist/engine/feature-ast/pattern-change-schema.js +4 -3
  17. package/dist/engine/feature-ui-extensions.js +5 -2
  18. package/dist/engine/index.d.ts +2 -1
  19. package/dist/engine/index.js +1 -0
  20. package/dist/engine/paged-list.d.ts +29 -0
  21. package/dist/engine/paged-list.js +56 -0
  22. package/dist/engine/project-app-schema-for-roles.js +37 -6
  23. package/dist/engine/types/index.d.ts +3 -3
  24. package/dist/engine/types/index.js +1 -1
  25. package/dist/files/bind-pending-file-refs.d.ts +31 -1
  26. package/dist/files/bind-pending-file-refs.js +80 -6
  27. package/dist/files/index.d.ts +2 -0
  28. package/dist/files/index.js +1 -0
  29. package/dist/files/load-save-file-refs.js +3 -1
  30. package/dist/i18n/required-surface-keys.js +50 -2
  31. package/dist/pipeline/dispatch-shared.js +55 -35
  32. package/dist/rate-limit/index.d.ts +1 -1
  33. package/dist/rate-limit/resolver.d.ts +1 -1
  34. package/dist/rate-limit/resolver.js +104 -2
  35. package/dist/rate-limit/unlimited-resolver.js +1 -0
  36. package/dist/ui-types/index.d.ts +1 -1
  37. package/package.json +5 -5
  38. package/src/changes.json +74 -0
@@ -27,6 +27,7 @@ import { ZodObject } from "zod";
27
27
  import { collectUrlPrefillFieldsByScreenQn } from "./boot-validator/url-prefill-fields.js";
28
28
  import { buildConfigFeatureSchema, SETTINGS_HUB_FEATURE, } from "./build-config-feature-schema.js";
29
29
  import { isEncryptedAtRest } from "./config-helpers.js";
30
+ import { isListQueryWithoutSearchableFields } from "./entity-list-searchability.js";
30
31
  import { QnTypes, qualifyEntityName } from "./qualified-name.js";
31
32
  export function buildAppSchema(registry, options = {}) {
32
33
  const features = [];
@@ -341,11 +342,14 @@ function projectConfigEditScreen(screen, encryptedConfigKeyQns) {
341
342
  return fields === undefined ? screen : { ...screen, fields };
342
343
  }
343
344
  function projectProjectionListScreen(screen, registry) {
344
- const schema = registry.getQueryHandler(screen.query)?.schema;
345
- const capabilities = deriveProjectionListCapabilities(schema);
345
+ const handler = registry.getQueryHandler(screen.query);
346
+ const capabilities = deriveProjectionListCapabilities(handler?.schema);
347
+ // A search box over an entity without searchable fields would never match.
348
+ const searchable = capabilities.searchable &&
349
+ !isListQueryWithoutSearchableFields(screen.query, handler, (name) => registry.getEntity(name));
346
350
  return {
347
351
  ...screen,
348
- searchable: screen.searchable ?? capabilities.searchable,
352
+ searchable: screen.searchable ?? searchable,
349
353
  sortable: capabilities.sortable,
350
354
  paginated: capabilities.paginated,
351
355
  };
@@ -0,0 +1,5 @@
1
+ import type { EntityDefinition, QueryHandlerDef } from "./types/index.ts";
2
+ export declare function resolveEntityBehindListQuery(queryQn: string, handler: QueryHandlerDef | undefined, lookupEntity: (entityName: string) => EntityDefinition | undefined): EntityDefinition | undefined;
3
+ /** True when the list query is an entity-convention one over an entity with no
4
+ * searchable field — a search box would never match anything. */
5
+ export declare function isListQueryWithoutSearchableFields(queryQn: string, handler: QueryHandlerDef | undefined, lookupEntity: (entityName: string) => EntityDefinition | undefined): boolean;
@@ -0,0 +1,35 @@
1
+ import { ENTITY_CONVENTION_QUERY_BRAND } from "@cosmicdrift/kumiko-types/handlers";
2
+ import { parseQn } from "./qualified-name.js";
3
+ // Mirrors buildSearchableSortableCaches (registry-validate.ts): a `search`
4
+ // payload only matches text fields, embedded sub-fields and references that
5
+ // opted in with `searchable: true`.
6
+ function entityHasSearchableField(entity) {
7
+ return Object.values(entity.fields).some((field) => {
8
+ if (field.type === "embedded") {
9
+ return Object.values(field.schema).some((subField) => subField.searchable === true);
10
+ }
11
+ return (field.type === "text" || field.type === "reference") && field.searchable === true;
12
+ });
13
+ }
14
+ // Entity-convention list queries (ENTITY_CONVENTION_QUERY_BRAND) carry no
15
+ // entity on the handler; the entity name is recovered from the query QN's
16
+ // `<entityName>:list` naming convention. Hand-written handlers resolve to
17
+ // undefined — "capability unknown, no throw".
18
+ export function resolveEntityBehindListQuery(queryQn, handler, lookupEntity) {
19
+ if (handler === undefined || handler[ENTITY_CONVENTION_QUERY_BRAND] !== true)
20
+ return undefined;
21
+ let entityName;
22
+ try {
23
+ entityName = parseQn(queryQn).name.split(":")[0] ?? "";
24
+ }
25
+ catch {
26
+ return undefined;
27
+ }
28
+ return entityName === "" ? undefined : lookupEntity(entityName);
29
+ }
30
+ /** True when the list query is an entity-convention one over an entity with no
31
+ * searchable field — a search box would never match anything. */
32
+ export function isListQueryWithoutSearchableFields(queryQn, handler, lookupEntity) {
33
+ const entity = resolveEntityBehindListQuery(queryQn, handler, lookupEntity);
34
+ return entity !== undefined && !entityHasSearchableField(entity);
35
+ }
@@ -178,7 +178,7 @@ function readHandlerHeaderFields(obj, methodName, sourceFile) {
178
178
  const accessResult = readHeaderField(readObjectPropertyInitializer(obj, "access"), readOptionalAccessRule, methodName, sourceFile, "access must be a recognized AccessRule ({ roles: [...] } or { openToAll: { reason } }), or a reference to one");
179
179
  if (accessResult.kind === "error")
180
180
  return accessResult;
181
- const rateLimitResult = readHeaderField(readObjectPropertyInitializer(obj, "rateLimit"), readOptionalRateLimit, methodName, sourceFile, "rateLimit must be { per, limit, windowSeconds } or { disabled: true, reason }, or a reference to one");
181
+ const rateLimitResult = readHeaderField(readObjectPropertyInitializer(obj, "rateLimit"), readOptionalRateLimit, methodName, sourceFile, "rateLimit must be { per, limit, windowSeconds }, a non-empty list of those, or { disabled: true, reason }, or a reference to one");
182
182
  if (rateLimitResult.kind === "error")
183
183
  return rateLimitResult;
184
184
  const additionalRateLimitsResult = readHeaderField(readObjectPropertyInitializer(obj, "additionalRateLimits"), readOptionalAdditionalRateLimits, methodName, sourceFile, "additionalRateLimits must be an array of { per: { payloadField }, limit, windowSeconds }, or a reference to one");
@@ -1,4 +1,4 @@
1
- import { isEscapeHatchGrant } from "@cosmicdrift/kumiko-types/handlers";
1
+ import { isEscapeHatchGrant, isRateLimitOption } from "@cosmicdrift/kumiko-types/handlers";
2
2
  import { SyntaxKind } from "ts-morph";
3
3
  import { sourceLocationFromNode } from "../source-location.js";
4
4
  import { containsRawRefSentinel, fail, findFunctionLiteral, isPlainObject, ok, readDataLiteralNode, readNameLiteral, readNameOrRef, readNameOrRefOrList, readObjectPropertyInitializer, } from "./shared.js";
@@ -52,6 +52,12 @@ export function readOptionalAccessRule(value) {
52
52
  return undefined;
53
53
  }
54
54
  export function readOptionalRateLimit(value) {
55
+ if (Array.isArray(value)) {
56
+ if (!value.every(isRateLimitOption))
57
+ return undefined;
58
+ const [first, ...rest] = value;
59
+ return first === undefined ? undefined : [first, ...rest];
60
+ }
55
61
  if (!isPlainObject(value))
56
62
  return undefined;
57
63
  if (value["disabled"] === true) {
@@ -63,13 +69,7 @@ export function readOptionalRateLimit(value) {
63
69
  return undefined;
64
70
  return { disabled: true, reason: value["reason"] };
65
71
  }
66
- if (typeof value["per"] !== "string")
67
- return undefined;
68
- if (typeof value["limit"] !== "number")
69
- return undefined;
70
- if (typeof value["windowSeconds"] !== "number")
71
- return undefined;
72
- return value;
72
+ return isRateLimitOption(value) ? value : undefined;
73
73
  }
74
74
  function isPayloadRateLimitOption(value) {
75
75
  if (!isPlainObject(value))
@@ -189,7 +189,31 @@ export declare const PATTERN_SCHEMAS_BY_KIND: {
189
189
  limit: z.ZodNumber;
190
190
  windowSeconds: z.ZodNumber;
191
191
  cost: z.ZodOptional<z.ZodNumber>;
192
- }, z.core.$strict>, z.ZodObject<{
192
+ }, z.core.$strict>, z.ZodTuple<[z.ZodObject<{
193
+ per: z.ZodEnum<{
194
+ ip: "ip";
195
+ "ip+handler": "ip+handler";
196
+ tenant: "tenant";
197
+ "tenant+handler": "tenant+handler";
198
+ user: "user";
199
+ "user+handler": "user+handler";
200
+ }>;
201
+ limit: z.ZodNumber;
202
+ windowSeconds: z.ZodNumber;
203
+ cost: z.ZodOptional<z.ZodNumber>;
204
+ }, z.core.$strict>], z.ZodObject<{
205
+ per: z.ZodEnum<{
206
+ ip: "ip";
207
+ "ip+handler": "ip+handler";
208
+ tenant: "tenant";
209
+ "tenant+handler": "tenant+handler";
210
+ user: "user";
211
+ "user+handler": "user+handler";
212
+ }>;
213
+ limit: z.ZodNumber;
214
+ windowSeconds: z.ZodNumber;
215
+ cost: z.ZodOptional<z.ZodNumber>;
216
+ }, z.core.$strict>>, z.ZodObject<{
193
217
  disabled: z.ZodLiteral<true>;
194
218
  reason: z.ZodString;
195
219
  }, z.core.$strict>]>, z.ZodObject<{
@@ -257,7 +281,31 @@ export declare const PATTERN_SCHEMAS_BY_KIND: {
257
281
  limit: z.ZodNumber;
258
282
  windowSeconds: z.ZodNumber;
259
283
  cost: z.ZodOptional<z.ZodNumber>;
260
- }, z.core.$strict>, z.ZodObject<{
284
+ }, z.core.$strict>, z.ZodTuple<[z.ZodObject<{
285
+ per: z.ZodEnum<{
286
+ ip: "ip";
287
+ "ip+handler": "ip+handler";
288
+ tenant: "tenant";
289
+ "tenant+handler": "tenant+handler";
290
+ user: "user";
291
+ "user+handler": "user+handler";
292
+ }>;
293
+ limit: z.ZodNumber;
294
+ windowSeconds: z.ZodNumber;
295
+ cost: z.ZodOptional<z.ZodNumber>;
296
+ }, z.core.$strict>], z.ZodObject<{
297
+ per: z.ZodEnum<{
298
+ ip: "ip";
299
+ "ip+handler": "ip+handler";
300
+ tenant: "tenant";
301
+ "tenant+handler": "tenant+handler";
302
+ user: "user";
303
+ "user+handler": "user+handler";
304
+ }>;
305
+ limit: z.ZodNumber;
306
+ windowSeconds: z.ZodNumber;
307
+ cost: z.ZodOptional<z.ZodNumber>;
308
+ }, z.core.$strict>>, z.ZodObject<{
261
309
  disabled: z.ZodLiteral<true>;
262
310
  reason: z.ZodString;
263
311
  }, z.core.$strict>]>, z.ZodObject<{
@@ -303,7 +351,31 @@ export declare const PATTERN_SCHEMAS_BY_KIND: {
303
351
  limit: z.ZodNumber;
304
352
  windowSeconds: z.ZodNumber;
305
353
  cost: z.ZodOptional<z.ZodNumber>;
306
- }, z.core.$strict>, z.ZodObject<{
354
+ }, z.core.$strict>, z.ZodTuple<[z.ZodObject<{
355
+ per: z.ZodEnum<{
356
+ ip: "ip";
357
+ "ip+handler": "ip+handler";
358
+ tenant: "tenant";
359
+ "tenant+handler": "tenant+handler";
360
+ user: "user";
361
+ "user+handler": "user+handler";
362
+ }>;
363
+ limit: z.ZodNumber;
364
+ windowSeconds: z.ZodNumber;
365
+ cost: z.ZodOptional<z.ZodNumber>;
366
+ }, z.core.$strict>], z.ZodObject<{
367
+ per: z.ZodEnum<{
368
+ ip: "ip";
369
+ "ip+handler": "ip+handler";
370
+ tenant: "tenant";
371
+ "tenant+handler": "tenant+handler";
372
+ user: "user";
373
+ "user+handler": "user+handler";
374
+ }>;
375
+ limit: z.ZodNumber;
376
+ windowSeconds: z.ZodNumber;
377
+ cost: z.ZodOptional<z.ZodNumber>;
378
+ }, z.core.$strict>>, z.ZodObject<{
307
379
  disabled: z.ZodLiteral<true>;
308
380
  reason: z.ZodString;
309
381
  }, z.core.$strict>]>, z.ZodObject<{
@@ -712,7 +784,31 @@ export declare const patternSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
712
784
  limit: z.ZodNumber;
713
785
  windowSeconds: z.ZodNumber;
714
786
  cost: z.ZodOptional<z.ZodNumber>;
715
- }, z.core.$strict>, z.ZodObject<{
787
+ }, z.core.$strict>, z.ZodTuple<[z.ZodObject<{
788
+ per: z.ZodEnum<{
789
+ ip: "ip";
790
+ "ip+handler": "ip+handler";
791
+ tenant: "tenant";
792
+ "tenant+handler": "tenant+handler";
793
+ user: "user";
794
+ "user+handler": "user+handler";
795
+ }>;
796
+ limit: z.ZodNumber;
797
+ windowSeconds: z.ZodNumber;
798
+ cost: z.ZodOptional<z.ZodNumber>;
799
+ }, z.core.$strict>], z.ZodObject<{
800
+ per: z.ZodEnum<{
801
+ ip: "ip";
802
+ "ip+handler": "ip+handler";
803
+ tenant: "tenant";
804
+ "tenant+handler": "tenant+handler";
805
+ user: "user";
806
+ "user+handler": "user+handler";
807
+ }>;
808
+ limit: z.ZodNumber;
809
+ windowSeconds: z.ZodNumber;
810
+ cost: z.ZodOptional<z.ZodNumber>;
811
+ }, z.core.$strict>>, z.ZodObject<{
716
812
  disabled: z.ZodLiteral<true>;
717
813
  reason: z.ZodString;
718
814
  }, z.core.$strict>]>, z.ZodObject<{
@@ -779,7 +875,31 @@ export declare const patternSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
779
875
  limit: z.ZodNumber;
780
876
  windowSeconds: z.ZodNumber;
781
877
  cost: z.ZodOptional<z.ZodNumber>;
782
- }, z.core.$strict>, z.ZodObject<{
878
+ }, z.core.$strict>, z.ZodTuple<[z.ZodObject<{
879
+ per: z.ZodEnum<{
880
+ ip: "ip";
881
+ "ip+handler": "ip+handler";
882
+ tenant: "tenant";
883
+ "tenant+handler": "tenant+handler";
884
+ user: "user";
885
+ "user+handler": "user+handler";
886
+ }>;
887
+ limit: z.ZodNumber;
888
+ windowSeconds: z.ZodNumber;
889
+ cost: z.ZodOptional<z.ZodNumber>;
890
+ }, z.core.$strict>], z.ZodObject<{
891
+ per: z.ZodEnum<{
892
+ ip: "ip";
893
+ "ip+handler": "ip+handler";
894
+ tenant: "tenant";
895
+ "tenant+handler": "tenant+handler";
896
+ user: "user";
897
+ "user+handler": "user+handler";
898
+ }>;
899
+ limit: z.ZodNumber;
900
+ windowSeconds: z.ZodNumber;
901
+ cost: z.ZodOptional<z.ZodNumber>;
902
+ }, z.core.$strict>>, z.ZodObject<{
783
903
  disabled: z.ZodLiteral<true>;
784
904
  reason: z.ZodString;
785
905
  }, z.core.$strict>]>, z.ZodObject<{
@@ -824,7 +944,31 @@ export declare const patternSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
824
944
  limit: z.ZodNumber;
825
945
  windowSeconds: z.ZodNumber;
826
946
  cost: z.ZodOptional<z.ZodNumber>;
827
- }, z.core.$strict>, z.ZodObject<{
947
+ }, z.core.$strict>, z.ZodTuple<[z.ZodObject<{
948
+ per: z.ZodEnum<{
949
+ ip: "ip";
950
+ "ip+handler": "ip+handler";
951
+ tenant: "tenant";
952
+ "tenant+handler": "tenant+handler";
953
+ user: "user";
954
+ "user+handler": "user+handler";
955
+ }>;
956
+ limit: z.ZodNumber;
957
+ windowSeconds: z.ZodNumber;
958
+ cost: z.ZodOptional<z.ZodNumber>;
959
+ }, z.core.$strict>], z.ZodObject<{
960
+ per: z.ZodEnum<{
961
+ ip: "ip";
962
+ "ip+handler": "ip+handler";
963
+ tenant: "tenant";
964
+ "tenant+handler": "tenant+handler";
965
+ user: "user";
966
+ "user+handler": "user+handler";
967
+ }>;
968
+ limit: z.ZodNumber;
969
+ windowSeconds: z.ZodNumber;
970
+ cost: z.ZodOptional<z.ZodNumber>;
971
+ }, z.core.$strict>>, z.ZodObject<{
828
972
  disabled: z.ZodLiteral<true>;
829
973
  reason: z.ZodString;
830
974
  }, z.core.$strict>]>, z.ZodObject<{
@@ -157,6 +157,7 @@ const rateLimitOptionSchema = z
157
157
  cost: z.number().optional(),
158
158
  })
159
159
  .strict();
160
+ const rateLimitOptionListSchema = z.tuple([rateLimitOptionSchema], rateLimitOptionSchema);
160
161
  const additionalRateLimitsSchema = z.array(z
161
162
  .object({
162
163
  per: z.object({ payloadField: z.string() }).strict(),
@@ -247,7 +248,7 @@ const WRITE_HANDLER_PATTERN_HEADER_SHAPE = {
247
248
  ...WRITE_HANDLER_HEADER_SHAPE,
248
249
  access: orRawRef(accessRuleSchema),
249
250
  agent: orRawRef(agentHandlerHintsSchema),
250
- rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitDisabledSchema])),
251
+ rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitOptionListSchema, rateLimitDisabledSchema])),
251
252
  additionalRateLimits: orRawRef(additionalRateLimitsSchema),
252
253
  escapeHatch: orRawRef(escapeHatchSchema),
253
254
  };
@@ -255,13 +256,13 @@ const QUERY_HANDLER_PATTERN_HEADER_SHAPE = {
255
256
  ...QUERY_HANDLER_HEADER_SHAPE,
256
257
  access: orRawRef(accessRuleSchema),
257
258
  agent: orRawRef(agentHandlerHintsSchema),
258
- rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitDisabledSchema])),
259
+ rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitOptionListSchema, rateLimitDisabledSchema])),
259
260
  escapeHatch: orRawRef(escapeHatchSchema),
260
261
  };
261
262
  const STREAM_HANDLER_PATTERN_HEADER_SHAPE = {
262
263
  ...STREAM_HANDLER_HEADER_SHAPE,
263
264
  access: orRawRef(accessRuleSchema),
264
- rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitDisabledSchema])),
265
+ rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitOptionListSchema, rateLimitDisabledSchema])),
265
266
  escapeHatch: orRawRef(escapeHatchSchema),
266
267
  };
267
268
  function requireHandlerBody(val, ctx, headerKeys) {
@@ -31,9 +31,12 @@ function qualifySelectorPanel(featureName, panel) {
31
31
  throw new Error(`[Feature ${featureName}] extensionSelector screen panel "${panel.id}" must not set a label — ` +
32
32
  `the settings dashboard has no i18n namespace for it; the embedded screen carries its own title.`);
33
33
  }
34
- if (panel.screen === "" || isValidQn(panel.screen))
34
+ const qualify = (ref) => ref === "" || isValidQn(ref) ? ref : qualifyEntityName(featureName, "screen", ref);
35
+ const screen = qualify(panel.screen);
36
+ const fallback = panel.fallback === undefined ? undefined : qualify(panel.fallback);
37
+ if (screen === panel.screen && fallback === panel.fallback)
35
38
  return panel;
36
- return { ...panel, screen: qualifyEntityName(featureName, "screen", panel.screen) };
39
+ return { ...panel, screen, ...(fallback !== undefined && { fallback }) };
37
40
  }
38
41
  throw new Error(`[Feature ${featureName}] extensionSelector panel ${JSON.stringify(panel)} has an unsupported kind — ` +
39
42
  `only "custom" and "screen" panels are allowed.`);
@@ -51,6 +51,7 @@ export { i18nKey } from "./i18n-key.ts";
51
51
  export { buildSessionRoles, findForbiddenMembershipRole, isForbiddenMembershipRole, stripForbiddenMembershipRoles, } from "./membership-roles.ts";
52
52
  export type { OwnershipClause, OwnershipMap, OwnershipRef, OwnershipRule } from "./ownership.ts";
53
53
  export { buildOwnershipClause, combineClauses, from, normalizeAccessEntry, userCanCreateFieldRow, userCanReadFieldRow, userCanWriteFieldRow, } from "./ownership.ts";
54
+ export { type PagedListRequest, type PagedListRowValue, pagedListSchema, pageRows, } from "./paged-list.ts";
54
55
  export type { ParsedRefTarget } from "./parse-ref-target.ts";
55
56
  export { parseRefTarget, parseRefTargetEntityName } from "./parse-ref-target.ts";
56
57
  export { buildPipelineSteps, stepsPipeline } from "./pipeline.ts";
@@ -83,7 +84,7 @@ export { assertNotificationVariables, templateVariable, templateVariablesToZod,
83
84
  export { type EffectiveFeaturesResolver, findTierResolverUsage, isTierResolverPlugin, requireTierResolverPlugin, TENANT_TIER_RESOLVER_EXT, type TierResolverPlugin, type TrialGate, } from "./tier-resolver-extension.ts";
84
85
  export { findOverDeepTransferChain, resolveTransferAdjacency as resolveEntityTransferAdjacency, type TransferAdjacency, type TransferEdge, type TransferEdgeLink, } from "./transfer-adjacency.ts";
85
86
  export { isSystemTenant, isUuid, parseTenantId, SYSTEM_TENANT_ID } from "./types/identifiers.ts";
86
- 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, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListPanel, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelVisibility, DashboardProgressListPanel, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupPanel, DashboardStatPanel, DashboardText, 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, 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, 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";
87
+ 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, 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, 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";
87
88
  export { DEFAULT_CURRENCIES, DEFAULT_LOCALES, DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, HookPhases, HTTP_ERROR_CODE_PATTERN, isAgentVisibleScreen, isDeliveryErrorCode, isOpenToAllGranted, resolveAgentExposure, } from "./types/index.ts";
88
89
  export type { AwaitedEventType, PipelineBuildCtx, PipelineCtx, PipelineDef, StepBuilder, StepDef, StepFailureStrategy, StepInstance, StepKind, StepNamespace, StepResolver, } from "./types/step.ts";
89
90
  export { runValidation } from "./validation.ts";
@@ -51,6 +51,7 @@ export { i18nKey } from "./i18n-key.js";
51
51
  // surface.
52
52
  export { buildSessionRoles, findForbiddenMembershipRole, isForbiddenMembershipRole, stripForbiddenMembershipRoles, } from "./membership-roles.js";
53
53
  export { buildOwnershipClause, combineClauses, from, normalizeAccessEntry, userCanCreateFieldRow, userCanReadFieldRow, userCanWriteFieldRow, } from "./ownership.js";
54
+ export { pagedListSchema, pageRows, } from "./paged-list.js";
54
55
  export { parseRefTarget, parseRefTargetEntityName } from "./parse-ref-target.js";
55
56
  export { buildPipelineSteps, stepsPipeline } from "./pipeline.js";
56
57
  export { projectAppSchemaForRoles } from "./project-app-schema-for-roles.js";
@@ -0,0 +1,29 @@
1
+ import type { CursorResult } from "@cosmicdrift/kumiko-types/cursor-types";
2
+ import * as z from "zod";
3
+ export type PagedListRowValue = string | number | boolean | null;
4
+ export declare function pagedListSchema<const TSortField extends string>(sortableFields: readonly [TSortField, ...TSortField[]]): z.ZodObject<{
5
+ limit: z.ZodDefault<z.ZodNumber>;
6
+ offset: z.ZodOptional<z.ZodNumber>;
7
+ search: z.ZodOptional<z.ZodString>;
8
+ sort: z.ZodOptional<z.ZodEnum<{ [k in TSortField]: k; } extends infer T ? { [k in keyof T]: T[k]; } : never>>;
9
+ sortDirection: z.ZodOptional<z.ZodEnum<{
10
+ asc: "asc";
11
+ desc: "desc";
12
+ }>>;
13
+ totalCount: z.ZodOptional<z.ZodBoolean>;
14
+ cursor: z.ZodOptional<z.ZodNever>;
15
+ }, z.core.$strip>;
16
+ export type PagedListRequest<TSortField extends string> = {
17
+ readonly limit: number;
18
+ readonly offset?: number | undefined;
19
+ readonly search?: string | undefined;
20
+ readonly sort?: TSortField | undefined;
21
+ readonly sortDirection?: "asc" | "desc" | undefined;
22
+ readonly totalCount?: boolean | undefined;
23
+ };
24
+ export declare function pageRows<TRow extends Readonly<Record<TSortField, PagedListRowValue>> & {
25
+ readonly id: string;
26
+ }, TSortField extends string>(rows: readonly TRow[], request: PagedListRequest<TSortField>, options: {
27
+ readonly searchFields: readonly TSortField[];
28
+ readonly defaultSort: TSortField;
29
+ }): CursorResult<TRow>;
@@ -0,0 +1,56 @@
1
+ // Search, sort and offset paging for projectionList queries whose rows are
2
+ // assembled in memory (merged from several tables, no single SQL query to
3
+ // page). The projectionList pager sends `offset` + `totalCount`, never a
4
+ // cursor, so `nextCursor` is always null here.
5
+ import * as z from "zod";
6
+ import { MAX_LIST_LIMIT } from "./entity-handlers.js";
7
+ export function pagedListSchema(sortableFields) {
8
+ return z.object({
9
+ limit: z.number().int().min(1).max(MAX_LIST_LIMIT).default(50),
10
+ offset: z.number().int().nonnegative().optional(),
11
+ search: z.string().optional(),
12
+ sort: z.enum(sortableFields).optional(),
13
+ sortDirection: z.enum(["asc", "desc"]).optional(),
14
+ totalCount: z.boolean().optional(),
15
+ // Declared so a caller still paging by cursor gets a 400 instead of page one.
16
+ cursor: z.never({ error: "cursor paging is not supported here; page with offset" }).optional(),
17
+ });
18
+ }
19
+ function isMissing(value) {
20
+ return value === null || value === undefined;
21
+ }
22
+ // Missing values sort last in both directions; numbers and booleans compare
23
+ // by value, everything else as a locale-aware string.
24
+ function compareRowValues(a, b, directionMultiplier) {
25
+ if (isMissing(a) && isMissing(b))
26
+ return 0;
27
+ if (isMissing(a))
28
+ return 1;
29
+ if (isMissing(b))
30
+ return -1;
31
+ if (typeof a === "number" && typeof b === "number")
32
+ return (a - b) * directionMultiplier;
33
+ if (typeof a === "boolean" && typeof b === "boolean") {
34
+ return (Number(a) - Number(b)) * directionMultiplier;
35
+ }
36
+ return String(a).localeCompare(String(b)) * directionMultiplier;
37
+ }
38
+ export function pageRows(rows, request, options) {
39
+ const needle = request.search?.trim().toLowerCase() ?? "";
40
+ const matching = needle === ""
41
+ ? rows
42
+ : rows.filter((row) => options.searchFields.some((field) => String(row[field] ?? "")
43
+ .toLowerCase()
44
+ .includes(needle)));
45
+ const sortField = request.sort ?? options.defaultSort;
46
+ const directionMultiplier = request.sortDirection === "desc" ? -1 : 1;
47
+ // The source rows come unordered, so ties fall back to the id; otherwise a
48
+ // tied row could show up on two pages or on none.
49
+ const sorted = [...matching].sort((a, b) => compareRowValues(a[sortField], b[sortField], directionMultiplier) || a.id.localeCompare(b.id));
50
+ const offset = request.offset ?? 0;
51
+ return {
52
+ rows: sorted.slice(offset, offset + request.limit),
53
+ nextCursor: null,
54
+ ...(request.totalCount === true && { total: matching.length }),
55
+ };
56
+ }
@@ -39,8 +39,8 @@
39
39
  // resolves app-wide via a global short-id map, mirroring
40
40
  // resolveRowActionNavigateTarget; kind:"drawer" resolves same-feature
41
41
  // only, mirroring validateDrawerTargetAction)
42
- // - projectionDetail header actions + metrics[].navigate
43
- // - entityEdit/actionForm/secretMint redirect + actionForm cancelTarget
42
+ // - projectionDetail and dashboard header actions + projectionDetail metrics[].navigate
43
+ // - entityEdit/actionForm/secretMint redirect + actionForm successLinks and cancelTarget
44
44
  // (resolveScreenTargetQn: same-feature short id or cross-feature QN)
45
45
  // - dashboard DashboardScreenPanel.screen (resolveScreenTargetQn)
46
46
  // - every EditSectionSpec kind's own `actions` (fields/extension/writeForm/
@@ -418,8 +418,27 @@ function projectHeader(header, indices, keptScreenQns) {
418
418
  return changed ? { ...header, subtitle: nextParts } : header;
419
419
  }
420
420
  function projectDashboardPanels(panels, feature, keptScreenQns) {
421
- const kept = panels.filter((p) => p.kind !== "screen" || isScreenTargetKept(feature.featureName, p.screen, keptScreenQns));
422
- return kept.length === panels.length ? panels : kept;
421
+ let changed = false;
422
+ const kept = [];
423
+ for (const panel of panels) {
424
+ if (panel.kind !== "screen") {
425
+ kept.push(panel);
426
+ }
427
+ else if (!isScreenTargetKept(feature.featureName, panel.screen, keptScreenQns)) {
428
+ changed = true;
429
+ }
430
+ else if (panel.fallback !== undefined &&
431
+ !isScreenTargetKept(feature.featureName, panel.fallback, keptScreenQns)) {
432
+ // The role cannot reach the stand-in, so the tile just hides.
433
+ const { fallback: _unreachable, ...withoutFallback } = panel;
434
+ kept.push(withoutFallback);
435
+ changed = true;
436
+ }
437
+ else {
438
+ kept.push(panel);
439
+ }
440
+ }
441
+ return changed ? kept : panels;
423
442
  }
424
443
  // --- per-screen-type projection ---
425
444
  function projectListScreenId(listScreenId, indices, keptScreenQns) {
@@ -512,12 +531,15 @@ function projectEntityEditScreen(screen, feature, indices, keptScreenQns) {
512
531
  };
513
532
  }
514
533
  function projectActionFormScreen(screen, feature, indices, keptScreenQns) {
515
- const { redirect, cancelTarget, layout, listScreenId, ...rest } = screen;
534
+ const { redirect, successLinks, cancelTarget, layout, listScreenId, ...rest } = screen;
516
535
  const nextRedirect = projectRedirect(feature.featureName, redirect, keptScreenQns);
536
+ const keptSuccessLinks = successLinks?.filter((link) => isRedirectTargetKept(feature.featureName, link, keptScreenQns));
537
+ const nextSuccessLinks = keptSuccessLinks?.length === 0 ? undefined : keptSuccessLinks;
517
538
  const nextCancelTarget = projectCancelTarget(feature.featureName, cancelTarget, keptScreenQns);
518
539
  const nextLayout = projectEditLayout(layout, feature, indices, keptScreenQns);
519
540
  const nextListScreenId = projectListScreenId(listScreenId, indices, keptScreenQns);
520
541
  const unchanged = nextRedirect === redirect &&
542
+ nextSuccessLinks?.length === successLinks?.length &&
521
543
  nextCancelTarget === cancelTarget &&
522
544
  nextLayout === layout &&
523
545
  nextListScreenId === listScreenId;
@@ -527,6 +549,7 @@ function projectActionFormScreen(screen, feature, indices, keptScreenQns) {
527
549
  ...rest,
528
550
  layout: nextLayout,
529
551
  ...(nextRedirect !== undefined && { redirect: nextRedirect }),
552
+ ...(nextSuccessLinks !== undefined && { successLinks: nextSuccessLinks }),
530
553
  ...(nextCancelTarget !== undefined && { cancelTarget: nextCancelTarget }),
531
554
  ...(nextListScreenId !== undefined && { listScreenId: nextListScreenId }),
532
555
  };
@@ -565,8 +588,16 @@ function projectScreen(screen, feature, indices, keptScreenQns) {
565
588
  case "projectionDetail":
566
589
  return projectProjectionDetailScreen(screen, feature, indices, keptScreenQns);
567
590
  case "dashboard": {
591
+ const { actions, ...rest } = screen;
568
592
  const nextPanels = projectDashboardPanels(screen.panels, feature, keptScreenQns);
569
- return nextPanels === screen.panels ? screen : { ...screen, panels: nextPanels };
593
+ const nextActions = projectRowActionArray(actions, feature, indices, keptScreenQns);
594
+ if (nextPanels === screen.panels && nextActions === actions)
595
+ return screen;
596
+ return {
597
+ ...rest,
598
+ panels: nextPanels,
599
+ ...(nextActions !== undefined && { actions: nextActions }),
600
+ };
570
601
  }
571
602
  case "entityEdit":
572
603
  return projectEntityEditScreen(screen, feature, indices, keptScreenQns);
@@ -7,8 +7,8 @@ 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, QualifiedEventName, QueryEvent, QueryHandlerDef, QueryHandlerFn, RateLimitDeclaration, RateLimitDisabled, RateLimitOption, RateLimitPer, RoleAccessPersonalData, RoleAccessRule, SessionUser, SessionUserOrigin, StreamHandlerDef, StreamHandlerFn, TenantWriteTarget, TryAppendEventFn, TryAppendEventResult, UnsafeAppendEventFn, WriteEvent, WriteHandlerDef, WriteHandlerFn, WriteResult, } from "@cosmicdrift/kumiko-types/handlers";
11
- export { DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, HTTP_ERROR_CODE_PATTERN, isDeliveryErrorCode, isOpenToAllGranted, isRateLimitDisabled, isUiAccessGranted, } 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, JobRunnerRef, JobTriggerEvent, MemberReader, NameOrRef, NotifyDeferred, NotifyDelivery, NotifyDeliveryStatus, NotifyDispatched, NotifyFactory, NotifyFn, NotifyJobDispatcher, NotifyOptions, NotifyPriority, NotifyResult, OpenToAllAccessRule, OpenToAllDeclaration, OpenToAllPersonalData, PayloadBucketNormalization, PayloadRateLimitOption, PreparedWriteEvent, 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
+ 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";
14
14
  export type { EntityId, TenantId } from "@cosmicdrift/kumiko-types/identifiers";
@@ -17,7 +17,7 @@ export type { ContentCollectionDefinition, NavDefinition, NavIconKey, } from "@c
17
17
  export type { FromRule, FromRuleKind, OwnershipClause, OwnershipMap, OwnershipRef, OwnershipRule, SqlFragment, WhereRule, WhereRuleContext, } from "@cosmicdrift/kumiko-types/ownership";
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
- export type { ActionFormScreenDefinition, ConfigEditScreenDefinition, CustomScreenDefinition, CustomScreenRoute, DashboardChartMarkerKind, DashboardChartPanel, DashboardChartRangeOption, DashboardChartRanges, DashboardCustomPanel, DashboardDateParam, DashboardFeedPanel, DashboardFilterDefinition, DashboardI18nText, DashboardListPanel, DashboardMoneyParam, DashboardPanelDefinition, DashboardPanelGate, DashboardPanelVisibility, DashboardProgressListPanel, DashboardScreenDefinition, DashboardScreenPanel, DashboardStatGroupPanel, DashboardStatPanel, DashboardText, DashboardTextParam, DashboardValueFormat, EditExtensionSection, EditFieldPrefill, EditFieldSpec, EditFieldsSection, EditLayout, EditRelatedListSection, EditSectionSpec, EditWriteFormSection, EmbeddedListEditSpec, EntityEditAction, EntityEditActionPlacement, EntityEditScreenDefinition, EntityListExpandableRow, EntityListScreenDefinition, FieldCondition, FieldFormatRegistry, FieldRenderer, FormatSpec, 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";
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, 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
21
  export { metricField, 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";
@@ -1,7 +1,7 @@
1
1
  // Barrel: re-exports all types from @cosmicdrift/kumiko-types, plus the
2
2
  // runtime helpers below that stay framework-side.
3
3
  export { isAgentVisibleScreen, resolveAgentExposure, } from "@cosmicdrift/kumiko-types/agent-exposure";
4
- export { DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, HTTP_ERROR_CODE_PATTERN, isDeliveryErrorCode, isOpenToAllGranted, isRateLimitDisabled, isUiAccessGranted, } from "@cosmicdrift/kumiko-types/handlers";
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
6
  export { metricField, relatedListGroupHeaderLabel, relatedListGroupKey, } from "@cosmicdrift/kumiko-types/screen";
7
7
  export { DEFAULT_CURRENCIES, DEFAULT_LOCALES, isFileField } from "../field-helpers.js";