shogun-core 5.2.0 → 5.2.2
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.
- package/README.md +145 -1143
- package/dist/browser/defaultVendors-node_modules_hpke_chacha20poly1305_esm_mod_js.shogun-core.js +1220 -0
- package/dist/browser/defaultVendors-node_modules_hpke_chacha20poly1305_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_hpke_hybridkem-x-wing_esm_mod_js.shogun-core.js +844 -0
- package/dist/browser/defaultVendors-node_modules_hpke_hybridkem-x-wing_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_mlkem_esm_mod_js.shogun-core.js +2335 -0
- package/dist/browser/defaultVendors-node_modules_mlkem_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_ciphers_chacha_js.shogun-core.js +999 -0
- package/dist/browser/defaultVendors-node_modules_noble_ciphers_chacha_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js +1651 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_curve_js-node_modules_noble_curves_esm_-1ce4ed.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_edwards_js-node_modules_noble_curves_es-a82056.shogun-core.js +825 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_abstract_edwards_js-node_modules_noble_curves_es-a82056.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed25519_js.shogun-core.js +508 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed25519_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js +747 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_ed448_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js +1608 -0
- package/dist/browser/defaultVendors-node_modules_noble_curves_esm_nist_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_noble_post-quantum_ml-dsa_js.shogun-core.js +2117 -0
- package/dist/browser/defaultVendors-node_modules_noble_post-quantum_ml-dsa_js.shogun-core.js.map +1 -0
- package/dist/browser/defaultVendors-node_modules_openpgp_dist_openpgp_min_mjs.shogun-core.js +86 -0
- package/dist/browser/defaultVendors-node_modules_openpgp_dist_openpgp_min_mjs.shogun-core.js.map +1 -0
- package/dist/browser/node_modules_hpke_ml-kem_esm_mod_js.shogun-core.js +539 -0
- package/dist/browser/node_modules_hpke_ml-kem_esm_mod_js.shogun-core.js.map +1 -0
- package/dist/browser/shogun-core.js +160386 -0
- package/dist/browser/shogun-core.js.map +1 -0
- package/dist/config/simplified-config.js +236 -0
- package/dist/core.js +329 -0
- package/dist/crypto/asymmetric.js +99 -0
- package/dist/crypto/double-ratchet.js +370 -0
- package/dist/crypto/file-encryption.js +213 -0
- package/dist/crypto/hashing.js +87 -0
- package/dist/crypto/index.js +34 -0
- package/dist/crypto/mls-codec.js +202 -0
- package/dist/crypto/mls.js +550 -0
- package/dist/crypto/pgp.js +390 -0
- package/dist/crypto/random-generation.js +341 -0
- package/dist/crypto/sframe.js +350 -0
- package/dist/crypto/signal-protocol.js +376 -0
- package/dist/crypto/symmetric.js +91 -0
- package/dist/crypto/types.js +2 -0
- package/dist/crypto/utils.js +140 -0
- package/dist/examples/auth-test.js +253 -0
- package/dist/examples/crypto-identity-example.js +151 -0
- package/dist/examples/crypto-working-test.js +83 -0
- package/dist/examples/double-ratchet-test.js +155 -0
- package/dist/examples/mls-advanced-example.js +294 -0
- package/dist/examples/mls-sframe-test.js +304 -0
- package/dist/examples/pgp-example.js +200 -0
- package/dist/examples/quick-auth-test.js +61 -0
- package/dist/examples/random-generation-test.js +151 -0
- package/dist/examples/signal-protocol-test.js +38 -0
- package/dist/examples/simple-api-test.js +114 -0
- package/dist/examples/simple-crypto-identity-example.js +84 -0
- package/dist/examples/timeout-test.js +227 -0
- package/dist/examples/zkproof-credentials-example.js +212 -0
- package/dist/examples/zkproof-example.js +201 -0
- package/dist/gundb/api.js +435 -0
- package/dist/gundb/crypto.js +283 -0
- package/dist/gundb/db.js +1946 -0
- package/dist/gundb/derive.js +232 -0
- package/dist/gundb/errors.js +76 -0
- package/dist/gundb/index.js +22 -0
- package/dist/gundb/rxjs.js +447 -0
- package/dist/gundb/types.js +5 -0
- package/dist/index.js +58 -0
- package/dist/interfaces/common.js +2 -0
- package/dist/interfaces/events.js +40 -0
- package/dist/interfaces/plugin.js +2 -0
- package/dist/interfaces/shogun.js +37 -0
- package/dist/managers/AuthManager.js +226 -0
- package/dist/managers/CoreInitializer.js +228 -0
- package/dist/managers/CryptoIdentityManager.js +366 -0
- package/dist/managers/EventManager.js +70 -0
- package/dist/managers/PluginManager.js +299 -0
- package/dist/plugins/base.js +50 -0
- package/dist/plugins/index.js +32 -0
- package/dist/plugins/nostr/index.js +20 -0
- package/dist/plugins/nostr/nostrConnector.js +419 -0
- package/dist/plugins/nostr/nostrConnectorPlugin.js +453 -0
- package/dist/plugins/nostr/nostrSigner.js +319 -0
- package/dist/plugins/nostr/types.js +2 -0
- package/dist/plugins/smartwallet/index.js +18 -0
- package/dist/plugins/smartwallet/smartWalletPlugin.js +511 -0
- package/dist/plugins/smartwallet/types.js +2 -0
- package/dist/plugins/web3/index.js +20 -0
- package/dist/plugins/web3/types.js +2 -0
- package/dist/plugins/web3/web3Connector.js +533 -0
- package/dist/plugins/web3/web3ConnectorPlugin.js +455 -0
- package/dist/plugins/web3/web3Signer.js +314 -0
- package/dist/plugins/webauthn/index.js +19 -0
- package/dist/plugins/webauthn/types.js +14 -0
- package/dist/plugins/webauthn/webauthn.js +496 -0
- package/dist/plugins/webauthn/webauthnPlugin.js +489 -0
- package/dist/plugins/webauthn/webauthnSigner.js +310 -0
- package/dist/plugins/zkproof/index.js +53 -0
- package/dist/plugins/zkproof/types.js +2 -0
- package/dist/plugins/zkproof/zkCredentials.js +213 -0
- package/dist/plugins/zkproof/zkProofConnector.js +198 -0
- package/dist/plugins/zkproof/zkProofPlugin.js +272 -0
- package/dist/storage/storage.js +145 -0
- package/dist/types/config/simplified-config.d.ts +114 -0
- package/dist/types/core.d.ts +305 -0
- package/dist/types/crypto/asymmetric.d.ts +6 -0
- package/dist/types/crypto/double-ratchet.d.ts +22 -0
- package/dist/types/crypto/file-encryption.d.ts +19 -0
- package/dist/types/crypto/hashing.d.ts +9 -0
- package/dist/types/crypto/index.d.ts +13 -0
- package/dist/types/crypto/mls-codec.d.ts +39 -0
- package/dist/types/crypto/mls.d.ts +130 -0
- package/dist/types/crypto/pgp.d.ts +95 -0
- package/dist/types/crypto/random-generation.d.ts +35 -0
- package/dist/types/crypto/sframe.d.ts +102 -0
- package/dist/types/crypto/signal-protocol.d.ts +26 -0
- package/dist/types/crypto/symmetric.d.ts +9 -0
- package/dist/types/crypto/types.d.ts +144 -0
- package/dist/types/crypto/utils.d.ts +22 -0
- package/dist/types/examples/auth-test.d.ts +8 -0
- package/dist/types/examples/crypto-identity-example.d.ts +5 -0
- package/dist/types/examples/crypto-working-test.d.ts +1 -0
- package/dist/types/examples/double-ratchet-test.d.ts +1 -0
- package/dist/types/examples/mls-advanced-example.d.ts +53 -0
- package/dist/types/examples/mls-sframe-test.d.ts +1 -0
- package/dist/types/examples/pgp-example.d.ts +75 -0
- package/dist/types/examples/quick-auth-test.d.ts +8 -0
- package/dist/types/examples/random-generation-test.d.ts +1 -0
- package/dist/types/examples/signal-protocol-test.d.ts +1 -0
- package/dist/types/examples/simple-api-test.d.ts +10 -0
- package/dist/types/examples/simple-crypto-identity-example.d.ts +6 -0
- package/dist/types/examples/timeout-test.d.ts +8 -0
- package/dist/types/examples/zkproof-credentials-example.d.ts +12 -0
- package/dist/types/examples/zkproof-example.d.ts +11 -0
- package/dist/types/gundb/api.d.ts +185 -0
- package/dist/types/gundb/crypto.d.ts +95 -0
- package/dist/types/gundb/db.d.ts +397 -0
- package/dist/types/gundb/derive.d.ts +21 -0
- package/dist/types/gundb/errors.d.ts +42 -0
- package/dist/types/gundb/index.d.ts +3 -0
- package/dist/types/gundb/rxjs.d.ts +110 -0
- package/dist/types/gundb/types.d.ts +255 -0
- package/dist/types/index.d.ts +16 -0
- package/dist/types/interfaces/common.d.ts +85 -0
- package/dist/types/interfaces/events.d.ts +131 -0
- package/dist/types/interfaces/plugin.d.ts +162 -0
- package/dist/types/interfaces/shogun.d.ts +208 -0
- package/dist/types/managers/AuthManager.d.ts +72 -0
- package/dist/types/managers/CoreInitializer.d.ts +40 -0
- package/dist/types/managers/CryptoIdentityManager.d.ts +102 -0
- package/dist/types/managers/EventManager.d.ts +49 -0
- package/dist/types/managers/PluginManager.d.ts +145 -0
- package/dist/types/plugins/base.d.ts +35 -0
- package/dist/types/plugins/index.d.ts +18 -0
- package/dist/types/plugins/nostr/index.d.ts +4 -0
- package/dist/types/plugins/nostr/nostrConnector.d.ts +119 -0
- package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +163 -0
- package/dist/types/plugins/nostr/nostrSigner.d.ts +105 -0
- package/dist/types/plugins/nostr/types.d.ts +122 -0
- package/dist/types/plugins/smartwallet/index.d.ts +2 -0
- package/dist/types/plugins/smartwallet/smartWalletPlugin.d.ts +67 -0
- package/dist/types/plugins/smartwallet/types.d.ts +80 -0
- package/dist/types/plugins/web3/index.d.ts +4 -0
- package/dist/types/plugins/web3/types.d.ts +107 -0
- package/dist/types/plugins/web3/web3Connector.d.ts +129 -0
- package/dist/types/plugins/web3/web3ConnectorPlugin.d.ts +160 -0
- package/dist/types/plugins/web3/web3Signer.d.ts +114 -0
- package/dist/types/plugins/webauthn/index.d.ts +3 -0
- package/dist/types/plugins/webauthn/types.d.ts +183 -0
- package/dist/types/plugins/webauthn/webauthn.d.ts +129 -0
- package/dist/types/plugins/webauthn/webauthnPlugin.d.ts +179 -0
- package/dist/types/plugins/webauthn/webauthnSigner.d.ts +91 -0
- package/dist/types/plugins/zkproof/index.d.ts +48 -0
- package/dist/types/plugins/zkproof/types.d.ts +123 -0
- package/dist/types/plugins/zkproof/zkCredentials.d.ts +112 -0
- package/dist/types/plugins/zkproof/zkProofConnector.d.ts +46 -0
- package/dist/types/plugins/zkproof/zkProofPlugin.d.ts +76 -0
- package/dist/types/storage/storage.d.ts +51 -0
- package/dist/types/utils/errorHandler.d.ts +119 -0
- package/dist/types/utils/eventEmitter.d.ts +39 -0
- package/dist/types/utils/seedPhrase.d.ts +50 -0
- package/dist/types/utils/validation.d.ts +27 -0
- package/dist/utils/errorHandler.js +246 -0
- package/dist/utils/eventEmitter.js +79 -0
- package/dist/utils/seedPhrase.js +97 -0
- package/dist/utils/validation.js +81 -0
- package/package.json +10 -57
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simplified configuration options to reduce complexity
|
|
3
|
+
* Provides sensible defaults and easy-to-use presets
|
|
4
|
+
*/
|
|
5
|
+
import { ShogunCoreConfig } from "../interfaces/shogun";
|
|
6
|
+
/**
|
|
7
|
+
* Preset configurations for common use cases
|
|
8
|
+
*/
|
|
9
|
+
export declare const ShogunPresets: {
|
|
10
|
+
/**
|
|
11
|
+
* Minimal configuration for simple apps
|
|
12
|
+
*/
|
|
13
|
+
minimal: () => ShogunCoreConfig;
|
|
14
|
+
/**
|
|
15
|
+
* Development configuration with local storage
|
|
16
|
+
*/
|
|
17
|
+
development: () => ShogunCoreConfig;
|
|
18
|
+
/**
|
|
19
|
+
* Production configuration with multiple peers
|
|
20
|
+
*/
|
|
21
|
+
production: (customPeers?: string[]) => ShogunCoreConfig;
|
|
22
|
+
/**
|
|
23
|
+
* Offline-first configuration
|
|
24
|
+
*/
|
|
25
|
+
offline: () => ShogunCoreConfig;
|
|
26
|
+
/**
|
|
27
|
+
* Web3-enabled configuration
|
|
28
|
+
*/
|
|
29
|
+
web3: () => ShogunCoreConfig;
|
|
30
|
+
/**
|
|
31
|
+
* WebAuthn-enabled configuration
|
|
32
|
+
*/
|
|
33
|
+
webauthn: () => ShogunCoreConfig;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Configuration builder for custom setups
|
|
37
|
+
*/
|
|
38
|
+
export declare class ShogunConfigBuilder {
|
|
39
|
+
private config;
|
|
40
|
+
/**
|
|
41
|
+
* Set Gun options
|
|
42
|
+
*/
|
|
43
|
+
gunOptions(options: any): this;
|
|
44
|
+
/**
|
|
45
|
+
* Add peers
|
|
46
|
+
*/
|
|
47
|
+
peers(peerList: string[]): this;
|
|
48
|
+
/**
|
|
49
|
+
* Enable WebAuthn
|
|
50
|
+
*/
|
|
51
|
+
enableWebAuthn(rpName?: string, rpId?: string): this;
|
|
52
|
+
/**
|
|
53
|
+
* Enable Web3
|
|
54
|
+
*/
|
|
55
|
+
enableWeb3(): this;
|
|
56
|
+
/**
|
|
57
|
+
* Enable Nostr
|
|
58
|
+
*/
|
|
59
|
+
enableNostr(): this;
|
|
60
|
+
/**
|
|
61
|
+
* Set timeouts
|
|
62
|
+
*/
|
|
63
|
+
timeouts(timeouts: {
|
|
64
|
+
login?: number;
|
|
65
|
+
signup?: number;
|
|
66
|
+
operation?: number;
|
|
67
|
+
}): this;
|
|
68
|
+
/**
|
|
69
|
+
* Build the final configuration
|
|
70
|
+
*/
|
|
71
|
+
build(): ShogunCoreConfig;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Helper functions for common configuration patterns
|
|
75
|
+
*/
|
|
76
|
+
export declare const ConfigHelpers: {
|
|
77
|
+
/**
|
|
78
|
+
* Create a configuration for a specific environment
|
|
79
|
+
*/
|
|
80
|
+
forEnvironment(env: "development" | "production" | "test"): ShogunCoreConfig;
|
|
81
|
+
/**
|
|
82
|
+
* Create a configuration with custom peers
|
|
83
|
+
*/
|
|
84
|
+
withPeers(peers: string[]): ShogunCoreConfig;
|
|
85
|
+
/**
|
|
86
|
+
* Create a configuration for a specific use case
|
|
87
|
+
*/
|
|
88
|
+
forUseCase(useCase: "chat" | "social" | "gaming" | "finance"): ShogunCoreConfig;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Quick configuration functions
|
|
92
|
+
*/
|
|
93
|
+
export declare const QuickConfig: {
|
|
94
|
+
/**
|
|
95
|
+
* Minimal setup for quick testing
|
|
96
|
+
*/
|
|
97
|
+
test: () => ShogunCoreConfig;
|
|
98
|
+
/**
|
|
99
|
+
* Standard setup for most apps
|
|
100
|
+
*/
|
|
101
|
+
standard: () => ShogunCoreConfig;
|
|
102
|
+
/**
|
|
103
|
+
* Setup with WebAuthn for secure apps
|
|
104
|
+
*/
|
|
105
|
+
secure: () => ShogunCoreConfig;
|
|
106
|
+
/**
|
|
107
|
+
* Setup with Web3 for crypto apps
|
|
108
|
+
*/
|
|
109
|
+
crypto: () => ShogunCoreConfig;
|
|
110
|
+
/**
|
|
111
|
+
* Offline setup for local development
|
|
112
|
+
*/
|
|
113
|
+
local: () => ShogunCoreConfig;
|
|
114
|
+
};
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { ShogunEventMap } from "./interfaces/events";
|
|
2
|
+
import { ShogunError } from "./utils/errorHandler";
|
|
3
|
+
import { ShogunStorage } from "./storage/storage";
|
|
4
|
+
import { IShogunCore, ShogunCoreConfig, AuthResult, SignUpResult, PluginCategory, AuthMethod, Wallets } from "./interfaces/shogun";
|
|
5
|
+
import { ethers } from "ethers";
|
|
6
|
+
import { ShogunPlugin } from "./interfaces/plugin";
|
|
7
|
+
import { ISEAPair, IGunInstance, IGunUserInstance } from "gun";
|
|
8
|
+
import { DataBase, RxJS } from "./gundb";
|
|
9
|
+
import { PluginManager } from "./managers/PluginManager";
|
|
10
|
+
/**
|
|
11
|
+
* Main ShogunCore class - implements the IShogunCore interface
|
|
12
|
+
*
|
|
13
|
+
* This is the primary entry point for the Shogun SDK, providing access to:
|
|
14
|
+
* - Decentralized database (GunInstance)
|
|
15
|
+
* - Authentication methods (traditional, WebAuthn, MetaMask)
|
|
16
|
+
* - Plugin system for extensibility
|
|
17
|
+
* - RxJS integration for reactive programming
|
|
18
|
+
*
|
|
19
|
+
* @since 2.0.0
|
|
20
|
+
*/
|
|
21
|
+
export declare class ShogunCore implements IShogunCore {
|
|
22
|
+
static readonly API_VERSION = "^4.0.7";
|
|
23
|
+
db: DataBase;
|
|
24
|
+
storage: ShogunStorage;
|
|
25
|
+
provider?: ethers.Provider;
|
|
26
|
+
config: ShogunCoreConfig;
|
|
27
|
+
rx: RxJS;
|
|
28
|
+
_gun: IGunInstance<any>;
|
|
29
|
+
_user: IGunUserInstance | null;
|
|
30
|
+
wallets: Wallets | undefined;
|
|
31
|
+
pluginManager: PluginManager;
|
|
32
|
+
private authManager;
|
|
33
|
+
private eventManager;
|
|
34
|
+
private coreInitializer;
|
|
35
|
+
/**
|
|
36
|
+
* Initialize the Shogun SDK
|
|
37
|
+
* @param config - SDK Configuration object
|
|
38
|
+
* @description Creates a new instance of ShogunCore with the provided configuration.
|
|
39
|
+
* Initializes all required components including storage, event emitter, GunInstance connection,
|
|
40
|
+
* and plugin system.
|
|
41
|
+
*/
|
|
42
|
+
constructor(config: ShogunCoreConfig);
|
|
43
|
+
/**
|
|
44
|
+
* Access to the Gun instance
|
|
45
|
+
* @returns The Gun instance
|
|
46
|
+
*/
|
|
47
|
+
get gun(): IGunInstance<any>;
|
|
48
|
+
/**
|
|
49
|
+
* Access to the current user
|
|
50
|
+
* @returns The current Gun user instance
|
|
51
|
+
*/
|
|
52
|
+
get user(): IGunUserInstance | null;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the current user information
|
|
55
|
+
* @returns Current user object or null
|
|
56
|
+
*/
|
|
57
|
+
getCurrentUser(): {
|
|
58
|
+
pub: string;
|
|
59
|
+
user?: any;
|
|
60
|
+
} | null;
|
|
61
|
+
/**
|
|
62
|
+
* Registers a plugin with the Shogun SDK
|
|
63
|
+
* @param plugin Plugin instance to register
|
|
64
|
+
* @throws Error if a plugin with the same name is already registered
|
|
65
|
+
*/
|
|
66
|
+
register(plugin: ShogunPlugin): void;
|
|
67
|
+
/**
|
|
68
|
+
* Unregisters a plugin from the Shogun SDK
|
|
69
|
+
* @param pluginName Name of the plugin to unregister
|
|
70
|
+
*/
|
|
71
|
+
unregister(pluginName: string): void;
|
|
72
|
+
/**
|
|
73
|
+
* Retrieve a registered plugin by name
|
|
74
|
+
* @param name Name of the plugin
|
|
75
|
+
* @returns The requested plugin or undefined if not found
|
|
76
|
+
* @template T Type of the plugin or its public interface
|
|
77
|
+
*/
|
|
78
|
+
getPlugin<T = ShogunPlugin>(name: string): T | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Get information about all registered plugins
|
|
81
|
+
* @returns Array of plugin information objects
|
|
82
|
+
*/
|
|
83
|
+
getPluginsInfo(): Array<{
|
|
84
|
+
name: string;
|
|
85
|
+
version: string;
|
|
86
|
+
category?: PluginCategory;
|
|
87
|
+
description?: string;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Get the total number of registered plugins
|
|
91
|
+
* @returns Number of registered plugins
|
|
92
|
+
*/
|
|
93
|
+
getPluginCount(): number;
|
|
94
|
+
/**
|
|
95
|
+
* Check if all plugins are properly initialized
|
|
96
|
+
* @returns Object with initialization status for each plugin
|
|
97
|
+
*/
|
|
98
|
+
getPluginsInitializationStatus(): Record<string, {
|
|
99
|
+
initialized: boolean;
|
|
100
|
+
error?: string;
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Validate plugin system integrity
|
|
104
|
+
* @returns Object with validation results
|
|
105
|
+
*/
|
|
106
|
+
validatePluginSystem(): {
|
|
107
|
+
totalPlugins: number;
|
|
108
|
+
initializedPlugins: number;
|
|
109
|
+
failedPlugins: string[];
|
|
110
|
+
warnings: string[];
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Attempt to reinitialize failed plugins
|
|
114
|
+
* @returns Object with reinitialization results
|
|
115
|
+
*/
|
|
116
|
+
reinitializeFailedPlugins(): {
|
|
117
|
+
success: string[];
|
|
118
|
+
failed: Array<{
|
|
119
|
+
name: string;
|
|
120
|
+
error: string;
|
|
121
|
+
}>;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Check plugin compatibility with current ShogunCore version
|
|
125
|
+
* @returns Object with compatibility information
|
|
126
|
+
*/
|
|
127
|
+
checkPluginCompatibility(): {
|
|
128
|
+
compatible: Array<{
|
|
129
|
+
name: string;
|
|
130
|
+
version: string;
|
|
131
|
+
}>;
|
|
132
|
+
incompatible: Array<{
|
|
133
|
+
name: string;
|
|
134
|
+
version: string;
|
|
135
|
+
reason: string;
|
|
136
|
+
}>;
|
|
137
|
+
unknown: Array<{
|
|
138
|
+
name: string;
|
|
139
|
+
version: string;
|
|
140
|
+
}>;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Get comprehensive debug information about the plugin system
|
|
144
|
+
* @returns Complete plugin system debug information
|
|
145
|
+
*/
|
|
146
|
+
getPluginSystemDebugInfo(): {
|
|
147
|
+
shogunCoreVersion: string;
|
|
148
|
+
totalPlugins: number;
|
|
149
|
+
plugins: Array<{
|
|
150
|
+
name: string;
|
|
151
|
+
version: string;
|
|
152
|
+
category?: PluginCategory;
|
|
153
|
+
description?: string;
|
|
154
|
+
initialized: boolean;
|
|
155
|
+
error?: string;
|
|
156
|
+
}>;
|
|
157
|
+
initializationStatus: Record<string, {
|
|
158
|
+
initialized: boolean;
|
|
159
|
+
error?: string;
|
|
160
|
+
}>;
|
|
161
|
+
validation: {
|
|
162
|
+
totalPlugins: number;
|
|
163
|
+
initializedPlugins: number;
|
|
164
|
+
failedPlugins: string[];
|
|
165
|
+
warnings: string[];
|
|
166
|
+
};
|
|
167
|
+
compatibility: {
|
|
168
|
+
compatible: Array<{
|
|
169
|
+
name: string;
|
|
170
|
+
version: string;
|
|
171
|
+
}>;
|
|
172
|
+
incompatible: Array<{
|
|
173
|
+
name: string;
|
|
174
|
+
version: string;
|
|
175
|
+
reason: string;
|
|
176
|
+
}>;
|
|
177
|
+
unknown: Array<{
|
|
178
|
+
name: string;
|
|
179
|
+
version: string;
|
|
180
|
+
}>;
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* Check if a plugin is registered
|
|
185
|
+
* @param name Name of the plugin to check
|
|
186
|
+
* @returns true if the plugin is registered, false otherwise
|
|
187
|
+
*/
|
|
188
|
+
hasPlugin(name: string): boolean;
|
|
189
|
+
/**
|
|
190
|
+
* Get all plugins of a specific category
|
|
191
|
+
* @param category Category of plugins to filter
|
|
192
|
+
* @returns Array of plugins in the specified category
|
|
193
|
+
*/
|
|
194
|
+
getPluginsByCategory(category: PluginCategory): ShogunPlugin[];
|
|
195
|
+
/**
|
|
196
|
+
* Get an authentication method plugin by type
|
|
197
|
+
* @param type The type of authentication method
|
|
198
|
+
* @returns The authentication plugin or undefined if not available
|
|
199
|
+
* This is a more modern approach to accessing authentication methods
|
|
200
|
+
*/
|
|
201
|
+
getAuthenticationMethod(type: AuthMethod): ShogunPlugin | {
|
|
202
|
+
login: (username: string, password: string) => Promise<AuthResult>;
|
|
203
|
+
signUp: (username: string, password: string, confirm?: string) => Promise<SignUpResult>;
|
|
204
|
+
} | undefined;
|
|
205
|
+
/**
|
|
206
|
+
* Retrieve recent errors logged by the system
|
|
207
|
+
* @param count - Number of errors to retrieve (default: 10)
|
|
208
|
+
* @returns List of most recent errors
|
|
209
|
+
*/
|
|
210
|
+
getRecentErrors(count?: number): ShogunError[];
|
|
211
|
+
/**
|
|
212
|
+
* Check if user is logged in
|
|
213
|
+
* @returns {boolean} True if user is logged in, false otherwise
|
|
214
|
+
* @description Verifies authentication status by checking GunInstance login state
|
|
215
|
+
* and presence of authentication credentials in storage
|
|
216
|
+
*/
|
|
217
|
+
isLoggedIn(): boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Perform user logout
|
|
220
|
+
* @description Logs out the current user from GunInstance and emits logout event.
|
|
221
|
+
* If user is not authenticated, the logout operation is ignored.
|
|
222
|
+
*/
|
|
223
|
+
logout(): void;
|
|
224
|
+
/**
|
|
225
|
+
* Authenticate user with username and password
|
|
226
|
+
* @param username - Username
|
|
227
|
+
* @param password - User password
|
|
228
|
+
* @returns {Promise<AuthResult>} Promise with authentication result
|
|
229
|
+
* @description Attempts to log in user with provided credentials.
|
|
230
|
+
* Emits login event on success.
|
|
231
|
+
*/
|
|
232
|
+
login(username: string, password: string, pair?: ISEAPair | null): Promise<AuthResult>;
|
|
233
|
+
/**
|
|
234
|
+
* Login with GunDB pair directly
|
|
235
|
+
* @param pair - GunDB SEA pair for authentication
|
|
236
|
+
* @returns {Promise<AuthResult>} Promise with authentication result
|
|
237
|
+
* @description Authenticates user using a GunDB pair directly.
|
|
238
|
+
* Emits login event on success.
|
|
239
|
+
*/
|
|
240
|
+
loginWithPair(username: string, pair: ISEAPair): Promise<AuthResult>;
|
|
241
|
+
/**
|
|
242
|
+
* Register a new user with provided credentials
|
|
243
|
+
* @param username - Username
|
|
244
|
+
* @param password - Password
|
|
245
|
+
* @param email - Email (optional)
|
|
246
|
+
* @param pair - Pair of keys
|
|
247
|
+
* @returns {Promise<SignUpResult>} Registration result
|
|
248
|
+
* @description Creates a new user account with the provided credentials.
|
|
249
|
+
* Validates password requirements and emits signup event on success.
|
|
250
|
+
*/
|
|
251
|
+
signUp(username: string, password?: string, pair?: ISEAPair | null): Promise<SignUpResult>;
|
|
252
|
+
/**
|
|
253
|
+
* Emits an event through the core's event emitter.
|
|
254
|
+
* Plugins should use this method to emit events instead of accessing the private eventEmitter directly.
|
|
255
|
+
* @param eventName The name of the event to emit.
|
|
256
|
+
* @param data The data to pass with the event.
|
|
257
|
+
* @returns {boolean} Indicates if the event had listeners.
|
|
258
|
+
*/
|
|
259
|
+
emit<K extends keyof ShogunEventMap>(eventName: K, data?: ShogunEventMap[K] extends void ? never : ShogunEventMap[K]): boolean;
|
|
260
|
+
/**
|
|
261
|
+
* Add an event listener
|
|
262
|
+
* @param eventName The name of the event to listen for
|
|
263
|
+
* @param listener The callback function to execute when the event is emitted
|
|
264
|
+
* @returns {this} Returns this instance for method chaining
|
|
265
|
+
*/
|
|
266
|
+
on<K extends keyof ShogunEventMap>(eventName: K, listener: ShogunEventMap[K] extends void ? () => void : (data: ShogunEventMap[K]) => void): this;
|
|
267
|
+
/**
|
|
268
|
+
* Add a one-time event listener
|
|
269
|
+
* @param eventName The name of the event to listen for
|
|
270
|
+
* @param listener The callback function to execute when the event is emitted
|
|
271
|
+
* @returns {this} Returns this instance for method chaining
|
|
272
|
+
*/
|
|
273
|
+
once<K extends keyof ShogunEventMap>(eventName: K, listener: ShogunEventMap[K] extends void ? () => void : (data: ShogunEventMap[K]) => void): this;
|
|
274
|
+
/**
|
|
275
|
+
* Remove an event listener
|
|
276
|
+
* @param eventName The name of the event to stop listening for
|
|
277
|
+
* @param listener The callback function to remove
|
|
278
|
+
* @returns {this} Returns this instance for method chaining
|
|
279
|
+
*/
|
|
280
|
+
off<K extends keyof ShogunEventMap>(eventName: K, listener: ShogunEventMap[K] extends void ? () => void : (data: ShogunEventMap[K]) => void): this;
|
|
281
|
+
/**
|
|
282
|
+
* Remove all listeners for a specific event or all events
|
|
283
|
+
* @param eventName Optional. The name of the event to remove listeners for.
|
|
284
|
+
* If not provided, all listeners for all events are removed.
|
|
285
|
+
* @returns {this} Returns this instance for method chaining
|
|
286
|
+
*/
|
|
287
|
+
removeAllListeners(eventName?: string | symbol): this;
|
|
288
|
+
/**
|
|
289
|
+
* Set the current authentication method
|
|
290
|
+
* This is used by plugins to indicate which authentication method was used
|
|
291
|
+
* @param method The authentication method used
|
|
292
|
+
*/
|
|
293
|
+
setAuthMethod(method: AuthMethod): void;
|
|
294
|
+
/**
|
|
295
|
+
* Get the current authentication method
|
|
296
|
+
* @returns The current authentication method or undefined if not set
|
|
297
|
+
*/
|
|
298
|
+
getAuthMethod(): AuthMethod | undefined;
|
|
299
|
+
/**
|
|
300
|
+
* Saves the current user credentials to storage
|
|
301
|
+
*/
|
|
302
|
+
saveCredentials(credentials: any): Promise<void>;
|
|
303
|
+
getIsLoggedIn(): boolean;
|
|
304
|
+
}
|
|
305
|
+
export default ShogunCore;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { JWKKeyPair } from "./types";
|
|
2
|
+
export declare const generateKeyPair: () => Promise<JWKKeyPair>;
|
|
3
|
+
export declare const deserializePublicKey: (key: JsonWebKey | string) => Promise<CryptoKey>;
|
|
4
|
+
export declare const deserializePrivateKey: (key: JsonWebKey | string) => Promise<CryptoKey>;
|
|
5
|
+
export declare const encrypt: (message: string, publicKey: CryptoKey) => Promise<string>;
|
|
6
|
+
export declare const decrypt: (encryptedMessage: string, privateKey: CryptoKey) => Promise<string>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DoubleRatchetState, MessageEnvelope } from "./types";
|
|
2
|
+
export declare const initializeDoubleRatchet: (sharedSecret: ArrayBuffer, isInitiator: boolean, remotePublicKey?: CryptoKey | null) => Promise<DoubleRatchetState>;
|
|
3
|
+
export declare const doubleRatchetEncrypt: (state: DoubleRatchetState, plaintext: string) => Promise<MessageEnvelope>;
|
|
4
|
+
export declare const doubleRatchetDecrypt: (state: DoubleRatchetState, messageEnvelope: MessageEnvelope) => Promise<string>;
|
|
5
|
+
export declare const serializeDoubleRatchetState: (state: DoubleRatchetState) => Promise<string>;
|
|
6
|
+
export declare const cleanupSkippedMessageKeys: (state: DoubleRatchetState, maxAge?: number) => void;
|
|
7
|
+
export declare const demonstrateDoubleRatchet: () => Promise<{
|
|
8
|
+
success: boolean;
|
|
9
|
+
aliceState: string;
|
|
10
|
+
bobState: string;
|
|
11
|
+
conversation: {
|
|
12
|
+
from: string;
|
|
13
|
+
envelope: MessageEnvelope;
|
|
14
|
+
}[];
|
|
15
|
+
messagesExchanged: number;
|
|
16
|
+
demonstration: {
|
|
17
|
+
forwardSecrecy: boolean;
|
|
18
|
+
outOfOrderHandling: boolean;
|
|
19
|
+
dhRatcheting: boolean;
|
|
20
|
+
chainKeyUpdating: boolean;
|
|
21
|
+
};
|
|
22
|
+
}>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EncryptedFilePackage, DecryptedFileResult } from "./types";
|
|
2
|
+
export declare const encryptFile: (fileContent: string | ArrayBuffer | File, password: string, fileName?: string) => Promise<EncryptedFilePackage>;
|
|
3
|
+
export declare const decryptFile: (encryptedPackage: EncryptedFilePackage, password: string) => Promise<DecryptedFileResult>;
|
|
4
|
+
export declare const encryptTextFile: (textContent: string, password: string, fileName?: string) => Promise<EncryptedFilePackage>;
|
|
5
|
+
export declare const decryptTextFile: (encryptedPackage: EncryptedFilePackage, password: string) => Promise<DecryptedFileResult & {
|
|
6
|
+
textContent: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const encryptBinaryFile: (file: File, password: string) => Promise<EncryptedFilePackage>;
|
|
9
|
+
export declare const decryptBinaryFile: (encryptedPackage: EncryptedFilePackage, password: string) => Promise<DecryptedFileResult & {
|
|
10
|
+
blob: Blob;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const createSecureFileDownload: (data: ArrayBuffer | string | Blob, fileName: string, mimeType?: string) => void;
|
|
13
|
+
export declare const parseEncryptedFilePackage: (file: File) => Promise<{
|
|
14
|
+
isValid: boolean;
|
|
15
|
+
package?: EncryptedFilePackage;
|
|
16
|
+
metadata?: any;
|
|
17
|
+
error?: string;
|
|
18
|
+
}>;
|
|
19
|
+
export declare const decryptUploadedFile: (encryptedFilePackage: File, password: string) => Promise<DecryptedFileResult>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const randomString: (additionalSalt?: string) => string;
|
|
2
|
+
export declare const sha256Hash: (input: any) => Promise<string>;
|
|
3
|
+
export declare const sha512Hash: (input: any) => Promise<string>;
|
|
4
|
+
export declare const sha3_512Hash: (input: any) => Promise<string>;
|
|
5
|
+
export declare const bufferToHex: (buffer: ArrayBuffer) => string;
|
|
6
|
+
export declare const hexToBuffer: (hex: string) => ArrayBuffer;
|
|
7
|
+
export declare const concatArrayBuffers: (...buffers: ArrayBuffer[]) => ArrayBuffer;
|
|
8
|
+
export declare const base64ToArrayBuffer: (base64: string) => ArrayBuffer;
|
|
9
|
+
export declare const arrayBufferToBase64: (buffer: ArrayBuffer) => string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from "./symmetric";
|
|
2
|
+
export * from "./asymmetric";
|
|
3
|
+
export * from "./hashing";
|
|
4
|
+
export * from "./file-encryption";
|
|
5
|
+
export * from "./signal-protocol";
|
|
6
|
+
export * from "./double-ratchet";
|
|
7
|
+
export * from "./random-generation";
|
|
8
|
+
export * from "./mls";
|
|
9
|
+
export * from "./mls-codec";
|
|
10
|
+
export * from "./sframe";
|
|
11
|
+
export * from "./pgp";
|
|
12
|
+
export * from "./types";
|
|
13
|
+
export * from "./utils";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MLS Message encoding/decoding utilities
|
|
3
|
+
*
|
|
4
|
+
* Since ts-mls doesn't export encode/decode functions from the main package,
|
|
5
|
+
* we'll use JSON serialization with Uint8Array and BigInt conversion for transmission.
|
|
6
|
+
* This works for KeyPackage, Welcome, Commit, and other MLS messages.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Encode a KeyPackage to JSON string for transmission
|
|
10
|
+
*/
|
|
11
|
+
export declare function encodeKeyPackage(keyPackage: any): string;
|
|
12
|
+
/**
|
|
13
|
+
* Decode JSON string back to a KeyPackage object
|
|
14
|
+
*/
|
|
15
|
+
export declare function decodeKeyPackage(encoded: string): any;
|
|
16
|
+
/**
|
|
17
|
+
* Encode a Welcome message to JSON string for transmission
|
|
18
|
+
*/
|
|
19
|
+
export declare function encodeWelcome(welcome: any): string;
|
|
20
|
+
/**
|
|
21
|
+
* Decode JSON string back to a Welcome object
|
|
22
|
+
*/
|
|
23
|
+
export declare function decodeWelcome(encoded: string): any;
|
|
24
|
+
/**
|
|
25
|
+
* Encode a Commit message to JSON string for transmission
|
|
26
|
+
*/
|
|
27
|
+
export declare function encodeCommit(commit: any): string;
|
|
28
|
+
/**
|
|
29
|
+
* Decode JSON string back to a Commit object
|
|
30
|
+
*/
|
|
31
|
+
export declare function decodeCommit(encoded: string): any;
|
|
32
|
+
/**
|
|
33
|
+
* Encode a RatchetTree to JSON string for transmission
|
|
34
|
+
*/
|
|
35
|
+
export declare function encodeRatchetTree(ratchetTree: any): string;
|
|
36
|
+
/**
|
|
37
|
+
* Decode JSON string back to a RatchetTree
|
|
38
|
+
*/
|
|
39
|
+
export declare function decodeRatchetTree(encoded: string): any;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MLS (Message Layer Security) Manager
|
|
3
|
+
* RFC 9420 implementation using ts-mls library
|
|
4
|
+
* Provides end-to-end encrypted group messaging with forward secrecy
|
|
5
|
+
*/
|
|
6
|
+
import { type PrivateKeyPackage, type KeyPackage, type Welcome } from "ts-mls";
|
|
7
|
+
export interface MLSGroupInfo {
|
|
8
|
+
groupId: Uint8Array;
|
|
9
|
+
members: string[];
|
|
10
|
+
epoch: bigint;
|
|
11
|
+
}
|
|
12
|
+
export interface MLSMessageEnvelope {
|
|
13
|
+
groupId: Uint8Array;
|
|
14
|
+
ciphertext: Uint8Array;
|
|
15
|
+
timestamp: number;
|
|
16
|
+
}
|
|
17
|
+
export interface MLSKeyPackageBundle {
|
|
18
|
+
publicPackage: KeyPackage;
|
|
19
|
+
privatePackage: PrivateKeyPackage;
|
|
20
|
+
userId: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* MLSManager wraps the ts-mls functional API with a class-based interface
|
|
24
|
+
* for easier state management in applications
|
|
25
|
+
*/
|
|
26
|
+
export declare class MLSManager {
|
|
27
|
+
private userId;
|
|
28
|
+
private cipherSuite;
|
|
29
|
+
private initialized;
|
|
30
|
+
private groups;
|
|
31
|
+
private keyPackage;
|
|
32
|
+
private credential;
|
|
33
|
+
constructor(userId: string);
|
|
34
|
+
/**
|
|
35
|
+
* Initialize the MLS client with a ciphersuite
|
|
36
|
+
*/
|
|
37
|
+
initialize(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Generate a new key package for joining groups
|
|
40
|
+
*/
|
|
41
|
+
generateKeyPackage(): Promise<MLSKeyPackageBundle>;
|
|
42
|
+
/**
|
|
43
|
+
* Get the current key package
|
|
44
|
+
*/
|
|
45
|
+
getKeyPackage(): MLSKeyPackageBundle | null;
|
|
46
|
+
/**
|
|
47
|
+
* Create a new MLS group
|
|
48
|
+
*/
|
|
49
|
+
createGroup(groupId: string): Promise<MLSGroupInfo>;
|
|
50
|
+
/**
|
|
51
|
+
* Add members to an existing group
|
|
52
|
+
*/
|
|
53
|
+
addMembers(groupId: string, keyPackages: MLSKeyPackageBundle[]): Promise<{
|
|
54
|
+
welcome: Welcome;
|
|
55
|
+
ratchetTree: any;
|
|
56
|
+
commit: any;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Process a Welcome message to join an MLS group
|
|
60
|
+
*
|
|
61
|
+
* RFC 9420 Compliance:
|
|
62
|
+
* - Interior null nodes represent blank parent nodes (unmerged positions)
|
|
63
|
+
* - These nulls are REQUIRED for proper binary tree structure
|
|
64
|
+
* - Trailing nulls are stripped by sender (per RFC 9420 requirement)
|
|
65
|
+
* - ratchetTree parameter is optional; ts-mls can extract from Welcome extension
|
|
66
|
+
*
|
|
67
|
+
* @param welcome - The Welcome message from group creator
|
|
68
|
+
* @param ratchetTree - Optional ratchet tree (normally provided out-of-band)
|
|
69
|
+
*/
|
|
70
|
+
processWelcome(welcome: Welcome, ratchetTree?: Uint8Array[]): Promise<MLSGroupInfo>;
|
|
71
|
+
/**
|
|
72
|
+
* Encrypt a message for a group
|
|
73
|
+
*/
|
|
74
|
+
encryptMessage(groupId: string, plaintext: string): Promise<MLSMessageEnvelope>;
|
|
75
|
+
/**
|
|
76
|
+
* Decrypt a message from a group
|
|
77
|
+
*/
|
|
78
|
+
decryptMessage(envelope: MLSMessageEnvelope): Promise<string>;
|
|
79
|
+
/**
|
|
80
|
+
* Update the group keys (key rotation)
|
|
81
|
+
*/
|
|
82
|
+
updateKey(groupId: string): Promise<any>;
|
|
83
|
+
/**
|
|
84
|
+
* Process a commit message (key rotation, member changes)
|
|
85
|
+
*
|
|
86
|
+
* RFC 9420 Section 12.1.8:
|
|
87
|
+
* - Update commits (key rotation) → PrivateMessage
|
|
88
|
+
* - Add/Remove commits → PublicMessage (for existing group members)
|
|
89
|
+
*
|
|
90
|
+
* This implementation handles both types based on wireformat.
|
|
91
|
+
*/
|
|
92
|
+
processCommit(groupId: string, commit: any): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Remove members from a group
|
|
95
|
+
*/
|
|
96
|
+
removeMembers(groupId: string, memberIndices: number[]): Promise<Uint8Array>;
|
|
97
|
+
/**
|
|
98
|
+
* Get list of groups
|
|
99
|
+
*/
|
|
100
|
+
getGroups(): Promise<Uint8Array[]>;
|
|
101
|
+
/**
|
|
102
|
+
* Export group state for persistence
|
|
103
|
+
*/
|
|
104
|
+
exportGroupState(groupId: string): Promise<any>;
|
|
105
|
+
/**
|
|
106
|
+
* Get user ID
|
|
107
|
+
*/
|
|
108
|
+
getUserId(): string;
|
|
109
|
+
/**
|
|
110
|
+
* Get group information
|
|
111
|
+
*/
|
|
112
|
+
getGroupKeyInfo(groupId: string): Promise<any>;
|
|
113
|
+
/**
|
|
114
|
+
* Clean up resources
|
|
115
|
+
*/
|
|
116
|
+
destroy(): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Extract member identities from group state
|
|
119
|
+
*/
|
|
120
|
+
private extractMembersFromState;
|
|
121
|
+
/**
|
|
122
|
+
* Convert bytes to hex string
|
|
123
|
+
*/
|
|
124
|
+
private bytesToHex;
|
|
125
|
+
/**
|
|
126
|
+
* Ensure the manager is initialized
|
|
127
|
+
*/
|
|
128
|
+
private ensureInitialized;
|
|
129
|
+
}
|
|
130
|
+
export default MLSManager;
|