payload-zitadel-plugin 0.1.5 → 0.2.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.
Files changed (74) hide show
  1. package/README.md +38 -59
  2. package/dist/components/Avatar.d.ts +3 -0
  3. package/dist/components/Avatar.d.ts.map +1 -0
  4. package/dist/components/{Avatar/index.js → Avatar.js} +13 -13
  5. package/dist/components/Avatar.js.map +1 -0
  6. package/dist/components/LoginButton.d.ts +3 -0
  7. package/dist/components/LoginButton.d.ts.map +1 -0
  8. package/dist/components/LoginButton.js +19 -0
  9. package/dist/components/LoginButton.js.map +1 -0
  10. package/dist/components/index.d.ts +2 -3
  11. package/dist/components/index.d.ts.map +1 -1
  12. package/dist/components/index.js +2 -3
  13. package/dist/components/index.js.map +1 -1
  14. package/dist/handlers/authorize.d.ts +3 -0
  15. package/dist/handlers/authorize.d.ts.map +1 -0
  16. package/dist/handlers/authorize.js +28 -0
  17. package/dist/handlers/authorize.js.map +1 -0
  18. package/dist/handlers/callback.d.ts +3 -0
  19. package/dist/handlers/callback.d.ts.map +1 -0
  20. package/dist/handlers/callback.js +50 -0
  21. package/dist/handlers/callback.js.map +1 -0
  22. package/dist/handlers/index.d.ts +3 -0
  23. package/dist/handlers/index.d.ts.map +1 -0
  24. package/dist/handlers/index.js +4 -0
  25. package/dist/handlers/index.js.map +1 -0
  26. package/dist/hooks/index.d.ts +2 -0
  27. package/dist/hooks/index.d.ts.map +1 -0
  28. package/dist/hooks/index.js +3 -0
  29. package/dist/hooks/index.js.map +1 -0
  30. package/dist/hooks/user.d.ts +6 -0
  31. package/dist/hooks/user.d.ts.map +1 -0
  32. package/dist/hooks/user.js +12 -0
  33. package/dist/hooks/user.js.map +1 -0
  34. package/dist/index.d.ts +3 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +132 -135
  37. package/dist/index.js.map +1 -1
  38. package/dist/strategy.d.ts.map +1 -1
  39. package/dist/strategy.js +27 -20
  40. package/dist/strategy.js.map +1 -1
  41. package/dist/translations.d.ts +2 -2
  42. package/dist/translations.js +4 -4
  43. package/dist/translations.js.map +1 -1
  44. package/dist/types.d.ts +14 -16
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/types.js.map +1 -1
  47. package/dist/utils/index.d.ts +2 -0
  48. package/dist/utils/index.d.ts.map +1 -0
  49. package/dist/utils/index.js +3 -0
  50. package/dist/utils/index.js.map +1 -0
  51. package/dist/utils/user.d.ts +5 -0
  52. package/dist/utils/user.d.ts.map +1 -0
  53. package/dist/utils/user.js +15 -0
  54. package/dist/utils/user.js.map +1 -0
  55. package/package.json +17 -12
  56. package/dist/components/Avatar/index.d.ts +0 -5
  57. package/dist/components/Avatar/index.d.ts.map +0 -1
  58. package/dist/components/Avatar/index.js.map +0 -1
  59. package/dist/components/LoginButton/button.d.ts +0 -6
  60. package/dist/components/LoginButton/button.d.ts.map +0 -1
  61. package/dist/components/LoginButton/button.js +0 -19
  62. package/dist/components/LoginButton/button.js.map +0 -1
  63. package/dist/components/LoginButton/index.d.ts +0 -6
  64. package/dist/components/LoginButton/index.d.ts.map +0 -1
  65. package/dist/components/LoginButton/index.js +0 -8
  66. package/dist/components/LoginButton/index.js.map +0 -1
  67. package/dist/components/Session/index.d.ts +0 -4
  68. package/dist/components/Session/index.d.ts.map +0 -1
  69. package/dist/components/Session/index.js +0 -6
  70. package/dist/components/Session/index.js.map +0 -1
  71. package/dist/options.d.ts +0 -3
  72. package/dist/options.d.ts.map +0 -1
  73. package/dist/options.js +0 -50
  74. package/dist/options.js.map +0 -1
