holosphere 2.0.0-alpha20 → 2.0.0-alpha22
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 +1 -2
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +43 -41
- package/dist/{index-COpLk9gL.cjs → index-B4xe-N5-.cjs} +2 -2
- package/dist/{index-COpLk9gL.cjs.map → index-B4xe-N5-.cjs.map} +1 -1
- package/dist/{index-D2WstuZJ.js → index-Bug_CGNq.js} +2 -2
- package/dist/{index-D2WstuZJ.js.map → index-Bug_CGNq.js.map} +1 -1
- package/dist/index-CaCPzdlv.cjs +29 -0
- package/dist/index-CaCPzdlv.cjs.map +1 -0
- package/dist/{index-B6-8KAQm.js → index-D76zMgwU.js} +2 -2
- package/dist/{index-B6-8KAQm.js.map → index-D76zMgwU.js.map} +1 -1
- package/dist/{index--QsHG_gD.cjs → index-DuOuk96g.cjs} +2 -2
- package/dist/{index--QsHG_gD.cjs.map → index-DuOuk96g.cjs.map} +1 -1
- package/dist/{index-BHptWysv.js → index-bYHRpACA.js} +2951 -7736
- package/dist/index-bYHRpACA.js.map +1 -0
- package/dist/{indexeddb-storage-kQ53UHEE.js → indexeddb-storage-BrIwr42m.js} +2 -2
- package/dist/{indexeddb-storage-kQ53UHEE.js.map → indexeddb-storage-BrIwr42m.js.map} +1 -1
- package/dist/{indexeddb-storage-wKG4mICM.cjs → indexeddb-storage-CFWfkdX9.cjs} +2 -2
- package/dist/{indexeddb-storage-wKG4mICM.cjs.map → indexeddb-storage-CFWfkdX9.cjs.map} +1 -1
- package/dist/{memory-storage-DnXCSbBl.js → memory-storage-BDQRj-2j.js} +2 -2
- package/dist/{memory-storage-DnXCSbBl.js.map → memory-storage-BDQRj-2j.js.map} +1 -1
- package/dist/{memory-storage-CGC8xM2G.cjs → memory-storage-bkatDnuR.cjs} +2 -2
- package/dist/{memory-storage-CGC8xM2G.cjs.map → memory-storage-bkatDnuR.cjs.map} +1 -1
- package/examples/demo.html +2 -29
- package/package.json +3 -8
- package/src/content/social-protocols.js +3 -59
- package/src/core/holosphere.js +16 -554
- package/src/crypto/nostr-utils.js +98 -1
- package/src/crypto/secp256k1.js +13 -411
- package/src/federation/discovery.js +7 -75
- package/src/federation/handshake.js +69 -202
- package/src/federation/hologram.js +275 -460
- package/src/federation/index.js +2 -9
- package/src/federation/registry.js +65 -1169
- package/src/federation/request-card.js +21 -35
- package/src/hierarchical/upcast.js +4 -9
- package/src/index.js +142 -296
- package/src/lib/federation-methods.js +388 -886
- package/src/storage/global-tables.js +1 -1
- package/src/storage/nostr-wrapper.js +9 -5
- package/src/subscriptions/manager.js +1 -1
- package/types/index.d.ts +145 -37
- package/bin/holosphere-activitypub.js +0 -158
- package/dist/2019-BzVkRcax.js +0 -6680
- package/dist/2019-BzVkRcax.js.map +0 -1
- package/dist/2019-C1hPR_Os.cjs +0 -8
- package/dist/2019-C1hPR_Os.cjs.map +0 -1
- package/dist/browser-BcmACE3G.js +0 -3058
- package/dist/browser-BcmACE3G.js.map +0 -1
- package/dist/browser-DaqYUTcG.cjs +0 -2
- package/dist/browser-DaqYUTcG.cjs.map +0 -1
- package/dist/index-BHptWysv.js.map +0 -1
- package/dist/index-CDlhzxT2.cjs +0 -29
- package/dist/index-CDlhzxT2.cjs.map +0 -1
- package/src/federation/capabilities.js +0 -162
- package/src/storage/backend-factory.js +0 -130
- package/src/storage/backend-interface.js +0 -161
- package/src/storage/backends/activitypub/server.js +0 -675
- package/src/storage/backends/activitypub-backend.js +0 -295
- package/src/storage/backends/gundb-backend.js +0 -875
- package/src/storage/backends/nostr-backend.js +0 -251
- package/src/storage/gun-async.js +0 -341
- package/src/storage/gun-auth.js +0 -373
- package/src/storage/gun-federation.js +0 -785
- package/src/storage/gun-references.js +0 -209
- package/src/storage/gun-schema.js +0 -306
- package/src/storage/gun-wrapper.js +0 -642
- package/src/storage/migration.js +0 -351
- package/src/storage/unified-storage.js +0 -161
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Federation Capabilities Module
|
|
3
|
-
*
|
|
4
|
-
* Handles capability token issuance, verification, and management
|
|
5
|
-
* for federation operations. Extracted from federation-methods.js
|
|
6
|
-
* for better modularity.
|
|
7
|
-
*
|
|
8
|
-
* @module federation/capabilities
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import * as crypto from '../crypto/secp256k1.js';
|
|
12
|
-
import * as registry from './registry.js';
|
|
13
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
14
|
-
import { bytesToHex } from '@noble/hashes/utils';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Issue a capability token for federation
|
|
18
|
-
* @param {Object} client - NostrClient instance
|
|
19
|
-
* @param {string} targetPubKey - Target public key to grant access to
|
|
20
|
-
* @param {Object} scope - Access scope { holonId, lensName, dataId }
|
|
21
|
-
* @param {string[]} permissions - Array of permissions ('read', 'write')
|
|
22
|
-
* @param {Object} options - Capability options
|
|
23
|
-
* @param {number} [options.expiresIn=3600000] - Expiration time in milliseconds
|
|
24
|
-
* @param {boolean} [options.isSelfCapability=false] - Whether this is a self-capability
|
|
25
|
-
* @returns {Promise<string>} Capability token
|
|
26
|
-
*/
|
|
27
|
-
export async function issueCapability(client, targetPubKey, scope, permissions, options = {}) {
|
|
28
|
-
const {
|
|
29
|
-
expiresIn = 3600000,
|
|
30
|
-
isSelfCapability = false,
|
|
31
|
-
} = options;
|
|
32
|
-
|
|
33
|
-
const token = await crypto.issueCapability(
|
|
34
|
-
permissions,
|
|
35
|
-
scope,
|
|
36
|
-
targetPubKey,
|
|
37
|
-
{
|
|
38
|
-
expiresIn,
|
|
39
|
-
issuer: client.publicKey,
|
|
40
|
-
issuerKey: client.privateKey,
|
|
41
|
-
isSelfCapability,
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
return token;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Issue capability for a specific lens
|
|
50
|
-
* @param {Object} client - NostrClient instance
|
|
51
|
-
* @param {string} holonId - Holon ID
|
|
52
|
-
* @param {string} lensName - Lens name
|
|
53
|
-
* @param {string} targetPubKey - Target public key
|
|
54
|
-
* @param {Object} options - Options
|
|
55
|
-
* @returns {Promise<Object>} Capability info { token, scope, permissions }
|
|
56
|
-
*/
|
|
57
|
-
export async function issueCapabilityForLens(client, holonId, lensName, targetPubKey, options = {}) {
|
|
58
|
-
const {
|
|
59
|
-
permissions = ['read'],
|
|
60
|
-
expiresIn = 365 * 24 * 60 * 60 * 1000, // 1 year default
|
|
61
|
-
} = options;
|
|
62
|
-
|
|
63
|
-
const scope = { holonId, lensName, dataId: '*' };
|
|
64
|
-
|
|
65
|
-
const token = await issueCapability(client, targetPubKey, scope, permissions, {
|
|
66
|
-
expiresIn,
|
|
67
|
-
isSelfCapability: client.publicKey === targetPubKey,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
return {
|
|
71
|
-
token,
|
|
72
|
-
scope,
|
|
73
|
-
permissions,
|
|
74
|
-
expiresAt: Date.now() + expiresIn,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Issue capabilities for multiple lenses
|
|
80
|
-
* @param {Object} client - NostrClient instance
|
|
81
|
-
* @param {string} holonId - Holon ID
|
|
82
|
-
* @param {string[]} lensNames - Array of lens names
|
|
83
|
-
* @param {string} targetPubKey - Target public key
|
|
84
|
-
* @param {Object} options - Options
|
|
85
|
-
* @returns {Promise<Object[]>} Array of capability info objects
|
|
86
|
-
*/
|
|
87
|
-
export async function issueCapabilitiesForLenses(client, holonId, lensNames, targetPubKey, options = {}) {
|
|
88
|
-
const capabilities = [];
|
|
89
|
-
|
|
90
|
-
for (const lensName of lensNames) {
|
|
91
|
-
try {
|
|
92
|
-
const capInfo = await issueCapabilityForLens(client, holonId, lensName, targetPubKey, options);
|
|
93
|
-
capabilities.push(capInfo);
|
|
94
|
-
} catch (err) {
|
|
95
|
-
console.warn(`[Capabilities] Failed to issue capability for ${lensName}:`, err.message);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return capabilities;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Store a capability in the registry
|
|
104
|
-
* @param {Object} client - NostrClient instance
|
|
105
|
-
* @param {string} appname - Application namespace
|
|
106
|
-
* @param {string} partnerPubKey - Partner's public key
|
|
107
|
-
* @param {Object} capabilityInfo - Capability info to store
|
|
108
|
-
* @param {Object} options - Options
|
|
109
|
-
* @returns {Promise<boolean>} Success indicator
|
|
110
|
-
*/
|
|
111
|
-
export async function storeCapability(client, appname, partnerPubKey, capabilityInfo, options = {}) {
|
|
112
|
-
const { isSelf = false } = options;
|
|
113
|
-
|
|
114
|
-
if (isSelf) {
|
|
115
|
-
return registry.storeSelfCapability(client, appname, capabilityInfo);
|
|
116
|
-
} else {
|
|
117
|
-
return registry.storeInboundCapability(client, appname, partnerPubKey, capabilityInfo);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Hash a capability token for storage
|
|
123
|
-
* @param {string} token - Capability token to hash
|
|
124
|
-
* @returns {string} SHA256 hash of token
|
|
125
|
-
*/
|
|
126
|
-
export function hashToken(token) {
|
|
127
|
-
const encoder = new TextEncoder();
|
|
128
|
-
return bytesToHex(sha256(encoder.encode(token)));
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Verify a capability token
|
|
133
|
-
* @param {string} token - Capability token
|
|
134
|
-
* @param {string} permission - Required permission
|
|
135
|
-
* @param {Object} scope - Requested scope
|
|
136
|
-
* @returns {Promise<boolean>} True if valid
|
|
137
|
-
*/
|
|
138
|
-
export async function verifyCapability(token, permission, scope) {
|
|
139
|
-
return crypto.verifyCapability(token, permission, scope);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Get capability for accessing a partner's data
|
|
144
|
-
* @param {Object} client - NostrClient instance
|
|
145
|
-
* @param {string} appname - Application namespace
|
|
146
|
-
* @param {string} partnerPubKey - Partner's public key
|
|
147
|
-
* @param {Object} scope - Requested scope
|
|
148
|
-
* @returns {Promise<Object|null>} Capability entry or null
|
|
149
|
-
*/
|
|
150
|
-
export async function getCapabilityForPartner(client, appname, partnerPubKey, scope) {
|
|
151
|
-
return registry.getCapabilityForAuthor(client, appname, partnerPubKey, scope);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export default {
|
|
155
|
-
issueCapability,
|
|
156
|
-
issueCapabilityForLens,
|
|
157
|
-
issueCapabilitiesForLenses,
|
|
158
|
-
storeCapability,
|
|
159
|
-
hashToken,
|
|
160
|
-
verifyCapability,
|
|
161
|
-
getCapabilityForPartner,
|
|
162
|
-
};
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Factory for Creating Storage Backends.
|
|
3
|
-
*
|
|
4
|
-
* Provides a factory pattern for creating and managing storage backend instances.
|
|
5
|
-
* Supports lazy loading of backend implementations to reduce initial bundle size.
|
|
6
|
-
*
|
|
7
|
-
* @module storage/backend-factory
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/** @type {Object<string, string>} Map of backend types to their module paths */
|
|
11
|
-
const BACKEND_MODULES = {
|
|
12
|
-
nostr: './backends/nostr-backend.js',
|
|
13
|
-
gundb: './backends/gundb-backend.js',
|
|
14
|
-
activitypub: './backends/activitypub-backend.js',
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
// Cache for loaded backend classes
|
|
18
|
-
const loadedBackends = new Map();
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Factory for creating storage backends
|
|
22
|
-
*/
|
|
23
|
-
export class BackendFactory {
|
|
24
|
-
/**
|
|
25
|
-
* Get list of available backend types
|
|
26
|
-
* @returns {string[]} Available backend type names
|
|
27
|
-
*/
|
|
28
|
-
static getAvailableBackends() {
|
|
29
|
-
return Object.keys(BACKEND_MODULES);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Check if a backend type is available
|
|
34
|
-
* @param {string} type - Backend type
|
|
35
|
-
* @returns {boolean} Whether the backend is available
|
|
36
|
-
*/
|
|
37
|
-
static isAvailable(type) {
|
|
38
|
-
return type in BACKEND_MODULES;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Load a backend class dynamically
|
|
43
|
-
* @param {string} type - Backend type
|
|
44
|
-
* @returns {Promise<Class>} Backend class
|
|
45
|
-
*/
|
|
46
|
-
static async loadBackend(type) {
|
|
47
|
-
if (loadedBackends.has(type)) {
|
|
48
|
-
return loadedBackends.get(type);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const modulePath = BACKEND_MODULES[type];
|
|
52
|
-
if (!modulePath) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`Unknown backend type: '${type}'. Available backends: ${Object.keys(BACKEND_MODULES).join(', ')}`
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const module = await import(modulePath);
|
|
60
|
-
const BackendClass = module.default || module[`${capitalize(type)}Backend`];
|
|
61
|
-
|
|
62
|
-
if (!BackendClass) {
|
|
63
|
-
throw new Error(`Backend module '${type}' does not export a valid backend class`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
loadedBackends.set(type, BackendClass);
|
|
67
|
-
return BackendClass;
|
|
68
|
-
} catch (error) {
|
|
69
|
-
if (error.code === 'ERR_MODULE_NOT_FOUND') {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Backend '${type}' requires additional dependencies. ` +
|
|
72
|
-
`Please install them: ${getDependencyHint(type)}`
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
throw error;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Create a storage backend instance
|
|
81
|
-
* @param {string} type - Backend type: 'nostr' | 'gundb' | 'activitypub'
|
|
82
|
-
* @param {Object} config - Backend-specific configuration
|
|
83
|
-
* @returns {Promise<StorageBackend>} Initialized backend
|
|
84
|
-
*/
|
|
85
|
-
static async create(type, config) {
|
|
86
|
-
const BackendClass = await this.loadBackend(type);
|
|
87
|
-
const backend = new BackendClass(config);
|
|
88
|
-
await backend.init();
|
|
89
|
-
return backend;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Register a custom backend
|
|
94
|
-
* @param {string} name - Backend name
|
|
95
|
-
* @param {Class|string} BackendClassOrPath - Backend class or module path
|
|
96
|
-
*/
|
|
97
|
-
static register(name, BackendClassOrPath) {
|
|
98
|
-
if (typeof BackendClassOrPath === 'string') {
|
|
99
|
-
BACKEND_MODULES[name] = BackendClassOrPath;
|
|
100
|
-
} else {
|
|
101
|
-
loadedBackends.set(name, BackendClassOrPath);
|
|
102
|
-
BACKEND_MODULES[name] = null; // Mark as registered but not file-based
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Capitalize first letter
|
|
109
|
-
* @param {string} str - String to capitalize
|
|
110
|
-
* @returns {string} Capitalized string
|
|
111
|
-
*/
|
|
112
|
-
function capitalize(str) {
|
|
113
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Get dependency installation hint for a backend
|
|
118
|
-
* @param {string} type - Backend type
|
|
119
|
-
* @returns {string} Installation hint
|
|
120
|
-
*/
|
|
121
|
-
function getDependencyHint(type) {
|
|
122
|
-
const hints = {
|
|
123
|
-
nostr: 'npm install nostr-tools',
|
|
124
|
-
gundb: 'npm install gun',
|
|
125
|
-
activitypub: 'npm install express',
|
|
126
|
-
};
|
|
127
|
-
return hints[type] || 'Check the documentation for required dependencies';
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export default BackendFactory;
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Abstract Storage Backend Interface.
|
|
3
|
-
*
|
|
4
|
-
* Defines the contract that all storage backends must implement.
|
|
5
|
-
* Provides a consistent API for CRUD operations, subscriptions,
|
|
6
|
-
* and data migration across different storage technologies.
|
|
7
|
-
*
|
|
8
|
-
* @module storage/backend-interface
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Abstract base class for storage backends.
|
|
13
|
-
* All concrete backends (Nostr, GunDB, ActivityPub) must extend this class.
|
|
14
|
-
*
|
|
15
|
-
* @abstract
|
|
16
|
-
* @class StorageBackend
|
|
17
|
-
*/
|
|
18
|
-
export class StorageBackend {
|
|
19
|
-
/**
|
|
20
|
-
* Creates a new StorageBackend instance.
|
|
21
|
-
*
|
|
22
|
-
* @param {Object} config - Backend-specific configuration
|
|
23
|
-
* @throws {Error} If instantiated directly (abstract class)
|
|
24
|
-
*/
|
|
25
|
-
constructor(config) {
|
|
26
|
-
if (new.target === StorageBackend) {
|
|
27
|
-
throw new Error('StorageBackend is abstract and cannot be instantiated directly');
|
|
28
|
-
}
|
|
29
|
-
this.config = config;
|
|
30
|
-
this.publicKey = null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Initialize the backend
|
|
35
|
-
* @returns {Promise<void>}
|
|
36
|
-
*/
|
|
37
|
-
async init() {
|
|
38
|
-
throw new Error('init() must be implemented by subclass');
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Build path from components
|
|
43
|
-
* @param {string} appName - Application namespace
|
|
44
|
-
* @param {string} holonId - Holon identifier (H3 hex or URI)
|
|
45
|
-
* @param {string} lensName - Lens name
|
|
46
|
-
* @param {string} [key] - Optional data key
|
|
47
|
-
* @returns {string} Constructed path
|
|
48
|
-
*/
|
|
49
|
-
buildPath(appName, holonId, lensName, key = null) {
|
|
50
|
-
throw new Error('buildPath() must be implemented by subclass');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Write data to storage
|
|
55
|
-
* @param {string} path - Storage path
|
|
56
|
-
* @param {Object} data - Data to write
|
|
57
|
-
* @param {Object} [options] - Write options
|
|
58
|
-
* @returns {Promise<boolean>} Success indicator
|
|
59
|
-
*/
|
|
60
|
-
async write(path, data, options = {}) {
|
|
61
|
-
throw new Error('write() must be implemented by subclass');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Read data from storage
|
|
66
|
-
* @param {string} path - Storage path
|
|
67
|
-
* @param {Object} [options] - Read options
|
|
68
|
-
* @param {string[]} [options.authors] - Public keys to query
|
|
69
|
-
* @param {boolean} [options.includeAuthor] - Include author in response
|
|
70
|
-
* @returns {Promise<Object|null>} Data or null
|
|
71
|
-
*/
|
|
72
|
-
async read(path, options = {}) {
|
|
73
|
-
throw new Error('read() must be implemented by subclass');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Read all data under a path prefix
|
|
78
|
-
* @param {string} path - Path prefix
|
|
79
|
-
* @param {Object} [options] - Query options
|
|
80
|
-
* @param {boolean} [options.hybrid] - Use hybrid mode (local + remote)
|
|
81
|
-
* @param {string[]} [options.authors] - Public keys to query
|
|
82
|
-
* @returns {Promise<Object[]>} Array of data objects
|
|
83
|
-
*/
|
|
84
|
-
async readAll(path, options = {}) {
|
|
85
|
-
throw new Error('readAll() must be implemented by subclass');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Update data (merge fields)
|
|
90
|
-
* @param {string} path - Storage path
|
|
91
|
-
* @param {Object} updates - Fields to update
|
|
92
|
-
* @returns {Promise<boolean>} Success indicator
|
|
93
|
-
*/
|
|
94
|
-
async update(path, updates) {
|
|
95
|
-
throw new Error('update() must be implemented by subclass');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Delete data at path
|
|
100
|
-
* @param {string} path - Storage path
|
|
101
|
-
* @returns {Promise<boolean>} Success indicator
|
|
102
|
-
*/
|
|
103
|
-
async delete(path) {
|
|
104
|
-
throw new Error('delete() must be implemented by subclass');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Delete all data under path prefix
|
|
109
|
-
* @param {string} path - Path prefix
|
|
110
|
-
* @returns {Promise<Object>} Deletion results { success: boolean, count: number }
|
|
111
|
-
*/
|
|
112
|
-
async deleteAll(path) {
|
|
113
|
-
throw new Error('deleteAll() must be implemented by subclass');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Subscribe to data changes
|
|
118
|
-
* @param {string} path - Path or path prefix
|
|
119
|
-
* @param {Function} callback - Called on changes: (data, key) => void
|
|
120
|
-
* @param {Object} [options] - Subscription options
|
|
121
|
-
* @returns {Promise<Object>} Subscription with unsubscribe() method
|
|
122
|
-
*/
|
|
123
|
-
async subscribe(path, callback, options = {}) {
|
|
124
|
-
throw new Error('subscribe() must be implemented by subclass');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Export all data for migration
|
|
129
|
-
* @param {string} [pathPrefix] - Optional prefix to filter
|
|
130
|
-
* @returns {Promise<Object[]>} Array of exportable records
|
|
131
|
-
*/
|
|
132
|
-
async exportData(pathPrefix = '') {
|
|
133
|
-
throw new Error('exportData() must be implemented by subclass');
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Import data from migration
|
|
138
|
-
* @param {Object[]} records - Records to import
|
|
139
|
-
* @param {Object} [options] - Import options
|
|
140
|
-
* @param {boolean} [options.overwrite] - Overwrite existing data
|
|
141
|
-
* @returns {Promise<Object>} Import results { success: number, failed: number, errors: [] }
|
|
142
|
-
*/
|
|
143
|
-
async importData(records, options = {}) {
|
|
144
|
-
throw new Error('importData() must be implemented by subclass');
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Close connections and cleanup
|
|
149
|
-
*/
|
|
150
|
-
close() {
|
|
151
|
-
throw new Error('close() must be implemented by subclass');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Get backend status/health
|
|
156
|
-
* @returns {Object} Status information { type, publicKey, connected, ... }
|
|
157
|
-
*/
|
|
158
|
-
getStatus() {
|
|
159
|
-
throw new Error('getStatus() must be implemented by subclass');
|
|
160
|
-
}
|
|
161
|
-
}
|