@cosmicdrift/kumiko-types 0.387.0 → 0.389.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 +3 -0
- package/dist/db-connection.d.ts +4 -4
- package/dist/define-handler.d.ts +6 -0
- package/dist/event-store-executor-types.d.ts +37 -21
- package/dist/feature-registrar.d.ts +326 -0
- package/dist/feature-registrar.js +1 -0
- package/dist/feature.d.ts +6 -314
- package/dist/fields.js +1 -1
- package/dist/handlers.d.ts +8 -6
- package/dist/list-aggregate-types.d.ts +43 -0
- package/dist/list-aggregate-types.js +22 -0
- package/dist/screen-entity-edit.d.ts +8 -20
- package/dist/screen-entity-edit.js +6 -4
- package/dist/screen-entity-list.d.ts +21 -8
- package/dist/screen-expandable-row.d.ts +16 -0
- package/dist/screen-expandable-row.js +1 -0
- package/dist/screen-list-bulk.d.ts +12 -0
- package/dist/screen-list-bulk.js +3 -0
- package/dist/screen-list-table.d.ts +70 -0
- package/dist/screen-list-table.js +28 -0
- package/dist/screen-projection.d.ts +6 -0
- package/dist/screen.d.ts +12 -4
- package/dist/screen.js +2 -0
- package/dist/tenant-db-types.d.ts +5 -0
- package/package.json +20 -4
- package/src/changes.json +13 -0
package/dist/config.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export type ConfigValidateContext = {
|
|
|
31
31
|
readonly tenantId: TenantId;
|
|
32
32
|
readonly userId: string | null;
|
|
33
33
|
readonly db: TenantDb;
|
|
34
|
+
readonly readCascade: (qualifiedKey: string) => Promise<ConfigCascade>;
|
|
34
35
|
};
|
|
35
36
|
export type ConfigValidateFn<T extends ConfigKeyType = ConfigKeyType> = (value: ConfigValue<T>, ctx: ConfigValidateContext) => Promise<void>;
|
|
36
37
|
export type ConfigBacking = "config" | "secrets";
|
|
@@ -231,6 +232,8 @@ export type NotificationTemplateMeta = {
|
|
|
231
232
|
readonly layoutSlug?: string;
|
|
232
233
|
readonly category?: "transactional" | "marketing";
|
|
233
234
|
readonly sender?: string;
|
|
235
|
+
readonly senderName?: string;
|
|
236
|
+
readonly replyTo?: string;
|
|
234
237
|
};
|
|
235
238
|
export type NotificationTemplateBody = {
|
|
236
239
|
readonly body: string;
|
package/dist/db-connection.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type { SQL, TransactionSQL } from "bun";
|
|
2
2
|
export type RawDbClient = {
|
|
3
3
|
unsafe: (sql: string, params?: readonly unknown[]) => PromiseLike<readonly unknown[]>;
|
|
4
4
|
begin: <T>(fn: (tx: DbTx) => Promise<T>) => Promise<T>;
|
|
@@ -6,11 +6,11 @@ export type RawDbClient = {
|
|
|
6
6
|
timeout?: number;
|
|
7
7
|
}) => Promise<void>;
|
|
8
8
|
};
|
|
9
|
-
export type DbConnection =
|
|
10
|
-
export type DbTx =
|
|
9
|
+
export type DbConnection = SQL | RawDbClient;
|
|
10
|
+
export type DbTx = TransactionSQL | RawDbClient;
|
|
11
11
|
export type DbRunner = DbConnection | DbTx;
|
|
12
12
|
export type DbRow = Record<string, unknown>;
|
|
13
|
-
export type PgClient =
|
|
13
|
+
export type PgClient = SQL;
|
|
14
14
|
export type PgListenSubscription = {
|
|
15
15
|
unlisten(): Promise<void>;
|
|
16
16
|
};
|
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 {};
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import type * as z from "zod";
|
|
2
|
+
import type { ZodType } from "zod";
|
|
3
|
+
import type { ConfigKeyDefinition, ConfigKeyHandle, ConfigKeyType, ConfigSeedDef, ExtensionSelectorPanel, JobDefinition, JobHandlerFn, NotificationDataFn, NotificationLocalizedTemplate, NotificationRecipientFn, NotificationRecordMapping, NotificationTemplateBody, NotificationTemplateFn, NotificationTemplateMeta, RegistrarExtensionDef, TemplateVariables, TranslationsDef } from "./config.ts";
|
|
4
|
+
import type { QueryHandlerDefinition, StreamHandlerDefinition, WriteHandlerDefinition } from "./define-handler.ts";
|
|
5
|
+
import type { RegisterEntityCrudOptions } from "./entity-handlers.ts";
|
|
6
|
+
import type { EntityTableMeta } from "./entity-table-meta-types.ts";
|
|
7
|
+
import type { KumikoEventTypeMap } from "./event-type-map.ts";
|
|
8
|
+
import type { ExtensionOptionsArgs, ExtensionOptionsFor } from "./extension-options-map.ts";
|
|
9
|
+
import type { BootCheckFn, MetricOptions, SecretKeyHandle, SecretNamespaceHandle, SecretNamespaceOptions, SecretOptions, StoreTableOptions, UiHints } from "./feature.ts";
|
|
10
|
+
import type { EntityDefinition } from "./fields.ts";
|
|
11
|
+
import type { AccessRule, AuthClaimsFn, ClaimKeyHandle, ClaimKeyType, DeclarativeEventMigration, EntityRef, EscapeHatchDeclaration, EventDef, EventPiiStance, EventUpcastFn, HandlerRef, NameOrRef, QualifiedEventName, RateLimitDeclaration, StreamHandlerFn } from "./handlers.ts";
|
|
12
|
+
import type { HookPhase, PostDeleteHookFn, PostQueryHookFn, PostSaveHookFn, PreDeleteHookFn, PreQueryHookFn, PreSaveHookFn, SearchPayloadContributorFn, ValidationHookFn } from "./hooks.ts";
|
|
13
|
+
import type { HttpRouteDefinition } from "./http-route.ts";
|
|
14
|
+
import type { ContentCollectionDefinition, NavDefinition } from "./nav.ts";
|
|
15
|
+
import type { EntityProjectionExtension, MultiStreamProjectionDefinition, ProjectionDefinition } from "./projection.ts";
|
|
16
|
+
import type { RelationDefinition } from "./relations.ts";
|
|
17
|
+
import type { ScreenDefinition } from "./screen.ts";
|
|
18
|
+
import type { TreeActionDef, TreeActionsHandle } from "./tree-node.ts";
|
|
19
|
+
import type { WebSocketRouteDefinition } from "./websocket-route.ts";
|
|
20
|
+
import type { WorkspaceDefinition } from "./workspace.ts";
|
|
21
|
+
type RefOrRefs = NameOrRef | readonly NameOrRef[];
|
|
22
|
+
type HookTarget = RefOrRefs | {
|
|
23
|
+
readonly allOf: NameOrRef;
|
|
24
|
+
};
|
|
25
|
+
export type EntityObjectDefinition = {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly backingTable?: unknown;
|
|
28
|
+
} & EntityDefinition;
|
|
29
|
+
type HookEscapeHatch = {
|
|
30
|
+
readonly escapeHatch?: EscapeHatchDeclaration;
|
|
31
|
+
};
|
|
32
|
+
type HookPhaseOption = {
|
|
33
|
+
readonly phase?: HookPhase;
|
|
34
|
+
};
|
|
35
|
+
export type HookDefinition = {
|
|
36
|
+
readonly type: "validation";
|
|
37
|
+
readonly target: RefOrRefs;
|
|
38
|
+
readonly handler: ValidationHookFn;
|
|
39
|
+
readonly escapeHatch?: never;
|
|
40
|
+
readonly phase?: never;
|
|
41
|
+
} | ({
|
|
42
|
+
readonly type: "preSave";
|
|
43
|
+
readonly target: RefOrRefs;
|
|
44
|
+
readonly handler: PreSaveHookFn;
|
|
45
|
+
readonly phase?: never;
|
|
46
|
+
} & HookEscapeHatch) | ({
|
|
47
|
+
readonly type: "postSave";
|
|
48
|
+
readonly target: HookTarget;
|
|
49
|
+
readonly handler: PostSaveHookFn;
|
|
50
|
+
} & HookEscapeHatch & HookPhaseOption) | ({
|
|
51
|
+
readonly type: "preDelete";
|
|
52
|
+
readonly target: HookTarget;
|
|
53
|
+
readonly handler: PreDeleteHookFn;
|
|
54
|
+
readonly phase?: never;
|
|
55
|
+
} & HookEscapeHatch) | ({
|
|
56
|
+
readonly type: "postDelete";
|
|
57
|
+
readonly target: HookTarget;
|
|
58
|
+
readonly handler: PostDeleteHookFn;
|
|
59
|
+
} & HookEscapeHatch & HookPhaseOption) | ({
|
|
60
|
+
readonly type: "preQuery";
|
|
61
|
+
readonly target: RefOrRefs;
|
|
62
|
+
readonly handler: PreQueryHookFn;
|
|
63
|
+
readonly phase?: never;
|
|
64
|
+
} & HookEscapeHatch) | ({
|
|
65
|
+
readonly type: "postQuery";
|
|
66
|
+
readonly target: HookTarget;
|
|
67
|
+
readonly handler: PostQueryHookFn;
|
|
68
|
+
readonly phase?: never;
|
|
69
|
+
} & HookEscapeHatch);
|
|
70
|
+
/**
|
|
71
|
+
* `r.requires({ features })` declares the features this one depends on; the
|
|
72
|
+
* `.projection` extension declares read-side projection tables that this
|
|
73
|
+
* feature's pipeline steps are allowed to write via
|
|
74
|
+
* `r.step.unsafeProjectionUpsert` (hard-required for any unsafeProjection-*
|
|
75
|
+
* step usage, see Q10).
|
|
76
|
+
*
|
|
77
|
+
* @example r.requires({ features: ["auth", "tenant"] });
|
|
78
|
+
*/
|
|
79
|
+
export type RequiresApi = ((options: {
|
|
80
|
+
readonly features: readonly string[];
|
|
81
|
+
}) => void) & {
|
|
82
|
+
readonly projection: (tableName: string) => void;
|
|
83
|
+
readonly step: (stepKind: string) => void;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* `TFeature` is the literal feature-name from `defineFeature("foo", ...)` —
|
|
87
|
+
* default-`string` keeps every existing usage zero-config. Strict-typed
|
|
88
|
+
* features (apps that opt into the literal-name flavour) get propagated
|
|
89
|
+
* through to `defineEvent` so the returned `EventDef.name` is a literal
|
|
90
|
+
* `${CamelToKebab<TFeature>}:event:${CamelToKebab<TInner>}`. That literal
|
|
91
|
+
* threads through `ctx.appendEvent({ type: eventDef.name, ... })`,
|
|
92
|
+
* keeping strict-mode alive even when handlers route via `eventDef.name`
|
|
93
|
+
* instead of hand-typed string literals.
|
|
94
|
+
*/
|
|
95
|
+
export type FeatureRegistrar<TFeature extends string = string> = {
|
|
96
|
+
systemScope(): void;
|
|
97
|
+
describe(text: string): void;
|
|
98
|
+
requires: RequiresApi;
|
|
99
|
+
optionalRequires(...featureNames: string[]): void;
|
|
100
|
+
optionalRequires(options: {
|
|
101
|
+
readonly features: readonly string[];
|
|
102
|
+
}): void;
|
|
103
|
+
toggleable(options: {
|
|
104
|
+
default: boolean;
|
|
105
|
+
}): void;
|
|
106
|
+
adoptsBundledLists(): void;
|
|
107
|
+
uiHints(hints: UiHints): void;
|
|
108
|
+
/**
|
|
109
|
+
* @example r.entity({ name: "note", fields: { title: createTextField({ required: true }) } });
|
|
110
|
+
*/
|
|
111
|
+
entity(definition: EntityObjectDefinition): EntityRef;
|
|
112
|
+
crud(entityName: string, entity: EntityDefinition, options?: RegisterEntityCrudOptions): void;
|
|
113
|
+
/**
|
|
114
|
+
* @example r.writeHandler({ name: "note:archive", schema, handler, access: { roles: ["User"] } });
|
|
115
|
+
*/
|
|
116
|
+
writeHandler<TName extends string, TSchema extends ZodType, TPrepared = undefined>(def: WriteHandlerDefinition<TName, TSchema, unknown, KumikoEventTypeMap, TPrepared>): HandlerRef;
|
|
117
|
+
/**
|
|
118
|
+
* @example r.queryHandler({ name: "note:list", schema, handler, access: { roles: ["User"] } });
|
|
119
|
+
*/
|
|
120
|
+
queryHandler<TName extends string, TSchema extends ZodType>(def: QueryHandlerDefinition<TName, TSchema>): HandlerRef;
|
|
121
|
+
streamHandler<TName extends string, TSchema extends ZodType>(def: StreamHandlerDefinition<TName, TSchema>): HandlerRef;
|
|
122
|
+
streamHandler<TSchema extends ZodType>(name: string, schema: TSchema, handler: StreamHandlerFn<z.infer<TSchema>>, options: {
|
|
123
|
+
access: AccessRule;
|
|
124
|
+
rateLimit?: RateLimitDeclaration;
|
|
125
|
+
escapeHatch?: EscapeHatchDeclaration;
|
|
126
|
+
}): HandlerRef;
|
|
127
|
+
relation(entity: NameOrRef, relationName: string, definition: RelationDefinition): void;
|
|
128
|
+
relation<TDef extends RelationDefinition>(definition: {
|
|
129
|
+
readonly entity: NameOrRef;
|
|
130
|
+
readonly name: string;
|
|
131
|
+
} & TDef): void;
|
|
132
|
+
/**
|
|
133
|
+
* @example r.hook({ type: "postSave", target: { allOf: noteRef }, handler: notifyOwner });
|
|
134
|
+
*/
|
|
135
|
+
hook(definition: HookDefinition): void;
|
|
136
|
+
searchPayloadExtension(entity: NameOrRef, fn: SearchPayloadContributorFn): void;
|
|
137
|
+
config<T extends ConfigKeyType>(keyName: string, def: ConfigKeyDefinition<T>): ConfigKeyHandle<T>;
|
|
138
|
+
config<TKeys extends Readonly<Record<string, ConfigKeyDefinition<ConfigKeyType>>>>(definition: {
|
|
139
|
+
readonly keys: TKeys;
|
|
140
|
+
readonly seeds?: Readonly<Record<string, ConfigSeedDef>>;
|
|
141
|
+
}): {
|
|
142
|
+
readonly [K in keyof TKeys]: ConfigKeyHandle<TKeys[K]["type"]>;
|
|
143
|
+
};
|
|
144
|
+
job(name: string, options: Omit<JobDefinition, "name" | "handler">, handler: JobHandlerFn): void;
|
|
145
|
+
job(definition: JobDefinition): void;
|
|
146
|
+
notification(name: string, definition: {
|
|
147
|
+
readonly trigger?: {
|
|
148
|
+
readonly on: NameOrRef;
|
|
149
|
+
};
|
|
150
|
+
readonly recipient?: NotificationRecipientFn;
|
|
151
|
+
readonly data?: NotificationDataFn;
|
|
152
|
+
readonly templates?: Readonly<Record<string, NotificationTemplateFn>>;
|
|
153
|
+
readonly variables?: TemplateVariables;
|
|
154
|
+
readonly record?: NotificationRecordMapping;
|
|
155
|
+
readonly template?: Readonly<Record<string, NotificationTemplateBody>>;
|
|
156
|
+
readonly meta?: Readonly<Record<string, NotificationTemplateMeta>>;
|
|
157
|
+
readonly localizedTemplate?: () => NotificationLocalizedTemplate;
|
|
158
|
+
readonly renamedFrom?: readonly string[];
|
|
159
|
+
readonly systemOnly?: boolean;
|
|
160
|
+
readonly unsubscribe?: boolean;
|
|
161
|
+
readonly tenantTransport?: boolean;
|
|
162
|
+
}): void;
|
|
163
|
+
notification(definition: {
|
|
164
|
+
readonly name: string;
|
|
165
|
+
readonly trigger?: {
|
|
166
|
+
readonly on: NameOrRef;
|
|
167
|
+
};
|
|
168
|
+
readonly recipient?: NotificationRecipientFn;
|
|
169
|
+
readonly data?: NotificationDataFn;
|
|
170
|
+
readonly templates?: Readonly<Record<string, NotificationTemplateFn>>;
|
|
171
|
+
readonly variables?: TemplateVariables;
|
|
172
|
+
readonly record?: NotificationRecordMapping;
|
|
173
|
+
readonly template?: Readonly<Record<string, NotificationTemplateBody>>;
|
|
174
|
+
readonly meta?: Readonly<Record<string, NotificationTemplateMeta>>;
|
|
175
|
+
readonly localizedTemplate?: () => NotificationLocalizedTemplate;
|
|
176
|
+
readonly renamedFrom?: readonly string[];
|
|
177
|
+
readonly systemOnly?: boolean;
|
|
178
|
+
readonly unsubscribe?: boolean;
|
|
179
|
+
readonly tenantTransport?: boolean;
|
|
180
|
+
}): void;
|
|
181
|
+
translations(def: TranslationsDef): void;
|
|
182
|
+
defineEvent<const TInner extends string, TPayload>(name: TInner, schema: ZodType<TPayload>, options: {
|
|
183
|
+
readonly version?: number;
|
|
184
|
+
readonly piiFields: EventPiiStance;
|
|
185
|
+
readonly migrations?: readonly {
|
|
186
|
+
readonly fromVersion: number;
|
|
187
|
+
readonly toVersion: number;
|
|
188
|
+
readonly transform: EventUpcastFn | DeclarativeEventMigration;
|
|
189
|
+
}[];
|
|
190
|
+
}): EventDef<TPayload, QualifiedEventName<TFeature, TInner>>;
|
|
191
|
+
readsConfig(...qualifiedKeys: string[]): void;
|
|
192
|
+
readsConfig(options: {
|
|
193
|
+
readonly keys: readonly string[];
|
|
194
|
+
}): void;
|
|
195
|
+
referenceData(entity: NameOrRef, data: readonly Record<string, unknown>[], options?: {
|
|
196
|
+
upsertKey?: string;
|
|
197
|
+
}): void;
|
|
198
|
+
referenceData(definition: {
|
|
199
|
+
readonly entity: NameOrRef;
|
|
200
|
+
readonly data: readonly Record<string, unknown>[];
|
|
201
|
+
readonly upsertKey?: string;
|
|
202
|
+
}): void;
|
|
203
|
+
extendsRegistrar(name: string, def: RegistrarExtensionDef): void;
|
|
204
|
+
useExtension<N extends string>(extensionName: N, entity: NameOrRef, ...options: ExtensionOptionsArgs<N>): void;
|
|
205
|
+
useExtension<N extends string>(definition: {
|
|
206
|
+
readonly name: N;
|
|
207
|
+
readonly entity: NameOrRef;
|
|
208
|
+
} & ExtensionOptionsFor<N>): void;
|
|
209
|
+
/**
|
|
210
|
+
* Declares which config key selects the active provider under an
|
|
211
|
+
* extension point — called by the point-owning foundation (e.g.
|
|
212
|
+
* `r.extensionSelector("mailTransport", configKeys.provider)`).
|
|
213
|
+
* Readiness gating counts a provider-feature's `required` keys and
|
|
214
|
+
* secrets only while that provider is the selected one. Registry-build
|
|
215
|
+
* fails on duplicate declarations per extension and on selector keys
|
|
216
|
+
* that no mounted feature declares. A masked tenant selector key makes the
|
|
217
|
+
* Settings-Hub render one tenant dashboard for the owner: the selector as a
|
|
218
|
+
* select of the mounted plugin ids, the selected plugin's config and secrets
|
|
219
|
+
* as panels, and plugin features lose their own tenant nav. `config:write:set`
|
|
220
|
+
* rejects unknown plugin ids (`""` clears). `options.panels` adds the owner's own
|
|
221
|
+
* `custom`/`screen` panels to that dashboard, after the selection and before the
|
|
222
|
+
* plugin panels (a short `screen` id means a screen of the declaring feature).
|
|
223
|
+
*/
|
|
224
|
+
extensionSelector(extensionName: string, key: {
|
|
225
|
+
readonly name: string;
|
|
226
|
+
} | string, options?: {
|
|
227
|
+
readonly panels?: readonly ExtensionSelectorPanel[];
|
|
228
|
+
}): void;
|
|
229
|
+
/**
|
|
230
|
+
* Marker declaration: this feature provides a cross-feature API under the
|
|
231
|
+
* given name. The implementation is registered separately as a query or
|
|
232
|
+
* write handler under the QN pattern; `r.exposesApi` is only a boot-check
|
|
233
|
+
* surface.
|
|
234
|
+
*
|
|
235
|
+
* The boot validator checks that every `r.usesApi(name)` finds a matching
|
|
236
|
+
* exposer, that the exposer feature is listed in requires/optionalRequires,
|
|
237
|
+
* and that no API name is exposed more than once.
|
|
238
|
+
*
|
|
239
|
+
* ```ts
|
|
240
|
+
* defineFeature("compliance-profiles", (r) => {
|
|
241
|
+
* r.exposesApi("compliance.forTenant");
|
|
242
|
+
* r.queryHandler({
|
|
243
|
+
* name: "compliance:query:for-tenant",
|
|
244
|
+
* // ... actual implementation
|
|
245
|
+
* });
|
|
246
|
+
* });
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
exposesApi(apiName: string): void;
|
|
250
|
+
/**
|
|
251
|
+
* Declares that this feature calls a cross-feature API. The boot validator
|
|
252
|
+
* checks that another feature provides `r.exposesApi(apiName)` and that
|
|
253
|
+
* this feature lists it in `r.requires/optionalRequires`.
|
|
254
|
+
*
|
|
255
|
+
* ```ts
|
|
256
|
+
* defineFeature("user-data-rights", (r) => {
|
|
257
|
+
* r.requires({ features: ["compliance-profiles"] });
|
|
258
|
+
* r.usesApi("compliance.forTenant");
|
|
259
|
+
* });
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
usesApi(apiName: string): void;
|
|
263
|
+
/**
|
|
264
|
+
* Declares a boot-time mount-invariant for this feature. `fn` runs once
|
|
265
|
+
* at boot with a ctx exposing every mounted feature — throw to fail the
|
|
266
|
+
* boot with a clear message. Multiple calls per feature are allowed.
|
|
267
|
+
*
|
|
268
|
+
* Use for cross-feature invariants that `r.requires` can't express
|
|
269
|
+
* because they're conditional (only fail when the feature has a
|
|
270
|
+
* specific shape), e.g. "if this feature has PII entities, some
|
|
271
|
+
* user-data-hook feature must be mounted" (the prompt-store trap —
|
|
272
|
+
* a UserData feature was written but never mounted, and nothing caught
|
|
273
|
+
* it at boot):
|
|
274
|
+
*
|
|
275
|
+
* ```ts
|
|
276
|
+
* defineFeature("prompt-store", (r) => {
|
|
277
|
+
* const promptFields = { text: createTextField({ personal: "self", find: "none" }) };
|
|
278
|
+
* r.entity({ name: "prompt", fields: promptFields });
|
|
279
|
+
* r.bootCheck(({ features }) => {
|
|
280
|
+
* // Conditional on this feature's own shape (has a pii field) —
|
|
281
|
+
* // r.requires({ features: ["user-data-hook"] }) can't express that, it would fail
|
|
282
|
+
* // even for a prompt-store variant with no PII fields at all.
|
|
283
|
+
* const hasPiiField = Object.values(promptFields).some((f) => f.pii);
|
|
284
|
+
* const hasUserDataHook = features.some((f) => f.name === "user-data-hook");
|
|
285
|
+
* if (hasPiiField && !hasUserDataHook) {
|
|
286
|
+
* throw new Error("prompt-store has PII fields but no user-data-hook feature is mounted");
|
|
287
|
+
* }
|
|
288
|
+
* });
|
|
289
|
+
* });
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
bootCheck(fn: BootCheckFn): void;
|
|
293
|
+
metric(shortName: string, options: MetricOptions): void;
|
|
294
|
+
metric(definition: {
|
|
295
|
+
readonly name: string;
|
|
296
|
+
} & MetricOptions): void;
|
|
297
|
+
secret(shortName: string, options: SecretOptions): SecretKeyHandle;
|
|
298
|
+
secret(definition: {
|
|
299
|
+
readonly name: string;
|
|
300
|
+
} & SecretOptions): SecretKeyHandle;
|
|
301
|
+
secretNamespace(shortName: string, options: SecretNamespaceOptions): SecretNamespaceHandle;
|
|
302
|
+
secretNamespace(definition: {
|
|
303
|
+
readonly name: string;
|
|
304
|
+
} & SecretNamespaceOptions): SecretNamespaceHandle;
|
|
305
|
+
projection(definition: ProjectionDefinition): void;
|
|
306
|
+
multiStreamProjection(definition: MultiStreamProjectionDefinition): void;
|
|
307
|
+
extendEntityProjection(entityName: string, extension: EntityProjectionExtension): void;
|
|
308
|
+
authClaims(fn: AuthClaimsFn): void;
|
|
309
|
+
claimKey<T extends ClaimKeyType>(shortName: string, options: {
|
|
310
|
+
readonly type: T;
|
|
311
|
+
}): ClaimKeyHandle<T>;
|
|
312
|
+
claimKey<T extends ClaimKeyType>(definition: {
|
|
313
|
+
readonly name: string;
|
|
314
|
+
readonly type: T;
|
|
315
|
+
}): ClaimKeyHandle<T>;
|
|
316
|
+
screen(definition: ScreenDefinition): void;
|
|
317
|
+
nav(definition: NavDefinition): void;
|
|
318
|
+
contentCollection(definition: ContentCollectionDefinition): string;
|
|
319
|
+
workspace(definition: WorkspaceDefinition): void;
|
|
320
|
+
httpRoute(definition: HttpRouteDefinition): void;
|
|
321
|
+
webSocketRoute(definition: WebSocketRouteDefinition): void;
|
|
322
|
+
storeTable(meta: EntityTableMeta, options: StoreTableOptions): void;
|
|
323
|
+
treeActions<const TActions extends Record<string, TreeActionDef>>(actions: TActions): TreeActionsHandle<TFeature, TActions>;
|
|
324
|
+
envSchema(schema: z.ZodObject<z.ZodRawShape>): void;
|
|
325
|
+
};
|
|
326
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|