@solarpunkltd/swarm-chat-js 7.2.0 → 8.0.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,8 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  /**
3
3
  * What the server writes: one feed entry per message at indices 0, 1, 2 and on, and one history file per chat that
4
- * the entries point to. The server builds these and the reader checks their shape. The reader does not check each
5
- * message's signature, because the server checked it before publishing.
4
+ * the entries point to. The server builds these and the reader checks their shape. Their `v` is MESSAGE_VERSION. The
5
+ * reader does not check each message's signature or binding, because the server checked both before publishing. A
6
+ * page that shows who sent a message verifies `msg` itself with `verifyChatMessage`, in a Web Worker.
6
7
  */
7
8
  /** A feed entry is always one chunk, so bee-js never wraps it. */
8
9
  export declare const MAX_ENTRY_BYTES = 4096;
@@ -12,11 +13,11 @@ export declare const historyLinkSchema: z.ZodObject<{
12
13
  }, z.core.$strict>;
13
14
  export type HistoryLink = z.infer<typeof historyLinkSchema>;
14
15
  export declare const feedEntrySchema: z.ZodObject<{
15
- v: z.ZodLiteral<7>;
16
+ v: z.ZodLiteral<8>;
16
17
  seq: z.ZodNumber;
17
18
  at: z.ZodNumber;
18
19
  msg: z.ZodObject<{
19
- v: z.ZodLiteral<7>;
20
+ v: z.ZodLiteral<8>;
20
21
  topic: z.ZodString;
21
22
  id: z.ZodString;
22
23
  type: z.ZodEnum<{
@@ -29,6 +30,15 @@ export declare const feedEntrySchema: z.ZodObject<{
29
30
  name: z.ZodString;
30
31
  addr: z.ZodString;
31
32
  ts: z.ZodNumber;
33
+ via: z.ZodEnum<{
34
+ gateway: "gateway";
35
+ "own-stamp": "own-stamp";
36
+ }>;
37
+ own: z.ZodBoolean;
38
+ idb: z.ZodOptional<z.ZodObject<{
39
+ msg: z.ZodString;
40
+ sig: z.ZodString;
41
+ }, z.core.$strict>>;
32
42
  sig: z.ZodString;
33
43
  }, z.core.$strict>;
34
44
  history: z.ZodNullable<z.ZodObject<{
@@ -41,7 +51,7 @@ export declare const historyRowSchema: z.ZodObject<{
41
51
  seq: z.ZodNumber;
42
52
  at: z.ZodNumber;
43
53
  msg: z.ZodObject<{
44
- v: z.ZodLiteral<7>;
54
+ v: z.ZodLiteral<8>;
45
55
  topic: z.ZodString;
46
56
  id: z.ZodString;
47
57
  type: z.ZodEnum<{
@@ -54,13 +64,22 @@ export declare const historyRowSchema: z.ZodObject<{
54
64
  name: z.ZodString;
55
65
  addr: z.ZodString;
56
66
  ts: z.ZodNumber;
67
+ via: z.ZodEnum<{
68
+ gateway: "gateway";
69
+ "own-stamp": "own-stamp";
70
+ }>;
71
+ own: z.ZodBoolean;
72
+ idb: z.ZodOptional<z.ZodObject<{
73
+ msg: z.ZodString;
74
+ sig: z.ZodString;
75
+ }, z.core.$strict>>;
57
76
  sig: z.ZodString;
58
77
  }, z.core.$strict>;
59
78
  }, z.core.$strict>;
60
79
  export type HistoryRow = z.infer<typeof historyRowSchema>;
61
80
  /** A row that fails its shape is left out and counted, so one bad row never hides the rest of the file. */
62
81
  export declare const historyFileSchema: z.ZodObject<{
63
- v: z.ZodLiteral<7>;
82
+ v: z.ZodLiteral<8>;
64
83
  topic: z.ZodString;
65
84
  fromSeq: z.ZodNumber;
66
85
  toSeq: z.ZodNumber;
@@ -1,3 +1,5 @@
1
1
  export * from './message.js';
2
+ export * from './binding.js';
3
+ export * from './ownFeed.js';
2
4
  export * from './entry.js';
3
5
  export * from './note.js';
@@ -1,13 +1,18 @@
1
1
  import { PrivateKey } from '@ethersphere/bee-js';
2
2
  import { z } from 'zod';
3
+ import { type ChatBinding, type ChatIdentity } from './binding.js';
3
4
  /**
4
- * The chat message of version 7: what a browser sends as a GSOC payload, what the server verifies before it
5
+ * The chat message of version 8: what a browser sends as a GSOC payload, what the server verifies before it
5
6
  * publishes, and what every feed entry carries back as `msg`. This module is the only place its bytes are built,
6
- * signed, checked and read, and the server imports it from here rather than keeping a copy.
7
+ * signed, checked and read, and the server imports it from here rather than keeping a copy. A message of any other
8
+ * version fails the shape check.
7
9
  */
8
- export declare const MESSAGE_VERSION = 7;
9
- /** Measured on the UTF-8 of the whole JSON object, on top of the per-field caps. */
10
- export declare const MAX_MESSAGE_BYTES = 2048;
10
+ export declare const MESSAGE_VERSION = 8;
11
+ /**
12
+ * Measured on the UTF-8 of the whole JSON object, on top of the per-field caps. Large enough for a 500 character text
13
+ * of two byte characters with a Swarm ID binding, at every other cap.
14
+ */
15
+ export declare const MAX_MESSAGE_BYTES = 3072;
11
16
  export declare const MAX_TOPIC_CHARACTERS = 128;
12
17
  export declare const MAX_TEXT_CHARACTERS = 500;
13
18
  export declare const MAX_NAME_CHARACTERS = 20;
@@ -17,13 +22,19 @@ export declare const MessageType: {
17
22
  readonly REACTION: 'reaction';
18
23
  };
19
24
  export type MessageType = (typeof MessageType)[keyof typeof MessageType];
25
+ /** Who paid for the inbox write: the gateway's stamp, or the sender's own. */
26
+ export declare const MessageVia: {
27
+ readonly GATEWAY: 'gateway';
28
+ readonly OWN_STAMP: 'own-stamp';
29
+ };
30
+ export type MessageVia = (typeof MessageVia)[keyof typeof MessageVia];
20
31
  /**
21
32
  * Characters are counted as Unicode code points, never as UTF-16 units, so an emoji outside the basic plane counts
22
33
  * once. A composer that shows a count uses this function, so it and the check agree.
23
34
  */
24
35
  export declare function countCharacters(value: string): number;
25
36
  export declare const chatMessageSchema: z.ZodObject<{
26
- v: z.ZodLiteral<7>;
37
+ v: z.ZodLiteral<8>;
27
38
  topic: z.ZodString;
28
39
  id: z.ZodString;
29
40
  type: z.ZodEnum<{
@@ -36,19 +47,39 @@ export declare const chatMessageSchema: z.ZodObject<{
36
47
  name: z.ZodString;
37
48
  addr: z.ZodString;
38
49
  ts: z.ZodNumber;
50
+ via: z.ZodEnum<{
51
+ gateway: "gateway";
52
+ "own-stamp": "own-stamp";
53
+ }>;
54
+ own: z.ZodBoolean;
55
+ idb: z.ZodOptional<z.ZodObject<{
56
+ msg: z.ZodString;
57
+ sig: z.ZodString;
58
+ }, z.core.$strict>>;
39
59
  sig: z.ZodString;
40
60
  }, z.core.$strict>;
41
61
  export type ChatMessage = z.infer<typeof chatMessageSchema>;
42
62
  export type UnsignedChatMessage = Omit<ChatMessage, 'sig'>;
43
- export type ChatMessageRefusal = 'too-large' | 'not-utf8' | 'not-json' | 'shape' | 'signature';
63
+ export type ChatMessageRefusal = 'too-large' | 'not-utf8' | 'not-json' | 'shape' | 'signature' | 'binding';
64
+ /** `identity` is null for a guest, a message with no binding. */
44
65
  export type ChatMessageCheck = {
45
66
  ok: true;
46
67
  message: ChatMessage;
68
+ identity: ChatIdentity | null;
47
69
  } | {
48
70
  ok: false;
49
71
  reason: ChatMessageRefusal;
50
72
  detail: string;
51
73
  };
74
+ /**
75
+ * `origin` is the site the chat runs on, a bare origin such as `https://example.com`, and is required: a binding for
76
+ * any other site is refused, so a binding signed for one site never passes in another site's chat.
77
+ */
78
+ export interface VerifyOptions {
79
+ origin: string;
80
+ /** Accept a binding for `http://localhost`, `http://127.0.0.1` or `http://[::1]`, as only a development build signs. */
81
+ allowLocalHttp?: boolean;
82
+ }
52
83
  export declare class ChatMessageError extends Error {
53
84
  readonly reason: ChatMessageRefusal;
54
85
  constructor(reason: ChatMessageRefusal, detail: string);
@@ -69,6 +100,12 @@ export interface ChatMessageDraft {
69
100
  id?: string;
70
101
  /** The sender's clock in milliseconds, `Date.now()` when left out. */
71
102
  ts?: number;
103
+ /** Who pays for the inbox write. Required, since nothing can tell from here. */
104
+ via: MessageVia;
105
+ /** Whether the sender also keeps a copy in its own feed, false when left out. */
106
+ own?: boolean;
107
+ /** The sender's Swarm ID chat binding, given only for a signed-in sender. */
108
+ idb?: ChatBinding;
72
109
  }
73
110
  export interface SignedChatMessage {
74
111
  message: ChatMessage;
@@ -76,15 +113,24 @@ export interface SignedChatMessage {
76
113
  }
77
114
  /**
78
115
  * Builds and signs a message, and throws a ChatMessageError before signing anything that the server would refuse:
79
- * a field outside its cap, or a payload over MAX_MESSAGE_BYTES.
116
+ * a field outside its cap, a payload over MAX_MESSAGE_BYTES, or a binding that is not for this key.
80
117
  */
81
118
  export declare function createChatMessage(privateKey: PrivateKey | Uint8Array | string, draft: ChatMessageDraft): SignedChatMessage;
82
- /** Whether `sig` was made over this message's signed bytes by the key behind `addr`. */
119
+ /**
120
+ * Whether `sig` was made over this message's signed bytes by the key behind `addr`, in its one canonical spelling: v 27
121
+ * or 28 and a low s, as bee-js signs. bee-js would also recover the signer from the high s twin, or from any other v.
122
+ */
83
123
  export declare function hasValidSignature(message: ChatMessage): boolean;
84
- /** Checks a message that arrived as an object, its shape and its signature. */
85
- export declare function checkChatMessage(value: unknown): ChatMessageCheck;
86
124
  /**
87
- * Checks a message as it arrived on the wire: the byte cap on the raw payload, then UTF-8, JSON, the shape and the
88
- * signature. Never throws, since the server calls it on whatever anybody writes to the chat's GSOC address.
125
+ * Verifies a message that arrived as an object: its shape, its signature, and, when it carries a binding, that the
126
+ * binding is the fork's four lines for this `addr` and for `options.origin`, and recovers an account. A message whose
127
+ * binding fails is refused as `binding`, never passed as a guest, and so is a bound message checked with no origin.
128
+ * Never throws, and touches no DOM and no Node API, so a page runs it in a Web Worker as the server runs it.
129
+ */
130
+ export declare function verifyChatMessage(value: unknown, options: VerifyOptions): ChatMessageCheck;
131
+ /**
132
+ * Verifies a message as it arrived on the wire: the byte cap on the raw payload, then UTF-8, JSON, and everything
133
+ * `verifyChatMessage` checks. Never throws, since the server calls it on whatever anybody writes to the chat's GSOC
134
+ * address.
89
135
  */
90
- export declare function parseChatMessage(payload: Uint8Array): ChatMessageCheck;
136
+ export declare function parseChatMessage(payload: Uint8Array, options: VerifyOptions): ChatMessageCheck;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A sender may keep a copy of each message it sends in a feed of its own, owned by its chat address `addr`, and says
3
+ * so with `own: true`. That feed is named by `ownFeedTopic(chatTopic)`, turned into a feed topic with
4
+ * `Topic.fromString` as the chat's own feed is named by `chatTopic`. The prefix carries a version, so a later layout of
5
+ * the copies takes a new topic rather than mixing with this one.
6
+ */
7
+ export declare const OWN_FEED_TOPIC_PREFIX = "swarm-chat-own-feed-v1:";
8
+ /** The topic string of the feed where the sender keeps its copies of the messages it sent to chat `chatTopic`. */
9
+ export declare function ownFeedTopic(chatTopic: string): string;
@@ -0,0 +1,3 @@
1
+ let e=require("@ethersphere/bee-js"),t=require("zod"),n=require("@ethersphere/core-sdk/crypto");var r=115792089237316195423570985008687907852837564279074904382605163141518161494337n,i=r/2n;function a(e,t){let n=BigInt(`0x${e}`),a=BigInt(`0x${t}`);return n>0n&&n<r&&a>0n&&a<=i}var o=`Swarm ID chat binding v1`,s=512,c=`Site: `,l=`Chat address: `,ee=`Date: `,te=`
2
+ `,u=4,d=`Ethereum Signed Message:
3
+ `,ne=new Set([27,28]),f=/^0x[0-9a-f]{40}$/,p=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/,m=/^[a-z0-9-]+(\.[a-z0-9-]+)*$/,re=new Set([`localhost`,`127.0.0.1`,`[::1]`]),h=t.z.strictObject({msg:t.z.string().max(512),sig:t.z.string().regex(/^0x[0-9a-f]{130}$/,`expected 0x and 130 lowercase hex characters`)}),g=new TextEncoder;function ie(e,t){let n;try{n=new URL(e)}catch{return!1}let r=n.protocol===`https:`,i=t&&n.protocol===`http:`&&re.has(n.hostname);return!r&&!i||!i&&!m.test(n.hostname)?!1:n.host!==``&&n.username===``&&n.password===``&&n.origin===e}function _(e){if(!p.test(e))return!1;let t=Date.parse(e);return!Number.isNaN(t)&&new Date(t).toISOString()===e}function v(e,t){return e.startsWith(t)?e.slice(t.length):null}function ae(e){let t=g.encode(e),n=g.encode(`${d}${t.length}`),r=new Uint8Array(n.length+t.length);return r.set(n),r.set(t,n.length),r}function oe(e){return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function y(e,t){let r=t.slice(2,66),i=t.slice(66,130),o=parseInt(t.slice(130),16);if(!ne.has(o)||!a(r,i))return null;try{let t=(0,n.recoverPublicKey)(ae(e),BigInt(`0x${r}`),BigInt(`0x${i}`),BigInt(o));return`0x${oe((0,n.publicKeyToAddress)(t))}`}catch{return null}}function b(e,t,n={}){if(!h.safeParse(e).success)return{ok:!1,detail:`not a binding of a text and a 65 byte signature`};let r=e.msg.split(te);if(r.length!==u||r[0]!==`Swarm ID chat binding v1`)return{ok:!1,detail:`not the ${u} lines of a ${o}`};let i=v(r[1],c),a=v(r[2],l),s=v(r[3],ee);if(i===null||!ie(i,n.allowLocalHttp===!0))return{ok:!1,detail:`the binding does not name a clean site origin`};if(a===null||!f.test(a))return{ok:!1,detail:`the binding does not name a chat address as 0x and 40 lowercase hex characters`};if(s===null||!_(s))return{ok:!1,detail:`the binding date is not ISO 8601 UTC with milliseconds`};if(a!==`0x${t}`)return{ok:!1,detail:`the binding is for another chat address than addr`};if(n.origin!==void 0&&i!==n.origin)return{ok:!1,detail:`the binding is for ${i}, not ${n.origin}`};let d=y(e.msg,e.sig);return d===null?{ok:!1,detail:`the binding signature recovers no account`}:{ok:!0,identity:{account:d,site:i,date:s}}}var x=8,S=3072,se=128,ce=500,C=20,w={TEXT:`text`,THREAD:`thread`,REACTION:`reaction`},T={GATEWAY:`gateway`,OWN_STAMP:`own-stamp`};function E(e){let t=0;for(let n of e)t++;return t}function D(e){return t.z.string().regex(RegExp(`^[0-9a-f]{${e}}$`),`expected ${e} lowercase hex characters`)}function O(e,n){return t.z.string().refine(t=>{let r=E(t);return r>=e&&r<=n},`expected ${e} to ${n} characters`)}var k=D(32),A=t.z.strictObject({v:t.z.literal(8),topic:O(1,128),id:k,type:t.z.enum([w.TEXT,w.THREAD,w.REACTION]),target:t.z.union([t.z.literal(``),k]),text:O(1,500),name:O(1,20),addr:D(40),ts:t.z.number().int().nonnegative().max(2**53-1),via:t.z.enum([T.GATEWAY,T.OWN_STAMP]),own:t.z.boolean(),idb:h.optional(),sig:D(130)}).refine(e=>e.type===w.TEXT==(e.target===``),{message:`a text message has no target, a thread reply or a reaction names one`,path:[`target`]}),j=class extends Error{constructor(e,t){super(`chat message refused (${e}): ${t}`),this.reason=e,this.name=`ChatMessageError`}},M=new TextEncoder,le=`1b`,ue=`1c`,de=new TextDecoder(`utf-8`,{fatal:!0});function N(e){return M.encode(JSON.stringify([e.v,e.topic,e.id,e.type,e.target,e.text,e.name,e.addr,e.ts,e.via,e.own,e.idb?.msg??``,e.idb?.sig??``]))}function P(e){let t={v:e.v,topic:e.topic,id:e.id,type:e.type,target:e.target,text:e.text,name:e.name,addr:e.addr,ts:e.ts,via:e.via,own:e.own,...e.idb?{idb:{msg:e.idb.msg,sig:e.idb.sig}}:{},sig:e.sig};return M.encode(JSON.stringify(t))}function F(){let e=crypto.getRandomValues(new Uint8Array(16));return Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``)}function I(e){return e.issues.map(e=>`${e.path.join(`.`)||`message`}: ${e.message}`).join(`, `)}function L(t,n){let r=t instanceof e.PrivateKey?t:new e.PrivateKey(t),i={v:8,topic:n.topic,id:n.id??F(),type:n.type,target:n.target??``,text:n.text,name:n.name,addr:r.publicKey().address().toHex(),ts:n.ts??Date.now(),via:n.via,own:n.own??!1,...n.idb?{idb:n.idb}:{}},a={...i,sig:`0`.repeat(130)},o=A.safeParse(a);if(!o.success)throw new j(`shape`,I(o.error));let s=P(a).byteLength;if(s>3072)throw new j(`too-large`,`${s} bytes, the cap is ${S}`);if(i.idb){let e=b(i.idb,i.addr,{allowLocalHttp:!0});if(!e.ok)throw new j(`binding`,e.detail)}let c={...i,sig:r.sign(N(i)).toHex()};return{message:c,bytes:P(c)}}function R(t){let n=t.sig.slice(128);if(n!==le&&n!==ue||!a(t.sig.slice(0,64),t.sig.slice(64,128)))return!1;try{return new e.Signature(t.sig).recoverPublicKey(N(t)).address().toHex()===t.addr}catch{return!1}}function z(e,t){let n=A.safeParse(e);if(!n.success)return{ok:!1,reason:`shape`,detail:I(n.error)};let r=n.data;if(!R(r))return{ok:!1,reason:`signature`,detail:`the signature was not made by addr over these fields`};if(!r.idb)return{ok:!0,message:r,identity:null};if(typeof t?.origin!=`string`)return{ok:!1,reason:`binding`,detail:`no origin was given to check the binding against`};let i=b(r.idb,r.addr,t);return i.ok?{ok:!0,message:r,identity:i.identity}:{ok:!1,reason:`binding`,detail:i.detail}}function B(e,t){if(e.byteLength>3072)return{ok:!1,reason:`too-large`,detail:`${e.byteLength} bytes, the cap is ${S}`};let n;try{n=de.decode(e)}catch{return{ok:!1,reason:`not-utf8`,detail:`the payload is not valid UTF-8`}}let r;try{r=JSON.parse(n)}catch{return{ok:!1,reason:`not-json`,detail:`the payload is not JSON`}}return z(r,t)}var V=`swarm-chat-own-feed-v1:`;function H(e){return`${V}${e}`}var fe=4096,pe=t.z.string().regex(/^[0-9a-f]{64}([0-9a-f]{64})?$/,`expected a 64 or 128 hex character reference`),U=t.z.number().int().nonnegative().max(2**53-1),W=t.z.strictObject({ref:pe,toSeq:U}),G=t.z.strictObject({v:t.z.literal(8),seq:U,at:U,msg:A,history:W.nullable()}),K=t.z.strictObject({seq:U,at:U,msg:A}),q=t.z.strictObject({v:t.z.literal(8),topic:t.z.string().min(1),fromSeq:U,toSeq:U,messages:t.z.array(t.z.unknown()),prev:W.nullable()}).refine(e=>e.fromSeq<=e.toSeq,{message:`fromSeq is after toSeq`,path:[`fromSeq`]}),me=new TextDecoder(`utf-8`,{fatal:!0});function J(e){let t;try{t=me.decode(e)}catch{return{ok:!1,reason:`not-utf8`,detail:`the payload is not valid UTF-8`}}try{return{ok:!0,value:JSON.parse(t)}}catch{return{ok:!1,reason:`not-json`,detail:`the payload is not JSON`}}}function Y(e){return e.issues.map(e=>`${e.path.join(`.`)||`value`}: ${e.message}`).join(`, `)}function he(e,t,n){let r=J(e);if(!r.ok)return r;let i=G.safeParse(r.value);return i.success?i.data.seq===t?i.data.msg.topic===n?{ok:!0,value:i.data}:{ok:!1,reason:`mismatch`,detail:`the message belongs to another chat`}:{ok:!1,reason:`mismatch`,detail:`seq ${i.data.seq} at index ${t}`}:{ok:!1,reason:`shape`,detail:Y(i.error)}}function ge(e,t,n){let r=J(e);if(!r.ok)return r;let i=q.safeParse(r.value);if(!i.success)return{ok:!1,reason:`shape`,detail:Y(i.error)};if(i.data.topic!==t||i.data.toSeq!==n.toSeq)return{ok:!1,reason:`mismatch`,detail:`the file is not the one its link names`};let{fromSeq:a,toSeq:o,prev:s}=i.data,c=[],l=0;for(let e of i.data.messages){let n=K.safeParse(e);n.success&&n.data.seq>=a&&n.data.seq<=o&&n.data.msg.topic===t?c.push(n.data):l++}return{ok:!0,value:{topic:t,fromSeq:a,toSeq:o,rows:c,prev:s,skipped:l}}}var _e=1,ve=2e3,ye=3e4,be=256,X=t.z.strictObject({v:t.z.literal(1),newest:t.z.number().int().min(-1).max(2**53-1),writtenAt:t.z.number().int().nonnegative().max(2**53-1)});function Z(e){if(!Number.isInteger(e)||e<=0)throw RangeError(`a note slot is a positive whole number of milliseconds, not ${e}`)}function xe(e,t){return Z(t),Math.floor(e/t)}function Se(e,t){return Z(t),(e+1)*t}function Q(e,t,n){return`${e}/note/${t}/${n}`}function $(t,n,r){return e.Identifier.fromString(Q(t,n,r))}function Ce(t,n,r,i){let a=$(t,n,r);return new e.Reference(e.Bytes.keccak256(e.Bytes.concat(a.toUint8Array(),new e.EthAddress(i).toUint8Array())))}var we=new TextEncoder,Te=new TextDecoder(`utf-8`,{fatal:!0});function Ee(e){let t={v:1,newest:e.newest,writtenAt:e.writtenAt};return we.encode(JSON.stringify(t))}function De(e){if(e.length>256)return null;try{let t=X.safeParse(JSON.parse(Te.decode(e)));return t.success?t.data:null}catch{return null}}Object.defineProperty(exports,"A",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"B",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"C",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"D",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"E",{enumerable:!0,get:function(){return se}}),Object.defineProperty(exports,"F",{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,"H",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"I",{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,"L",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"M",{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,"N",{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,"O",{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,"P",{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,"R",{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,"S",{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,"T",{enumerable:!0,get:function(){return ce}}),Object.defineProperty(exports,"V",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return Ee}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return Q}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return De}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return X}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return _e}}),Object.defineProperty(exports,"j",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"k",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return Se}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return ve}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return Ce}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return fe}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return be}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return ye}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return xe}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return he}}),Object.defineProperty(exports,"w",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"x",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return ge}}),Object.defineProperty(exports,"z",{enumerable:!0,get:function(){return o}});