@konemono/nostr-login 1.7.11

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 (43) hide show
  1. package/.prettierrc.json +13 -0
  2. package/README.md +167 -0
  3. package/dist/const/index.d.ts +1 -0
  4. package/dist/iife-module.d.ts +1 -0
  5. package/dist/index.d.ts +27 -0
  6. package/dist/index.esm.js +18 -0
  7. package/dist/index.esm.js.map +1 -0
  8. package/dist/modules/AuthNostrService.d.ts +84 -0
  9. package/dist/modules/BannerManager.d.ts +20 -0
  10. package/dist/modules/ModalManager.d.ts +25 -0
  11. package/dist/modules/Nip46.d.ts +56 -0
  12. package/dist/modules/Nostr.d.ts +34 -0
  13. package/dist/modules/NostrExtensionService.d.ts +17 -0
  14. package/dist/modules/NostrParams.d.ts +8 -0
  15. package/dist/modules/Popup.d.ts +7 -0
  16. package/dist/modules/ProcessManager.d.ts +10 -0
  17. package/dist/modules/Signer.d.ts +9 -0
  18. package/dist/modules/index.d.ts +8 -0
  19. package/dist/types.d.ts +72 -0
  20. package/dist/unpkg.js +17 -0
  21. package/dist/utils/index.d.ts +27 -0
  22. package/dist/utils/nip44.d.ts +9 -0
  23. package/index.html +30 -0
  24. package/package.json +28 -0
  25. package/rollup.config.js +55 -0
  26. package/src/const/index.ts +1 -0
  27. package/src/iife-module.ts +81 -0
  28. package/src/index.ts +347 -0
  29. package/src/modules/AuthNostrService.ts +756 -0
  30. package/src/modules/BannerManager.ts +146 -0
  31. package/src/modules/ModalManager.ts +635 -0
  32. package/src/modules/Nip46.ts +441 -0
  33. package/src/modules/Nostr.ts +107 -0
  34. package/src/modules/NostrExtensionService.ts +99 -0
  35. package/src/modules/NostrParams.ts +18 -0
  36. package/src/modules/Popup.ts +27 -0
  37. package/src/modules/ProcessManager.ts +67 -0
  38. package/src/modules/Signer.ts +25 -0
  39. package/src/modules/index.ts +8 -0
  40. package/src/types.ts +124 -0
  41. package/src/utils/index.ts +326 -0
  42. package/src/utils/nip44.ts +185 -0
  43. package/tsconfig.json +15 -0
