@kywi-software/js 0.15.0 → 0.15.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.
@@ -1,3 +1,4 @@
1
+ import { type ConsentGateOptions } from '../consent.js';
1
2
  export interface BehavioralResult {
2
3
  session: {
3
4
  pageViewCount: number;
@@ -11,5 +12,5 @@ export interface BehavioralResult {
11
12
  totalScore: number;
12
13
  };
13
14
  }
14
- export declare function collectBehavioral(currentPath: string, category?: string): BehavioralResult;
15
+ export declare function collectBehavioral(currentPath: string, category?: string, gate?: ConsentGateOptions): BehavioralResult;
15
16
  //# sourceMappingURL=behavioral-collector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"behavioral-collector.d.ts","sourceRoot":"","sources":["../../src/audience/behavioral-collector.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC9H,UAAU,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3E;AAsBD,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAqB1F"}
1
+ {"version":3,"file":"behavioral-collector.d.ts","sourceRoot":"","sources":["../../src/audience/behavioral-collector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAA;AASnE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IAC9H,UAAU,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3E;AAsBD,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,GAAE,kBAAuB,GAC5B,gBAAgB,CA+BlB"}
@@ -1,3 +1,11 @@
1
1
  import type { Audience, VisitorSignals, AudienceResult } from '@kywi-software/core/audiences/types';
2
- export declare function evaluateClientSide(audiences: Audience[], serverSignals: Partial<VisitorSignals>, currentPath: string, pageCategory?: string): AudienceResult;
2
+ import type { ConsentGateOptions } from '../consent.js';
3
+ export declare function evaluateClientSide(audiences: Audience[], serverSignals: Partial<VisitorSignals>, currentPath: string, pageCategory?: string,
4
+ /**
5
+ * `theme.personalization.requireConsent` (kywi-cms#91), passed through to the
6
+ * behavioral collector so what it REMEMBERS between page views follows the
7
+ * same rule the server's cookies do. Omitted, consent is required — the
8
+ * compliant default.
9
+ */
10
+ gate?: ConsentGateOptions): AudienceResult;
3
11
  //# sourceMappingURL=evaluate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/audience/evaluate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAenG,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GACxG,cAAc,CAQhB"}
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/audience/evaluate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAMnG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAYvD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;AACzG;;;;;GAKG;AACH,IAAI,GAAE,kBAAuB,GAC5B,cAAc,CAWhB"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Every query parameter of the current URL. Repeated params keep the FIRST
3
+ * value, matching the server's `collectQuery`. Empty off the browser.
4
+ */
5
+ export declare function collectQuery(): Record<string, string>;
6
+ /**
7
+ * The entry page to record for a page view: the path the host handed us, with
8
+ * this page's query string appended when the path does not already carry one.
9
+ *
10
+ * The query is the interesting half of a campaign landing (`?from=marketer`),
11
+ * and the host passes a bare pathname — so without this the client's entry page
12
+ * and the server's would disagree on every campaign link.
13
+ */
14
+ export declare function entryPageFor(currentPath: string): string;
15
+ //# sourceMappingURL=query-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-collector.d.ts","sourceRoot":"","sources":["../../src/audience/query-collector.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASrD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAIxD"}
@@ -0,0 +1,57 @@
1
+ /** The audience the server resolved the visitor to, if any. */
2
+ export interface SelfIdAudience {
3
+ id: string;
4
+ name: string;
5
+ }
6
+ export interface SelfIdResult {
7
+ /** The audience the answers resolved to, or null when nothing matched. */
8
+ audience: SelfIdAudience | null;
9
+ /**
10
+ * Whether the answers were stored SERVER-side. False for a visitor who has
11
+ * not consented to personalization — the audience is still pinned and this
12
+ * page still changes, the profile simply is not kept (kywi-cms#91).
13
+ */
14
+ persisted: boolean;
15
+ /** The answers now on record in the browser. */
16
+ fields: Record<string, string>;
17
+ }
18
+ export interface SelfIdOptions {
19
+ /** Mounted CMS API base. Defaults to the one `Kywi.boot()` derived. */
20
+ apiBase?: string;
21
+ csrfToken?: string | null;
22
+ /** Reload so the server can re-render with the new pin. Default true. */
23
+ reload?: boolean;
24
+ /**
25
+ * Pin this audience BY ID instead of resolving one from the answers — the id
26
+ * comes from `GET {apiBase}/kywi/audiences`, which lists the audiences an
27
+ * editor marked public (kywi-cms#200). Use it when the page renders the
28
+ * chooser FROM that list, so the visitor's pick lands exactly, and an
29
+ * audience with no rules of its own is still reachable. The server validates
30
+ * the id against the same public, site-scoped list.
31
+ */
32
+ audienceId?: string;
33
+ }
34
+ /**
35
+ * Record the visitor's self-identification and resolve their audience.
36
+ *
37
+ * Answers MERGE into whatever is already on record — two controls on the same
38
+ * page (a role picker and an industry picker) do not clobber each other — and a
39
+ * field submitted as `''` is removed, which is what a "Change" / "Clear"
40
+ * control sends.
41
+ *
42
+ * Pass `audienceId` to pin one of the site's PUBLIC audiences directly instead
43
+ * of resolving from the answers; see {@link SelfIdOptions}.
44
+ *
45
+ * Resolves once the server has answered, with the audience it resolved to.
46
+ * Never throws for a failed request: an offline visitor gets
47
+ * `{ audience: null, persisted: false }` and no reload, so the page is not
48
+ * dropped back onto itself with nothing changed.
49
+ */
50
+ export declare function setSelfId(fields: Record<string, string>, options?: SelfIdOptions): Promise<SelfIdResult>;
51
+ /**
52
+ * Forget the visitor's self-identification: clears the browser copy, the
53
+ * server-side copy and the audience pin, so resolution goes back to signals.
54
+ * The mirror of `setSelfId`, and what a "Change" control calls.
55
+ */
56
+ export declare function clearSelfId(options?: SelfIdOptions): Promise<SelfIdResult>;
57
+ //# sourceMappingURL=selfid-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selfid-api.d.ts","sourceRoot":"","sources":["../../src/audience/selfid-api.ts"],"names":[],"mappings":"AAiCA,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAA;IAC/B;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAA;IAClB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,yEAAyE;IACzE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAqBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAYvB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKpF"}
@@ -1,3 +1,5 @@
1
1
  export declare function collectSelfId(): Record<string, string>;
2
2
  export declare function storeSelfId(responses: Record<string, string>): void;
3
+ /** Forget the visitor's answers entirely (the browser half of clearSelfId). */
4
+ export declare function clearStoredSelfId(): void;
3
5
  //# sourceMappingURL=selfid-collector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selfid-collector.d.ts","sourceRoot":"","sources":["../../src/audience/selfid-collector.ts"],"names":[],"mappings":"AAGA,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAItD;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAEnE"}
1
+ {"version":3,"file":"selfid-collector.d.ts","sourceRoot":"","sources":["../../src/audience/selfid-collector.ts"],"names":[],"mappings":"AAQA,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQtD;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAEnE;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -1 +1 @@
1
- {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../src/consent.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,EAAG,cAAuB,CAAA;AAErD,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,EAAG,eAAwB,CAAA;AAE3D;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAG,WAAoB,CAAA;AAEvD,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,iBAAiB,CAAA;AAEzF;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CASnE,CAAA;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;CACzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAmBrD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,GAC9C,IAAI,CAYN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,EAAE,CAYvE;AAyBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAM/F"}
1
+ {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../src/consent.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,EAAG,cAAuB,CAAA;AAErD,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,EAAG,eAAwB,CAAA;AAE3D;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAG,WAAoB,CAAA;AAEvD,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,iBAAiB,CAAA;AAEzF;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAWnE,CAAA;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;CACzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAmBrD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,GAC9C,IAAI,CAYN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,EAAE,CAYvE;AAyBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAM/F"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { KywiContext, KywiModuleDefinition } from './types.js';
2
+ import { setSelfId, clearSelfId } from './audience/selfid-api.js';
2
3
  type PreInitCallback = (kywi: typeof Kywi) => void;
3
4
  export declare const Kywi: {
4
5
  version: string;
@@ -14,12 +15,26 @@ export declare const Kywi: {
14
15
  extend(methods: Record<string, (...args: unknown[]) => unknown>): void;
15
16
  };
16
17
  };
18
+ /**
19
+ * Record who the visitor says they are, and resolve their audience
20
+ * (kywi-cms#200). Writes the browser-side answers, posts them to the
21
+ * consent-gated runtime endpoint, and reloads so the SERVER can re-render
22
+ * with the resolved audience pinned — which is the only way to reach a
23
+ * variant arm, since every losing arm is pruned server-side (#167).
24
+ *
25
+ * On the global because a site's own "What brings you here?" control needs
26
+ * it: the built-in widget's write path is module-private.
27
+ */
28
+ setSelfId: typeof setSelfId;
29
+ /** Forget the visitor's self-identification and un-pin their audience. */
30
+ clearSelfId: typeof clearSelfId;
17
31
  getEntity: (type: string) => any;
18
32
  getFeed: (type: string) => any;
19
33
  renderFeed: (options: any) => void;
20
34
  boot(): void;
21
35
  };
22
36
  export { bootAudienceEngine } from './audience/index.js';
37
+ export { setSelfId, clearSelfId, type SelfIdAudience, type SelfIdOptions, type SelfIdResult, } from './audience/selfid-api.js';
23
38
  export { openTransparencyPanel, renderTransparencyPanel, type TransparencyState, type TransparencyAudience, } from './audience/transparency.js';
24
39
  export { bootExperiments, type ExperimentRuntime, type ConversionSignal } from './experiments/index.js';
25
40
  export { initNavMenus, enhanceNav, NAV_BREAKPOINT } from './nav/menu.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAUnE,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,IAAI,CAAA;AAIlD,eAAO,MAAM,IAAI;;aAEa,WAAW;YACzB,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC;gBACtC,eAAe,GAAG,IAAI;;2BAIb,oBAAoB,GAAG,oBAAoB;;;;oBAM9C,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;4BAC7C,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,IAAI;;;eAK5C,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG;aACvB,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG;gBAClB,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI;YAC7C,IAAI;CAkBb,CAAA;AAWD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACvG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAIxE,OAAO,EACL,eAAe,EACf,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AASnE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAEjE,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,IAAI,CAAA;AAIlD,eAAO,MAAM,IAAI;;aAEa,WAAW;YACzB,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC;gBACtC,eAAe,GAAG,IAAI;;2BAIb,oBAAoB,GAAG,oBAAoB;;;;oBAM9C,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;4BAC7C,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,IAAI;;;IAK1E;;;;;;;;;OASG;;IAEH,0EAA0E;;eAE5C,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG;aACvB,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG;gBAClB,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI;YAC7C,IAAI;CAkBb,CAAA;AAWD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EACL,SAAS,EACT,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACvG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAIxE,OAAO,EACL,eAAe,EACf,UAAU,EACV,UAAU,EACV,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAA"}