@sanity/client 7.23.2 → 7.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
3
  var client = require("@sanity/client"), stegaEncodeSourceMap = require("./_chunks-cjs/stegaEncodeSourceMap.cjs"), stegaClean = require("./_chunks-cjs/stegaClean.cjs");
4
+ function stegaBrand(result) {
5
+ return result;
6
+ }
4
7
  class SanityStegaClient extends client.SanityClient {
5
8
  }
6
9
  class ObservableSanityStegaClient extends client.ObservableSanityClient {
@@ -14,6 +17,7 @@ exports.ObservableSanityStegaClient = ObservableSanityStegaClient;
14
17
  exports.SanityStegaClient = SanityStegaClient;
15
18
  exports.createClient = createClient;
16
19
  exports.requester = requester;
20
+ exports.stegaBrand = stegaBrand;
17
21
  Object.keys(client).forEach(function(k) {
18
22
  k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k) && Object.defineProperty(exports, k, {
19
23
  enumerable: !0,
@@ -1 +1 @@
1
- {"version":3,"file":"stega.browser.cjs","sources":["../src/stega/index.ts"],"sourcesContent":["export * from '@sanity/client'\nimport {\n createClient as originalCreateClient,\n ObservableSanityClient,\n requester as originalRequester,\n SanityClient,\n} from '@sanity/client'\n\nexport {encodeIntoResult} from './encodeIntoResult'\nexport {stegaClean, vercelStegaCleanAll} from './stegaClean'\nexport {stegaEncodeSourceMap} from './stegaEncodeSourceMap'\nexport * from './types'\n\n/**\n * @deprecated -- Use `import {SanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class SanityStegaClient extends SanityClient {}\n\n/**\n * @deprecated -- Use `import {ObservableSanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class ObservableSanityStegaClient extends ObservableSanityClient {}\n\n/**\n * @deprecated -- Use `import {requester} from '@sanity/client'` instead\n * @public\n */\nexport const requester = originalRequester\n\n/**\n * @deprecated -- Use `import {createClient} from '@sanity/client'` instead\n * @public\n */\nexport const createClient = originalCreateClient\n"],"names":["SanityClient","ObservableSanityClient","originalRequester","originalCreateClient"],"mappings":";;;AAiBO,MAAM,0BAA0BA,OAAAA,aAAa;AAAC;AAM9C,MAAM,oCAAoCC,OAAAA,uBAAuB;AAAC;AAMlE,MAAM,YAAYC,OAAAA,WAMZ,eAAeC,OAAAA;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"stega.browser.cjs","sources":["../src/stega/stegaBrand.ts","../src/stega/index.ts"],"sourcesContent":["import type {Any, ClientReturn} from '@sanity/client'\n\n/**\n * A string that might contain stega-encoded data, and is unsafe to compare against string literals\n * until it's been cleaned with `stegaClean()`.\n *\n * The type intersects a template literal that has a human readable suffix, with a brand property\n * that holds the original string type:\n * - The suffix makes TypeScript report \"This comparison appears to be unintentional\" (TS2367) when\n * the string is compared to a literal (`===`, `switch` cases), and makes it unassignable to\n * literal unions like `'left' | 'right'`, while keeping it assignable to `string` so rendering,\n * interpolation and string methods keep working. The suffix is a type-level fiction, the runtime\n * value never ends with that text.\n * - The brand property preserves the original type so `stegaClean()` can recover it exactly. It's\n * a string-keyed property rather than a `unique symbol` so that branded types stay structurally\n * compatible across duplicated copies of `@sanity/client` in `node_modules`. It only exists in\n * the type system and is never present at runtime.\n *\n * @beta\n */\nexport type StegaString<T extends string = string> =\n `${T} (may contain hidden stega characters)` & {\n readonly ' stegaBrand': T\n }\n\n/**\n * Deeply brands the string properties of a query result as `StegaString`, marking them as\n * potentially containing stega-encoded data.\n *\n * String properties that the stega encoder is guaranteed to never encode keep their plain type:\n * - keys starting with `_` (`_id`, `_type`, `_createdAt`, `_updatedAt`, `_key`, `_ref`, `_rev` and\n * so on), which also preserves discriminated union narrowing on `_type`\n * - `slug.current` patterns: a `current` key directly under a `slug` key, as well as string valued\n * `slug` keys (covering `\"slug\": slug.current` projections)\n * - Portable Text internals: the encoder only visits `children` of `_type: 'block'` objects and\n * `text` of `_type: 'span'` objects, so properties like `style`, `listItem` and `marks` stay\n * plain\n *\n * Every other string is assumed to be \"poisoned\", even if the runtime `filter` happens to skip it\n * (URLs, dates, keys ending in `Id`, denylisted keys). Being conservative is safe: the worst case\n * is a redundant `stegaClean()` call, whereas under-branding would hide real bugs.\n *\n * The `Key` and `ParentKey` type parameters track the key the current value is found under, and\n * the key of the object containing it, they're only used internally during recursion.\n *\n * @beta\n */\nexport type StegaBranded<\n T,\n Key extends PropertyKey = number,\n ParentKey extends PropertyKey = number,\n> = 0 extends 1 & T\n ? T\n : T extends string\n ? T extends {readonly ' stegaBrand': string}\n ? T\n : Key extends `_${string}` | 'slug'\n ? T\n : Key extends 'current'\n ? ParentKey extends 'slug'\n ? T\n : StegaString<T>\n : StegaString<T>\n : T extends number | bigint | boolean | null | undefined\n ? T\n : T extends Date | RegExp | ((...args: never[]) => unknown)\n ? T\n : T extends readonly unknown[]\n ? {[Index in keyof T]: StegaBranded<T[Index], number, number>}\n : T extends {_type: 'block'}\n ? {[K in keyof T]: K extends 'children' ? StegaBranded<T[K], K, Key> : T[K]}\n : T extends {_type: 'span'}\n ? {[K in keyof T]: K extends 'text' ? StegaBranded<T[K], K, Key> : T[K]}\n : T extends object\n ? {[K in keyof T]: StegaBranded<T[K], K, Key>}\n : T\n\n/**\n * Drop-in replacement for `ClientReturn` that brands the result strings as `StegaString`, for use\n * as the first generic of `client.fetch` when stega is enabled:\n * ```ts\n * import {createClient} from '@sanity/client'\n * import type {ClientReturnStega} from '@sanity/client/stega'\n *\n * const query = '*[_type == \"post\"][0]'\n * const post = await client.fetch<ClientReturnStega<typeof query>>(query)\n * ```\n * When the query is registered in the `SanityQueries` interface (for example by `sanity typegen`),\n * the result type is looked up and deeply branded with `StegaBranded`. Otherwise it falls back to\n * `Fallback`, which defaults to `any`, just like `ClientReturn`.\n *\n * @beta\n */\nexport type ClientReturnStega<GroqString extends string, Fallback = Any> = StegaBranded<\n ClientReturn<GroqString, Fallback>\n>\n\n/**\n * Marks strings in an already fetched query result as potentially containing stega-encoded data,\n * by re-typing them as `StegaString`. Comparing branded strings to string literals is a type error\n * until they're cleaned with `stegaClean()`, which recovers the original type.\n *\n * This is an identity function, it only changes the type of the input, not its value.\n * Prefer passing `ClientReturnStega` as the first generic to `client.fetch` when possible, and use\n * this function for data that has already been fetched.\n *\n * @beta\n */\nexport function stegaBrand<Result>(result: Result): StegaBranded<Result> {\n return result as StegaBranded<Result>\n}\n","export * from '@sanity/client'\nimport {\n createClient as originalCreateClient,\n ObservableSanityClient,\n requester as originalRequester,\n SanityClient,\n} from '@sanity/client'\n\nexport {encodeIntoResult} from './encodeIntoResult'\nexport {type ClientReturnStega, stegaBrand, type StegaBranded, type StegaString} from './stegaBrand'\nexport {stegaClean, type StegaCleaned, vercelStegaCleanAll} from './stegaClean'\nexport {stegaEncodeSourceMap} from './stegaEncodeSourceMap'\nexport * from './types'\n\n/**\n * @deprecated -- Use `import {SanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class SanityStegaClient extends SanityClient {}\n\n/**\n * @deprecated -- Use `import {ObservableSanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class ObservableSanityStegaClient extends ObservableSanityClient {}\n\n/**\n * @deprecated -- Use `import {requester} from '@sanity/client'` instead\n * @public\n */\nexport const requester = originalRequester\n\n/**\n * @deprecated -- Use `import {createClient} from '@sanity/client'` instead\n * @public\n */\nexport const createClient = originalCreateClient\n"],"names":["SanityClient","ObservableSanityClient","originalRequester","originalCreateClient"],"mappings":";;;AA4GO,SAAS,WAAmB,QAAsC;AACvE,SAAO;AACT;AC5FO,MAAM,0BAA0BA,OAAAA,aAAa;AAAC;AAM9C,MAAM,oCAAoCC,OAAAA,uBAAuB;AAAC;AAMlE,MAAM,YAAYC,OAAAA,WAMZ,eAAeC,OAAAA;;;;;;;;;;;;;;;;;;"}
@@ -719,6 +719,10 @@ export declare interface ClientConfig {
719
719
  * @defaultValue 'published'
720
720
  */
721
721
  perspective?: ClientPerspective
722
+ /**
723
+ * @beta
724
+ */
725
+ variant?: ClientVariant
722
726
  apiHost?: string
723
727
  /**
724
728
  @remarks
@@ -874,12 +878,44 @@ export declare type ClientReturn<
874
878
  Fallback = Any,
875
879
  > = GroqString extends keyof SanityQueries ? SanityQueries[GroqString] : Fallback
876
880
 
881
+ /**
882
+ * Drop-in replacement for `ClientReturn` that brands the result strings as `StegaString`, for use
883
+ * as the first generic of `client.fetch` when stega is enabled:
884
+ * ```ts
885
+ * import {createClient} from '@sanity/client'
886
+ * import type {ClientReturnStega} from '@sanity/client/stega'
887
+ *
888
+ * const query = '*[_type == "post"][0]'
889
+ * const post = await client.fetch<ClientReturnStega<typeof query>>(query)
890
+ * ```
891
+ * When the query is registered in the `SanityQueries` interface (for example by `sanity typegen`),
892
+ * the result type is looked up and deeply branded with `StegaBranded`. Otherwise it falls back to
893
+ * `Fallback`, which defaults to `any`, just like `ClientReturn`.
894
+ *
895
+ * @beta
896
+ */
897
+ export declare type ClientReturnStega<GroqString extends string, Fallback = Any> = StegaBranded<
898
+ ClientReturn<GroqString, Fallback>
899
+ >
900
+
877
901
  /**
878
902
  * @public
879
903
  * @deprecated -- use `ClientConfig` instead
880
904
  */
881
905
  export declare interface ClientStegaConfig extends ClientConfig {}
882
906
 
907
+ /**
908
+ * @public
909
+ * @beta
910
+ */
911
+ export declare type ClientVariant = ClientVariantConditions | string
912
+
913
+ /**
914
+ * @public
915
+ * @beta
916
+ */
917
+ export declare type ClientVariantConditions = Record<string, string>
918
+
883
919
  /**
884
920
  * Sanity API specific EventSource handler shared between the listen and live APIs
885
921
  *
@@ -4526,6 +4562,8 @@ export declare interface QueryParams {
4526
4562
  /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4527
4563
  perspective?: never
4528
4564
  /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4565
+ variant?: never
4566
+ /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4529
4567
  query?: never
4530
4568
  /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4531
4569
  resultSourceMap?: never
@@ -5066,6 +5104,10 @@ export declare interface RequestObservableOptions extends Omit<RequestOptions, '
5066
5104
  returnQuery?: boolean
5067
5105
  resultSourceMap?: boolean | 'withKeyArraySelector'
5068
5106
  perspective?: ClientPerspective
5107
+ /**
5108
+ * @beta
5109
+ */
5110
+ variant?: ClientVariant
5069
5111
  lastLiveEventId?: string
5070
5112
  cacheMode?: 'noStale'
5071
5113
  }
@@ -5114,6 +5156,10 @@ export declare interface ResponseEvent<T = unknown> {
5114
5156
  /** @public */
5115
5157
  export declare interface ResponseQueryOptions extends RequestOptions {
5116
5158
  perspective?: ClientPerspective
5159
+ /**
5160
+ * @beta
5161
+ */
5162
+ variant?: ClientVariant
5117
5163
  resultSourceMap?: boolean | 'withKeyArraySelector'
5118
5164
  returnQuery?: boolean
5119
5165
  useCdn?: boolean
@@ -6142,12 +6188,118 @@ export declare interface SingleMutationResult {
6142
6188
  /** @public */
6143
6189
  export declare type StackablePerspective = ('published' | 'drafts' | string) & {}
6144
6190
 
6191
+ /**
6192
+ * Marks strings in an already fetched query result as potentially containing stega-encoded data,
6193
+ * by re-typing them as `StegaString`. Comparing branded strings to string literals is a type error
6194
+ * until they're cleaned with `stegaClean()`, which recovers the original type.
6195
+ *
6196
+ * This is an identity function, it only changes the type of the input, not its value.
6197
+ * Prefer passing `ClientReturnStega` as the first generic to `client.fetch` when possible, and use
6198
+ * this function for data that has already been fetched.
6199
+ *
6200
+ * @beta
6201
+ */
6202
+ export declare function stegaBrand<Result>(result: Result): StegaBranded<Result>
6203
+
6204
+ /**
6205
+ * Deeply brands the string properties of a query result as `StegaString`, marking them as
6206
+ * potentially containing stega-encoded data.
6207
+ *
6208
+ * String properties that the stega encoder is guaranteed to never encode keep their plain type:
6209
+ * - keys starting with `_` (`_id`, `_type`, `_createdAt`, `_updatedAt`, `_key`, `_ref`, `_rev` and
6210
+ * so on), which also preserves discriminated union narrowing on `_type`
6211
+ * - `slug.current` patterns: a `current` key directly under a `slug` key, as well as string valued
6212
+ * `slug` keys (covering `"slug": slug.current` projections)
6213
+ * - Portable Text internals: the encoder only visits `children` of `_type: 'block'` objects and
6214
+ * `text` of `_type: 'span'` objects, so properties like `style`, `listItem` and `marks` stay
6215
+ * plain
6216
+ *
6217
+ * Every other string is assumed to be "poisoned", even if the runtime `filter` happens to skip it
6218
+ * (URLs, dates, keys ending in `Id`, denylisted keys). Being conservative is safe: the worst case
6219
+ * is a redundant `stegaClean()` call, whereas under-branding would hide real bugs.
6220
+ *
6221
+ * The `Key` and `ParentKey` type parameters track the key the current value is found under, and
6222
+ * the key of the object containing it, they're only used internally during recursion.
6223
+ *
6224
+ * @beta
6225
+ */
6226
+ export declare type StegaBranded<
6227
+ T,
6228
+ Key extends PropertyKey = number,
6229
+ ParentKey extends PropertyKey = number,
6230
+ > = 0 extends 1 & T
6231
+ ? T
6232
+ : T extends string
6233
+ ? T extends {
6234
+ readonly ' stegaBrand': string
6235
+ }
6236
+ ? T
6237
+ : Key extends `_${string}` | 'slug'
6238
+ ? T
6239
+ : Key extends 'current'
6240
+ ? ParentKey extends 'slug'
6241
+ ? T
6242
+ : StegaString<T>
6243
+ : StegaString<T>
6244
+ : T extends number | bigint | boolean | null | undefined
6245
+ ? T
6246
+ : T extends Date | RegExp | ((...args: never[]) => unknown)
6247
+ ? T
6248
+ : T extends readonly unknown[]
6249
+ ? {
6250
+ [Index in keyof T]: StegaBranded<T[Index], number, number>
6251
+ }
6252
+ : T extends {
6253
+ _type: 'block'
6254
+ }
6255
+ ? {
6256
+ [K in keyof T]: K extends 'children' ? StegaBranded<T[K], K, Key> : T[K]
6257
+ }
6258
+ : T extends {
6259
+ _type: 'span'
6260
+ }
6261
+ ? {
6262
+ [K in keyof T]: K extends 'text' ? StegaBranded<T[K], K, Key> : T[K]
6263
+ }
6264
+ : T extends object
6265
+ ? {
6266
+ [K in keyof T]: StegaBranded<T[K], K, Key>
6267
+ }
6268
+ : T
6269
+
6145
6270
  /**
6146
6271
  * Can take a `result` JSON from a `const {result} = client.fetch(query, params, {filterResponse: false})`
6147
6272
  * and remove all stega-encoded data from it.
6273
+ * If the result type has strings branded as `StegaString` (by `ClientReturnStega` or `stegaBrand()`),
6274
+ * the brand is stripped and the original string type is restored.
6148
6275
  * @public
6149
6276
  */
6150
- export declare function stegaClean<Result = unknown>(result: Result): Result
6277
+ export declare function stegaClean<Result = unknown>(result: Result): StegaCleaned<Result>
6278
+
6279
+ /**
6280
+ * The result of removing stega-encoded data from a value with `stegaClean()`: strings that were
6281
+ * branded as `StegaString` are returned to their original type, everything else is left as-is.
6282
+ * @public
6283
+ */
6284
+ export declare type StegaCleaned<T> = 0 extends 1 & T
6285
+ ? T
6286
+ : T extends {
6287
+ readonly ' stegaBrand': infer Original extends string
6288
+ }
6289
+ ? Original
6290
+ : T extends string | number | bigint | boolean | null | undefined
6291
+ ? T
6292
+ : T extends Date | RegExp | ((...args: never[]) => unknown)
6293
+ ? T
6294
+ : T extends readonly unknown[]
6295
+ ? {
6296
+ [Index in keyof T]: StegaCleaned<T[Index]>
6297
+ }
6298
+ : T extends object
6299
+ ? {
6300
+ [K in keyof T]: StegaCleaned<T[K]>
6301
+ }
6302
+ : T
6151
6303
 
6152
6304
  /** @public */
6153
6305
  export declare interface StegaConfig {
@@ -6227,6 +6379,29 @@ export declare function stegaEncodeSourceMap<Result = unknown>(
6227
6379
  config: InitializedStegaConfig_2,
6228
6380
  ): Result
6229
6381
 
6382
+ /**
6383
+ * A string that might contain stega-encoded data, and is unsafe to compare against string literals
6384
+ * until it's been cleaned with `stegaClean()`.
6385
+ *
6386
+ * The type intersects a template literal that has a human readable suffix, with a brand property
6387
+ * that holds the original string type:
6388
+ * - The suffix makes TypeScript report "This comparison appears to be unintentional" (TS2367) when
6389
+ * the string is compared to a literal (`===`, `switch` cases), and makes it unassignable to
6390
+ * literal unions like `'left' | 'right'`, while keeping it assignable to `string` so rendering,
6391
+ * interpolation and string methods keep working. The suffix is a type-level fiction, the runtime
6392
+ * value never ends with that text.
6393
+ * - The brand property preserves the original type so `stegaClean()` can recover it exactly. It's
6394
+ * a string-keyed property rather than a `unique symbol` so that branded types stay structurally
6395
+ * compatible across duplicated copies of `@sanity/client` in `node_modules`. It only exists in
6396
+ * the type system and is never present at runtime.
6397
+ *
6398
+ * @beta
6399
+ */
6400
+ export declare type StegaString<T extends string = string> =
6401
+ `${T} (may contain hidden stega characters)` & {
6402
+ readonly ' stegaBrand': T
6403
+ }
6404
+
6230
6405
  /**
6231
6406
  * Allowed still image formats (thumbnail + storyboard).
6232
6407
  * @public
@@ -719,6 +719,10 @@ export declare interface ClientConfig {
719
719
  * @defaultValue 'published'
720
720
  */
721
721
  perspective?: ClientPerspective
722
+ /**
723
+ * @beta
724
+ */
725
+ variant?: ClientVariant
722
726
  apiHost?: string
723
727
  /**
724
728
  @remarks
@@ -874,12 +878,44 @@ export declare type ClientReturn<
874
878
  Fallback = Any,
875
879
  > = GroqString extends keyof SanityQueries ? SanityQueries[GroqString] : Fallback
876
880
 
881
+ /**
882
+ * Drop-in replacement for `ClientReturn` that brands the result strings as `StegaString`, for use
883
+ * as the first generic of `client.fetch` when stega is enabled:
884
+ * ```ts
885
+ * import {createClient} from '@sanity/client'
886
+ * import type {ClientReturnStega} from '@sanity/client/stega'
887
+ *
888
+ * const query = '*[_type == "post"][0]'
889
+ * const post = await client.fetch<ClientReturnStega<typeof query>>(query)
890
+ * ```
891
+ * When the query is registered in the `SanityQueries` interface (for example by `sanity typegen`),
892
+ * the result type is looked up and deeply branded with `StegaBranded`. Otherwise it falls back to
893
+ * `Fallback`, which defaults to `any`, just like `ClientReturn`.
894
+ *
895
+ * @beta
896
+ */
897
+ export declare type ClientReturnStega<GroqString extends string, Fallback = Any> = StegaBranded<
898
+ ClientReturn<GroqString, Fallback>
899
+ >
900
+
877
901
  /**
878
902
  * @public
879
903
  * @deprecated -- use `ClientConfig` instead
880
904
  */
881
905
  export declare interface ClientStegaConfig extends ClientConfig {}
882
906
 
907
+ /**
908
+ * @public
909
+ * @beta
910
+ */
911
+ export declare type ClientVariant = ClientVariantConditions | string
912
+
913
+ /**
914
+ * @public
915
+ * @beta
916
+ */
917
+ export declare type ClientVariantConditions = Record<string, string>
918
+
883
919
  /**
884
920
  * Sanity API specific EventSource handler shared between the listen and live APIs
885
921
  *
@@ -4526,6 +4562,8 @@ export declare interface QueryParams {
4526
4562
  /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4527
4563
  perspective?: never
4528
4564
  /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4565
+ variant?: never
4566
+ /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4529
4567
  query?: never
4530
4568
  /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
4531
4569
  resultSourceMap?: never
@@ -5066,6 +5104,10 @@ export declare interface RequestObservableOptions extends Omit<RequestOptions, '
5066
5104
  returnQuery?: boolean
5067
5105
  resultSourceMap?: boolean | 'withKeyArraySelector'
5068
5106
  perspective?: ClientPerspective
5107
+ /**
5108
+ * @beta
5109
+ */
5110
+ variant?: ClientVariant
5069
5111
  lastLiveEventId?: string
5070
5112
  cacheMode?: 'noStale'
5071
5113
  }
@@ -5114,6 +5156,10 @@ export declare interface ResponseEvent<T = unknown> {
5114
5156
  /** @public */
5115
5157
  export declare interface ResponseQueryOptions extends RequestOptions {
5116
5158
  perspective?: ClientPerspective
5159
+ /**
5160
+ * @beta
5161
+ */
5162
+ variant?: ClientVariant
5117
5163
  resultSourceMap?: boolean | 'withKeyArraySelector'
5118
5164
  returnQuery?: boolean
5119
5165
  useCdn?: boolean
@@ -6142,12 +6188,118 @@ export declare interface SingleMutationResult {
6142
6188
  /** @public */
6143
6189
  export declare type StackablePerspective = ('published' | 'drafts' | string) & {}
6144
6190
 
6191
+ /**
6192
+ * Marks strings in an already fetched query result as potentially containing stega-encoded data,
6193
+ * by re-typing them as `StegaString`. Comparing branded strings to string literals is a type error
6194
+ * until they're cleaned with `stegaClean()`, which recovers the original type.
6195
+ *
6196
+ * This is an identity function, it only changes the type of the input, not its value.
6197
+ * Prefer passing `ClientReturnStega` as the first generic to `client.fetch` when possible, and use
6198
+ * this function for data that has already been fetched.
6199
+ *
6200
+ * @beta
6201
+ */
6202
+ export declare function stegaBrand<Result>(result: Result): StegaBranded<Result>
6203
+
6204
+ /**
6205
+ * Deeply brands the string properties of a query result as `StegaString`, marking them as
6206
+ * potentially containing stega-encoded data.
6207
+ *
6208
+ * String properties that the stega encoder is guaranteed to never encode keep their plain type:
6209
+ * - keys starting with `_` (`_id`, `_type`, `_createdAt`, `_updatedAt`, `_key`, `_ref`, `_rev` and
6210
+ * so on), which also preserves discriminated union narrowing on `_type`
6211
+ * - `slug.current` patterns: a `current` key directly under a `slug` key, as well as string valued
6212
+ * `slug` keys (covering `"slug": slug.current` projections)
6213
+ * - Portable Text internals: the encoder only visits `children` of `_type: 'block'` objects and
6214
+ * `text` of `_type: 'span'` objects, so properties like `style`, `listItem` and `marks` stay
6215
+ * plain
6216
+ *
6217
+ * Every other string is assumed to be "poisoned", even if the runtime `filter` happens to skip it
6218
+ * (URLs, dates, keys ending in `Id`, denylisted keys). Being conservative is safe: the worst case
6219
+ * is a redundant `stegaClean()` call, whereas under-branding would hide real bugs.
6220
+ *
6221
+ * The `Key` and `ParentKey` type parameters track the key the current value is found under, and
6222
+ * the key of the object containing it, they're only used internally during recursion.
6223
+ *
6224
+ * @beta
6225
+ */
6226
+ export declare type StegaBranded<
6227
+ T,
6228
+ Key extends PropertyKey = number,
6229
+ ParentKey extends PropertyKey = number,
6230
+ > = 0 extends 1 & T
6231
+ ? T
6232
+ : T extends string
6233
+ ? T extends {
6234
+ readonly ' stegaBrand': string
6235
+ }
6236
+ ? T
6237
+ : Key extends `_${string}` | 'slug'
6238
+ ? T
6239
+ : Key extends 'current'
6240
+ ? ParentKey extends 'slug'
6241
+ ? T
6242
+ : StegaString<T>
6243
+ : StegaString<T>
6244
+ : T extends number | bigint | boolean | null | undefined
6245
+ ? T
6246
+ : T extends Date | RegExp | ((...args: never[]) => unknown)
6247
+ ? T
6248
+ : T extends readonly unknown[]
6249
+ ? {
6250
+ [Index in keyof T]: StegaBranded<T[Index], number, number>
6251
+ }
6252
+ : T extends {
6253
+ _type: 'block'
6254
+ }
6255
+ ? {
6256
+ [K in keyof T]: K extends 'children' ? StegaBranded<T[K], K, Key> : T[K]
6257
+ }
6258
+ : T extends {
6259
+ _type: 'span'
6260
+ }
6261
+ ? {
6262
+ [K in keyof T]: K extends 'text' ? StegaBranded<T[K], K, Key> : T[K]
6263
+ }
6264
+ : T extends object
6265
+ ? {
6266
+ [K in keyof T]: StegaBranded<T[K], K, Key>
6267
+ }
6268
+ : T
6269
+
6145
6270
  /**
6146
6271
  * Can take a `result` JSON from a `const {result} = client.fetch(query, params, {filterResponse: false})`
6147
6272
  * and remove all stega-encoded data from it.
6273
+ * If the result type has strings branded as `StegaString` (by `ClientReturnStega` or `stegaBrand()`),
6274
+ * the brand is stripped and the original string type is restored.
6148
6275
  * @public
6149
6276
  */
6150
- export declare function stegaClean<Result = unknown>(result: Result): Result
6277
+ export declare function stegaClean<Result = unknown>(result: Result): StegaCleaned<Result>
6278
+
6279
+ /**
6280
+ * The result of removing stega-encoded data from a value with `stegaClean()`: strings that were
6281
+ * branded as `StegaString` are returned to their original type, everything else is left as-is.
6282
+ * @public
6283
+ */
6284
+ export declare type StegaCleaned<T> = 0 extends 1 & T
6285
+ ? T
6286
+ : T extends {
6287
+ readonly ' stegaBrand': infer Original extends string
6288
+ }
6289
+ ? Original
6290
+ : T extends string | number | bigint | boolean | null | undefined
6291
+ ? T
6292
+ : T extends Date | RegExp | ((...args: never[]) => unknown)
6293
+ ? T
6294
+ : T extends readonly unknown[]
6295
+ ? {
6296
+ [Index in keyof T]: StegaCleaned<T[Index]>
6297
+ }
6298
+ : T extends object
6299
+ ? {
6300
+ [K in keyof T]: StegaCleaned<T[K]>
6301
+ }
6302
+ : T
6151
6303
 
6152
6304
  /** @public */
6153
6305
  export declare interface StegaConfig {
@@ -6227,6 +6379,29 @@ export declare function stegaEncodeSourceMap<Result = unknown>(
6227
6379
  config: InitializedStegaConfig_2,
6228
6380
  ): Result
6229
6381
 
6382
+ /**
6383
+ * A string that might contain stega-encoded data, and is unsafe to compare against string literals
6384
+ * until it's been cleaned with `stegaClean()`.
6385
+ *
6386
+ * The type intersects a template literal that has a human readable suffix, with a brand property
6387
+ * that holds the original string type:
6388
+ * - The suffix makes TypeScript report "This comparison appears to be unintentional" (TS2367) when
6389
+ * the string is compared to a literal (`===`, `switch` cases), and makes it unassignable to
6390
+ * literal unions like `'left' | 'right'`, while keeping it assignable to `string` so rendering,
6391
+ * interpolation and string methods keep working. The suffix is a type-level fiction, the runtime
6392
+ * value never ends with that text.
6393
+ * - The brand property preserves the original type so `stegaClean()` can recover it exactly. It's
6394
+ * a string-keyed property rather than a `unique symbol` so that branded types stay structurally
6395
+ * compatible across duplicated copies of `@sanity/client` in `node_modules`. It only exists in
6396
+ * the type system and is never present at runtime.
6397
+ *
6398
+ * @beta
6399
+ */
6400
+ export declare type StegaString<T extends string = string> =
6401
+ `${T} (may contain hidden stega characters)` & {
6402
+ readonly ' stegaBrand': T
6403
+ }
6404
+
6230
6405
  /**
6231
6406
  * Allowed still image formats (thumbnail + storyboard).
6232
6407
  * @public
@@ -2,6 +2,9 @@ import { createClient as createClient$1, requester as requester$1, ObservableSan
2
2
  export * from "@sanity/client";
3
3
  import { encodeIntoResult, stegaEncodeSourceMap } from "./_chunks-es/stegaEncodeSourceMap.js";
4
4
  import { stegaClean, vercelStegaCleanAll } from "./_chunks-es/stegaClean.js";
5
+ function stegaBrand(result) {
6
+ return result;
7
+ }
5
8
  class SanityStegaClient extends SanityClient {
6
9
  }
7
10
  class ObservableSanityStegaClient extends ObservableSanityClient {
@@ -13,6 +16,7 @@ export {
13
16
  createClient,
14
17
  encodeIntoResult,
15
18
  requester,
19
+ stegaBrand,
16
20
  stegaClean,
17
21
  stegaEncodeSourceMap,
18
22
  vercelStegaCleanAll
@@ -1 +1 @@
1
- {"version":3,"file":"stega.browser.js","sources":["../src/stega/index.ts"],"sourcesContent":["export * from '@sanity/client'\nimport {\n createClient as originalCreateClient,\n ObservableSanityClient,\n requester as originalRequester,\n SanityClient,\n} from '@sanity/client'\n\nexport {encodeIntoResult} from './encodeIntoResult'\nexport {stegaClean, vercelStegaCleanAll} from './stegaClean'\nexport {stegaEncodeSourceMap} from './stegaEncodeSourceMap'\nexport * from './types'\n\n/**\n * @deprecated -- Use `import {SanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class SanityStegaClient extends SanityClient {}\n\n/**\n * @deprecated -- Use `import {ObservableSanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class ObservableSanityStegaClient extends ObservableSanityClient {}\n\n/**\n * @deprecated -- Use `import {requester} from '@sanity/client'` instead\n * @public\n */\nexport const requester = originalRequester\n\n/**\n * @deprecated -- Use `import {createClient} from '@sanity/client'` instead\n * @public\n */\nexport const createClient = originalCreateClient\n"],"names":["originalRequester","originalCreateClient"],"mappings":";;;;AAiBO,MAAM,0BAA0B,aAAa;AAAC;AAM9C,MAAM,oCAAoC,uBAAuB;AAAC;AAMlE,MAAM,YAAYA,aAMZ,eAAeC;"}
1
+ {"version":3,"file":"stega.browser.js","sources":["../src/stega/stegaBrand.ts","../src/stega/index.ts"],"sourcesContent":["import type {Any, ClientReturn} from '@sanity/client'\n\n/**\n * A string that might contain stega-encoded data, and is unsafe to compare against string literals\n * until it's been cleaned with `stegaClean()`.\n *\n * The type intersects a template literal that has a human readable suffix, with a brand property\n * that holds the original string type:\n * - The suffix makes TypeScript report \"This comparison appears to be unintentional\" (TS2367) when\n * the string is compared to a literal (`===`, `switch` cases), and makes it unassignable to\n * literal unions like `'left' | 'right'`, while keeping it assignable to `string` so rendering,\n * interpolation and string methods keep working. The suffix is a type-level fiction, the runtime\n * value never ends with that text.\n * - The brand property preserves the original type so `stegaClean()` can recover it exactly. It's\n * a string-keyed property rather than a `unique symbol` so that branded types stay structurally\n * compatible across duplicated copies of `@sanity/client` in `node_modules`. It only exists in\n * the type system and is never present at runtime.\n *\n * @beta\n */\nexport type StegaString<T extends string = string> =\n `${T} (may contain hidden stega characters)` & {\n readonly ' stegaBrand': T\n }\n\n/**\n * Deeply brands the string properties of a query result as `StegaString`, marking them as\n * potentially containing stega-encoded data.\n *\n * String properties that the stega encoder is guaranteed to never encode keep their plain type:\n * - keys starting with `_` (`_id`, `_type`, `_createdAt`, `_updatedAt`, `_key`, `_ref`, `_rev` and\n * so on), which also preserves discriminated union narrowing on `_type`\n * - `slug.current` patterns: a `current` key directly under a `slug` key, as well as string valued\n * `slug` keys (covering `\"slug\": slug.current` projections)\n * - Portable Text internals: the encoder only visits `children` of `_type: 'block'` objects and\n * `text` of `_type: 'span'` objects, so properties like `style`, `listItem` and `marks` stay\n * plain\n *\n * Every other string is assumed to be \"poisoned\", even if the runtime `filter` happens to skip it\n * (URLs, dates, keys ending in `Id`, denylisted keys). Being conservative is safe: the worst case\n * is a redundant `stegaClean()` call, whereas under-branding would hide real bugs.\n *\n * The `Key` and `ParentKey` type parameters track the key the current value is found under, and\n * the key of the object containing it, they're only used internally during recursion.\n *\n * @beta\n */\nexport type StegaBranded<\n T,\n Key extends PropertyKey = number,\n ParentKey extends PropertyKey = number,\n> = 0 extends 1 & T\n ? T\n : T extends string\n ? T extends {readonly ' stegaBrand': string}\n ? T\n : Key extends `_${string}` | 'slug'\n ? T\n : Key extends 'current'\n ? ParentKey extends 'slug'\n ? T\n : StegaString<T>\n : StegaString<T>\n : T extends number | bigint | boolean | null | undefined\n ? T\n : T extends Date | RegExp | ((...args: never[]) => unknown)\n ? T\n : T extends readonly unknown[]\n ? {[Index in keyof T]: StegaBranded<T[Index], number, number>}\n : T extends {_type: 'block'}\n ? {[K in keyof T]: K extends 'children' ? StegaBranded<T[K], K, Key> : T[K]}\n : T extends {_type: 'span'}\n ? {[K in keyof T]: K extends 'text' ? StegaBranded<T[K], K, Key> : T[K]}\n : T extends object\n ? {[K in keyof T]: StegaBranded<T[K], K, Key>}\n : T\n\n/**\n * Drop-in replacement for `ClientReturn` that brands the result strings as `StegaString`, for use\n * as the first generic of `client.fetch` when stega is enabled:\n * ```ts\n * import {createClient} from '@sanity/client'\n * import type {ClientReturnStega} from '@sanity/client/stega'\n *\n * const query = '*[_type == \"post\"][0]'\n * const post = await client.fetch<ClientReturnStega<typeof query>>(query)\n * ```\n * When the query is registered in the `SanityQueries` interface (for example by `sanity typegen`),\n * the result type is looked up and deeply branded with `StegaBranded`. Otherwise it falls back to\n * `Fallback`, which defaults to `any`, just like `ClientReturn`.\n *\n * @beta\n */\nexport type ClientReturnStega<GroqString extends string, Fallback = Any> = StegaBranded<\n ClientReturn<GroqString, Fallback>\n>\n\n/**\n * Marks strings in an already fetched query result as potentially containing stega-encoded data,\n * by re-typing them as `StegaString`. Comparing branded strings to string literals is a type error\n * until they're cleaned with `stegaClean()`, which recovers the original type.\n *\n * This is an identity function, it only changes the type of the input, not its value.\n * Prefer passing `ClientReturnStega` as the first generic to `client.fetch` when possible, and use\n * this function for data that has already been fetched.\n *\n * @beta\n */\nexport function stegaBrand<Result>(result: Result): StegaBranded<Result> {\n return result as StegaBranded<Result>\n}\n","export * from '@sanity/client'\nimport {\n createClient as originalCreateClient,\n ObservableSanityClient,\n requester as originalRequester,\n SanityClient,\n} from '@sanity/client'\n\nexport {encodeIntoResult} from './encodeIntoResult'\nexport {type ClientReturnStega, stegaBrand, type StegaBranded, type StegaString} from './stegaBrand'\nexport {stegaClean, type StegaCleaned, vercelStegaCleanAll} from './stegaClean'\nexport {stegaEncodeSourceMap} from './stegaEncodeSourceMap'\nexport * from './types'\n\n/**\n * @deprecated -- Use `import {SanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class SanityStegaClient extends SanityClient {}\n\n/**\n * @deprecated -- Use `import {ObservableSanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class ObservableSanityStegaClient extends ObservableSanityClient {}\n\n/**\n * @deprecated -- Use `import {requester} from '@sanity/client'` instead\n * @public\n */\nexport const requester = originalRequester\n\n/**\n * @deprecated -- Use `import {createClient} from '@sanity/client'` instead\n * @public\n */\nexport const createClient = originalCreateClient\n"],"names":["originalRequester","originalCreateClient"],"mappings":";;;;AA4GO,SAAS,WAAmB,QAAsC;AACvE,SAAO;AACT;AC5FO,MAAM,0BAA0B,aAAa;AAAC;AAM9C,MAAM,oCAAoC,uBAAuB;AAAC;AAMlE,MAAM,YAAYA,aAMZ,eAAeC;"}
package/dist/stega.cjs CHANGED
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: !0 });
3
3
  var client = require("@sanity/client"), stegaEncodeSourceMap = require("./_chunks-cjs/stegaEncodeSourceMap.cjs"), stegaClean = require("./_chunks-cjs/stegaClean.cjs");
4
+ function stegaBrand(result) {
5
+ return result;
6
+ }
4
7
  class SanityStegaClient extends client.SanityClient {
5
8
  }
6
9
  class ObservableSanityStegaClient extends client.ObservableSanityClient {
@@ -14,6 +17,7 @@ exports.ObservableSanityStegaClient = ObservableSanityStegaClient;
14
17
  exports.SanityStegaClient = SanityStegaClient;
15
18
  exports.createClient = createClient;
16
19
  exports.requester = requester;
20
+ exports.stegaBrand = stegaBrand;
17
21
  Object.keys(client).forEach(function(k) {
18
22
  k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k) && Object.defineProperty(exports, k, {
19
23
  enumerable: !0,
@@ -1 +1 @@
1
- {"version":3,"file":"stega.cjs","sources":["../src/stega/index.ts"],"sourcesContent":["export * from '@sanity/client'\nimport {\n createClient as originalCreateClient,\n ObservableSanityClient,\n requester as originalRequester,\n SanityClient,\n} from '@sanity/client'\n\nexport {encodeIntoResult} from './encodeIntoResult'\nexport {stegaClean, vercelStegaCleanAll} from './stegaClean'\nexport {stegaEncodeSourceMap} from './stegaEncodeSourceMap'\nexport * from './types'\n\n/**\n * @deprecated -- Use `import {SanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class SanityStegaClient extends SanityClient {}\n\n/**\n * @deprecated -- Use `import {ObservableSanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class ObservableSanityStegaClient extends ObservableSanityClient {}\n\n/**\n * @deprecated -- Use `import {requester} from '@sanity/client'` instead\n * @public\n */\nexport const requester = originalRequester\n\n/**\n * @deprecated -- Use `import {createClient} from '@sanity/client'` instead\n * @public\n */\nexport const createClient = originalCreateClient\n"],"names":["SanityClient","ObservableSanityClient","originalRequester","originalCreateClient"],"mappings":";;;AAiBO,MAAM,0BAA0BA,OAAAA,aAAa;AAAC;AAM9C,MAAM,oCAAoCC,OAAAA,uBAAuB;AAAC;AAMlE,MAAM,YAAYC,OAAAA,WAMZ,eAAeC,OAAAA;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"stega.cjs","sources":["../src/stega/stegaBrand.ts","../src/stega/index.ts"],"sourcesContent":["import type {Any, ClientReturn} from '@sanity/client'\n\n/**\n * A string that might contain stega-encoded data, and is unsafe to compare against string literals\n * until it's been cleaned with `stegaClean()`.\n *\n * The type intersects a template literal that has a human readable suffix, with a brand property\n * that holds the original string type:\n * - The suffix makes TypeScript report \"This comparison appears to be unintentional\" (TS2367) when\n * the string is compared to a literal (`===`, `switch` cases), and makes it unassignable to\n * literal unions like `'left' | 'right'`, while keeping it assignable to `string` so rendering,\n * interpolation and string methods keep working. The suffix is a type-level fiction, the runtime\n * value never ends with that text.\n * - The brand property preserves the original type so `stegaClean()` can recover it exactly. It's\n * a string-keyed property rather than a `unique symbol` so that branded types stay structurally\n * compatible across duplicated copies of `@sanity/client` in `node_modules`. It only exists in\n * the type system and is never present at runtime.\n *\n * @beta\n */\nexport type StegaString<T extends string = string> =\n `${T} (may contain hidden stega characters)` & {\n readonly ' stegaBrand': T\n }\n\n/**\n * Deeply brands the string properties of a query result as `StegaString`, marking them as\n * potentially containing stega-encoded data.\n *\n * String properties that the stega encoder is guaranteed to never encode keep their plain type:\n * - keys starting with `_` (`_id`, `_type`, `_createdAt`, `_updatedAt`, `_key`, `_ref`, `_rev` and\n * so on), which also preserves discriminated union narrowing on `_type`\n * - `slug.current` patterns: a `current` key directly under a `slug` key, as well as string valued\n * `slug` keys (covering `\"slug\": slug.current` projections)\n * - Portable Text internals: the encoder only visits `children` of `_type: 'block'` objects and\n * `text` of `_type: 'span'` objects, so properties like `style`, `listItem` and `marks` stay\n * plain\n *\n * Every other string is assumed to be \"poisoned\", even if the runtime `filter` happens to skip it\n * (URLs, dates, keys ending in `Id`, denylisted keys). Being conservative is safe: the worst case\n * is a redundant `stegaClean()` call, whereas under-branding would hide real bugs.\n *\n * The `Key` and `ParentKey` type parameters track the key the current value is found under, and\n * the key of the object containing it, they're only used internally during recursion.\n *\n * @beta\n */\nexport type StegaBranded<\n T,\n Key extends PropertyKey = number,\n ParentKey extends PropertyKey = number,\n> = 0 extends 1 & T\n ? T\n : T extends string\n ? T extends {readonly ' stegaBrand': string}\n ? T\n : Key extends `_${string}` | 'slug'\n ? T\n : Key extends 'current'\n ? ParentKey extends 'slug'\n ? T\n : StegaString<T>\n : StegaString<T>\n : T extends number | bigint | boolean | null | undefined\n ? T\n : T extends Date | RegExp | ((...args: never[]) => unknown)\n ? T\n : T extends readonly unknown[]\n ? {[Index in keyof T]: StegaBranded<T[Index], number, number>}\n : T extends {_type: 'block'}\n ? {[K in keyof T]: K extends 'children' ? StegaBranded<T[K], K, Key> : T[K]}\n : T extends {_type: 'span'}\n ? {[K in keyof T]: K extends 'text' ? StegaBranded<T[K], K, Key> : T[K]}\n : T extends object\n ? {[K in keyof T]: StegaBranded<T[K], K, Key>}\n : T\n\n/**\n * Drop-in replacement for `ClientReturn` that brands the result strings as `StegaString`, for use\n * as the first generic of `client.fetch` when stega is enabled:\n * ```ts\n * import {createClient} from '@sanity/client'\n * import type {ClientReturnStega} from '@sanity/client/stega'\n *\n * const query = '*[_type == \"post\"][0]'\n * const post = await client.fetch<ClientReturnStega<typeof query>>(query)\n * ```\n * When the query is registered in the `SanityQueries` interface (for example by `sanity typegen`),\n * the result type is looked up and deeply branded with `StegaBranded`. Otherwise it falls back to\n * `Fallback`, which defaults to `any`, just like `ClientReturn`.\n *\n * @beta\n */\nexport type ClientReturnStega<GroqString extends string, Fallback = Any> = StegaBranded<\n ClientReturn<GroqString, Fallback>\n>\n\n/**\n * Marks strings in an already fetched query result as potentially containing stega-encoded data,\n * by re-typing them as `StegaString`. Comparing branded strings to string literals is a type error\n * until they're cleaned with `stegaClean()`, which recovers the original type.\n *\n * This is an identity function, it only changes the type of the input, not its value.\n * Prefer passing `ClientReturnStega` as the first generic to `client.fetch` when possible, and use\n * this function for data that has already been fetched.\n *\n * @beta\n */\nexport function stegaBrand<Result>(result: Result): StegaBranded<Result> {\n return result as StegaBranded<Result>\n}\n","export * from '@sanity/client'\nimport {\n createClient as originalCreateClient,\n ObservableSanityClient,\n requester as originalRequester,\n SanityClient,\n} from '@sanity/client'\n\nexport {encodeIntoResult} from './encodeIntoResult'\nexport {type ClientReturnStega, stegaBrand, type StegaBranded, type StegaString} from './stegaBrand'\nexport {stegaClean, type StegaCleaned, vercelStegaCleanAll} from './stegaClean'\nexport {stegaEncodeSourceMap} from './stegaEncodeSourceMap'\nexport * from './types'\n\n/**\n * @deprecated -- Use `import {SanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class SanityStegaClient extends SanityClient {}\n\n/**\n * @deprecated -- Use `import {ObservableSanityClient} from '@sanity/client'` instead\n * @public\n */\nexport class ObservableSanityStegaClient extends ObservableSanityClient {}\n\n/**\n * @deprecated -- Use `import {requester} from '@sanity/client'` instead\n * @public\n */\nexport const requester = originalRequester\n\n/**\n * @deprecated -- Use `import {createClient} from '@sanity/client'` instead\n * @public\n */\nexport const createClient = originalCreateClient\n"],"names":["SanityClient","ObservableSanityClient","originalRequester","originalCreateClient"],"mappings":";;;AA4GO,SAAS,WAAmB,QAAsC;AACvE,SAAO;AACT;AC5FO,MAAM,0BAA0BA,OAAAA,aAAa;AAAC;AAM9C,MAAM,oCAAoCC,OAAAA,uBAAuB;AAAC;AAMlE,MAAM,YAAYC,OAAAA,WAMZ,eAAeC,OAAAA;;;;;;;;;;;;;;;;;;"}