@@ -0,0 +1,15 @@
1
+ import { getPayloadHMR } from '@payloadcms/next/utilities';
2
+ import { headers } from 'next/headers.js';
3
+ export const getCurrentUser = async ({ config })=>{
4
+ const payload = await getPayloadHMR({
5
+ config
6
+ });
7
+ const { user } = await payload.auth({
8
+ headers: headers()
9
+ });
10
+ return user ? await payload.findByID({
11
+ ...user
12
+ }) : null;
13
+ };
14
+
15
+ //# sourceMappingURL=user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/user.ts"],"sourcesContent":["import {getPayloadHMR} from '@payloadcms/next/utilities'\nimport {headers} from 'next/headers.js'\nimport {SanitizedConfig} from 'payload'\n\nexport const getCurrentUser = async ({config}: { config: Promise<SanitizedConfig> }) => {\n const payload = await getPayloadHMR({config})\n const {user} = await payload.auth({headers: headers()})\n return user ? await payload.findByID({...user}) : null\n}"],"names":["getPayloadHMR","headers","getCurrentUser","config","payload","user","auth","findByID"],"mappings":"AAAA,SAAQA,aAAa,QAAO,6BAA4B;AACxD,SAAQC,OAAO,QAAO,kBAAiB;AAGvC,OAAO,MAAMC,iBAAiB,OAAO,EAACC,MAAM,EAAuC;IAC/E,MAAMC,UAAU,MAAMJ,cAAc;QAACG;IAAM;IAC3C,MAAM,EAACE,IAAI,EAAC,GAAG,MAAMD,QAAQE,IAAI,CAAC;QAACL,SAASA;IAAS;IACrD,OAAOI,OAAO,MAAMD,QAAQG,QAAQ,CAAC;QAAC,GAAGF,IAAI;IAAA,KAAK;AACtD,EAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-zitadel-plugin",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "plugin for Payload CMS, which enables authentication via Zitadel IdP",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -36,27 +36,27 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@payloadcms/translations": "3.0.0-beta.53",
40
- "@payloadcms/ui": "3.0.0-beta.53",
39
+ "@payloadcms/next": "3.0.0-beta.59",
40
+ "@payloadcms/translations": "3.0.0-beta.59",
41
+ "@payloadcms/ui": "3.0.0-beta.59",
41
42
  "jsonwebtoken": "^9.0.2",
42
- "next": "^15.0.0-rc.0",
43
- "next-auth": "^4.24.7",
44
- "payload": "3.0.0-beta.53",
43
+ "next": "^15.0.0-canary.59",
44
+ "payload": "3.0.0-beta.59",
45
45
  "react": "rc",
46
46
  "react-dom": "rc"
47
47
  },
48
48
  "devDependencies": {
49
- "@swc/cli": "^0.3.12",
50
- "@swc/core": "^1.6.3",
49
+ "@swc/cli": "^0.4.0",
50
+ "@swc/core": "^1.6.13",
51
51
  "@types/jsonwebtoken": "^9.0.6",
52
- "@types/node": "^20.14.6",
52
+ "@types/node": "^20.14.10",
53
53
  "@types/react": "^18.3.3",
54
54
  "@types/react-dom": "^18.3.0",
55
- "rimraf": "^5.0.7",
56
- "typescript": "^5.5.1-rc"
55
+ "rimraf": "^6.0.0",
56
+ "typescript": "^5.5.3"
57
57
  },
58
58
  "engines": {
59
- "node": "^22.3.0"
59
+ "node": "^22.4.1"
60
60
  },
