@cosmicdrift/kumiko-types 0.362.0 → 0.363.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 CHANGED
@@ -183,14 +183,64 @@ export type NotificationRecipientFn = (result: import("./hooks.js").SaveContext)
183
183
  } | null;
184
184
  export type NotificationDataFn = (result: import("./hooks.js").SaveContext) => Record<string, unknown>;
185
185
  export type NotificationTemplateFn = (data: Record<string, unknown>) => Record<string, unknown>;
186
+ type TemplateVariableCommon = {
187
+ readonly label?: string;
188
+ readonly required?: boolean;
189
+ };
190
+ export type TemplateScalarVariableDef = (TemplateVariableCommon & {
191
+ readonly type: "text";
192
+ readonly example?: string;
193
+ }) | (TemplateVariableCommon & {
194
+ readonly type: "link";
195
+ readonly example?: string;
196
+ }) | (TemplateVariableCommon & {
197
+ readonly type: "money";
198
+ readonly example?: number | {
199
+ readonly amount: number;
200
+ readonly currency: string;
201
+ };
202
+ }) | (TemplateVariableCommon & {
203
+ readonly type: "date";
204
+ readonly example?: string;
205
+ });
206
+ export type TemplateListVariableDef = TemplateVariableCommon & {
207
+ readonly type: "list";
208
+ readonly item: Readonly<Record<string, TemplateScalarVariableDef>>;
209
+ readonly example?: readonly Readonly<Record<string, unknown>>[];
210
+ };
211
+ export type TemplateVariableDef = TemplateScalarVariableDef | TemplateListVariableDef;
212
+ export type TemplateVariables = Readonly<Record<string, TemplateVariableDef>>;
213
+ export type NotificationTemplateMeta = {
214
+ readonly subject: string;
215
+ readonly previewText?: string;
216
+ readonly layoutSlug?: string;
217
+ readonly category?: "transactional" | "marketing";
218
+ readonly sender?: string;
219
+ };
220
+ export type NotificationTemplateBody = {
221
+ readonly body: string;
222
+ };
223
+ export type NotificationLocalizedTemplate = Readonly<Record<string, {
224
+ readonly body: string;
225
+ readonly meta: NotificationTemplateMeta;
226
+ }>>;
227
+ export type NotificationRecordMapping = {
228
+ readonly entity: string;
229
+ readonly map: Readonly<Record<string, string>>;
230
+ };
186
231
  export type NotificationDefinition = {
187
232
  readonly name: string;
188
- readonly trigger: {
233
+ readonly trigger?: {
189
234
  readonly on: string;
190
235
  };
191
- readonly recipient: NotificationRecipientFn;
192
- readonly data: NotificationDataFn;
236
+ readonly recipient?: NotificationRecipientFn;
237
+ readonly data?: NotificationDataFn;
193
238
  readonly templates: Readonly<Record<string, NotificationTemplateFn>> | undefined;
239
+ readonly variables?: TemplateVariables;
240
+ readonly record?: NotificationRecordMapping;
241
+ readonly template?: Readonly<Record<string, NotificationTemplateBody>>;
242
+ readonly meta?: Readonly<Record<string, NotificationTemplateMeta>>;
243
+ readonly localizedTemplate?: () => NotificationLocalizedTemplate;
194
244
  };
195
245
  export type PluralForms = {
196
246
  readonly zero?: string;
@@ -259,3 +309,4 @@ export type CreateUserSeedOptions = {
259
309
  readonly tenantId: string;
260
310
  readonly userId: string;
261
311
  };
312
+ export {};
package/dist/feature.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type * as z from "zod";
2
2
  import type { ZodType } from "zod";
3
- import type { ConfigKeyDefinition, ConfigKeyHandle, ConfigKeyType, ConfigSeedDef, ExtensionSelectorDef, ExtensionSelectorPanel, JobDefinition, JobHandlerFn, NotificationDataFn, NotificationDefinition, NotificationRecipientFn, NotificationTemplateFn, ReferenceDataDef, RegistrarExtensionDef, RegistrarExtensionRegistration, TranslationKeys, TranslationsDef } from "./config.js";
3
+ import type { ConfigKeyDefinition, ConfigKeyHandle, ConfigKeyType, ConfigSeedDef, ExtensionSelectorDef, ExtensionSelectorPanel, JobDefinition, JobHandlerFn, NotificationDataFn, NotificationDefinition, NotificationLocalizedTemplate, NotificationRecipientFn, NotificationRecordMapping, NotificationTemplateBody, NotificationTemplateFn, NotificationTemplateMeta, ReferenceDataDef, RegistrarExtensionDef, RegistrarExtensionRegistration, TemplateVariables, TranslationKeys, TranslationsDef } from "./config.js";
4
4
  import type { QueryHandlerDefinition, StreamHandlerDefinition, WriteHandlerDefinition } from "./define-handler.js";
5
5
  import type { RegisterEntityCrudOptions } from "./entity-handlers.js";
6
6
  import type { EntityTableMeta } from "./entity-table-meta-types.js";
@@ -296,21 +296,31 @@ export type FeatureRegistrar<TFeature extends string = string> = {
296
296
  job(name: string, options: Omit<JobDefinition, "name" | "handler">, handler: JobHandlerFn): void;
297
297
  job(definition: JobDefinition): void;
298
298
  notification(name: string, definition: {
299
- readonly trigger: {
299
+ readonly trigger?: {
300
300
  readonly on: NameOrRef;
301
301
  };
302
- readonly recipient: NotificationRecipientFn;
303
- readonly data: NotificationDataFn;
302
+ readonly recipient?: NotificationRecipientFn;
303
+ readonly data?: NotificationDataFn;
304
304
  readonly templates?: Readonly<Record<string, NotificationTemplateFn>>;
305
+ readonly variables?: TemplateVariables;
306
+ readonly record?: NotificationRecordMapping;
307
+ readonly template?: Readonly<Record<string, NotificationTemplateBody>>;
308
+ readonly meta?: Readonly<Record<string, NotificationTemplateMeta>>;
309
+ readonly localizedTemplate?: () => NotificationLocalizedTemplate;
305
310
  }): void;
306
311
  notification(definition: {
307
312
  readonly name: string;
308
- readonly trigger: {
313
+ readonly trigger?: {
309
314
  readonly on: NameOrRef;
310
315
  };
311
- readonly recipient: NotificationRecipientFn;
312
- readonly data: NotificationDataFn;
316
+ readonly recipient?: NotificationRecipientFn;
317
+ readonly data?: NotificationDataFn;
313
318
  readonly templates?: Readonly<Record<string, NotificationTemplateFn>>;
319
+ readonly variables?: TemplateVariables;
320
+ readonly record?: NotificationRecordMapping;
321
+ readonly template?: Readonly<Record<string, NotificationTemplateBody>>;
322
+ readonly meta?: Readonly<Record<string, NotificationTemplateMeta>>;
323
+ readonly localizedTemplate?: () => NotificationLocalizedTemplate;
314
324
  }): void;
315
325
  translations(def: TranslationsDef): void;
316
326
  defineEvent<const TInner extends string, TPayload>(name: TInner, schema: ZodType<TPayload>, options: {
@@ -157,16 +157,26 @@ export type NotifyDelivery = {
157
157
  readonly confirmed?: false;
158
158
  readonly deliveryAttemptId?: string;
159
159
  };
160
- export type NotifyResult = {
160
+ export type NotifyDispatched = {
161
+ readonly kind: "dispatched";
161
162
  readonly deliveries: readonly NotifyDelivery[];
162
163
  };
163
- export type NotifyFn = (notificationType: string, options: NotifyOptions) => Promise<NotifyResult>;
164
+ export type NotifyDeferred = {
165
+ readonly kind: "deferred";
166
+ };
167
+ export type NotifyResult = NotifyDispatched | NotifyDeferred;
168
+ export type NotifyFn = {
169
+ (notificationType: string, options: NotifyOptions & {
170
+ readonly immediate: true;
171
+ }): Promise<NotifyDispatched>;
172
+ (notificationType: string, options: NotifyOptions): Promise<NotifyResult>;
173
+ };
164
174
  export type NotifyJobDispatcher = {
165
175
  dispatch(jobName: string, payload: Record<string, unknown>, meta?: {
166
176
  readonly priority?: number;
167
177
  }): Promise<unknown>;
168
178
  };
169
- export type NotifyFactory = (user: SessionUser, tenantId: TenantId, jobDispatcher?: NotifyJobDispatcher) => NotifyFn;
179
+ export type NotifyFactory = (user: SessionUser, tenantId: TenantId, jobDispatcher?: NotifyJobDispatcher, deliveryDb?: DbConnection, fileProviderResolver?: FileProviderResolver) => NotifyFn;
170
180
  export type EscapeHatchKind = "unsafe-raw" | "acknowledge-cross-tenant" | "global-write" | "identity-switch" | "unsafe-all-tenants" | "cross-tenant-read";
171
181
  export type EscapeHatchTarget = {
172
182
  readonly id: string;
@@ -221,6 +231,7 @@ type SharedContextFields = {
221
231
  readonly entityCache?: EntityCache;
222
232
  readonly notify?: NotifyFn;
223
233
  readonly _notifyFactory?: NotifyFactory;
234
+ readonly _notifyInTransactionFactory?: (user: SessionUser, tenantId: TenantId) => NotifyFn;
224
235
  readonly _escapeHatchAuditSink?: EscapeHatchAuditSink;
225
236
  readonly secrets?: import("./secrets-types.js").SecretsContext;
226
237
  readonly masterKeyProvider?: import("./secrets-types.js").MasterKeyProvider;
@@ -34,7 +34,7 @@ export function subjectIdFromKey(key) {
34
34
  if (key.startsWith("user:"))
35
35
  return { kind: "user", userId: key.slice("user:".length) };
36
36
  if (key.startsWith("tenant:")) {
37
- return { kind: "tenant", tenantId: key.slice("tenant:".length) }; // @cast-boundary parse of a key this module minted
37
+ return { kind: "tenant", tenantId: key.slice("tenant:".length) };
38
38
  }
39
39
  if (key.startsWith("record:")) {
40
40
  const rest = key.slice("record:".length);
package/dist/nav.d.ts CHANGED
@@ -18,7 +18,7 @@ export type NavDefinition = {
18
18
  readonly workspaces?: readonly string[];
19
19
  };
20
20
  /** Client editor format for r.contentCollection() — not template body storage formats. */
21
- export type ContentEditorFormat = "plain" | "rich" | "markdown";
21
+ export type ContentEditorFormat = "plain" | "rich" | "markdown" | "document";
22
22
  export type ContentCollectionDefinition = {
23
23
  readonly id: string;
24
24
  readonly kind: string;
@@ -0,0 +1,8 @@
1
+ /** Non-null object that is not an array — shared guard for deep-merge and AST extractors. */
2
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
3
+ /** Membership test that narrows `candidate` to the element union of a const tuple. */
4
+ export declare function isOneOf<const T extends readonly unknown[]>(values: T, candidate: unknown): candidate is T[number];
5
+ /** Reads a string `code` (e.g. Node `ErrnoException`, Postgres SQLSTATE) off an unknown thrown value. */
6
+ export declare function errorCodeOf(error: unknown): string | undefined;
7
+ /** Reads one property off an unknown value (object or function); undefined for primitives, null and absent keys. */
8
+ export declare function propertyOf(value: unknown, key: PropertyKey): unknown;
@@ -0,0 +1,21 @@
1
+ /** Non-null object that is not an array — shared guard for deep-merge and AST extractors. */
2
+ export function isPlainObject(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ /** Membership test that narrows `candidate` to the element union of a const tuple. */
6
+ export function isOneOf(values, candidate) {
7
+ return values.some((value) => value === candidate);
8
+ }
9
+ /** Reads a string `code` (e.g. Node `ErrnoException`, Postgres SQLSTATE) off an unknown thrown value. */
10
+ export function errorCodeOf(error) {
11
+ if (typeof error !== "object" || error === null || !("code" in error))
12
+ return undefined;
13
+ return typeof error.code === "string" ? error.code : undefined;
14
+ }
15
+ /** Reads one property off an unknown value (object or function); undefined for primitives, null and absent keys. */
16
+ export function propertyOf(value, key) {
17
+ if ((typeof value !== "object" && typeof value !== "function") || value === null) {
18
+ return undefined;
19
+ }
20
+ return Reflect.get(value, key);
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.362.0",
3
+ "version": "0.363.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": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -26,6 +26,10 @@
26
26
  "types": "./dist/identifiers.d.ts",
27
27
  "default": "./dist/identifiers.js"
28
28
  },
29
+ "./type-guards": {
30
+ "types": "./dist/type-guards.d.ts",
31
+ "default": "./dist/type-guards.js"
32
+ },
29
33
  "./session-cookies": {
30
34
  "types": "./dist/session-cookies.d.ts",
31
35
  "default": "./dist/session-cookies.js"
@@ -297,6 +301,10 @@
297
301
  "types": "./dist/identifiers.d.ts",
298
302
  "default": "./dist/identifiers.js"
299
303
  },
304
+ "./type-guards": {
305
+ "types": "./dist/type-guards.d.ts",
306
+ "default": "./dist/type-guards.js"
307
+ },
300
308
  "./session-cookies": {
301
309
  "types": "./dist/session-cookies.d.ts",
302
310
  "default": "./dist/session-cookies.js"