@cosmicdrift/kumiko-types 0.327.0 → 0.328.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action-icon.d.ts +3 -0
- package/dist/action-icon.js +51 -0
- package/{src/agent-exposure.ts → dist/agent-exposure.d.ts} +8 -15
- package/dist/agent-exposure.js +16 -0
- package/dist/concurrency-mode.d.ts +1 -0
- package/dist/config-scope.d.ts +1 -0
- package/dist/config-scope.js +1 -0
- package/dist/config.d.ts +234 -0
- package/dist/config.js +1 -0
- package/dist/cursor-types.d.ts +16 -0
- package/dist/cursor-types.js +1 -0
- package/dist/db-connection.d.ts +14 -0
- package/dist/db-connection.js +1 -0
- package/dist/define-handler.d.ts +58 -0
- package/dist/define-handler.js +1 -0
- package/dist/derivatives-types.d.ts +53 -0
- package/dist/derivatives-types.js +3 -0
- package/dist/entity-cache.d.ts +16 -0
- package/dist/entity-cache.js +1 -0
- package/dist/entity-handlers.d.ts +54 -0
- package/dist/entity-handlers.js +1 -0
- package/dist/entity-table-meta-types.d.ts +44 -0
- package/dist/entity-table-meta-types.js +6 -0
- package/dist/envelope-cipher-types.d.ts +5 -0
- package/dist/envelope-cipher-types.js +1 -0
- package/dist/event-store-executor-types.d.ts +86 -0
- package/dist/event-store-executor-types.js +1 -0
- package/dist/event-store-types.d.ts +37 -0
- package/dist/event-store-types.js +7 -0
- package/dist/event-type-map.d.ts +8 -0
- package/{src/event-type-map.ts → dist/event-type-map.js} +1 -16
- package/dist/executor-brand.d.ts +8 -0
- package/dist/executor-brand.js +1 -0
- package/dist/extension-options-map.d.ts +9 -0
- package/dist/extension-options-map.js +4 -0
- package/dist/feature.d.ts +518 -0
- package/dist/feature.js +1 -0
- package/dist/field-icon.d.ts +1 -0
- package/dist/field-icon.js +1 -0
- package/dist/fields.d.ts +729 -0
- package/dist/fields.js +50 -0
- package/dist/file-handle-types.d.ts +12 -0
- package/dist/file-handle-types.js +1 -0
- package/dist/file-provider-resolver-types.d.ts +3 -0
- package/dist/file-provider-resolver-types.js +1 -0
- package/dist/file-storage-provider-types.d.ts +17 -0
- package/dist/file-storage-provider-types.js +1 -0
- package/dist/geo-tz.d.ts +17 -0
- package/{src/geo-tz.ts → dist/geo-tz.js} +1 -20
- package/dist/handlers.d.ts +493 -0
- package/dist/handlers.js +49 -0
- package/dist/hook-phase.d.ts +1 -0
- package/dist/hook-phase.js +1 -0
- package/dist/hooks.d.ts +75 -0
- package/dist/hooks.js +1 -0
- package/dist/http-route.d.ts +52 -0
- package/dist/http-route.js +13 -0
- package/dist/identifiers.d.ts +8 -0
- package/{src/identifiers.ts → dist/identifiers.js} +7 -24
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/kms-adapter-types.d.ts +68 -0
- package/dist/kms-adapter-types.js +49 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +1 -0
- package/dist/multi-stream-apply-context-types.d.ts +18 -0
- package/dist/multi-stream-apply-context-types.js +1 -0
- package/dist/nav-icon.d.ts +3 -0
- package/dist/nav-icon.js +100 -0
- package/dist/nav.d.ts +39 -0
- package/dist/nav.js +1 -0
- package/dist/observability/index.d.ts +3 -0
- package/dist/observability/index.js +2 -0
- package/dist/observability/metric.d.ts +34 -0
- package/dist/observability/metric.js +3 -0
- package/dist/observability/provider.d.ts +24 -0
- package/dist/observability/provider.js +4 -0
- package/dist/observability/span.d.ts +32 -0
- package/dist/observability/span.js +4 -0
- package/dist/ownership.d.ts +33 -0
- package/dist/ownership.js +5 -0
- package/dist/projection.d.ts +38 -0
- package/dist/projection.js +1 -0
- package/dist/rate-limit-types.d.ts +19 -0
- package/dist/rate-limit-types.js +1 -0
- package/dist/relations.d.ts +25 -0
- package/dist/relations.js +1 -0
- package/dist/schema-table-types.d.ts +15 -0
- package/{src/schema-table-types.ts → dist/schema-table-types.js} +0 -20
- package/dist/screen.d.ts +1265 -0
- package/dist/screen.js +3 -0
- package/dist/search-adapter.d.ts +32 -0
- package/dist/search-adapter.js +1 -0
- package/dist/secrets-types.d.ts +52 -0
- package/dist/secrets-types.js +30 -0
- package/dist/snapshot-types.d.ts +13 -0
- package/dist/snapshot-types.js +1 -0
- package/dist/step.d.ts +304 -0
- package/dist/step.js +11 -0
- package/dist/target-ref.d.ts +5 -0
- package/{src/target-ref.ts → dist/target-ref.js} +1 -6
- package/dist/tenancy-brand.d.ts +6 -0
- package/dist/tenancy-brand.js +1 -0
- package/dist/tenant-db-types.d.ts +67 -0
- package/dist/tenant-db-types.js +5 -0
- package/dist/tree-node.d.ts +26 -0
- package/dist/tree-node.js +22 -0
- package/dist/tz-context.d.ts +48 -0
- package/dist/tz-context.js +6 -0
- package/dist/websocket-route.d.ts +46 -0
- package/dist/websocket-route.js +10 -0
- package/dist/where-clause-types.d.ts +20 -0
- package/dist/where-clause-types.js +1 -0
- package/dist/workspace.d.ts +10 -0
- package/dist/workspace.js +1 -0
- package/dist/write-error-info-types.d.ts +12 -0
- package/dist/write-error-info-types.js +1 -0
- package/package.json +372 -124
- package/src/changes.json +18 -0
- package/src/__tests__/handlers.test.ts +0 -40
- package/src/__tests__/plural-forms.test.ts +0 -18
- package/src/action-icon.ts +0 -57
- package/src/concurrency-mode.ts +0 -5
- package/src/config-scope.ts +0 -5
- package/src/config.ts +0 -563
- package/src/cursor-types.ts +0 -18
- package/src/db-connection.ts +0 -25
- package/src/define-handler.ts +0 -138
- package/src/derivatives-types.ts +0 -106
- package/src/entity-cache.ts +0 -35
- package/src/entity-handlers.ts +0 -68
- package/src/entity-table-meta-types.ts +0 -101
- package/src/envelope-cipher-types.ts +0 -6
- package/src/event-store-executor-types.ts +0 -163
- package/src/event-store-types.ts +0 -85
- package/src/executor-brand.ts +0 -19
- package/src/extension-options-map.ts +0 -21
- package/src/feature.ts +0 -1141
- package/src/field-icon.ts +0 -23
- package/src/fields.ts +0 -1114
- package/src/file-handle-types.ts +0 -20
- package/src/file-provider-resolver-types.ts +0 -7
- package/src/file-storage-provider-types.ts +0 -54
- package/src/handlers.ts +0 -1246
- package/src/hook-phase.ts +0 -2
- package/src/hooks.ts +0 -170
- package/src/http-route.ts +0 -78
- package/src/kms-adapter-types.ts +0 -128
- package/src/logger.ts +0 -7
- package/src/multi-stream-apply-context-types.ts +0 -52
- package/src/nav-icon.ts +0 -105
- package/src/nav.ts +0 -139
- package/src/observability/index.ts +0 -28
- package/src/observability/metric.ts +0 -56
- package/src/observability/provider.ts +0 -32
- package/src/observability/span.ts +0 -58
- package/src/ownership.ts +0 -83
- package/src/projection.ts +0 -170
- package/src/rate-limit-types.ts +0 -32
- package/src/relations.ts +0 -52
- package/src/screen.ts +0 -1593
- package/src/search-adapter.ts +0 -45
- package/src/secrets-types.ts +0 -182
- package/src/snapshot-types.ts +0 -36
- package/src/step.ts +0 -390
- package/src/tenancy-brand.ts +0 -9
- package/src/tenant-db-types.ts +0 -116
- package/src/tree-node.ts +0 -134
- package/src/tz-context.ts +0 -63
- package/src/websocket-route.ts +0 -68
- package/src/where-clause-types.ts +0 -31
- package/src/workspace.ts +0 -42
- package/src/write-error-info-types.ts +0 -20
- /package/{src/index.ts → dist/concurrency-mode.js} +0 -0
package/dist/screen.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { EntityId, TenantId } from "./identifiers.js";
|
|
2
|
+
export type SearchAdapterConfig = {
|
|
3
|
+
searchableFields: readonly string[];
|
|
4
|
+
rankingFields?: readonly string[];
|
|
5
|
+
};
|
|
6
|
+
export type SearchDocument = {
|
|
7
|
+
entityType: string;
|
|
8
|
+
entityId: EntityId;
|
|
9
|
+
weight: number;
|
|
10
|
+
fields: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
export type SearchResult = {
|
|
13
|
+
entityType: string;
|
|
14
|
+
entityId: EntityId;
|
|
15
|
+
};
|
|
16
|
+
export type SearchOptions = {
|
|
17
|
+
limit?: number;
|
|
18
|
+
filterType?: string;
|
|
19
|
+
};
|
|
20
|
+
export type SearchAdapter = {
|
|
21
|
+
configure(tenantId: TenantId, config: SearchAdapterConfig): Promise<void>;
|
|
22
|
+
setDefaultConfig?(config: SearchAdapterConfig): void;
|
|
23
|
+
index(tenantId: TenantId, doc: SearchDocument): Promise<void>;
|
|
24
|
+
search(tenantId: TenantId, query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
25
|
+
remove(tenantId: TenantId, entityType: string, entityId: EntityId): Promise<void>;
|
|
26
|
+
indexBatch?(tenantId: TenantId, docs: readonly SearchDocument[]): Promise<void>;
|
|
27
|
+
removeBatch?(tenantId: TenantId, items: readonly {
|
|
28
|
+
entityType: string;
|
|
29
|
+
entityId: EntityId;
|
|
30
|
+
}[]): Promise<void>;
|
|
31
|
+
dropAllIndexes?(): Promise<number>;
|
|
32
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { TenantId } from "./identifiers.js";
|
|
2
|
+
declare const SecretBrand: unique symbol;
|
|
3
|
+
export type Secret<T = string> = {
|
|
4
|
+
readonly [SecretBrand]: true;
|
|
5
|
+
readonly reveal: () => T;
|
|
6
|
+
};
|
|
7
|
+
export declare function createSecret<T>(value: T): Secret<T>;
|
|
8
|
+
export declare function isSecret(v: unknown): v is Secret<unknown>;
|
|
9
|
+
type Primitive = string | number | boolean | bigint | symbol | null | undefined;
|
|
10
|
+
type SafeLeaf = Date | RegExp | Temporal.Instant | Temporal.ZonedDateTime | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.PlainTime | Temporal.PlainYearMonth | Temporal.PlainMonthDay | Temporal.Duration | Map<unknown, unknown> | Set<unknown>;
|
|
11
|
+
export type ContainsSecret<T> = [T] extends [never] ? false : unknown extends T ? false : T extends Secret<unknown> ? true : T extends Primitive ? false : T extends SafeLeaf ? false : T extends readonly (infer U)[] ? ContainsSecret<U> : T extends object ? true extends {
|
|
12
|
+
[K in keyof T]-?: ContainsSecret<T[K]>;
|
|
13
|
+
}[keyof T] ? true : false : false;
|
|
14
|
+
export type SecretAuditContext = {
|
|
15
|
+
readonly userId: string;
|
|
16
|
+
readonly handlerName: string;
|
|
17
|
+
};
|
|
18
|
+
export type SecretKeyRef = string | {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
};
|
|
21
|
+
export interface SecretsContext {
|
|
22
|
+
get(tenantId: TenantId, key: SecretKeyRef, auditCtx?: SecretAuditContext): Promise<Secret<string> | undefined>;
|
|
23
|
+
has(tenantId: TenantId, key: SecretKeyRef): Promise<boolean>;
|
|
24
|
+
set(tenantId: TenantId, key: SecretKeyRef, value: string, opts?: {
|
|
25
|
+
redact?: (plaintext: string) => string;
|
|
26
|
+
hint?: string;
|
|
27
|
+
updatedBy?: string;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
delete(tenantId: TenantId, key: SecretKeyRef, opts?: {
|
|
30
|
+
deletedBy?: string;
|
|
31
|
+
}): Promise<boolean>;
|
|
32
|
+
}
|
|
33
|
+
export type Envelope = {
|
|
34
|
+
readonly ciphertext: Buffer;
|
|
35
|
+
readonly iv: Buffer;
|
|
36
|
+
readonly authTag: Buffer;
|
|
37
|
+
readonly encryptedDek: Buffer;
|
|
38
|
+
readonly kekVersion: number;
|
|
39
|
+
};
|
|
40
|
+
export type KeyScope = {
|
|
41
|
+
readonly tenantId?: TenantId;
|
|
42
|
+
};
|
|
43
|
+
export interface MasterKeyProvider {
|
|
44
|
+
wrapDek(dek: Buffer, scope?: KeyScope): Promise<{
|
|
45
|
+
encryptedDek: Buffer;
|
|
46
|
+
kekVersion: number;
|
|
47
|
+
}>;
|
|
48
|
+
unwrapDek(encryptedDek: Buffer, kekVersion: number, scope?: KeyScope): Promise<Buffer>;
|
|
49
|
+
currentVersion(): number;
|
|
50
|
+
isAvailable(): Promise<boolean>;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Envelope Encryption types. Separating DEK (per-value) from KEK (central)
|
|
2
|
+
// is what makes key rotation cheap: on rotation we only re-wrap the small
|
|
3
|
+
// encryptedDek, never touch the ciphertext.
|
|
4
|
+
// Plaintext-secret wrapper (branded). Carries the actual string internally
|
|
5
|
+
// but the nominal typing stops it from landing in an HTTP response by
|
|
6
|
+
// accident — a response-serializer guard + the reveal() cost make the leak
|
|
7
|
+
// intentional. Framework code that sees `Secret<string>` knows the caller
|
|
8
|
+
// has already gone through the audited ctx.secrets.get path.
|
|
9
|
+
//
|
|
10
|
+
// Registered symbol, matching KUMIKO_*_SYMBOL in schema-table-types.ts. A
|
|
11
|
+
// plain Symbol() is per-copy: two resolved copies of this package brand with
|
|
12
|
+
// two different symbols, so createSecret() from one and isSecret() from the
|
|
13
|
+
// other disagree — and isSecret() is the ONLY thing assertNoSecretLeak has,
|
|
14
|
+
// so a false there serializes the plaintext into the response. The namespaced
|
|
15
|
+
// key makes accidental user-land collision implausible; a deliberate forge
|
|
16
|
+
// would only over-trigger the guard, which fails safe.
|
|
17
|
+
const SecretBrand = Symbol.for("kumiko.secret");
|
|
18
|
+
// Implementation helper — bundled-features uses this to wrap a plaintext after
|
|
19
|
+
// decryption. Kept in the framework so both sides share one canonical brand.
|
|
20
|
+
export function createSecret(value) {
|
|
21
|
+
return {
|
|
22
|
+
[SecretBrand]: true,
|
|
23
|
+
reveal: () => value,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// True for any object carrying the Secret brand. Used by the response guard
|
|
27
|
+
// to reject leaks before serialization.
|
|
28
|
+
export function isSecret(v) {
|
|
29
|
+
return typeof v === "object" && v !== null && SecretBrand in v;
|
|
30
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { StoredEvent } from "./event-store-types.js";
|
|
2
|
+
export type SnapshotReducer<TState extends Record<string, unknown>> = (state: TState, event: StoredEvent) => TState;
|
|
3
|
+
export type LoadAggregateWithSnapshotResult<TState extends Record<string, unknown>> = {
|
|
4
|
+
readonly state: TState;
|
|
5
|
+
readonly version: number;
|
|
6
|
+
readonly snapshotHit: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type LoadAggregateWithSnapshotOptions = {
|
|
9
|
+
readonly includeArchived?: boolean;
|
|
10
|
+
readonly upcastEvent?: (event: StoredEvent) => Promise<StoredEvent>;
|
|
11
|
+
readonly snapshotEvery?: number;
|
|
12
|
+
readonly snapshotVersion?: number;
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/step.d.ts
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import type { EventStoreExecutor } from "./event-store-executor-types.js";
|
|
2
|
+
import type { KumikoEventTypeMap } from "./event-type-map.js";
|
|
3
|
+
import type { HandlerContext, WriteEvent, WriteResult } from "./handlers.js";
|
|
4
|
+
import type { SaveContext } from "./hooks.js";
|
|
5
|
+
import type { EntityId } from "./identifiers.js";
|
|
6
|
+
import type { WhereObject } from "./where-clause-types.js";
|
|
7
|
+
/**
|
|
8
|
+
* The kind discriminator for a step instance — matches the step's
|
|
9
|
+
* registration name in the step-registry (e.g. "return", "compute",
|
|
10
|
+
* "aggregate.create"). Steps register themselves at module-load time
|
|
11
|
+
* via defineStep().
|
|
12
|
+
*/
|
|
13
|
+
export type StepKind = string;
|
|
14
|
+
/**
|
|
15
|
+
* Pipeline-side context handed to step argument resolvers.
|
|
16
|
+
*
|
|
17
|
+
* Contains the full HandlerContext (no per-step subset in M.1) plus
|
|
18
|
+
* the accumulated `steps` map of prior step results, and a `scope`
|
|
19
|
+
* record for forEach/branch-local bindings.
|
|
20
|
+
*
|
|
21
|
+
* `scope` is `Record<string, unknown>` — sub-step builders (forEach,
|
|
22
|
+
* branch) populate it once they land in later M.1 slices. M.1.1 ships
|
|
23
|
+
* with `r.step.return` only, which reads `event` and ignores both
|
|
24
|
+
* `steps` and `scope`.
|
|
25
|
+
*/
|
|
26
|
+
export type PipelineCtx<TPayload = unknown, TMap extends object = KumikoEventTypeMap> = HandlerContext<TMap> & {
|
|
27
|
+
readonly event: WriteEvent<TPayload>;
|
|
28
|
+
readonly steps: Readonly<Record<string, unknown>>;
|
|
29
|
+
readonly scope: Readonly<Record<string, unknown>>;
|
|
30
|
+
readonly workflow?: {
|
|
31
|
+
readonly runId: string;
|
|
32
|
+
readonly workflowName: string;
|
|
33
|
+
/** Current step index in the pipeline — set by the executor before each step. */
|
|
34
|
+
readonly stepIndex: number;
|
|
35
|
+
/**
|
|
36
|
+
* Retry attempt counter for the current workflow.retry step.
|
|
37
|
+
* Set by the workflow-engine resume-loop on re-entry; starts at 1.
|
|
38
|
+
* Absent (undefined) means first attempt.
|
|
39
|
+
*/
|
|
40
|
+
readonly retryAttempt?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Q7 Snapshot-at-Start fingerprint of the workflow definition that
|
|
43
|
+
* started this run. Propagated into every suspension event payload so
|
|
44
|
+
* the resume-loop can detect library-upgrades that changed the closure
|
|
45
|
+
* source and surface them as a typed failure instead of running a
|
|
46
|
+
* stale-vs-new mix of steps. Optional only for legacy callers; the
|
|
47
|
+
* workflow-runner sets it on every newly-started run.
|
|
48
|
+
*/
|
|
49
|
+
readonly definitionFingerprint?: string;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* A resolver is either a static value or a function that derives the
|
|
54
|
+
* value from the pipeline-context. M.1 keeps the resolver signature
|
|
55
|
+
* uniform — every step accepts both forms via a normalise helper.
|
|
56
|
+
*/
|
|
57
|
+
export type StepResolver<T, TPayload = unknown> = T | ((ctx: PipelineCtx<TPayload>) => T);
|
|
58
|
+
export type AwaitedEventType = string & {
|
|
59
|
+
readonly __awaitedEvent: unique symbol;
|
|
60
|
+
};
|
|
61
|
+
export type EventMatchValue = string | number | boolean | null;
|
|
62
|
+
export type EventMatchOp = {
|
|
63
|
+
readonly kind: "eq";
|
|
64
|
+
readonly value: EventMatchValue;
|
|
65
|
+
} | {
|
|
66
|
+
readonly kind: "ne";
|
|
67
|
+
readonly value: EventMatchValue;
|
|
68
|
+
} | {
|
|
69
|
+
readonly kind: "in";
|
|
70
|
+
readonly values: readonly EventMatchValue[];
|
|
71
|
+
} | {
|
|
72
|
+
readonly kind: "gt";
|
|
73
|
+
readonly value: number | string;
|
|
74
|
+
} | {
|
|
75
|
+
readonly kind: "gte";
|
|
76
|
+
readonly value: number | string;
|
|
77
|
+
} | {
|
|
78
|
+
readonly kind: "lt";
|
|
79
|
+
readonly value: number | string;
|
|
80
|
+
} | {
|
|
81
|
+
readonly kind: "lte";
|
|
82
|
+
readonly value: number | string;
|
|
83
|
+
};
|
|
84
|
+
export type EventMatchExpr = {
|
|
85
|
+
readonly kind: "and";
|
|
86
|
+
readonly nodes: readonly EventMatchExpr[];
|
|
87
|
+
} | {
|
|
88
|
+
readonly kind: "or";
|
|
89
|
+
readonly nodes: readonly EventMatchExpr[];
|
|
90
|
+
} | {
|
|
91
|
+
readonly kind: "atom";
|
|
92
|
+
readonly path: readonly string[];
|
|
93
|
+
readonly op: EventMatchOp;
|
|
94
|
+
};
|
|
95
|
+
export type EventMatch = {
|
|
96
|
+
readonly version: 1;
|
|
97
|
+
readonly expr: EventMatchExpr;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Per-step error strategy. M.1.1 only supports "throw" — the type is
|
|
101
|
+
* deliberately narrowed so callers cannot pass an unsupported strategy
|
|
102
|
+
* past the type-checker. The doc lists "return" / "skip" / fallback as
|
|
103
|
+
* future strategies; each lands together with its own runtime support
|
|
104
|
+
* + integration test in a later slice (no untested type expansion).
|
|
105
|
+
*/
|
|
106
|
+
export type StepFailureStrategy = "throw";
|
|
107
|
+
export type StepDef<TArgs = unknown, TResult = unknown> = {
|
|
108
|
+
readonly kind: StepKind;
|
|
109
|
+
readonly defaultFailureStrategy: StepFailureStrategy;
|
|
110
|
+
readonly resultKey?: (args: TArgs) => string | undefined;
|
|
111
|
+
readonly subPaths?: readonly string[];
|
|
112
|
+
readonly tier?: 1 | 2 | 3;
|
|
113
|
+
readonly run: (args: TArgs, ctx: PipelineCtx) => Promise<TResult> | TResult;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* An instance of a step in a pipeline — what users build via the
|
|
117
|
+
* step-builder (`r.step.compute(...)`). Carries the kind + resolved-or-
|
|
118
|
+
* resolver args + the user-chosen onFailure override.
|
|
119
|
+
*
|
|
120
|
+
* `args` is `unknown` at this layer — the registered StepDef knows the
|
|
121
|
+
* concrete shape and casts at run() time. Cross-step type-safety lives
|
|
122
|
+
* in the per-step builder factories, not in this central type.
|
|
123
|
+
*/
|
|
124
|
+
export type StepInstance = {
|
|
125
|
+
readonly kind: StepKind;
|
|
126
|
+
readonly args: unknown;
|
|
127
|
+
readonly onFailure?: StepFailureStrategy;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* What `stepsPipeline(closure)` returns. Carries the closure (instead of an
|
|
131
|
+
* eagerly-built array) so each handler-call sees a fresh event ref and
|
|
132
|
+
* the `r` step-builder is resolved at runtime, not at module-load time.
|
|
133
|
+
*
|
|
134
|
+
* `__kind: "pipeline"` lets defineWriteHandler distinguish a pipeline-
|
|
135
|
+
* form `perform` from accidental other shapes.
|
|
136
|
+
*
|
|
137
|
+
* `_TData` is a phantom type-parameter — held in constraint position
|
|
138
|
+
* only, never referenced in the type body. defineWriteHandler binds it
|
|
139
|
+
* via `def.perform: PipelineDef<…, TData>` (the call-site uses TData
|
|
140
|
+
* without underscore — phantom-prefix is purely a Biome
|
|
141
|
+
* `noUnusedVariables` marker, not user-facing). _TData is NOT inferred
|
|
142
|
+
* from the closure body (r.step.return has its own per-call TData), so
|
|
143
|
+
* callers must spell it explicitly:
|
|
144
|
+
* `stepsPipeline<{ greeting: string }, { echoed: string }>(...)`
|
|
145
|
+
* Better DX is a known follow-up — see step-vocabulary.md M.1-Followups.
|
|
146
|
+
*/
|
|
147
|
+
export type PipelineDef<TPayload = unknown, _TData = unknown, TAwaits extends Record<string, AwaitedEventType> = Record<string, AwaitedEventType>> = {
|
|
148
|
+
readonly __kind: "pipeline";
|
|
149
|
+
readonly awaits?: Readonly<Record<string, string>>;
|
|
150
|
+
readonly build: (ctx: PipelineBuildCtx<TPayload, TAwaits>) => readonly StepInstance[];
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Argument bundle passed to the closure inside `stepsPipeline(closure)`.
|
|
154
|
+
* Build-time only — no `steps`, no `scope`, no `db`: at build time no
|
|
155
|
+
* step has run yet.
|
|
156
|
+
*
|
|
157
|
+
* The closure is invoked ONCE per handler-call and returns the immutable
|
|
158
|
+
* list of step instances. Values inside the closure that depend on prior
|
|
159
|
+
* step results MUST go through resolvers (functions) — those receive the
|
|
160
|
+
* resolver-side PipelineCtx which carries `steps` + `scope`.
|
|
161
|
+
*
|
|
162
|
+
* **Closure-body contract:** the closure must produce a deterministic
|
|
163
|
+
* step-list that doesn't depend on `event.payload` — branching on payload
|
|
164
|
+
* fields belongs inside resolvers (where they fire per-call), not in the
|
|
165
|
+
* outer closure body. Boot-validation runs the closure once with a dummy
|
|
166
|
+
* empty payload to scan unsafeProjection-* step targets; a closure that
|
|
167
|
+
* conditionally builds different step-lists per payload would silently
|
|
168
|
+
* skip validation. See validate-projection-allowlist.ts for the
|
|
169
|
+
* boot-side mechanics.
|
|
170
|
+
*/
|
|
171
|
+
export type PipelineBuildCtx<TPayload = unknown, TAwaits extends Record<string, AwaitedEventType> = Record<string, AwaitedEventType>> = {
|
|
172
|
+
readonly event: WriteEvent<TPayload>;
|
|
173
|
+
readonly r: StepBuilder;
|
|
174
|
+
readonly awaits: TAwaits;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Step-builder namespace handed to the pipeline closure. The fields
|
|
178
|
+
* grow as M.1 adds more steps. Each is a thin factory that returns a
|
|
179
|
+
* StepInstance — the runtime resolution happens later in run().
|
|
180
|
+
*
|
|
181
|
+
* Why nested under `step`: matches the doc-API surface and leaves room
|
|
182
|
+
* for future sibling namespaces (`r.trigger`, `r.transform`) without
|
|
183
|
+
* crowding the top-level r.
|
|
184
|
+
*/
|
|
185
|
+
export type StepBuilder = {
|
|
186
|
+
readonly step: StepNamespace;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* The collection of step factory functions. Grown incrementally —
|
|
190
|
+
* landed: return (M.1.1), compute (M.1.2), unsafeProjectionUpsert
|
|
191
|
+
* (M.1.3), aggregate.create (M.1.4). Pending: branch, forEach,
|
|
192
|
+
* read.*, aggregate.update, aggregate.appendEvent,
|
|
193
|
+
* unsafeProjectionDelete.
|
|
194
|
+
*/
|
|
195
|
+
export type StepNamespace = {
|
|
196
|
+
readonly return: <TData>(resolver: StepResolver<WriteResult<TData>>) => StepInstance;
|
|
197
|
+
readonly compute: <TResult>(name: string, fn: (ctx: PipelineCtx) => TResult) => StepInstance;
|
|
198
|
+
readonly unsafeProjectionUpsert: (args: {
|
|
199
|
+
readonly table: unknown;
|
|
200
|
+
readonly on: readonly string[];
|
|
201
|
+
readonly row: StepResolver<Record<string, unknown>>;
|
|
202
|
+
}) => StepInstance;
|
|
203
|
+
readonly unsafeProjectionDelete: (args: {
|
|
204
|
+
readonly table: unknown;
|
|
205
|
+
readonly where: StepResolver<WhereObject>;
|
|
206
|
+
}) => StepInstance;
|
|
207
|
+
readonly read: {
|
|
208
|
+
readonly findOne: (name: string, opts: {
|
|
209
|
+
readonly table: unknown;
|
|
210
|
+
readonly where: StepResolver<WhereObject | undefined>;
|
|
211
|
+
readonly unsafeAllTenants?: {
|
|
212
|
+
readonly reason: string;
|
|
213
|
+
};
|
|
214
|
+
}) => StepInstance;
|
|
215
|
+
readonly findMany: (name: string, opts: {
|
|
216
|
+
readonly table: unknown;
|
|
217
|
+
readonly where?: StepResolver<WhereObject | undefined>;
|
|
218
|
+
readonly limit?: number;
|
|
219
|
+
readonly unsafeAllTenants?: {
|
|
220
|
+
readonly reason: string;
|
|
221
|
+
};
|
|
222
|
+
}) => StepInstance;
|
|
223
|
+
};
|
|
224
|
+
readonly aggregate: {
|
|
225
|
+
readonly create: (name: string, opts: {
|
|
226
|
+
readonly executor: EventStoreExecutor;
|
|
227
|
+
readonly data: StepResolver<Record<string, unknown>>;
|
|
228
|
+
}) => StepInstance;
|
|
229
|
+
readonly update: (name: string, opts: {
|
|
230
|
+
readonly executor: EventStoreExecutor;
|
|
231
|
+
readonly id: StepResolver<EntityId>;
|
|
232
|
+
readonly changes: StepResolver<Record<string, unknown>>;
|
|
233
|
+
readonly version?: StepResolver<number | undefined>;
|
|
234
|
+
readonly skipOptimisticLock?: boolean;
|
|
235
|
+
}) => StepInstance;
|
|
236
|
+
readonly appendEvent: (args: {
|
|
237
|
+
readonly aggregateId: StepResolver<string>;
|
|
238
|
+
readonly aggregateType: string;
|
|
239
|
+
readonly type: string;
|
|
240
|
+
readonly payload: StepResolver<unknown>;
|
|
241
|
+
readonly headers?: StepResolver<Readonly<Record<string, string | number | boolean>>>;
|
|
242
|
+
}) => StepInstance;
|
|
243
|
+
};
|
|
244
|
+
readonly branch: (args: {
|
|
245
|
+
readonly if: StepResolver<boolean>;
|
|
246
|
+
readonly onTrue: readonly StepInstance[];
|
|
247
|
+
readonly onFalse?: readonly StepInstance[];
|
|
248
|
+
}) => StepInstance;
|
|
249
|
+
readonly forEach: <TItem = unknown>(args: {
|
|
250
|
+
readonly over: StepResolver<readonly TItem[]>;
|
|
251
|
+
readonly as: string;
|
|
252
|
+
readonly do: readonly StepInstance[];
|
|
253
|
+
readonly concurrency?: 1;
|
|
254
|
+
}) => StepInstance;
|
|
255
|
+
readonly webhook: {
|
|
256
|
+
readonly send: (args: {
|
|
257
|
+
readonly url: StepResolver<string>;
|
|
258
|
+
readonly method?: "POST" | "PUT" | "PATCH";
|
|
259
|
+
readonly headers?: StepResolver<Readonly<Record<string, string>>>;
|
|
260
|
+
readonly body?: StepResolver<unknown>;
|
|
261
|
+
readonly auth?: {
|
|
262
|
+
readonly kind: "bearer";
|
|
263
|
+
readonly secret: string;
|
|
264
|
+
} | {
|
|
265
|
+
readonly kind: "header";
|
|
266
|
+
readonly name: string;
|
|
267
|
+
readonly secret: string;
|
|
268
|
+
};
|
|
269
|
+
readonly mode: "deferred";
|
|
270
|
+
readonly retry?: {
|
|
271
|
+
readonly times: number;
|
|
272
|
+
readonly backoff: "exponential" | "linear";
|
|
273
|
+
};
|
|
274
|
+
}) => StepInstance;
|
|
275
|
+
};
|
|
276
|
+
readonly mail: {
|
|
277
|
+
readonly send: (args: {
|
|
278
|
+
readonly to: StepResolver<string | readonly string[]>;
|
|
279
|
+
readonly subject: StepResolver<string>;
|
|
280
|
+
readonly body: StepResolver<string>;
|
|
281
|
+
readonly from?: StepResolver<string>;
|
|
282
|
+
readonly mode: "deferred";
|
|
283
|
+
}) => StepInstance;
|
|
284
|
+
};
|
|
285
|
+
readonly callFeature: (name: string, opts: {
|
|
286
|
+
readonly handler: string;
|
|
287
|
+
readonly payload: StepResolver<unknown>;
|
|
288
|
+
readonly as?: import("./handlers.js").SessionUser;
|
|
289
|
+
}) => StepInstance;
|
|
290
|
+
readonly wait: (args: {
|
|
291
|
+
readonly for: StepResolver<string>;
|
|
292
|
+
}) => StepInstance;
|
|
293
|
+
readonly waitForEvent: (args: {
|
|
294
|
+
readonly event: AwaitedEventType;
|
|
295
|
+
readonly match?: StepResolver<EventMatch>;
|
|
296
|
+
readonly timeout: StepResolver<string>;
|
|
297
|
+
}) => StepInstance;
|
|
298
|
+
readonly retry: (args: {
|
|
299
|
+
readonly times: number;
|
|
300
|
+
readonly backoff: "exponential" | "linear";
|
|
301
|
+
readonly do: readonly StepInstance[];
|
|
302
|
+
}) => StepInstance;
|
|
303
|
+
};
|
|
304
|
+
export type AggregateStepResult = SaveContext;
|
package/dist/step.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Step-Vocabulary Types — see docs/plans/architecture/intern/step-vocabulary.md
|
|
2
|
+
//
|
|
3
|
+
// M.1 minimal scope:
|
|
4
|
+
// - Steps execute against the existing HandlerContext (no per-step subset).
|
|
5
|
+
// - steps-accumulator is Record<string, unknown> (no tuple-reduce typing).
|
|
6
|
+
// - Resolvers receive the full PipelineCtx as one argument.
|
|
7
|
+
//
|
|
8
|
+
// Strict typing on appendEvent inside steps is deferred to a later pass
|
|
9
|
+
// (see TS-typing notes in the design doc). M.1 uses unsafeAppendEvent
|
|
10
|
+
// semantics under the hood for r.step.aggregate.appendEvent.
|
|
11
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { DbRunner } from "./db-connection.js";
|
|
2
|
+
import type { EntityTableMeta } from "./entity-table-meta-types.js";
|
|
3
|
+
import type { ExecutorOnly, NotExecutorOnly } from "./executor-brand.js";
|
|
4
|
+
import type { TenantId } from "./identifiers.js";
|
|
5
|
+
import type { SchemaTable } from "./schema-table-types.js";
|
|
6
|
+
import type { TenancyBrand } from "./tenancy-brand.js";
|
|
7
|
+
import type { SelectOptions, WhereObject } from "./where-clause-types.js";
|
|
8
|
+
type WritableTable = (SchemaTable | EntityTableMeta) & NotExecutorOnly;
|
|
9
|
+
type GlobalReads = {
|
|
10
|
+
selectMany<T = Record<string, unknown>>(where?: WhereObject, options?: SelectOptions): Promise<readonly T[]>;
|
|
11
|
+
fetchOne<T = Record<string, unknown>>(where: WhereObject): Promise<T | undefined>;
|
|
12
|
+
};
|
|
13
|
+
type GlobalWrites = {
|
|
14
|
+
insertOne<T = Record<string, unknown>>(values: Record<string, unknown>): Promise<T | undefined>;
|
|
15
|
+
updateMany<T = Record<string, unknown>>(set: Record<string, unknown>, where: WhereObject): Promise<readonly T[]>;
|
|
16
|
+
deleteMany(where: WhereObject): Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
export type GlobalTableDb<TTable> = GlobalReads & (TTable extends ExecutorOnly ? unknown : GlobalWrites);
|
|
19
|
+
/**
|
|
20
|
+
* TenantDb scope modes:
|
|
21
|
+
*
|
|
22
|
+
* - "tenant" (default): SELECT/UPDATE/DELETE filtered by tenantId + reference data (tenantId=SYSTEM_TENANT_ID).
|
|
23
|
+
* INSERT forces tenantId — handler cannot override.
|
|
24
|
+
*
|
|
25
|
+
* - "system" (r.systemScope()): No tenant filter on reads/updates/deletes.
|
|
26
|
+
* INSERT uses tenantId as default but handler can override.
|
|
27
|
+
*
|
|
28
|
+
* Tables without a tenantId column are always unfiltered regardless of mode.
|
|
29
|
+
*/
|
|
30
|
+
export type TenantDbMode = "tenant" | "system";
|
|
31
|
+
export type TenantDb = {
|
|
32
|
+
readonly tenantId: TenantId;
|
|
33
|
+
readonly mode: TenantDbMode;
|
|
34
|
+
/**
|
|
35
|
+
* Unfiltered DbRunner escape hatch for handlers/hooks that declare `escapeHatch: { reason }`.
|
|
36
|
+
* Throws `AccessDeniedError` when ungranted, or `Error` when `reason` is empty.
|
|
37
|
+
*/
|
|
38
|
+
unsafeRaw(reason: string): DbRunner;
|
|
39
|
+
/**
|
|
40
|
+
* Reach a "global" table with the tenant filter lifted — reads always work; writes
|
|
41
|
+
* reject unless the write handler declared `escapeHatch: { reason }`. "tenant"-tenancy is a compile error here.
|
|
42
|
+
*/
|
|
43
|
+
global<TTable extends (SchemaTable | EntityTableMeta) & TenancyBrand<"global">>(table: TTable): GlobalTableDb<TTable>;
|
|
44
|
+
selectMany<T = Record<string, unknown>>(table: SchemaTable | EntityTableMeta, where?: WhereObject, options?: SelectOptions): Promise<readonly T[]>;
|
|
45
|
+
fetchOne<T = Record<string, unknown>>(table: SchemaTable | EntityTableMeta, where: WhereObject): Promise<T | undefined>;
|
|
46
|
+
count(table: SchemaTable | EntityTableMeta, where?: WhereObject): Promise<number>;
|
|
47
|
+
insertOne<T = Record<string, unknown>>(table: WritableTable, values: Record<string, unknown>): Promise<T | undefined>;
|
|
48
|
+
updateMany<T = Record<string, unknown>>(table: WritableTable, set: Record<string, unknown>, where: WhereObject): Promise<readonly T[]>;
|
|
49
|
+
deleteMany(table: WritableTable, where: WhereObject): Promise<void>;
|
|
50
|
+
};
|
|
51
|
+
export declare const SYSTEM_SCOPE_CHECK_BRAND: unique symbol;
|
|
52
|
+
export type UncheckedSystemDb = {
|
|
53
|
+
readonly [SYSTEM_SCOPE_CHECK_BRAND]: true;
|
|
54
|
+
assertTenantMatch(tenantId: TenantId): TenantDb;
|
|
55
|
+
assertRowsTenant<T>(rows: readonly T[], tenantField: keyof T): readonly T[];
|
|
56
|
+
acknowledgeCrossTenant(reason: string): TenantDb;
|
|
57
|
+
/**
|
|
58
|
+
* Raw unfiltered DbRunner, gated behind a mandatory non-empty `reason` for auditability.
|
|
59
|
+
* Throws on an empty (or whitespace-only) reason.
|
|
60
|
+
*/
|
|
61
|
+
unsafeRaw(reason: string): DbRunner;
|
|
62
|
+
readonly outsideTransaction: {
|
|
63
|
+
assertTenantMatch(tenantId: TenantId): TenantDb;
|
|
64
|
+
acknowledgeCrossTenant(reason: string): TenantDb;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Symbol.for (global registry) so the brand identity matches even if kumiko-types
|
|
2
|
+
// resolves to two independent copies (workspace symlink vs. published npm) — a plain
|
|
3
|
+
// `Symbol()` per copy would make each resolution's `UncheckedSystemDb` structurally
|
|
4
|
+
// incompatible with the other, per the kumiko.secret precedent in secrets-types.ts.
|
|
5
|
+
export const SYSTEM_SCOPE_CHECK_BRAND = Symbol.for("kumiko.system-scope-check");
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { TargetRef } from "./target-ref.js";
|
|
2
|
+
export type TreeNodeState = "filled" | "stub" | "empty" | "loading" | "error";
|
|
3
|
+
export type TreeAction = {
|
|
4
|
+
readonly icon: string;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly screen?: string;
|
|
7
|
+
readonly target?: TargetRef;
|
|
8
|
+
};
|
|
9
|
+
export type TreeNode = {
|
|
10
|
+
readonly label: string;
|
|
11
|
+
readonly icon?: string;
|
|
12
|
+
readonly state?: TreeNodeState;
|
|
13
|
+
readonly target?: TargetRef;
|
|
14
|
+
readonly actions?: readonly TreeAction[];
|
|
15
|
+
readonly children?: readonly TreeNode[] | TreeChildrenSubscribe;
|
|
16
|
+
readonly createAction?: TreeAction;
|
|
17
|
+
};
|
|
18
|
+
export type Subscribe<T> = (emit: (value: T) => void, emitError?: (error: Error) => void) => () => void;
|
|
19
|
+
export type TreeChildrenSubscribe = () => Subscribe<readonly TreeNode[]>;
|
|
20
|
+
export type TreeActionDef<TArgs = Record<string, unknown>> = {
|
|
21
|
+
readonly args?: TArgs;
|
|
22
|
+
};
|
|
23
|
+
export type TreeActionsHandle<TFeature extends string, TActions extends Record<string, TreeActionDef>> = {
|
|
24
|
+
readonly id: TFeature;
|
|
25
|
+
readonly treeActions: TActions;
|
|
26
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// TreeNode — single Knoten im Client-navProvider-Tree. Provider liefern
|
|
2
|
+
// entweder statische readonly TreeNode[] oder dynamische TreeChildrenSubscribe.
|
|
3
|
+
//
|
|
4
|
+
// **Mental-Modell** (VS-Code-Explorer):
|
|
5
|
+
// [icon] [label] [...hover-actions]
|
|
6
|
+
// optional ein target zum Klicken (öffnet Editor-Maske via
|
|
7
|
+
// Target-Resolver) und optional children als nested tree.
|
|
8
|
+
//
|
|
9
|
+
// **State** markiert Visual-Modus für Skeleton-Pattern:
|
|
10
|
+
// - "filled" (default) — schwarz, Knoten hat Inhalt
|
|
11
|
+
// - "stub" — hellgrau, existing aber leer (Designer-Stub-File)
|
|
12
|
+
// - "empty" — Platzhalter für "+ create"-Affordance
|
|
13
|
+
// - "loading" — Children werden gerade aufgelöst
|
|
14
|
+
// - "error" — Provider hat Fehler emittiert
|
|
15
|
+
// Provider die kein Skeleton-Pattern brauchen müssen state nicht setzen.
|
|
16
|
+
//
|
|
17
|
+
// **Subscribe-Form** für dynamic Children: Provider erhält emit(),
|
|
18
|
+
// gibt unsubscribe() zurück. Initial-Emit synchron oder async, weitere
|
|
19
|
+
// Emits beliebig oft (z.B. wenn Entity-Row neu erscheint via SSE).
|
|
20
|
+
// Spielt natürlich mit existing SSE-Frame: ein Provider kann intern
|
|
21
|
+
// auf Entity-Update-Events abonnieren und bei Änderung emit() aufrufen.
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { GeoAddress, GeoCoordinates, GeoTzProvider } from "./geo-tz.js";
|
|
2
|
+
export type LocatedTimestampJson = {
|
|
3
|
+
/** Wall-clock ISO without offset, e.g. "2026-04-03T10:00:00" */
|
|
4
|
+
readonly at: string;
|
|
5
|
+
/** IANA zone, e.g. "Europe/Lisbon" */
|
|
6
|
+
readonly tz: string;
|
|
7
|
+
};
|
|
8
|
+
export type TzContext = {
|
|
9
|
+
/** Default TZ of the tenant (from tenant.timezone, default "UTC"). */
|
|
10
|
+
readonly tenant: string;
|
|
11
|
+
/** Display TZ of the current user (profile override, fallback tenant). */
|
|
12
|
+
readonly user: string;
|
|
13
|
+
/** Current moment as UTC instant. */
|
|
14
|
+
now(): Temporal.Instant;
|
|
15
|
+
/** Current moment as ZonedDateTime in the requested zone. */
|
|
16
|
+
nowIn(tz: string): Temporal.ZonedDateTime;
|
|
17
|
+
/** Today's calendar date in the requested zone. */
|
|
18
|
+
today(tz: string): Temporal.PlainDate;
|
|
19
|
+
/** Day boundaries (00:00 to 24:00 next day) as UTC instants — for DB range queries. */
|
|
20
|
+
todayRange(tz: string): {
|
|
21
|
+
readonly start: Temporal.Instant;
|
|
22
|
+
readonly end: Temporal.Instant;
|
|
23
|
+
};
|
|
24
|
+
/** Wall-clock string + IANA zone → ZonedDateTime. */
|
|
25
|
+
parse(wallClock: string, tz: string): Temporal.ZonedDateTime;
|
|
26
|
+
/** ZonedDateTime → UTC instant. */
|
|
27
|
+
toInstant(zdt: Temporal.ZonedDateTime): Temporal.Instant;
|
|
28
|
+
/** ZonedDateTime → JSON pair { at, tz } (API boundary). */
|
|
29
|
+
toLocatedJson(zdt: Temporal.ZonedDateTime): LocatedTimestampJson;
|
|
30
|
+
/** JSON pair { at, tz } → ZonedDateTime (wall-clock + IANA). */
|
|
31
|
+
fromLocatedJson(obj: LocatedTimestampJson): Temporal.ZonedDateTime;
|
|
32
|
+
/** Geo coordinates → IANA zone via the configured GeoTzProvider.
|
|
33
|
+
* Throws when no provider is configured (v1 default). */
|
|
34
|
+
fromCoordinates(coords: GeoCoordinates): Promise<string>;
|
|
35
|
+
/** Postal address → IANA zone via GeoTzProvider. Throws when no provider is
|
|
36
|
+
* configured OR the provider does not support fromAddress (the offline
|
|
37
|
+
* lat/lng provider does not). */
|
|
38
|
+
fromAddress(address: GeoAddress): Promise<string>;
|
|
39
|
+
};
|
|
40
|
+
export type TzContextOptions = {
|
|
41
|
+
/** Tenant default TZ. Default "UTC" when unset. */
|
|
42
|
+
readonly tenant?: string;
|
|
43
|
+
/** User override. Default = tenant. */
|
|
44
|
+
readonly user?: string;
|
|
45
|
+
/** Optional geo→zone adapter for ctx.tz.fromCoordinates / fromAddress.
|
|
46
|
+
* Without a provider those methods throw. */
|
|
47
|
+
readonly geoTz?: GeoTzProvider;
|
|
48
|
+
};
|