61
61
  "exports": {
62
62
  ".": {
@@ -64,6 +64,11 @@
64
64
  "require": "./dist/index.js",
65
65
  "types": "./dist/index.d.ts"
66
66
  },
67
+ "./hooks": {
68
+ "import": "./dist/hooks/index.js",
69
+ "require": "./dist/hooks/index.js",
70
+ "types": "./dist/hooks/index.d.ts"
71
+ },
67
72
  "./types": {
68
73
  "import": "./dist/types.js",
69
74
  "require": "./dist/types.js",
@@ -1,5 +0,0 @@
1
- import { CustomComponent } from 'payload';
2
- export declare const Avatar: CustomComponent<{
3
- active: boolean;
4
- }>;
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Avatar/index.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAC,eAAe,EAAC,MAAM,SAAS,CAAA;AAGvC,eAAO,MAAM,MAAM,EAAE,eAAe,CAAC;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAgCvD,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/components/Avatar/index.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\n// https://github.com/vercel/next.js/issues/46078\n// import Image from 'next/image.js'\nimport {useSession} from 'next-auth/react'\nimport {DefaultAccountIcon} from '@payloadcms/ui/graphics/Account/Default'\nimport {CustomComponent} from 'payload'\n\n\nexport const Avatar: CustomComponent<{ active: boolean }> = ({active}) => {\n\n const session = useSession()\n\n const imageUrl = session?.data?.user?.image\n\n return (imageUrl ?\n <>\n <style>\n {`\n .avatar {\n height: 2rem;\n width: 2rem;\n }\n \n .avatar:hover {\n filter: brightness(.8);\n }\n \n .avatar img {\n object-fit: fill;\n border-radius: 100%;\n }\n `}\n </style>\n <div className=\"avatar\">\n {/*<Image src={imageUrl} alt=\"Profile Picture\" fill/>*/}\n {<img src={imageUrl} alt=\"Profile Picture\"/>}\n </div>\n </> :\n <DefaultAccountIcon active={active}/>\n )\n}"],"names":["React","useSession","DefaultAccountIcon","Avatar","active","session","imageUrl","data","user","image","style","div","className","img","src","alt"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;AAEA,YAAYA,WAAW,QAAO;AAC9B,iDAAiD;AACjD,oCAAoC;AACpC,SAAQC,UAAU,QAAO,kBAAiB;AAC1C,SAAQC,kBAAkB,QAAO,0CAAyC;AAI1E,OAAO,MAAMC,SAA+C,CAAC,EAACC,MAAM,EAAC;IAEjE,MAAMC,UAAUJ;IAEhB,MAAMK,WAAWD,SAASE,MAAMC,MAAMC;IAEtC,OAAQH,yBACA,wDACI,oBAACI,eACI,CAAC;;;;;;;;;;;;;;wBAcE,CAAC,iBAET,oBAACC;QAAIC,WAAU;qBAEV,oBAACC;QAAIC,KAAKR;QAAUS,KAAI;yBAGjC,oBAACb;QAAmBE,QAAQA;;AAExC,EAAC"}
@@ -1,6 +0,0 @@
1
- import { CustomComponent } from 'payload';
2
- export declare const _LoginButton: CustomComponent<{
3
- internalProviderName: string;
4
- externalProviderName: string;
5
- }>;
6
- //# sourceMappingURL=button.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/LoginButton/button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAC,eAAe,EAAC,MAAM,SAAS,CAAA;AAKvC,eAAO,MAAM,YAAY,EAAE,eAAe,CAAC;IACvC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAA;CAC/B,CAUA,CAAA"}
@@ -1,19 +0,0 @@
1
- 'use client';
2
- import React from 'react';
3
- import { signIn } from 'next-auth/react';
4
- import { Button, useTranslation } from '@payloadcms/ui';
5
- export const _LoginButton = ({ internalProviderName, externalProviderName })=>{
6
- const { t } = useTranslation();
7
- return /*#__PURE__*/ React.createElement("div", {
8
- style: {
9
- display: 'flex',
10
- justifyContent: 'center'
11
- }
12
- }, /*#__PURE__*/ React.createElement(Button, {
13
- onClick: ()=>signIn(internalProviderName)
14
- }, t('zitadelPlugin:signIn', {
15
- externalProviderName
16
- })));
17
- };
18
-
19
- //# sourceMappingURL=button.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/components/LoginButton/button.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport {signIn} from 'next-auth/react'\nimport {CustomComponent} from 'payload'\nimport {NestedKeysStripped} from '@payloadcms/translations'\nimport {Button, useTranslation} from '@payloadcms/ui'\nimport {translations} from '../../translations.js'\n\nexport const _LoginButton: CustomComponent<{\n internalProviderName: string,\n externalProviderName: string\n}> = ({internalProviderName, externalProviderName}) => {\n const {t} = useTranslation<typeof translations.en, NestedKeysStripped<typeof translations.en>>()\n\n return (\n <div style={{display: 'flex', justifyContent: 'center'}}>\n <Button onClick={() => signIn(internalProviderName)}>\n {t('zitadelPlugin:signIn', {externalProviderName})}\n </Button>\n </div>\n )\n}"],"names":["React","signIn","Button","useTranslation","_LoginButton","internalProviderName","externalProviderName","t","div","style","display","justifyContent","onClick"],"rangeMappings":";;;;;;;;;;;;;;;;","mappings":"AAAA;AAEA,OAAOA,WAAW,QAAO;AACzB,SAAQC,MAAM,QAAO,kBAAiB;AAGtC,SAAQC,MAAM,EAAEC,cAAc,QAAO,iBAAgB;AAGrD,OAAO,MAAMC,eAGR,CAAC,EAACC,oBAAoB,EAAEC,oBAAoB,EAAC;IAC9C,MAAM,EAACC,CAAC,EAAC,GAAGJ;IAEZ,qBACI,oBAACK;QAAIC,OAAO;YAACC,SAAS;YAAQC,gBAAgB;QAAQ;qBAClD,oBAACT;QAAOU,SAAS,IAAMX,OAAOI;OACzBE,EAAE,wBAAwB;QAACD;IAAoB;AAIhE,EAAC"}
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- export declare const LoginButton: ({ internalProviderName, externalProviderName }: {
3
- internalProviderName: string;
4
- externalProviderName: string;
5
- }) => () => React.JSX.Element;
6
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/LoginButton/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,eAAO,MAAM,WAAW,mDAAkD;IACtE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAA;CAC/B,4BAAkH,CAAA"}
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- import { _LoginButton } from './button.js';
3
- export const LoginButton = ({ internalProviderName, externalProviderName })=>()=>/*#__PURE__*/ React.createElement(_LoginButton, {
4
- internalProviderName: internalProviderName,
5
- externalProviderName: externalProviderName
6
- });
7
-
8
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/components/LoginButton/index.tsx"],"sourcesContent":["import React from 'react'\nimport {_LoginButton} from './button.js'\n\nexport const LoginButton = ({internalProviderName, externalProviderName}: {\n internalProviderName: string,\n externalProviderName: string\n}) => () => <_LoginButton internalProviderName={internalProviderName} externalProviderName={externalProviderName}/>"],"names":["React","_LoginButton","LoginButton","internalProviderName","externalProviderName"],"rangeMappings":";;;;;","mappings":"AAAA,OAAOA,WAAW,QAAO;AACzB,SAAQC,YAAY,QAAO,cAAa;AAExC,OAAO,MAAMC,cAAc,CAAC,EAACC,oBAAoB,EAAEC,oBAAoB,EAGtE,GAAK,kBAAM,oBAACH;YAAaE,sBAAsBA;YAAsBC,sBAAsBA;WAAuB"}
@@ -1,4 +0,0 @@
1
- import * as React from 'react';
2
- import { PropsWithChildren } from 'react';
3
- export declare const Session: ({ children }: PropsWithChildren) => React.JSX.Element;
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Session/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAA;AAGvC,eAAO,MAAM,OAAO,iBAAgB,iBAAiB,sBAAkD,CAAA"}
@@ -1,6 +0,0 @@
1
- 'use client';
2
- import * as React from 'react';
3
- import { SessionProvider } from 'next-auth/react';
4
- export const Session = ({ children })=>/*#__PURE__*/ React.createElement(SessionProvider, null, children);
5
-
6
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/components/Session/index.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport {SessionProvider} from 'next-auth/react'\nimport {PropsWithChildren} from 'react'\n\n\nexport const Session = ({children}: PropsWithChildren) => <SessionProvider>{children}</SessionProvider>"],"names":["React","SessionProvider","Session","children"],"rangeMappings":";;;","mappings":"AAAA;AAEA,YAAYA,WAAW,QAAO;AAC9B,SAAQC,eAAe,QAAO,kBAAiB;AAI/C,OAAO,MAAMC,UAAU,CAAC,EAACC,QAAQ,EAAoB,iBAAK,oBAACF,uBAAiBE,UAA2B"}
package/dist/options.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import { ZitadelAuthOptionsType } from './types.js';
2
- export declare const authOptions: ZitadelAuthOptionsType;
3
- //# sourceMappingURL=options.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,YAAY,CAAA;AAEjD,eAAO,MAAM,WAAW,EAAE,sBA4CxB,CAAA"}
package/dist/options.js DELETED
@@ -1,50 +0,0 @@
1
- export const authOptions = ({ internalProviderName, issuerUrl, clientId })=>({
2
- providers: [
3
- {
4
- id: internalProviderName,
5
- name: internalProviderName,
6
- type: 'oauth',
7
- version: '2',
8
- wellKnown: issuerUrl,
9
- authorization: {
10
- params: {
11
- scope: 'openid email profile'
12
- }
13
- },
14
- idToken: true,
15
- checks: [
16
- 'pkce',
17
- 'state'
18
- ],
19
- client: {
20
- token_endpoint_auth_method: 'none'
21
- },
22
- profile: async (profile)=>({
23
- id: profile.sub,
24
- name: profile.name,
25
- firstName: profile.given_name,
26
- lastName: profile.family_name,
27
- email: profile.email,
28
- loginName: profile.preferred_username,
29
- image: profile.picture
30
- }),
31
- userinfo: {
32
- async request (context) {
33
- return await context.client.userinfo(context.tokens.access_token);
34
- }
35
- },
36
- clientId
37
- }
38
- ],
39
- callbacks: {
40
- session: async ({ session, token })=>({
41
- ...session,
42
- user: {
43
- id: token.sub,
44
- ...session.user
45
- }
46
- })
47
- }
48
- });
49
-
50
- //# sourceMappingURL=options.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/options.ts"],"sourcesContent":["import {ZitadelAuthOptionsType} from './types.js'\n\nexport const authOptions: ZitadelAuthOptionsType = ({internalProviderName, issuerUrl, clientId}) => ({\n providers: [\n {\n id: internalProviderName,\n name: internalProviderName,\n type: 'oauth',\n version: '2',\n wellKnown: issuerUrl,\n authorization: {\n params: {\n scope: 'openid email profile'\n }\n },\n idToken: true,\n checks: ['pkce', 'state'],\n client: {\n token_endpoint_auth_method: 'none'\n },\n profile: async (profile) => ({\n id: profile.sub,\n name: profile.name,\n firstName: profile.given_name,\n lastName: profile.family_name,\n email: profile.email,\n loginName: profile.preferred_username,\n image: profile.picture\n }),\n userinfo: {\n async request(context) {\n return await context.client.userinfo(context.tokens.access_token!)\n }\n },\n clientId\n }\n ],\n callbacks: {\n session: async ({session, token}) => ({\n ...session,\n user: {\n id: token.sub,\n ...session.user\n }\n })\n }\n})"],"names":["authOptions","internalProviderName","issuerUrl","clientId","providers","id","name","type","version","wellKnown","authorization","params","scope","idToken","checks","client","token_endpoint_auth_method","profile","sub","firstName","given_name","lastName","family_name","email","loginName","preferred_username","image","picture","userinfo","request","context","tokens","access_token","callbacks","session","token","user"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAEA,OAAO,MAAMA,cAAsC,CAAC,EAACC,oBAAoB,EAAEC,SAAS,EAAEC,QAAQ,EAAC,GAAM,CAAA;QACjGC,WAAW;YACP;gBACIC,IAAIJ;gBACJK,MAAML;gBACNM,MAAM;gBACNC,SAAS;gBACTC,WAAWP;gBACXQ,eAAe;oBACXC,QAAQ;wBACJC,OAAO;oBACX;gBACJ;gBACAC,SAAS;gBACTC,QAAQ;oBAAC;oBAAQ;iBAAQ;gBACzBC,QAAQ;oBACJC,4BAA4B;gBAChC;gBACAC,SAAS,OAAOA,UAAa,CAAA;wBACzBZ,IAAIY,QAAQC,GAAG;wBACfZ,MAAMW,QAAQX,IAAI;wBAClBa,WAAWF,QAAQG,UAAU;wBAC7BC,UAAUJ,QAAQK,WAAW;wBAC7BC,OAAON,QAAQM,KAAK;wBACpBC,WAAWP,QAAQQ,kBAAkB;wBACrCC,OAAOT,QAAQU,OAAO;oBAC1B,CAAA;gBACAC,UAAU;oBACN,MAAMC,SAAQC,OAAO;wBACjB,OAAO,MAAMA,QAAQf,MAAM,CAACa,QAAQ,CAACE,QAAQC,MAAM,CAACC,YAAY;oBACpE;gBACJ;gBACA7B;YACJ;SACH;QACD8B,WAAW;YACPC,SAAS,OAAO,EAACA,OAAO,EAAEC,KAAK,EAAC,GAAM,CAAA;oBAClC,GAAGD,OAAO;oBACVE,MAAM;wBACF/B,IAAI8B,MAAMjB,GAAG;wBACb,GAAGgB,QAAQE,IAAI;oBACnB;gBACJ,CAAA;QACJ;IACJ,CAAA,EAAE"}