@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.
Files changed (89) hide show
  1. package/README.md +105 -0
  2. package/dist/application/client.d.ts +120 -0
  3. package/dist/application/client.d.ts.map +1 -0
  4. package/dist/application/client.js +160 -0
  5. package/dist/application/client.js.map +1 -0
  6. package/dist/application/mode.d.ts +100 -0
  7. package/dist/application/mode.d.ts.map +1 -0
  8. package/dist/application/mode.js +99 -0
  9. package/dist/application/mode.js.map +1 -0
  10. package/dist/{adapter.d.ts → application/ports.d.ts} +19 -4
  11. package/dist/application/ports.d.ts.map +1 -0
  12. package/dist/application/ports.js +2 -0
  13. package/dist/application/ports.js.map +1 -0
  14. package/dist/{runtime.d.ts → application/runtime.d.ts} +15 -6
  15. package/dist/application/runtime.d.ts.map +1 -0
  16. package/dist/{runtime.js → application/runtime.js} +80 -27
  17. package/dist/application/runtime.js.map +1 -0
  18. package/dist/domain/context.d.ts +52 -0
  19. package/dist/domain/context.d.ts.map +1 -0
  20. package/dist/domain/context.js +68 -0
  21. package/dist/domain/context.js.map +1 -0
  22. package/dist/domain/errors.d.ts.map +1 -0
  23. package/dist/domain/errors.js.map +1 -0
  24. package/dist/domain/target.d.ts +3 -0
  25. package/dist/domain/target.d.ts.map +1 -0
  26. package/dist/domain/target.js +2 -0
  27. package/dist/domain/target.js.map +1 -0
  28. package/dist/domain/types.d.ts.map +1 -0
  29. package/dist/domain/types.js.map +1 -0
  30. package/dist/domain/validation.d.ts +129 -0
  31. package/dist/domain/validation.d.ts.map +1 -0
  32. package/dist/domain/validation.js +350 -0
  33. package/dist/domain/validation.js.map +1 -0
  34. package/dist/index.d.ts +37 -31
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +25 -21
  37. package/dist/index.js.map +1 -1
  38. package/dist/{adapters → infrastructure/adapters}/inmemory.d.ts +3 -3
  39. package/dist/infrastructure/adapters/inmemory.d.ts.map +1 -0
  40. package/dist/{adapters → infrastructure/adapters}/inmemory.js +1 -1
  41. package/dist/infrastructure/adapters/inmemory.js.map +1 -0
  42. package/dist/infrastructure/adapters/local.d.ts +80 -0
  43. package/dist/infrastructure/adapters/local.d.ts.map +1 -0
  44. package/dist/infrastructure/adapters/local.js +95 -0
  45. package/dist/infrastructure/adapters/local.js.map +1 -0
  46. package/dist/{adapters → infrastructure/adapters}/remote.d.ts +2 -2
  47. package/dist/infrastructure/adapters/remote.d.ts.map +1 -0
  48. package/dist/{adapters → infrastructure/adapters}/remote.js +9 -15
  49. package/dist/infrastructure/adapters/remote.js.map +1 -0
  50. package/dist/infrastructure/hosts.d.ts.map +1 -0
  51. package/dist/{hosts.js → infrastructure/hosts.js} +1 -1
  52. package/dist/infrastructure/hosts.js.map +1 -0
  53. package/package.json +16 -11
  54. package/dist/adapter.d.ts.map +0 -1
  55. package/dist/adapter.js +0 -2
  56. package/dist/adapter.js.map +0 -1
  57. package/dist/adapters/inmemory.d.ts.map +0 -1
  58. package/dist/adapters/inmemory.js.map +0 -1
  59. package/dist/adapters/local.d.ts +0 -38
  60. package/dist/adapters/local.d.ts.map +0 -1
  61. package/dist/adapters/local.js +0 -51
  62. package/dist/adapters/local.js.map +0 -1
  63. package/dist/adapters/remote.d.ts.map +0 -1
  64. package/dist/adapters/remote.js.map +0 -1
  65. package/dist/client.d.ts +0 -134
  66. package/dist/client.d.ts.map +0 -1
  67. package/dist/client.js +0 -0
  68. package/dist/client.js.map +0 -1
  69. package/dist/context.d.ts +0 -26
  70. package/dist/context.d.ts.map +0 -1
  71. package/dist/context.js +0 -106
  72. package/dist/context.js.map +0 -1
  73. package/dist/errors.d.ts.map +0 -1
  74. package/dist/errors.js.map +0 -1
  75. package/dist/hosts.d.ts.map +0 -1
  76. package/dist/hosts.js.map +0 -1
  77. package/dist/provider.d.ts +0 -39
  78. package/dist/provider.d.ts.map +0 -1
  79. package/dist/provider.js +0 -93
  80. package/dist/provider.js.map +0 -1
  81. package/dist/runtime.d.ts.map +0 -1
  82. package/dist/runtime.js.map +0 -1
  83. package/dist/types.d.ts.map +0 -1
  84. package/dist/types.js.map +0 -1
  85. /package/dist/{errors.d.ts → domain/errors.d.ts} +0 -0
  86. /package/dist/{errors.js → domain/errors.js} +0 -0
  87. /package/dist/{types.d.ts → domain/types.d.ts} +0 -0
  88. /package/dist/{types.js → domain/types.js} +0 -0
  89. /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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ports.js.map
@@ -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 './context.js';
2
- import type { RegisterTargetOptions, RegisterTargetResult, WebBackendAdapter } from './adapter.js';
3
- import type { Decision, Exposure, JsonValue, LifecycleState, ReleaseContext, Signal } from './types.js';
4
- export type ExpectedFlagType = 'boolean' | 'string' | 'number' | 'object';
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 limits;
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 contract.
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 './errors.js';
24
- import { canonicalizeContext, DEFAULT_CONTEXT_LIMITS, mergeContexts } from './context.js';
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
- limits;
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.limits = { ...DEFAULT_CONTEXT_LIMITS, ...(config.limits ?? {}) };
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 = mergeContexts(this.globalContext, context);
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.limits);
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 contract.
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
- if (this.state === 'SHUTDOWN') {
149
- return this.errorDecision(flagKey, defaultValue, new FireweaveError('AlreadyClosed'));
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
- if (this.state === 'UNINITIALIZED' || this.state === 'INITIALIZING') {
152
- return this.errorDecision(flagKey, defaultValue, new FireweaveError('NotReady'));
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
- if (this.state === 'ERROR') {
155
- return this.errorDecision(flagKey, defaultValue, new FireweaveError('BackendUnavailable'));
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 caller
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,3 @@
1
+ /** What is being registered — see spec/remote-register-target.schema.json. */
2
+ export type TargetKind = 'user' | 'device';
3
+ //# sourceMappingURL=target.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=target.js.map
@@ -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"}