@cosmicdrift/kumiko-types 0.387.0 → 0.388.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/dist/config.d.ts +2 -0
- package/dist/define-handler.d.ts +6 -0
- package/dist/event-store-executor-types.d.ts +37 -21
- package/dist/fields.js +1 -1
- package/dist/handlers.d.ts +3 -0
- package/dist/list-aggregate-types.d.ts +38 -0
- package/dist/list-aggregate-types.js +19 -0
- package/package.json +10 -2
package/dist/config.d.ts
CHANGED
|
@@ -231,6 +231,8 @@ export type NotificationTemplateMeta = {
|
|
|
231
231
|
readonly layoutSlug?: string;
|
|
232
232
|
readonly category?: "transactional" | "marketing";
|
|
233
233
|
readonly sender?: string;
|
|
234
|
+
readonly senderName?: string;
|
|
235
|
+
readonly replyTo?: string;
|
|
234
236
|
};
|
|
235
237
|
export type NotificationTemplateBody = {
|
|
236
238
|
readonly body: string;
|
package/dist/define-handler.d.ts
CHANGED
|
@@ -14,6 +14,9 @@ export type WriteHandlerDefinition<TName extends string = string, TSchema extend
|
|
|
14
14
|
readonly unsafeSkipTransitionGuard?: boolean;
|
|
15
15
|
readonly rateLimit?: RateLimitDeclaration;
|
|
16
16
|
readonly additionalRateLimits?: readonly PayloadRateLimitOption[];
|
|
17
|
+
/** Tokens each request books on every declared rateLimit bucket, computed from the validated
|
|
18
|
+
* payload (e.g. `(p) => p.files.length`). Replaces the options' `cost`; results below 1 count as 1. */
|
|
19
|
+
readonly rateLimitCost?: (payload: z.infer<TSchema>) => number;
|
|
17
20
|
readonly escapeHatch?: EscapeHatchDeclaration;
|
|
18
21
|
readonly reserveBeforeTransaction?: PreTransactionReservation;
|
|
19
22
|
readonly beforeTransaction?: BeforeTransactionPhase<z.infer<TSchema>, TPrepared>;
|
|
@@ -31,6 +34,9 @@ export type WriteHandlerInput<TName extends string = string, TSchema extends Zod
|
|
|
31
34
|
readonly unsafeSkipTransitionGuard?: boolean;
|
|
32
35
|
readonly rateLimit?: RateLimitDeclaration;
|
|
33
36
|
readonly additionalRateLimits?: readonly PayloadRateLimitOption[];
|
|
37
|
+
/** Tokens each request books on every declared rateLimit bucket, computed from the validated
|
|
38
|
+
* payload (e.g. `(p) => p.files.length`). Replaces the options' `cost`; results below 1 count as 1. */
|
|
39
|
+
readonly rateLimitCost?: (payload: z.infer<TSchema>) => number;
|
|
34
40
|
readonly escapeHatch?: EscapeHatchDeclaration;
|
|
35
41
|
readonly reserveBeforeTransaction?: PreTransactionReservation;
|
|
36
42
|
readonly beforeTransaction?: BeforeTransactionPhase<z.infer<TSchema>, TPrepared>;
|
|
@@ -3,6 +3,7 @@ import type { EntityDefinition } from "./fields.ts";
|
|
|
3
3
|
import type { SessionUser, WriteResult } from "./handlers.ts";
|
|
4
4
|
import type { DeleteContext, SaveContext } from "./hooks.ts";
|
|
5
5
|
import type { EntityId, TenantId } from "./identifiers.ts";
|
|
6
|
+
import type { ListAggregatePayload, ListAggregateResult } from "./list-aggregate-types.ts";
|
|
6
7
|
import type { SearchAdapter } from "./search-adapter.ts";
|
|
7
8
|
import type { TenantDb } from "./tenant-db-types.ts";
|
|
8
9
|
export type ParentVisibilityOption = {
|
|
@@ -21,6 +22,38 @@ export type LockGuardOption = {
|
|
|
21
22
|
readonly unsafeSkipLockGuard?: boolean;
|
|
22
23
|
readonly writePurpose?: WritePurpose;
|
|
23
24
|
};
|
|
25
|
+
export type ListRuntimeOptions = {
|
|
26
|
+
readonly searchAdapter?: SearchAdapter;
|
|
27
|
+
readonly includeDeleted?: boolean;
|
|
28
|
+
readonly referenceSearch?: {
|
|
29
|
+
readonly fields: ReadonlyArray<{
|
|
30
|
+
readonly fieldName: string;
|
|
31
|
+
readonly targetEntityName: string;
|
|
32
|
+
readonly labelField: string;
|
|
33
|
+
}>;
|
|
34
|
+
readonly resolveEntity: (entityName: string) => EntityDefinition | undefined;
|
|
35
|
+
};
|
|
36
|
+
readonly referenceSort?: {
|
|
37
|
+
readonly fields: ReadonlyArray<{
|
|
38
|
+
readonly fieldName: string;
|
|
39
|
+
readonly targetEntityName: string;
|
|
40
|
+
readonly labelField: string;
|
|
41
|
+
}>;
|
|
42
|
+
readonly resolveEntity: (entityName: string) => EntityDefinition | undefined;
|
|
43
|
+
};
|
|
44
|
+
readonly parentVisibility?: ParentVisibilityOption;
|
|
45
|
+
};
|
|
46
|
+
type ListFilterOption = {
|
|
47
|
+
readonly field: string;
|
|
48
|
+
readonly op: "eq" | "ne" | "lt" | "gt" | "lte" | "gte" | "in";
|
|
49
|
+
readonly value: unknown;
|
|
50
|
+
};
|
|
51
|
+
export type ListAggregateRequest = {
|
|
52
|
+
readonly search?: string | undefined;
|
|
53
|
+
readonly filter?: ListFilterOption | undefined;
|
|
54
|
+
readonly filters?: readonly ListFilterOption[] | undefined;
|
|
55
|
+
readonly aggregate: ListAggregatePayload;
|
|
56
|
+
};
|
|
24
57
|
export type EventStoreExecutor<Row extends Record<string, unknown> = Record<string, unknown>> = {
|
|
25
58
|
create: (payload: Record<string, unknown>, user: SessionUser, db: TenantDb, options?: StreamTenantOption & {
|
|
26
59
|
preSave?: PreSaveRunner;
|
|
@@ -70,30 +103,13 @@ export type EventStoreExecutor<Row extends Record<string, unknown> = Record<stri
|
|
|
70
103
|
* one from ctx.searchAdapter here at runtime.
|
|
71
104
|
* options.searchAdapter (build-time) wins — the runtime override
|
|
72
105
|
* is the fallback for the default wrapper. */
|
|
73
|
-
runtimeOptions?:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
readonly referenceSearch?: {
|
|
77
|
-
readonly fields: ReadonlyArray<{
|
|
78
|
-
readonly fieldName: string;
|
|
79
|
-
readonly targetEntityName: string;
|
|
80
|
-
readonly labelField: string;
|
|
81
|
-
}>;
|
|
82
|
-
readonly resolveEntity: (entityName: string) => EntityDefinition | undefined;
|
|
83
|
-
};
|
|
84
|
-
readonly referenceSort?: {
|
|
85
|
-
readonly fields: ReadonlyArray<{
|
|
86
|
-
readonly fieldName: string;
|
|
87
|
-
readonly targetEntityName: string;
|
|
88
|
-
readonly labelField: string;
|
|
89
|
-
}>;
|
|
90
|
-
readonly resolveEntity: (entityName: string) => EntityDefinition | undefined;
|
|
91
|
-
};
|
|
92
|
-
readonly parentVisibility?: ParentVisibilityOption;
|
|
93
|
-
}) => Promise<CursorResult<Row>>;
|
|
106
|
+
runtimeOptions?: ListRuntimeOptions) => Promise<CursorResult<Row>>;
|
|
107
|
+
/** Groups and measures over the same WHERE as `list` (filters, search, ownership, field-read gates); paging and sort are ignored. */
|
|
108
|
+
aggregate: (payload: ListAggregateRequest, user: SessionUser, db: TenantDb, runtimeOptions?: ListRuntimeOptions) => Promise<ListAggregateResult>;
|
|
94
109
|
detail: (payload: {
|
|
95
110
|
id: EntityId;
|
|
96
111
|
}, user: SessionUser, db: TenantDb, options?: {
|
|
97
112
|
readonly parentVisibility?: ParentVisibilityOption;
|
|
98
113
|
}) => Promise<Row | null>;
|
|
99
114
|
};
|
|
115
|
+
export {};
|
package/dist/fields.js
CHANGED
|
@@ -47,7 +47,7 @@ function isFieldTypeName(name) {
|
|
|
47
47
|
export const FIELD_TYPE_NAMES = Object.keys(FIELD_TYPE_NAME_FLAGS).filter(isFieldTypeName);
|
|
48
48
|
// Field types with no bound, editable widget on the auto-wired entityEdit
|
|
49
49
|
// path (render-field.tsx renders a read-only banner instead) — shared by
|
|
50
|
-
// the boot validator (packages/framework/src/engine/boot-validator/screens.ts)
|
|
50
|
+
// the boot validator (packages/framework/src/engine/boot-validator/screens-forms.ts)
|
|
51
51
|
// and the client-side required-field check (packages/renderer/src/app/form-schema.ts).
|
|
52
52
|
// Embedded LIST fields (`multiple: true`) are the one exception — they get
|
|
53
53
|
// their own EmbeddedListField grid widget — callers must check that
|
package/dist/handlers.d.ts
CHANGED
|
@@ -632,6 +632,9 @@ export type WriteHandlerDef = {
|
|
|
632
632
|
/** Per-payload-field limits, e.g. per recipient address. Complements
|
|
633
633
|
* `rateLimit`; anonymous handlers still need an ip-keyed `rateLimit`. */
|
|
634
634
|
readonly additionalRateLimits?: readonly PayloadRateLimitOption[];
|
|
635
|
+
/** Tokens each request books on every declared rateLimit bucket, computed from the validated
|
|
636
|
+
* payload (e.g. `(p) => p.files.length`). Replaces the options' `cost`; results below 1 count as 1. */
|
|
637
|
+
readonly rateLimitCost?: (payload: unknown) => number;
|
|
635
638
|
readonly escapeHatch?: EscapeHatchDeclaration;
|
|
636
639
|
/** Reserves before the handler transaction opens. Reached through a nested ctx.write the
|
|
637
640
|
* reservation cannot run, so the dispatcher rejects it unless the top-level batch reserved it. */
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { AggregateKey } from "./aggregate-types.ts";
|
|
3
|
+
export declare const MAX_LIST_AGGREGATE_MEASURES = 20;
|
|
4
|
+
export declare const LIST_AGGREGATE_MEASURE_KINDS: readonly ["sum", "avg", "count", "min", "max"];
|
|
5
|
+
export type ListAggregateMeasureKind = (typeof LIST_AGGREGATE_MEASURE_KINDS)[number];
|
|
6
|
+
export declare const listAggregatePayloadSchema: z.ZodObject<{
|
|
7
|
+
groupBy: z.ZodOptional<z.ZodString>;
|
|
8
|
+
measures: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
9
|
+
field: z.ZodString;
|
|
10
|
+
kind: z.ZodEnum<{
|
|
11
|
+
avg: "avg";
|
|
12
|
+
count: "count";
|
|
13
|
+
max: "max";
|
|
14
|
+
min: "min";
|
|
15
|
+
sum: "sum";
|
|
16
|
+
}>;
|
|
17
|
+
}, z.core.$strip>>>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
export type ListAggregatePayload = {
|
|
20
|
+
readonly groupBy?: string | undefined;
|
|
21
|
+
readonly measures: readonly {
|
|
22
|
+
readonly field: string;
|
|
23
|
+
readonly kind: ListAggregateMeasureKind;
|
|
24
|
+
}[];
|
|
25
|
+
};
|
|
26
|
+
export type ListAggregateValue = number | string | null;
|
|
27
|
+
export type ListAggregateGroup = {
|
|
28
|
+
readonly key: AggregateKey;
|
|
29
|
+
readonly label?: string | null;
|
|
30
|
+
readonly count: number;
|
|
31
|
+
readonly measures: readonly ListAggregateValue[];
|
|
32
|
+
};
|
|
33
|
+
export type ListAggregateResult = {
|
|
34
|
+
readonly groups: readonly ListAggregateGroup[];
|
|
35
|
+
readonly truncated?: true;
|
|
36
|
+
readonly searchTruncated?: true;
|
|
37
|
+
};
|
|
38
|
+
export declare function isListAggregateResult(value: unknown): value is ListAggregateResult;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { isPlainObject } from "./type-guards.js";
|
|
3
|
+
export const MAX_LIST_AGGREGATE_MEASURES = 20;
|
|
4
|
+
export const LIST_AGGREGATE_MEASURE_KINDS = ["sum", "avg", "count", "min", "max"];
|
|
5
|
+
export const listAggregatePayloadSchema = z.object({
|
|
6
|
+
groupBy: z.string().optional(),
|
|
7
|
+
measures: z
|
|
8
|
+
.array(z.object({ field: z.string(), kind: z.enum(LIST_AGGREGATE_MEASURE_KINDS) }))
|
|
9
|
+
.max(MAX_LIST_AGGREGATE_MEASURES)
|
|
10
|
+
.default([]),
|
|
11
|
+
});
|
|
12
|
+
const LIST_AGGREGATE_RESULT_KEYS = ["groups", "truncated", "searchTruncated"];
|
|
13
|
+
// Closed key set: a row that merely has a `groups` field (jsonb column) must not
|
|
14
|
+
// be mistaken for an aggregate and skip the row-level read filter.
|
|
15
|
+
export function isListAggregateResult(value) {
|
|
16
|
+
return (isPlainObject(value) &&
|
|
17
|
+
Array.isArray(value["groups"]) &&
|
|
18
|
+
Object.keys(value).every((key) => LIST_AGGREGATE_RESULT_KEYS.includes(key)));
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.388.0",
|
|
4
4
|
"description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren. Enthaelt keine identitaets-sensitiven Runtime-Werte mehr (Error-Klassen leben seit #1629 in kumiko-framework, Brand-Symbole nutzen Symbol.for) und ist deshalb eine plain dependency, keine peerDependency.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -154,6 +154,10 @@
|
|
|
154
154
|
"types": "./dist/aggregate-types.d.ts",
|
|
155
155
|
"default": "./dist/aggregate-types.js"
|
|
156
156
|
},
|
|
157
|
+
"./list-aggregate-types": {
|
|
158
|
+
"types": "./dist/list-aggregate-types.d.ts",
|
|
159
|
+
"default": "./dist/list-aggregate-types.js"
|
|
160
|
+
},
|
|
157
161
|
"./tenant-db-types": {
|
|
158
162
|
"types": "./dist/tenant-db-types.d.ts",
|
|
159
163
|
"default": "./dist/tenant-db-types.js"
|
|
@@ -281,7 +285,7 @@
|
|
|
281
285
|
},
|
|
282
286
|
"devDependencies": {
|
|
283
287
|
"hono": "^4.13.1",
|
|
284
|
-
"postgres": "npm:@bender0oo0/postgres@3.4.9-kumiko.
|
|
288
|
+
"postgres": "npm:@bender0oo0/postgres@3.4.9-kumiko.2",
|
|
285
289
|
"temporal-polyfill": "^0.3.2",
|
|
286
290
|
"zod": "^4.4.3",
|
|
287
291
|
"ioredis": "^5.10.1"
|
|
@@ -433,6 +437,10 @@
|
|
|
433
437
|
"types": "./dist/aggregate-types.d.ts",
|
|
434
438
|
"default": "./dist/aggregate-types.js"
|
|
435
439
|
},
|
|
440
|
+
"./list-aggregate-types": {
|
|
441
|
+
"types": "./dist/list-aggregate-types.d.ts",
|
|
442
|
+
"default": "./dist/list-aggregate-types.js"
|
|
443
|
+
},
|
|
436
444
|
"./tenant-db-types": {
|
|
437
445
|
"types": "./dist/tenant-db-types.d.ts",
|
|
438
446
|
"default": "./dist/tenant-db-types.js"
|