@@ -0,0 +1,27 @@
1
+ import { Info, RecentType } from 'nostr-login-components';
2
+ import NDK, { NDKSigner } from '@nostr-dev-kit/ndk';
3
+ import { NostrLoginOptions } from '../types';
4
+ export declare const localStorageSetItem: (key: string, value: string) => void;
5
+ export declare const localStorageGetItem: (key: string) => any;
6
+ export declare const localStorageRemoveItem: (key: string) => void;
7
+ export declare const fetchProfile: (info: Info, profileNdk: NDK) => Promise<import("@nostr-dev-kit/ndk").NDKUserProfile | null>;
8
+ export declare const prepareSignupRelays: (signupRelays?: string) => string[];
9
+ export declare const createProfile: (info: Info, profileNdk: NDK, signer: NDKSigner, signupRelays?: string, outboxRelays?: string[]) => Promise<void>;
10
+ export declare const bunkerUrlToInfo: (bunkerUrl: string, sk?: string) => Info;
11
+ export declare const isBunkerUrl: (value: string) => boolean;
12
+ export declare const getBunkerUrl: (value: string, optionsModal: NostrLoginOptions) => Promise<string>;
13
+ export declare const checkNip05: (nip05: string) => Promise<{
14
+ available: boolean;
15
+ taken: boolean;
16
+ error: string;
17
+ pubkey: string;
18
+ }>;
19
+ export declare const localStorageAddAccount: (info: Info) => void;
20
+ export declare const localStorageRemoveCurrentAccount: () => void;
21
+ export declare const localStorageRemoveRecent: (user: RecentType) => void;
22
+ export declare const localStorageGetRecents: () => RecentType[];
23
+ export declare const localStorageGetAccounts: () => Info[];
24
+ export declare const localStorageGetCurrent: () => Info | null;
25
+ export declare const setDarkMode: (dark: boolean) => void;
26
+ export declare const getDarkMode: (opt: NostrLoginOptions) => boolean;
27
+ export declare const getIcon: () => Promise<string>;
@@ -0,0 +1,9 @@
1
+ export declare function encryptNip44(plaintext: string, conversationKey: Uint8Array, nonce?: Uint8Array): string;
2
+ export declare function decryptNip44(payload: string, conversationKey: Uint8Array): string;
3
+ export declare class Nip44 {
4
+ private cache;
5
+ createKey(privkey: string, pubkey: string): Uint8Array;
6
+ private getKey;
7
+ encrypt(privkey: string, pubkey: string, text: string): string;
8
+ decrypt(privkey: string, pubkey: string, data: string): string;
9
+ }
package/index.html ADDED
@@ -0,0 +1,30 @@
1
+ <!doctype html>
2
+ <html dir="ltr" lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" />
6
+ <title>Modal Auth Demo</title>
7
+
8
+ <script type="module">
9
+ // import { init } from './dist/index.esm.js';
10
+ //
11
+ // const test = async () => {
12
+ // const bunkerUrl = await launch({
13
+ // theme: 'purple',
14
+ // startScreen: 'signup',
15
+ // });
16
+ //
17
+ // console.log(bunkerUrl);
18
+ // };
19
+ </script>
20
+
21
+ <script src="./dist/unpkg.js" data-start-screen="local-signup"
22
+ data-signup-relays="wss://relay.nostr.band/,wss://relay.primal.net"></script>
23
+
24
+ </head>
25
+ <body>
26
+
27
+ <!--<nl-button title-btn="Sign in" start-screen="login" nl-theme="lemonade"></nl-button>-->
28
+
29
+ </body>
30
+ </html>
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@konemono/nostr-login",
3
+ "version": "1.7.11",
4
+ "description": "",
5
+ "main": "./dist/index.esm.js",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "build": "rollup -c",
10
+ "format": "npx prettier --write src"
11
+ },
12
+ "author": "a-fralou",
13
+ "dependencies": {
14
+ "@nostr-dev-kit/ndk": "^2.3.1",
15
+ "nostr-tools": "^1.17.0",
16
+ "tseep": "^1.2.1"
17
+ },
18
+ "devDependencies": {
19
+ "@rollup/plugin-commonjs": "^25.0.7",
20
+ "@rollup/plugin-node-resolve": "^15.2.3",
21
+ "@rollup/plugin-terser": "^0.4.4",
22
+ "nostr-login-components": "^1.0.3",
23
+ "prettier": "^3.2.2",
24
+ "rollup": "^4.9.6",
25
+ "rollup-plugin-typescript2": "^0.36.0"
26
+ },
27
+ "license": "MIT"
28
+ }
@@ -0,0 +1,55 @@
1
+ import commonjs from '@rollup/plugin-commonjs';
2
+ import resolve from '@rollup/plugin-node-resolve';
3
+ import typescript from 'rollup-plugin-typescript2';
4
+ import terser from '@rollup/plugin-terser';
5
+
6
+ export default [
7
+ {
8
+ input: 'src/index.ts',
9
+ output: [
10
+ {
11
+ file: 'dist/index.esm.js',
12
+ format: 'esm',
13
+ sourcemap: true,
14
+ },
15
+ ],
16
+ plugins: [
17
+ typescript({
18
+ tsconfig: 'tsconfig.json',
19
+ }),
20
+ resolve({
21
+ browser: true
22
+ }),
23
+ commonjs(),
24
+ terser({
25
+ compress: {
26
+ toplevel: true,
27
+ }
28
+ })
29
+ ],
30
+ },
31
+ {
32
+ input: 'src/iife-module.ts',
33
+ output: [
34
+ {
35
+ file: 'dist/unpkg.js',
36
+ format: 'iife',
37
+ }
38
+ ],
39
+ plugins: [
40
+ typescript({
41
+ tsconfig: 'tsconfig.json',
42
+ }),
43
+ resolve({
44
+ browser: true
45
+ }),
46
+ commonjs(),
47
+ terser({
48
+ compress: {
49
+ toplevel: true,
50
+ },
51
+ })
52
+ ],
53
+ }
54
+ ];
55
+
@@ -0,0 +1 @@
1
+ export const CALL_TIMEOUT = 5000;
@@ -0,0 +1,81 @@
1
+ import { init } from './index';
2
+ import { NostrLoginOptions, StartScreens } from './types';
3
+
4
+ // wrap to hide local vars
5
+ (() => {
6
+ // currentScript only visible in global scope code, not event handlers
7
+ const cs = document.currentScript;
8
+ const start = async () => {
9
+ const options: NostrLoginOptions = {};
10
+
11
+ if (cs) {
12
+ const dm = cs.getAttribute('data-dark-mode');
13
+ if (dm) options.darkMode = dm === 'true';
14
+
15
+ const bunkers = cs.getAttribute('data-bunkers');
16
+ if (bunkers) options.bunkers = bunkers;
17
+
18
+ const startScreen = cs.getAttribute('data-start-screen');
19
+ if (startScreen) options.startScreen = startScreen as StartScreens;
20
+
21
+ const perms = cs.getAttribute('data-perms');
22
+ if (perms) options.perms = perms;
23
+
24
+ const theme = cs.getAttribute('data-theme');
25
+ if (theme) options.theme = theme;
26
+
27
+ const noBanner = cs.getAttribute('data-no-banner');
28
+ if (noBanner) options.noBanner = noBanner === 'true';
29
+
30
+ const localSignup = cs.getAttribute('data-local-signup');
31
+ if (localSignup) options.localSignup = localSignup === 'true';
32
+
33
+ const signupNjump = cs.getAttribute('data-signup-nstart') || cs.getAttribute('data-signup-njump');
34
+ if (signupNjump) options.signupNstart = signupNjump === 'true';
35
+
36
+ const followNpubs = cs.getAttribute('data-follow-npubs');
37
+ if (followNpubs) options.followNpubs = followNpubs;
38
+
39
+ const otpRequestUrl = cs.getAttribute('data-otp-request-url');
40
+ if (otpRequestUrl) options.otpRequestUrl = otpRequestUrl;
41
+
42
+ const otpReplyUrl = cs.getAttribute('data-otp-reply-url');
43
+ if (otpReplyUrl) options.otpReplyUrl = otpReplyUrl;
44
+
45
+ if (!!otpRequestUrl !== !!otpReplyUrl) console.warn('nostr-login: need request and reply urls for OTP auth');
46
+
47
+ const methods = cs.getAttribute('data-methods');
48
+ if (methods) {
49
+ // @ts-ignore
50
+ options.methods = methods
51
+ .trim()
52
+ .split(',')
53
+ .filter(m => !!m);
54
+ }
55
+
56
+ const title = cs.getAttribute('data-title');
57
+ if (title) options.title = title;
58
+
59
+ const description = cs.getAttribute('data-description');
60
+ if (description) options.description = description;
61
+
62
+ const signupRelays = cs.getAttribute('data-signup-relays');
63
+ if (signupRelays) options.signupRelays = signupRelays;
64
+
65
+ const outboxRelays = cs.getAttribute('data-outbox-relays');
66
+ if (outboxRelays) options.outboxRelays = outboxRelays.split(',');
67
+
68
+ const dev = cs.getAttribute('data-dev') === 'true';
69
+ if (dev) options.dev = dev;
70
+
71
+ const custom = cs.getAttribute('data-custom-nostr-connect') === 'true';
72
+ if (custom) options.customNostrConnect = custom;
73
+
74
+ console.log('nostr-login options', options);
75
+ }
76
+
77
+ init(options);
78
+ };
79
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start);
80
+ else start();
81
+ })();
package/src/index.ts ADDED
@@ -0,0 +1,347 @@
1
+ import 'nostr-login-components';
2
+ import { AuthNostrService, NostrExtensionService, Popup, NostrParams, Nostr, ProcessManager, BannerManager, ModalManager } from './modules';
3
+ import { NostrLoginAuthOptions, NostrLoginOptions, StartScreens } from './types';
4
+ import { localStorageGetAccounts, localStorageGetCurrent, localStorageGetRecents, localStorageSetItem } from './utils';
5
+ import { Info } from 'nostr-login-components';
6
+ import { NostrObjectParams } from './modules/Nostr';
7
+
8
+ export class NostrLoginInitializer {
9
+ public extensionService: NostrExtensionService;
10
+ public params: NostrParams;
11
+ public authNostrService: AuthNostrService;
12
+ public nostr: Nostr;
13
+ public processManager: ProcessManager;
14
+ public popupManager: Popup;
15
+ public bannerManager: BannerManager;
16
+ public modalManager: ModalManager;
17
+
18
+ private customLaunchCallback?: () => void;
19
+
20
+ constructor() {
21
+ this.params = new NostrParams();
22
+ this.processManager = new ProcessManager();
23
+ this.popupManager = new Popup();
24
+ this.bannerManager = new BannerManager(this.params);
25
+ this.authNostrService = new AuthNostrService(this.params);
26
+ this.extensionService = new NostrExtensionService(this.params);
27
+ this.modalManager = new ModalManager(this.params, this.authNostrService, this.extensionService);
28
+
29
+ const nostrApi: NostrObjectParams = {
30
+ waitReady: async () => {
31
+ await this.authNostrService.waitReady();
32
+ await this.modalManager.waitReady();
33
+ },
34
+ getUserInfo: () => this.params.userInfo,
35
+ getSigner: () => {
36
+ if (this.params.userInfo!.authMethod === 'readOnly') throw new Error('Read only');
37
+ return this.params.userInfo!.authMethod === 'extension' ? this.extensionService.getExtension() : this.authNostrService;
38
+ },
39
+ launch: () => {
40
+ return this.launch();
41
+ },
42
+ wait: cb => this.processManager.wait(cb),
43
+ };
44
+
45
+ this.nostr = new Nostr(nostrApi);
46
+
47
+ this.processManager.on('onCallTimeout', () => {
48
+ this.bannerManager.onCallTimeout();
49
+ });
50
+
51
+ this.processManager.on('onCallEnd', () => {
52
+ this.bannerManager.onCallEnd();
53
+ this.modalManager.onCallEnd();
54
+ });
55
+
56
+ this.processManager.on('onCallStart', () => {
57
+ this.bannerManager.onCallStart();
58
+ });
59
+
60
+ this.authNostrService.on('onIframeUrl', url => {
61
+ this.modalManager.onIframeUrl(url);
62
+ });
63
+
64
+ this.authNostrService.on('iframeRestart', ({ iframeUrl }) => {
65
+ this.processManager.onIframeUrl();
66
+ this.bannerManager.onIframeRestart(iframeUrl);
67
+ });
68
+
69
+ this.authNostrService.on('onAuthUrl', ({ url, iframeUrl, eventToAddAccount }) => {
70
+ this.processManager.onAuthUrl();
71
+
72
+ if (eventToAddAccount) {
73
+ this.modalManager.onAuthUrl(url);
74
+ return;
75
+ }
76
+
77
+ if (this.params.userInfo) {
78
+ // show the 'Please confirm' banner
79
+ this.bannerManager.onAuthUrl(url, iframeUrl);
80
+ } else {
81
+ // if it fails we will either return 'failed'
82
+ // to the window.nostr caller, or show proper error
83
+ // in our modal
84
+ this.modalManager.onAuthUrl(url);
85
+ }
86
+ });
87
+
88
+ this.authNostrService.on('updateAccounts', () => {
89
+ this.updateAccounts();
90
+ });
91
+
92
+ this.authNostrService.on('onUserInfo', info => {
93
+ this.bannerManager.onUserInfo(info);
94
+ });
95
+
96
+ this.modalManager.on('onAuthUrlClick', url => {
97
+ this.openPopup(url);
98
+ });
99
+
100
+ this.bannerManager.on('onIframeAuthUrlClick', url => {
101
+ this.modalManager.showIframeUrl(url);
102
+ });
103
+
104
+ this.modalManager.on('onSwitchAccount', async (info: Info) => {
105
+ this.switchAccount(info);
106
+ });
107
+
108
+ this.modalManager.on('onLogoutBanner', async (info: Info) => {
109
+ logout();
110
+ });
111
+
112
+ this.bannerManager.on('onConfirmLogout', async () => {
113
+ // @ts-ignore
114
+ this.launch('confirm-logout');
115
+ });
116
+
117
+ this.modalManager.on('updateAccounts', () => {
118
+ this.updateAccounts();
119
+ });
120
+
121
+ this.bannerManager.on('logout', () => {
122
+ logout();
123
+ });
124
+
125
+ this.bannerManager.on('onAuthUrlClick', url => {
126
+ this.openPopup(url);
127
+ });
128
+
129
+ this.bannerManager.on('onSwitchAccount', async (info: Info) => {
130
+ this.switchAccount(info);
131
+ });
132
+
133
+ this.bannerManager.on('import', () => {
134
+ this.launch('import');
135
+ });
136
+
137
+ this.extensionService.on('extensionLogin', (pubkey: string) => {
138
+ this.authNostrService.setExtension(pubkey);
139
+ });
140
+
141
+ this.extensionService.on('extensionLogout', () => {
142
+ logout();
143
+ });
144
+
145
+ this.bannerManager.on('launch', (startScreen?: StartScreens) => {
146
+ this.launch(startScreen);
147
+ });
148
+ }
149
+
150
+ private openPopup(url: string) {
151
+ this.popupManager.openPopup(url);
152
+ }
153
+
154
+ private async switchAccount(info: Info, signup = false) {
155
+ console.log('nostr login switch to info', info);
156
+
157
+ // make sure extension is unlinked
158
+ this.extensionService.unsetExtension(this.nostr);
159
+
160
+ if (info.authMethod === 'readOnly') {
161
+ this.authNostrService.setReadOnly(info.pubkey);
162
+ } else if (info.authMethod === 'otp') {
163
+ this.authNostrService.setOTP(info.pubkey, info.otpData || '');
164
+ } else if (info.authMethod === 'local' && info.sk) {
165
+ this.authNostrService.setLocal(info, signup);
166
+ } else if (info.authMethod === 'extension') {
167
+ // trySetExtensionForPubkey will check if
168
+ // we still have the extension and it's the same pubkey
169
+ await this.extensionService.trySetExtensionForPubkey(info.pubkey);
170
+ } else if (info.authMethod === 'connect' && info.sk && info.relays && info.relays[0]) {
171
+ this.authNostrService.setConnect(info);
172
+ } else {
173
+ throw new Error('Bad auth info');
174
+ }
175
+ }
176
+
177
+ private updateAccounts() {
178
+ const accounts = localStorageGetAccounts();
179
+ const recents = localStorageGetRecents();
180
+ this.bannerManager.onUpdateAccounts(accounts);
181
+ this.modalManager.onUpdateAccounts(accounts, recents);
182
+ }
183
+
184
+ public async launchCustomNostrConnect() {
185
+ try {
186
+ if (this.authNostrService.isAuthing()) this.authNostrService.cancelNostrConnect();
187
+
188
+ const customLaunchPromise = new Promise<void>(ok => (this.customLaunchCallback = ok));
189
+ await this.authNostrService.startAuth();
190
+ await this.authNostrService.sendNeedAuth();
191
+
192
+ try {
193
+ await this.authNostrService.nostrConnect();
194
+ await this.authNostrService.endAuth();
195
+ } catch (e) {
196
+ // if client manually launches the UI we'll
197
+ // have cancelled error from the nostrConnect call,
198
+ // and that's when we should block on the customLaunchPromise
199
+ if (e === 'cancelled') await customLaunchPromise;
200
+ }
201
+ } catch (e) {
202
+ console.error('launchCustomNostrConnect', e);
203
+ }
204
+ }
205
+
206
+ private fulfillCustomLaunchPromise() {
207
+ if (this.customLaunchCallback) {
208
+ const cb = this.customLaunchCallback;
209
+ this.customLaunchCallback = undefined;
210
+ cb();
211
+ }
212
+ }
213
+
214
+ public launch = async (startScreen?: StartScreens | 'default') => {
215
+ if (!startScreen) {
216
+ if (this.params.optionsModal.customNostrConnect) {
217
+ return this.launchCustomNostrConnect();
218
+ }
219
+ }
220
+
221
+ const recent = localStorageGetRecents();
222
+ const accounts = localStorageGetAccounts();
223
+
224
+ const options = { ...this.params.optionsModal };
225
+ if (startScreen && startScreen !== 'default') options.startScreen = startScreen;
226
+ else if (Boolean(recent?.length) || Boolean(accounts?.length)) {
227
+ options.startScreen = 'switch-account';
228
+ }
229
+
230
+ // if we're being manually called in the middle of customNostrConnect
231
+ // flow then we'll reset the current auth session and launch
232
+ // our manual flow and then release the customNostrConnect session
233
+ // as if it finished properly
234
+ if (this.customLaunchCallback) this.authNostrService.cancelNostrConnect();
235
+ try {
236
+ await this.modalManager.launch(options);
237
+
238
+ // if custom launch was interrupted by manual
239
+ // launch then we unlock the custom launch to make
240
+ // it proceed
241
+ this.fulfillCustomLaunchPromise();
242
+ } catch (e) {
243
+ // don't throw if cancelled
244
+ console.log('nostr-login failed', e);
245
+ }
246
+ };
247
+
248
+ public init = async (opt: NostrLoginOptions) => {
249
+ // watch for extension trying to overwrite our window.nostr
250
+ this.extensionService.startCheckingExtension(this.nostr);
251
+
252
+ // set ourselves as nostr
253
+
254
+ // @ts-ignore
255
+ window.nostr = this.nostr;
256
+
257
+ // connect launching of our modals to nl-button elements
258
+ this.modalManager.connectModals(opt);
259
+
260
+ // launch
261
+ this.bannerManager.launchAuthBanner(opt);
262
+
263
+ // store options
264
+ if (opt) {
265
+ this.params.optionsModal = { ...opt };
266
+ }
267
+
268
+ try {
269
+ // read conf from localstore
270
+ const info = localStorageGetCurrent();
271
+
272
+ // have current session?
273
+ if (info) {
274
+ // wtf?
275
+ if (!info.pubkey) throw new Error('Bad stored info');
276
+
277
+ // switch to it
278
+ await this.switchAccount(info);
279
+ }
280
+ } catch (e) {
281
+ console.log('nostr login init error', e);
282
+
283
+ await logout();
284
+ }
285
+
286
+ // ensure current state
287
+ this.updateAccounts();
288
+ };
289
+
290
+ public logout = async () => {
291
+ // replace back
292
+ this.extensionService.unsetExtension(this.nostr);
293
+
294
+ await this.authNostrService.logout();
295
+ };
296
+
297
+ public setDarkMode = (dark: boolean) => {
298
+ localStorageSetItem('nl-dark-mode', `${dark}`);
299
+ this.bannerManager.onDarkMode(dark);
300
+ this.modalManager.onDarkMode(dark);
301
+ };
302
+
303
+ public setAuth = async (o: NostrLoginAuthOptions) => {
304
+ if (!o.type) throw new Error('Invalid auth event');
305
+ if (o.type !== 'login' && o.type !== 'logout' && o.type !== 'signup') throw new Error('Invalid auth event');
306
+ if (o.method && o.method !== 'connect' && o.method !== 'extension' && o.method !== 'local' && o.method !== 'otp' && o.method !== 'readOnly')
307
+ throw new Error('Invalid auth event');
308
+
309
+ if (o.type === 'logout') return this.logout();
310
+
311
+ if (!o.method || !o.pubkey) throw new Error('Invalid pubkey');
312
+
313
+ const info: Info = {
314
+ authMethod: o.method,
315
+ pubkey: o.pubkey,
316
+ relays: o.relays,
317
+ sk: o.localNsec,
318
+ otpData: o.otpData,
319
+ name: o.name,
320
+ };
321
+ await this.switchAccount(info, o.type === 'signup');
322
+ };
323
+
324
+ public cancelNeedAuth = () => {
325
+ console.log("cancelNeedAuth");
326
+ this.fulfillCustomLaunchPromise();
327
+ this.authNostrService.cancelNostrConnect();
328
+ };
329
+ }
330
+
331
+ const initializer = new NostrLoginInitializer();
332
+
333
+ export const { init, launch, logout, setDarkMode, setAuth, cancelNeedAuth } = initializer;
334
+
335
+ document.addEventListener('nlLogout', logout);
336
+ document.addEventListener('nlLaunch', (event: any) => {
337
+ launch(event.detail || '');
338
+ });
339
+ document.addEventListener('nlNeedAuthCancel', () => {
340
+ cancelNeedAuth();
341
+ });
342
+ document.addEventListener('nlDarkMode', (event: any) => {
343
+ setDarkMode(!!event.detail);
344
+ });
345
+ document.addEventListener('nlSetAuth', (event: any) => {
346
+ setAuth(event.detail as NostrLoginAuthOptions);
347
+ });