@fireweaveai/web-sdk 2.1.0 → 2.1.1-staging.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/README.md +105 -0
- package/dist/application/client.d.ts +120 -0
- package/dist/application/client.d.ts.map +1 -0
- package/dist/application/client.js +160 -0
- package/dist/application/client.js.map +1 -0
- package/dist/application/mode.d.ts +100 -0
- package/dist/application/mode.d.ts.map +1 -0
- package/dist/application/mode.js +99 -0
- package/dist/application/mode.js.map +1 -0
- package/dist/{adapter.d.ts → application/ports.d.ts} +19 -4
- package/dist/application/ports.d.ts.map +1 -0
- package/dist/application/ports.js +2 -0
- package/dist/application/ports.js.map +1 -0
- package/dist/{runtime.d.ts → application/runtime.d.ts} +15 -6
- package/dist/application/runtime.d.ts.map +1 -0
- package/dist/{runtime.js → application/runtime.js} +80 -27
- package/dist/application/runtime.js.map +1 -0
- package/dist/domain/context.d.ts +52 -0
- package/dist/domain/context.d.ts.map +1 -0
- package/dist/domain/context.js +68 -0
- package/dist/domain/context.js.map +1 -0
- package/dist/domain/errors.d.ts.map +1 -0
- package/dist/domain/errors.js.map +1 -0
- package/dist/domain/target.d.ts +3 -0
- package/dist/domain/target.d.ts.map +1 -0
- package/dist/domain/target.js +2 -0
- package/dist/domain/target.js.map +1 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/domain/types.js.map +1 -0
- package/dist/domain/validation.d.ts +129 -0
- package/dist/domain/validation.d.ts.map +1 -0
- package/dist/domain/validation.js +350 -0
- package/dist/domain/validation.js.map +1 -0
- package/dist/index.d.ts +37 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -21
- package/dist/index.js.map +1 -1
- package/dist/{adapters → infrastructure/adapters}/inmemory.d.ts +3 -3
- package/dist/infrastructure/adapters/inmemory.d.ts.map +1 -0
- package/dist/{adapters → infrastructure/adapters}/inmemory.js +1 -1
- package/dist/infrastructure/adapters/inmemory.js.map +1 -0
- package/dist/infrastructure/adapters/local.d.ts +80 -0
- package/dist/infrastructure/adapters/local.d.ts.map +1 -0
- package/dist/infrastructure/adapters/local.js +95 -0
- package/dist/infrastructure/adapters/local.js.map +1 -0
- package/dist/{adapters → infrastructure/adapters}/remote.d.ts +2 -2
- package/dist/infrastructure/adapters/remote.d.ts.map +1 -0
- package/dist/{adapters → infrastructure/adapters}/remote.js +9 -15
- package/dist/infrastructure/adapters/remote.js.map +1 -0
- package/dist/infrastructure/hosts.d.ts.map +1 -0
- package/dist/{hosts.js → infrastructure/hosts.js} +1 -1
- package/dist/infrastructure/hosts.js.map +1 -0
- package/package.json +16 -11
- package/dist/adapter.d.ts.map +0 -1
- package/dist/adapter.js +0 -2
- package/dist/adapter.js.map +0 -1
- package/dist/adapters/inmemory.d.ts.map +0 -1
- package/dist/adapters/inmemory.js.map +0 -1
- package/dist/adapters/local.d.ts +0 -38
- package/dist/adapters/local.d.ts.map +0 -1
- package/dist/adapters/local.js +0 -51
- package/dist/adapters/local.js.map +0 -1
- package/dist/adapters/remote.d.ts.map +0 -1
- package/dist/adapters/remote.js.map +0 -1
- package/dist/client.d.ts +0 -134
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -0
- package/dist/client.js.map +0 -1
- package/dist/context.d.ts +0 -26
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -106
- package/dist/context.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/hosts.d.ts.map +0 -1
- package/dist/hosts.js.map +0 -1
- package/dist/provider.d.ts +0 -39
- package/dist/provider.d.ts.map +0 -1
- package/dist/provider.js +0 -93
- package/dist/provider.js.map +0 -1
- package/dist/runtime.d.ts.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{errors.d.ts → domain/errors.d.ts} +0 -0
- /package/dist/{errors.js → domain/errors.js} +0 -0
- /package/dist/{types.d.ts → domain/types.d.ts} +0 -0
- /package/dist/{types.js → domain/types.js} +0 -0
- /package/dist/{hosts.d.ts → infrastructure/hosts.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/application/ports.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/application/ports.ts"],"names":[],"mappings":""}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import type { ContextInput, ContextLimits } from '
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
|
|
1
|
+
import type { ContextInput, ContextLimits } from '../domain/context.js';
|
|
2
|
+
import type { ExpectedFlagType } from '../domain/validation.js';
|
|
3
|
+
import type { RegisterTargetOptions, RegisterTargetResult, WebBackendAdapter } from './ports.js';
|
|
4
|
+
import type { Decision, Exposure, JsonValue, LifecycleState, ReleaseContext, Signal } from '../domain/types.js';
|
|
5
|
+
export type { ExpectedFlagType } from '../domain/validation.js';
|
|
5
6
|
/** Ceiling on the initial prefetch so a hung backend cannot block boot. */
|
|
6
7
|
export declare const DEFAULT_FLAGS_READY_TIMEOUT_MS = 5000;
|
|
7
8
|
export interface FireweaveWebRuntimeConfig {
|
|
8
9
|
/** Context applied to every evaluation unless overridden per call. */
|
|
9
10
|
readonly globalContext?: ContextInput;
|
|
10
11
|
readonly limits?: Partial<ContextLimits>;
|
|
12
|
+
/** Additional reserved attribute keys, beyond DEFAULT_RESERVED_ATTRIBUTE_KEYS. */
|
|
13
|
+
readonly reservedAttributeKeys?: readonly string[];
|
|
11
14
|
readonly flagsReadyTimeoutMs?: number;
|
|
12
15
|
/** Restrict prefetch to a known set of control points. */
|
|
13
16
|
readonly flagKeys?: readonly string[];
|
|
@@ -20,7 +23,7 @@ export declare class FireweaveWebRuntime {
|
|
|
20
23
|
private state;
|
|
21
24
|
private cache;
|
|
22
25
|
private globalContext;
|
|
23
|
-
private readonly
|
|
26
|
+
private readonly contextPolicy;
|
|
24
27
|
private releaseContext;
|
|
25
28
|
private readonly listeners;
|
|
26
29
|
constructor(adapter: WebBackendAdapter, config?: FireweaveWebRuntimeConfig);
|
|
@@ -43,7 +46,12 @@ export declare class FireweaveWebRuntime {
|
|
|
43
46
|
refresh(): Promise<void>;
|
|
44
47
|
/**
|
|
45
48
|
* Synchronous evaluation against the prefetched cache. Never throws —
|
|
46
|
-
* failures surface as ERROR decisions, exactly like the OpenFeature
|
|
49
|
+
* failures surface as ERROR decisions, exactly like the OpenFeature
|
|
50
|
+
* contract.
|
|
51
|
+
*
|
|
52
|
+
* Validates in the fixed order spec/control-points.md "Validation, before
|
|
53
|
+
* any I/O" names — key, default-vs-type, context, lifecycle — stopping at
|
|
54
|
+
* the first failure. Only once all four pass does this consult the cache.
|
|
47
55
|
*/
|
|
48
56
|
evaluateSync(flagKey: string, expectedType: ExpectedFlagType, defaultValue: JsonValue, invocationContext?: ContextInput): Decision;
|
|
49
57
|
private reasonFor;
|
|
@@ -57,6 +65,7 @@ export declare class FireweaveWebRuntime {
|
|
|
57
65
|
}): Promise<void>;
|
|
58
66
|
shutdown(): Promise<void>;
|
|
59
67
|
private changedKeys;
|
|
68
|
+
private lifecycleError;
|
|
60
69
|
private errorDecision;
|
|
61
70
|
}
|
|
62
71
|
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/application/runtime.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAiB,MAAM,sBAAsB,CAAC;AAQvF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAGV,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,QAAQ,EAER,QAAQ,EACR,SAAS,EACT,cAAc,EACd,cAAc,EACd,MAAM,EACP,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,2EAA2E;AAC3E,eAAO,MAAM,8BAA8B,OAAQ,CAAC;AAEpD,MAAM,WAAW,yBAAyB;IACxC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,YAAY,CAAC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACzC,kFAAkF;IAClF,QAAQ,CAAC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,yBAAyB,CAAC;IAE3C,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8C;gBAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,GAAE,yBAA8B;IAc9E,QAAQ,IAAI,cAAc;IAI1B,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI;IAKpE,OAAO,CAAC,QAAQ;IAKhB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI;IAI5C,iBAAiB,IAAI,cAAc;IAInC,mEAAmE;IAC7D,UAAU,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAcvD;;;;;;OAMG;IACG,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC;IAOnE,8DAA8D;IACxD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8C9B;;;;;;;;OAQG;IACH,YAAY,CACV,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,gBAAgB,EAC9B,YAAY,EAAE,SAAS,EACvB,iBAAiB,CAAC,EAAE,YAAY,GAC/B,QAAQ;IAwEX,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,iBAAiB;IAkBzB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIxC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI5B,cAAc,CAClB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,oBAAoB,CAAC;IAiB1B,KAAK,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB/B,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,aAAa;CAWtB"}
|
|
@@ -19,37 +19,43 @@
|
|
|
19
19
|
* between "nobody got the feature because the ramp is at 0%" and "nobody got
|
|
20
20
|
* the feature because the SDK never reached the server", and no operator can
|
|
21
21
|
* tell those apart after the fact.
|
|
22
|
+
*
|
|
23
|
+
* ## Validation order (spec/control-points.md "Validation, before any I/O")
|
|
24
|
+
*
|
|
25
|
+
* `evaluateSync` validates in the fixed order the spec names — key,
|
|
26
|
+
* default-vs-type, context, lifecycle — stopping at the first failure, and
|
|
27
|
+
* only THEN consults the prefetched cache. "Before any I/O" reads literally
|
|
28
|
+
* for node (the adapter call is the I/O); web has already done its I/O
|
|
29
|
+
* earlier (the prefetch), so here the same four-step order gates the cache
|
|
30
|
+
* READ instead, for the same reason: a malformed call must degrade to the
|
|
31
|
+
* caller's default without depending on what happens to be in the cache.
|
|
22
32
|
*/
|
|
23
|
-
import { FireweaveError, isFireweaveError } from '
|
|
24
|
-
import {
|
|
33
|
+
import { FireweaveError, isFireweaveError } from '../domain/errors.js';
|
|
34
|
+
import { DEFAULT_CONTEXT_LIMITS, DEFAULT_RESERVED_ATTRIBUTE_KEYS, mergeContexts } from '../domain/context.js';
|
|
35
|
+
import { canonicalizeContext, matchesExpectedType, validateContext, validateControlPointKey, validateDefaultValue, } from '../domain/validation.js';
|
|
25
36
|
/** Ceiling on the initial prefetch so a hung backend cannot block boot. */
|
|
26
37
|
export const DEFAULT_FLAGS_READY_TIMEOUT_MS = 5_000;
|
|
27
|
-
function matchesExpectedType(value, expected) {
|
|
28
|
-
switch (expected) {
|
|
29
|
-
case 'boolean':
|
|
30
|
-
return typeof value === 'boolean';
|
|
31
|
-
case 'string':
|
|
32
|
-
return typeof value === 'string';
|
|
33
|
-
case 'number':
|
|
34
|
-
return typeof value === 'number';
|
|
35
|
-
case 'object':
|
|
36
|
-
return typeof value === 'object' && value !== null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
38
|
export class FireweaveWebRuntime {
|
|
40
39
|
adapter;
|
|
41
40
|
config;
|
|
42
41
|
state = 'UNINITIALIZED';
|
|
43
42
|
cache = new Map();
|
|
44
43
|
globalContext;
|
|
45
|
-
|
|
44
|
+
contextPolicy;
|
|
46
45
|
releaseContext = {};
|
|
47
46
|
listeners = new Set();
|
|
48
47
|
constructor(adapter, config = {}) {
|
|
49
48
|
this.adapter = adapter;
|
|
50
49
|
this.config = config;
|
|
51
50
|
this.globalContext = { ...(config.globalContext ?? {}) };
|
|
52
|
-
this.
|
|
51
|
+
this.contextPolicy = {
|
|
52
|
+
limits: { ...DEFAULT_CONTEXT_LIMITS, ...(config.limits ?? {}) },
|
|
53
|
+
reservedAttributeKeys: [...DEFAULT_RESERVED_ATTRIBUTE_KEYS, ...(config.reservedAttributeKeys ?? [])],
|
|
54
|
+
// Not required at the generic context-validation layer — web's
|
|
55
|
+
// targetingKey requirement is enforced at the remote adapter's
|
|
56
|
+
// prefetch/registerTarget boundary, not on every read.
|
|
57
|
+
requireTargetingKey: false,
|
|
58
|
+
};
|
|
53
59
|
}
|
|
54
60
|
getState() {
|
|
55
61
|
return this.state;
|
|
@@ -75,7 +81,7 @@ export class FireweaveWebRuntime {
|
|
|
75
81
|
return;
|
|
76
82
|
this.setState('INITIALIZING');
|
|
77
83
|
if (context !== undefined)
|
|
78
|
-
this.globalContext =
|
|
84
|
+
this.globalContext = { ...this.globalContext, ...context };
|
|
79
85
|
try {
|
|
80
86
|
await this.adapter.initialize();
|
|
81
87
|
}
|
|
@@ -104,7 +110,7 @@ export class FireweaveWebRuntime {
|
|
|
104
110
|
return;
|
|
105
111
|
let canonical;
|
|
106
112
|
try {
|
|
107
|
-
canonical = canonicalizeContext(this.globalContext, this.
|
|
113
|
+
canonical = canonicalizeContext(mergeContexts(this.globalContext), this.contextPolicy);
|
|
108
114
|
}
|
|
109
115
|
catch {
|
|
110
116
|
this.setState('ERROR');
|
|
@@ -142,23 +148,49 @@ export class FireweaveWebRuntime {
|
|
|
142
148
|
}
|
|
143
149
|
/**
|
|
144
150
|
* Synchronous evaluation against the prefetched cache. Never throws —
|
|
145
|
-
* failures surface as ERROR decisions, exactly like the OpenFeature
|
|
151
|
+
* failures surface as ERROR decisions, exactly like the OpenFeature
|
|
152
|
+
* contract.
|
|
153
|
+
*
|
|
154
|
+
* Validates in the fixed order spec/control-points.md "Validation, before
|
|
155
|
+
* any I/O" names — key, default-vs-type, context, lifecycle — stopping at
|
|
156
|
+
* the first failure. Only once all four pass does this consult the cache.
|
|
146
157
|
*/
|
|
147
158
|
evaluateSync(flagKey, expectedType, defaultValue, invocationContext) {
|
|
148
|
-
|
|
149
|
-
|
|
159
|
+
const keyResult = validateControlPointKey(flagKey);
|
|
160
|
+
if (!keyResult.ok) {
|
|
161
|
+
return this.errorDecision(flagKey, defaultValue, keyResult.error);
|
|
162
|
+
}
|
|
163
|
+
const defaultResult = validateDefaultValue(expectedType, defaultValue);
|
|
164
|
+
if (!defaultResult.ok) {
|
|
165
|
+
return this.errorDecision(flagKey, defaultValue, defaultResult.error);
|
|
150
166
|
}
|
|
151
|
-
|
|
152
|
-
|
|
167
|
+
// The validated context here is not what SELECTS the cached decision —
|
|
168
|
+
// that was fixed by the last prefetch (ADR-0009: evaluation is a pure
|
|
169
|
+
// cache read). It still has to be validated: a caller must not be able to
|
|
170
|
+
// bypass context limits/reserved-key checks just by moving an oversized or
|
|
171
|
+
// malformed structure into the per-call argument instead of the
|
|
172
|
+
// constructor's globalContext.
|
|
173
|
+
const merged = mergeContexts(this.globalContext, invocationContext);
|
|
174
|
+
const contextResult = validateContext(merged, this.contextPolicy);
|
|
175
|
+
if (!contextResult.ok) {
|
|
176
|
+
return this.errorDecision(flagKey, defaultValue, contextResult.error);
|
|
153
177
|
}
|
|
154
|
-
|
|
155
|
-
|
|
178
|
+
const lifecycleError = this.lifecycleError();
|
|
179
|
+
if (lifecycleError !== undefined) {
|
|
180
|
+
return this.errorDecision(flagKey, defaultValue, lifecycleError);
|
|
156
181
|
}
|
|
157
182
|
const resolution = this.cache.get(flagKey);
|
|
158
183
|
if (resolution === undefined || resolution.found === false) {
|
|
184
|
+
// spec/modes.md "Behaviour per mode": local's unknown-key row is
|
|
185
|
+
// `default`/reason `DEFAULT` — deliberately not an error. The local
|
|
186
|
+
// adapter signals this via `missReason: 'DEFAULT'` (adapter.ts); every
|
|
187
|
+
// other adapter leaves it undefined and keeps the path below.
|
|
188
|
+
if (this.adapter.missReason === 'DEFAULT') {
|
|
189
|
+
return { flagKey, value: defaultValue, reason: 'DEFAULT', metadata: {} };
|
|
190
|
+
}
|
|
159
191
|
// A cache miss while STALE is not a missing control point — it is an
|
|
160
|
-
// unanswered question. Reporting FLAG_NOT_FOUND there would send a
|
|
161
|
-
// hunting for a flag that may well exist.
|
|
192
|
+
// unanswered question. Reporting FLAG_NOT_FOUND there would send a
|
|
193
|
+
// caller hunting for a flag that may well exist.
|
|
162
194
|
if (this.state === 'STALE') {
|
|
163
195
|
return {
|
|
164
196
|
flagKey,
|
|
@@ -254,6 +286,12 @@ export class FireweaveWebRuntime {
|
|
|
254
286
|
async shutdown() {
|
|
255
287
|
if (this.state === 'SHUTDOWN')
|
|
256
288
|
return;
|
|
289
|
+
try {
|
|
290
|
+
await this.adapter.flush?.();
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// best-effort flush; never throw from shutdown
|
|
294
|
+
}
|
|
257
295
|
try {
|
|
258
296
|
await this.adapter.shutdown();
|
|
259
297
|
}
|
|
@@ -274,6 +312,21 @@ export class FireweaveWebRuntime {
|
|
|
274
312
|
}
|
|
275
313
|
return changed;
|
|
276
314
|
}
|
|
315
|
+
lifecycleError() {
|
|
316
|
+
switch (this.state) {
|
|
317
|
+
case 'UNINITIALIZED':
|
|
318
|
+
case 'INITIALIZING':
|
|
319
|
+
return new FireweaveError('NotReady');
|
|
320
|
+
case 'ERROR':
|
|
321
|
+
return new FireweaveError('BackendUnavailable');
|
|
322
|
+
case 'SHUTDOWN':
|
|
323
|
+
return new FireweaveError('AlreadyClosed');
|
|
324
|
+
default:
|
|
325
|
+
// READY, STALE: no lifecycle error — a STALE miss is handled
|
|
326
|
+
// specially in the cache-lookup branch above.
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
277
330
|
errorDecision(flagKey, defaultValue, err) {
|
|
278
331
|
return {
|
|
279
332
|
flagKey,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/application/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluation-context merge & normalization — pure, no validation.
|
|
3
|
+
*
|
|
4
|
+
* Bound/reserved-key ENFORCEMENT (the Validated<T>-returning checks) lives in
|
|
5
|
+
* validation.ts (`validateContext`) — spec/control-points.md "Validation,
|
|
6
|
+
* before any I/O" rule 3. This module has no throwing/failing surface of its
|
|
7
|
+
* own, mirroring the split sdks/node/src/domain/{context,validation}.ts
|
|
8
|
+
* makes.
|
|
9
|
+
*
|
|
10
|
+
* A browser context is smaller than a server one — there is one user per
|
|
11
|
+
* page, not one per request — but the same shape applies: `targetingKey` plus
|
|
12
|
+
* a flat bag of attributes, later layers winning key by key (the OpenFeature
|
|
13
|
+
* merge order).
|
|
14
|
+
*/
|
|
15
|
+
export interface ContextLimits {
|
|
16
|
+
readonly maxAttributeCount: number;
|
|
17
|
+
readonly maxKeyBytes: number;
|
|
18
|
+
readonly maxValueBytes: number;
|
|
19
|
+
readonly maxSerializedBytes: number;
|
|
20
|
+
readonly maxNestingDepth: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const DEFAULT_CONTEXT_LIMITS: ContextLimits;
|
|
23
|
+
/**
|
|
24
|
+
* Keys the backend owns. A client that could set these could claim another
|
|
25
|
+
* tenant's identity, so they are rejected rather than dropped — silently
|
|
26
|
+
* discarding them would leave the caller believing targeting was applied.
|
|
27
|
+
*/
|
|
28
|
+
export declare const DEFAULT_RESERVED_ATTRIBUTE_KEYS: readonly string[];
|
|
29
|
+
export interface ContextPolicy {
|
|
30
|
+
readonly limits: ContextLimits;
|
|
31
|
+
readonly reservedAttributeKeys: readonly string[];
|
|
32
|
+
readonly requireTargetingKey: boolean;
|
|
33
|
+
}
|
|
34
|
+
export type ContextInput = Record<string, unknown> & {
|
|
35
|
+
targetingKey?: string;
|
|
36
|
+
};
|
|
37
|
+
/** One raw layer → {targetingKey?, attributes}. No validation, no copying beyond Object.entries. */
|
|
38
|
+
export declare function normalizeContextInput(input: ContextInput | undefined): {
|
|
39
|
+
targetingKey?: string;
|
|
40
|
+
attributes: Record<string, unknown>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Merge context layers with later layers winning at the attribute-key level.
|
|
44
|
+
* Layers are raw inputs; output is a plain {targetingKey?, attributes} bag —
|
|
45
|
+
* validation (limits, reserved keys, cycle-safety) happens downstream in
|
|
46
|
+
* validation.ts's `validateContext`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function mergeContexts(...layers: ReadonlyArray<ContextInput | undefined>): {
|
|
49
|
+
targetingKey?: string;
|
|
50
|
+
attributes: Record<string, unknown>;
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/domain/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,eAAO,MAAM,sBAAsB,EAAE,aAMnC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,EAAE,SAAS,MAAM,EAI3D,CAAC;AAEH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,qBAAqB,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,oGAAoG;AACpG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC,CAYA;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,MAAM,EAAE,aAAa,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC,CAWA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluation-context merge & normalization — pure, no validation.
|
|
3
|
+
*
|
|
4
|
+
* Bound/reserved-key ENFORCEMENT (the Validated<T>-returning checks) lives in
|
|
5
|
+
* validation.ts (`validateContext`) — spec/control-points.md "Validation,
|
|
6
|
+
* before any I/O" rule 3. This module has no throwing/failing surface of its
|
|
7
|
+
* own, mirroring the split sdks/node/src/domain/{context,validation}.ts
|
|
8
|
+
* makes.
|
|
9
|
+
*
|
|
10
|
+
* A browser context is smaller than a server one — there is one user per
|
|
11
|
+
* page, not one per request — but the same shape applies: `targetingKey` plus
|
|
12
|
+
* a flat bag of attributes, later layers winning key by key (the OpenFeature
|
|
13
|
+
* merge order).
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_CONTEXT_LIMITS = Object.freeze({
|
|
16
|
+
maxAttributeCount: 100,
|
|
17
|
+
maxKeyBytes: 256,
|
|
18
|
+
maxValueBytes: 8_192,
|
|
19
|
+
maxSerializedBytes: 32_768,
|
|
20
|
+
maxNestingDepth: 8,
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Keys the backend owns. A client that could set these could claim another
|
|
24
|
+
* tenant's identity, so they are rejected rather than dropped — silently
|
|
25
|
+
* discarding them would leave the caller believing targeting was applied.
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_RESERVED_ATTRIBUTE_KEYS = Object.freeze([
|
|
28
|
+
'fireweave.orgId',
|
|
29
|
+
'fireweave.projectId',
|
|
30
|
+
'fireweave.tenant',
|
|
31
|
+
]);
|
|
32
|
+
/** One raw layer → {targetingKey?, attributes}. No validation, no copying beyond Object.entries. */
|
|
33
|
+
export function normalizeContextInput(input) {
|
|
34
|
+
if (input === undefined || input === null)
|
|
35
|
+
return { attributes: {} };
|
|
36
|
+
const attributes = {};
|
|
37
|
+
let targetingKey;
|
|
38
|
+
for (const [key, value] of Object.entries(input)) {
|
|
39
|
+
if (key === 'targetingKey') {
|
|
40
|
+
if (typeof value === 'string' && value.length > 0)
|
|
41
|
+
targetingKey = value;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (value !== undefined)
|
|
45
|
+
attributes[key] = value;
|
|
46
|
+
}
|
|
47
|
+
return targetingKey !== undefined ? { targetingKey, attributes } : { attributes };
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Merge context layers with later layers winning at the attribute-key level.
|
|
51
|
+
* Layers are raw inputs; output is a plain {targetingKey?, attributes} bag —
|
|
52
|
+
* validation (limits, reserved keys, cycle-safety) happens downstream in
|
|
53
|
+
* validation.ts's `validateContext`.
|
|
54
|
+
*/
|
|
55
|
+
export function mergeContexts(...layers) {
|
|
56
|
+
let targetingKey;
|
|
57
|
+
const attributes = {};
|
|
58
|
+
for (const layer of layers) {
|
|
59
|
+
const { targetingKey: tk, attributes: attrs } = normalizeContextInput(layer);
|
|
60
|
+
if (tk !== undefined)
|
|
61
|
+
targetingKey = tk;
|
|
62
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
63
|
+
attributes[k] = v;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return targetingKey !== undefined ? { targetingKey, attributes } : { attributes };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/domain/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,MAAM,CAAC,MAAM,sBAAsB,GAAkB,MAAM,CAAC,MAAM,CAAC;IACjE,iBAAiB,EAAE,GAAG;IACtB,WAAW,EAAE,GAAG;IAChB,aAAa,EAAE,KAAK;IACpB,kBAAkB,EAAE,MAAM;IAC1B,eAAe,EAAE,CAAC;CACnB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC9E,iBAAiB;IACjB,qBAAqB;IACrB,kBAAkB;CACnB,CAAC,CAAC;AAUH,oGAAoG;AACpG,MAAM,UAAU,qBAAqB,CAAC,KAA+B;IAInE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IACrE,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,IAAI,YAAgC,CAAC;IACrC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,GAAG,KAAK,cAAc,EAAE,CAAC;YAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,YAAY,GAAG,KAAK,CAAC;YACxE,SAAS;QACX,CAAC;QACD,IAAI,KAAK,KAAK,SAAS;YAAE,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnD,CAAC;IACD,OAAO,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;AACpF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAG,MAA+C;IAI9E,IAAI,YAAgC,CAAC;IACrC,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,EAAE,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC7E,IAAI,EAAE,KAAK,SAAS;YAAE,YAAY,GAAG,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/domain/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,kBAAkB,GAC1B,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,SAAS,GACT,SAAS,GACT,aAAa,GACb,oBAAoB,GACpB,mBAAmB,GACnB,gBAAgB,GAChB,cAAc,GACd,cAAc,GACd,UAAU,GACV,eAAe,GACf,uBAAuB,GACvB,UAAU,CAAC;AAEf,MAAM,MAAM,oBAAoB,GAC5B,oBAAoB,GACpB,gBAAgB,GAChB,gBAAgB,GAChB,aAAa,GACb,eAAe,GACf,uBAAuB,GACvB,iBAAiB,GACjB,SAAS,CAAC;AAEd,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;IACpD,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,kBAAkB,EAAE,aAAa,CAAC,CA4D7E,CAAC;AAEH,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IACrD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;IACpD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;gBAEjD,IAAI,EAAE,kBAAkB,EAAE,OAAO,GAAE,qBAA0B;CAS1E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAExE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/domain/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../../src/domain/target.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../../src/domain/target.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/domain/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/domain/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fireweave web SDK validation — pure, total functions per
|
|
3
|
+
* spec/control-points.md "Validation, before any I/O" and spec/modes.md
|
|
4
|
+
* "Initialisation validation".
|
|
5
|
+
*
|
|
6
|
+
* Ported from sdks/node/src/domain/validation.ts (the reference
|
|
7
|
+
* implementation) — same five validators, same `Validated<T>` discipline,
|
|
8
|
+
* same malformed-key → FlagNotFound mapping. Reimplemented here rather than
|
|
9
|
+
* shared so the browser package keeps zero cross-package dependency to
|
|
10
|
+
* audit — the same reasoning ADR-0009 gives for duplicating types.ts/errors.ts
|
|
11
|
+
* extends to this module.
|
|
12
|
+
*
|
|
13
|
+
* Every read-path validator here (`validateControlPointKey`,
|
|
14
|
+
* `validateDefaultValue`, `validateContext`) returns `Validated<T>` instead
|
|
15
|
+
* of throwing. `FireweaveWebRuntime.evaluateSync` runs them, in the fixed
|
|
16
|
+
* order the spec names — key, default-vs-type, context, lifecycle — and
|
|
17
|
+
* degrades to the caller's default on the first failure; it NEVER throws
|
|
18
|
+
* (spec/control-points.md "Return discipline — never throw into a read
|
|
19
|
+
* path"). `validateInitOptions` is the one exception (spec/modes.md
|
|
20
|
+
* "Initialisation validation"): it still returns `Validated<T>` — mode.ts is
|
|
21
|
+
* what converts a failed result into the throw spec/modes.md requires.
|
|
22
|
+
*
|
|
23
|
+
* Note: unlike node, web's `FireweaveError` has no custom-message support —
|
|
24
|
+
* messages are FIXED per kind by design, because a browser error is visible
|
|
25
|
+
* in a devtools console on a machine this package does not control
|
|
26
|
+
* (errors.ts's own doc comment). So every branch below that would carry a
|
|
27
|
+
* distinct node message instead just uses the taxonomy's fixed message for
|
|
28
|
+
* its kind.
|
|
29
|
+
*/
|
|
30
|
+
import { FireweaveError } from './errors.js';
|
|
31
|
+
import type { ContextPolicy } from './context.js';
|
|
32
|
+
import type { CanonicalContext, JsonValue } from './types.js';
|
|
33
|
+
/** Result of a pure validator: success carries the validated value, failure the canonical error. */
|
|
34
|
+
export type Validated<T> = {
|
|
35
|
+
ok: true;
|
|
36
|
+
value: T;
|
|
37
|
+
} | {
|
|
38
|
+
ok: false;
|
|
39
|
+
error: FireweaveError;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* key — non-empty, ≤256 characters, no control characters
|
|
43
|
+
* (spec/control-points.md rule 1, the first check in the fixed order).
|
|
44
|
+
*
|
|
45
|
+
* No taxonomy kind names "malformed key" explicitly (the return-discipline
|
|
46
|
+
* table's closest row is "key unknown to the backend" → FlagNotFound):
|
|
47
|
+
* controller-ruled interim mapping (mirrors node's domain/validation.ts
|
|
48
|
+
* verbatim) — the 15-kind taxonomy in errors.schema.json is frozen at
|
|
49
|
+
* exactly 15 entries, `InvalidContext` is textually scoped to the evaluation
|
|
50
|
+
* *context* (not the key), and the schema already maps another non-literal
|
|
51
|
+
* case — quota-limited responses — onto `FlagNotFound` rather than adding a
|
|
52
|
+
* kind for it. `FlagNotFound` is therefore the least-wrong existing kind,
|
|
53
|
+
* not a literal fit. Other-language implementations copying node as the
|
|
54
|
+
* reference SHOULD use the same mapping rather than each independently
|
|
55
|
+
* guessing a different one.
|
|
56
|
+
*/
|
|
57
|
+
export declare function validateControlPointKey(key: string): Validated<string>;
|
|
58
|
+
export type ExpectedFlagType = 'boolean' | 'string' | 'number' | 'object';
|
|
59
|
+
/**
|
|
60
|
+
* Whether `value` matches the shape `expected` names. Shared by
|
|
61
|
+
* {@link validateDefaultValue} (the caller's default, before any read) and
|
|
62
|
+
* `FireweaveWebRuntime.evaluateSync`'s post-cache-lookup check (the backend's
|
|
63
|
+
* resolved value, from the prefetched cache) — same predicate, two different
|
|
64
|
+
* inputs.
|
|
65
|
+
*/
|
|
66
|
+
export declare function matchesExpectedType(value: JsonValue | undefined, expected: ExpectedFlagType): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* default vs type — e.g. `getBooleanValue` with a non-boolean default is
|
|
69
|
+
* TypeMismatch (spec/control-points.md rule 2, checked before any read).
|
|
70
|
+
*/
|
|
71
|
+
export declare function validateDefaultValue(expectedType: ExpectedFlagType, defaultValue: JsonValue): Validated<JsonValue>;
|
|
72
|
+
/**
|
|
73
|
+
* targetingKey: "An SDK MUST NOT invent one: a missing targeting key is
|
|
74
|
+
* InvalidContext where the evaluation needs it, never a generated anonymous
|
|
75
|
+
* id" (spec/control-points.md "Context"). `required` is call-site policy —
|
|
76
|
+
* the remote adapter always requires one for `prefetch`/`registerTarget`; the
|
|
77
|
+
* generic context pipeline ({@link validateContext}) only does when
|
|
78
|
+
* `ContextPolicy.requireTargetingKey` opts in (unset by default here — web's
|
|
79
|
+
* targetingKey requirement is enforced at the remote adapter, not the
|
|
80
|
+
* general-purpose context validator every read runs).
|
|
81
|
+
*/
|
|
82
|
+
export declare function validateTargetingKey(targetingKey: string | undefined, required: boolean): Validated<string | undefined>;
|
|
83
|
+
/**
|
|
84
|
+
* context — depth, key count, value size, reserved keys
|
|
85
|
+
* (evaluation-context.schema.json) (spec/control-points.md rule 3). Also
|
|
86
|
+
* enforces `policy.requireTargetingKey` via {@link validateTargetingKey}, and
|
|
87
|
+
* — on success — extracts `groups`/`groupProperties` the same way the former
|
|
88
|
+
* `canonicalizeContext` did.
|
|
89
|
+
*
|
|
90
|
+
* `groups`/`groupProperties` (and their `fireweave.*` aliases) are pulled out
|
|
91
|
+
* BEFORE the attribute-count/size limit checks run, matching the pre-existing
|
|
92
|
+
* behaviour this module replaces: they are not ordinary attributes and were
|
|
93
|
+
* never counted against those limits.
|
|
94
|
+
*
|
|
95
|
+
* `merged` is the already-merged (global → invocation) raw input; merging
|
|
96
|
+
* itself (`mergeContexts`) lives in context.ts and carries no validation
|
|
97
|
+
* concerns of its own.
|
|
98
|
+
*/
|
|
99
|
+
export declare function validateContext(merged: {
|
|
100
|
+
targetingKey?: string;
|
|
101
|
+
attributes: Record<string, unknown>;
|
|
102
|
+
}, policy: ContextPolicy): Validated<CanonicalContext>;
|
|
103
|
+
/**
|
|
104
|
+
* Throwing wrapper around {@link validateContext}, kept for callers that
|
|
105
|
+
* genuinely want a throw (`FireweaveWebRuntime.refresh`, which is already
|
|
106
|
+
* inside its own try/catch feeding lifecycle state — see runtime.ts). Read
|
|
107
|
+
* paths do not use this — they call {@link validateContext} directly so a
|
|
108
|
+
* failure degrades instead of throwing.
|
|
109
|
+
*/
|
|
110
|
+
export declare function canonicalizeContext(merged: {
|
|
111
|
+
targetingKey?: string;
|
|
112
|
+
attributes: Record<string, unknown>;
|
|
113
|
+
}, policy: ContextPolicy): CanonicalContext;
|
|
114
|
+
/**
|
|
115
|
+
* Initialisation-validation table (spec/modes.md), rows 1, 2 and 4:
|
|
116
|
+
* - `mode` absent or unrecognised
|
|
117
|
+
* - `mode: 'remote'` with `apiKey` or `apiUrl` missing/blank
|
|
118
|
+
* - `mode: 'local'` with credentials supplied (a config half-migrated from
|
|
119
|
+
* remote to local reads as neither, silently — reject it instead)
|
|
120
|
+
*
|
|
121
|
+
* Row 3 ("apiUrl fails the host allowlist") is intentionally NOT checked
|
|
122
|
+
* here — mode.ts validates it directly via `assertHostAllowed` before
|
|
123
|
+
* calling into the (deliberately non-throwing) runtime; see mode.ts's module
|
|
124
|
+
* doc comment for why web cannot rely on the runtime the way node does.
|
|
125
|
+
*/
|
|
126
|
+
export declare function validateInitOptions<T extends {
|
|
127
|
+
readonly mode?: unknown;
|
|
128
|
+
}>(options: T): Validated<T>;
|
|
129
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/domain/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE9D,oGAAoG;AACpG,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC;AAkBzF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAWtE;AAOD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAWrG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAKlH;AAMD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,QAAQ,EAAE,OAAO,GAChB,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,CAK/B;AA6FD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EACtE,MAAM,EAAE,aAAa,GACpB,SAAS,CAAC,gBAAgB,CAAC,CA4E7B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EACtE,MAAM,EAAE,aAAa,GACpB,gBAAgB,CAIlB;AAWD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAoBnG"}
|