@feltdb/core 0.2.0 → 0.3.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.
- package/LICENSE +19 -0
- package/dist/analytics-backend.d.ts +39 -0
- package/dist/analytics-backend.d.ts.map +1 -0
- package/dist/analytics-backend.js +152 -0
- package/dist/application-contract.d.ts +49 -0
- package/dist/application-contract.d.ts.map +1 -0
- package/dist/application-contract.js +13 -0
- package/dist/application-manifest.d.ts +305 -0
- package/dist/application-manifest.d.ts.map +1 -0
- package/dist/application-manifest.js +26 -0
- package/dist/artifact.d.ts +73 -0
- package/dist/artifact.d.ts.map +1 -0
- package/dist/artifact.js +21 -0
- package/dist/authorization.d.ts +99 -0
- package/dist/authorization.d.ts.map +1 -0
- package/dist/authorization.js +15 -0
- package/dist/bundle.d.ts +55 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +13 -0
- package/dist/collection.d.ts +28 -0
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +83 -0
- package/dist/db.d.ts +18 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +20 -8
- package/dist/distributed-indexing.d.ts +170 -0
- package/dist/distributed-indexing.d.ts.map +1 -0
- package/dist/distributed-indexing.js +260 -0
- package/dist/flowspec.d.ts +4 -0
- package/dist/flowspec.d.ts.map +1 -1
- package/dist/flowspec.js +8 -0
- package/dist/http-client.d.ts +35 -0
- package/dist/http-client.d.ts.map +1 -0
- package/dist/http-client.js +70 -0
- package/dist/identity.d.ts +40 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +10 -0
- package/dist/index-analytics.d.ts +121 -0
- package/dist/index-analytics.d.ts.map +1 -0
- package/dist/index-analytics.js +279 -0
- package/dist/index-backend.d.ts +26 -0
- package/dist/index-backend.d.ts.map +1 -0
- package/dist/index-backend.js +115 -0
- package/dist/index-dashboard.d.ts +114 -0
- package/dist/index-dashboard.d.ts.map +1 -0
- package/dist/index-dashboard.js +256 -0
- package/dist/index-manager.d.ts +18 -0
- package/dist/index-manager.d.ts.map +1 -0
- package/dist/index-manager.js +333 -0
- package/dist/index-monitoring.d.ts +133 -0
- package/dist/index-monitoring.d.ts.map +1 -0
- package/dist/index-monitoring.js +218 -0
- package/dist/index-recovery.d.ts +57 -0
- package/dist/index-recovery.d.ts.map +1 -0
- package/dist/index-recovery.js +117 -0
- package/dist/index-store.d.ts +62 -0
- package/dist/index-store.d.ts.map +1 -0
- package/dist/index-store.js +141 -0
- package/dist/index-types.d.ts +70 -0
- package/dist/index-types.d.ts.map +1 -0
- package/dist/index-types.js +6 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -0
- package/dist/observe.d.ts +51 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +14 -0
- package/dist/protocol.d.ts +25 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +18 -0
- package/dist/provider.d.ts +61 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +17 -0
- package/dist/query-planner.d.ts +69 -0
- package/dist/query-planner.d.ts.map +1 -0
- package/dist/query-planner.js +184 -0
- package/dist/release.d.ts +60 -0
- package/dist/release.d.ts.map +1 -0
- package/dist/release.js +18 -0
- package/dist/sharding.d.ts +159 -0
- package/dist/sharding.d.ts.map +1 -0
- package/dist/sharding.js +317 -0
- package/dist/state-contract.d.ts +173 -0
- package/dist/state-contract.d.ts.map +1 -0
- package/dist/state-contract.js +24 -0
- package/dist/sync-contract.d.ts +101 -0
- package/dist/sync-contract.d.ts.map +1 -0
- package/dist/sync-contract.js +90 -0
- package/dist/worker.d.ts +90 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +26 -0
- package/dist/workload.d.ts +102 -0
- package/dist/workload.d.ts.map +1 -0
- package/dist/workload.js +23 -0
- package/package.json +17 -5
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distributed Indexing - Multi-node synchronization and replication
|
|
3
|
+
*
|
|
4
|
+
* Extends local indexing with distributed capabilities:
|
|
5
|
+
* - Index replication across peers
|
|
6
|
+
* - Vector clock-based consistency tracking
|
|
7
|
+
* - Conflict detection and resolution
|
|
8
|
+
* - Synchronization protocols
|
|
9
|
+
*/
|
|
10
|
+
export interface IndexVectorClock {
|
|
11
|
+
clock: Record<string, number>;
|
|
12
|
+
}
|
|
13
|
+
export interface IndexReplicationState {
|
|
14
|
+
indexName: string;
|
|
15
|
+
localVersion: IndexVectorClock;
|
|
16
|
+
peerVersions: Record<string, IndexVectorClock>;
|
|
17
|
+
replicatedPeers: Set<string>;
|
|
18
|
+
pendingSync: IndexOperation[];
|
|
19
|
+
}
|
|
20
|
+
export type IndexOperation = {
|
|
21
|
+
type: 'create_index';
|
|
22
|
+
name: string;
|
|
23
|
+
field: string;
|
|
24
|
+
indexType: string;
|
|
25
|
+
} | {
|
|
26
|
+
type: 'update_index';
|
|
27
|
+
name: string;
|
|
28
|
+
recordId: string;
|
|
29
|
+
value: string;
|
|
30
|
+
} | {
|
|
31
|
+
type: 'delete_index';
|
|
32
|
+
name: string;
|
|
33
|
+
};
|
|
34
|
+
export interface IndexSyncMessage {
|
|
35
|
+
sourcePeer: string;
|
|
36
|
+
targetPeer: string;
|
|
37
|
+
indexName: string;
|
|
38
|
+
version: IndexVectorClock;
|
|
39
|
+
operations: IndexOperation[];
|
|
40
|
+
timestamp: number;
|
|
41
|
+
}
|
|
42
|
+
export interface RemoteIndexMetadata {
|
|
43
|
+
name: string;
|
|
44
|
+
version: IndexVectorClock;
|
|
45
|
+
entryCount: number;
|
|
46
|
+
avgQueryTimeMs: number;
|
|
47
|
+
lastUpdated: number;
|
|
48
|
+
}
|
|
49
|
+
export interface RemoteIndexState {
|
|
50
|
+
peerId: string;
|
|
51
|
+
indexes: Record<string, RemoteIndexMetadata>;
|
|
52
|
+
lastSync: number;
|
|
53
|
+
reachable: boolean;
|
|
54
|
+
}
|
|
55
|
+
export type ConsistencyLevel = 'local' | 'eventual' | 'causal' | 'strong';
|
|
56
|
+
export interface ReplicationStatus {
|
|
57
|
+
indexName: string;
|
|
58
|
+
replicatedTo: number;
|
|
59
|
+
totalPeers: number;
|
|
60
|
+
reachablePeers: number;
|
|
61
|
+
pendingSyncs: number;
|
|
62
|
+
consistencyLevel: ConsistencyLevel;
|
|
63
|
+
}
|
|
64
|
+
export interface VersionConflict {
|
|
65
|
+
indexName: string;
|
|
66
|
+
localVersion: IndexVectorClock;
|
|
67
|
+
remotePeer: string;
|
|
68
|
+
remoteVersion: IndexVectorClock;
|
|
69
|
+
}
|
|
70
|
+
export interface DistributedSyncStatus {
|
|
71
|
+
totalIndexes: number;
|
|
72
|
+
fullyReplicated: number;
|
|
73
|
+
partiallyReplicated: number;
|
|
74
|
+
pendingOperations: number;
|
|
75
|
+
unreachablePeers: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Distributed Index Manager - TypeScript implementation
|
|
79
|
+
*/
|
|
80
|
+
export declare class DistributedIndexManager {
|
|
81
|
+
private localPeerId;
|
|
82
|
+
private replicationStates;
|
|
83
|
+
private peerStates;
|
|
84
|
+
private pendingOperations;
|
|
85
|
+
constructor(localPeerId: string);
|
|
86
|
+
/**
|
|
87
|
+
* Create a replicated index
|
|
88
|
+
*/
|
|
89
|
+
createReplicatedIndex(name: string, field: string, indexType: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Register a peer for replication
|
|
92
|
+
*/
|
|
93
|
+
registerPeer(peerId: string): void;
|
|
94
|
+
/**
|
|
95
|
+
* Update remote peer's index metadata
|
|
96
|
+
*/
|
|
97
|
+
updatePeerIndexMetadata(peerId: string, indexName: string, metadata: RemoteIndexMetadata): void;
|
|
98
|
+
/**
|
|
99
|
+
* Enqueue a sync message
|
|
100
|
+
*/
|
|
101
|
+
enqueueSyncMessage(message: IndexSyncMessage): void;
|
|
102
|
+
/**
|
|
103
|
+
* Get pending sync messages for a peer
|
|
104
|
+
*/
|
|
105
|
+
getPendingForPeer(peerId: string): IndexSyncMessage[];
|
|
106
|
+
/**
|
|
107
|
+
* Acknowledge sync from peer
|
|
108
|
+
*/
|
|
109
|
+
acknowledgePeerSync(peerId: string, indexName: string): void;
|
|
110
|
+
/**
|
|
111
|
+
* Get replication status for an index
|
|
112
|
+
*/
|
|
113
|
+
getReplicationStatus(indexName: string): ReplicationStatus | null;
|
|
114
|
+
/**
|
|
115
|
+
* Calculate consistency level for an index
|
|
116
|
+
*/
|
|
117
|
+
private calculateConsistencyLevel;
|
|
118
|
+
/**
|
|
119
|
+
* Get replication targets for an index
|
|
120
|
+
*/
|
|
121
|
+
getReplicationTargets(indexName: string): string[];
|
|
122
|
+
/**
|
|
123
|
+
* Detect version conflicts
|
|
124
|
+
*/
|
|
125
|
+
detectConflicts(indexName: string): VersionConflict[];
|
|
126
|
+
/**
|
|
127
|
+
* Merge versions using CRDT strategy
|
|
128
|
+
*/
|
|
129
|
+
mergeVersions(indexName: string): void;
|
|
130
|
+
/**
|
|
131
|
+
* Set peer reachability
|
|
132
|
+
*/
|
|
133
|
+
setPeerReachable(peerId: string, reachable: boolean): void;
|
|
134
|
+
/**
|
|
135
|
+
* Get overall sync status
|
|
136
|
+
*/
|
|
137
|
+
getSyncStatus(): DistributedSyncStatus;
|
|
138
|
+
/**
|
|
139
|
+
* Vector clock utilities
|
|
140
|
+
*/
|
|
141
|
+
private isConcurrent;
|
|
142
|
+
private happensBefore;
|
|
143
|
+
private mergeClocks;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Synchronization coordinator for multi-node environments
|
|
147
|
+
*/
|
|
148
|
+
export declare class DistributedSyncCoordinator {
|
|
149
|
+
private indexManager;
|
|
150
|
+
private syncInterval;
|
|
151
|
+
private syncIntervalMs;
|
|
152
|
+
constructor(indexManager: DistributedIndexManager);
|
|
153
|
+
/**
|
|
154
|
+
* Start periodic synchronization
|
|
155
|
+
*/
|
|
156
|
+
startSync(intervalMs?: number): void;
|
|
157
|
+
/**
|
|
158
|
+
* Stop synchronization
|
|
159
|
+
*/
|
|
160
|
+
stopSync(): void;
|
|
161
|
+
/**
|
|
162
|
+
* Perform synchronization cycle
|
|
163
|
+
*/
|
|
164
|
+
private performSync;
|
|
165
|
+
/**
|
|
166
|
+
* Explicitly sync a specific index
|
|
167
|
+
*/
|
|
168
|
+
syncIndex(indexName: string): void;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=distributed-indexing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distributed-indexing.d.ts","sourceRoot":"","sources":["../src/distributed-indexing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Distributed Indexing - Multi-node synchronization and replication
|
|
3
|
+
*
|
|
4
|
+
* Extends local indexing with distributed capabilities:
|
|
5
|
+
* - Index replication across peers
|
|
6
|
+
* - Vector clock-based consistency tracking
|
|
7
|
+
* - Conflict detection and resolution
|
|
8
|
+
* - Synchronization protocols
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Distributed Index Manager - TypeScript implementation
|
|
12
|
+
*/
|
|
13
|
+
export class DistributedIndexManager {
|
|
14
|
+
constructor(localPeerId) {
|
|
15
|
+
this.replicationStates = new Map();
|
|
16
|
+
this.peerStates = new Map();
|
|
17
|
+
this.pendingOperations = [];
|
|
18
|
+
this.localPeerId = localPeerId;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a replicated index
|
|
22
|
+
*/
|
|
23
|
+
createReplicatedIndex(name, field, indexType) {
|
|
24
|
+
const version = { clock: { [this.localPeerId]: 1 } };
|
|
25
|
+
this.replicationStates.set(name, {
|
|
26
|
+
indexName: name,
|
|
27
|
+
localVersion: version,
|
|
28
|
+
peerVersions: {},
|
|
29
|
+
replicatedPeers: new Set(),
|
|
30
|
+
pendingSync: [
|
|
31
|
+
{
|
|
32
|
+
type: 'create_index',
|
|
33
|
+
name,
|
|
34
|
+
field,
|
|
35
|
+
indexType,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Register a peer for replication
|
|
42
|
+
*/
|
|
43
|
+
registerPeer(peerId) {
|
|
44
|
+
this.peerStates.set(peerId, {
|
|
45
|
+
peerId,
|
|
46
|
+
indexes: {},
|
|
47
|
+
lastSync: Date.now(),
|
|
48
|
+
reachable: true,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Update remote peer's index metadata
|
|
53
|
+
*/
|
|
54
|
+
updatePeerIndexMetadata(peerId, indexName, metadata) {
|
|
55
|
+
const peer = this.peerStates.get(peerId);
|
|
56
|
+
if (peer) {
|
|
57
|
+
peer.indexes[indexName] = metadata;
|
|
58
|
+
peer.lastSync = Date.now();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Enqueue a sync message
|
|
63
|
+
*/
|
|
64
|
+
enqueueSyncMessage(message) {
|
|
65
|
+
this.pendingOperations.push(message);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get pending sync messages for a peer
|
|
69
|
+
*/
|
|
70
|
+
getPendingForPeer(peerId) {
|
|
71
|
+
return this.pendingOperations.filter((msg) => msg.targetPeer === peerId);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Acknowledge sync from peer
|
|
75
|
+
*/
|
|
76
|
+
acknowledgePeerSync(peerId, indexName) {
|
|
77
|
+
const state = this.replicationStates.get(indexName);
|
|
78
|
+
if (state) {
|
|
79
|
+
state.replicatedPeers.add(peerId);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get replication status for an index
|
|
84
|
+
*/
|
|
85
|
+
getReplicationStatus(indexName) {
|
|
86
|
+
const state = this.replicationStates.get(indexName);
|
|
87
|
+
if (!state)
|
|
88
|
+
return null;
|
|
89
|
+
const totalPeers = this.peerStates.size;
|
|
90
|
+
const reachablePeers = Array.from(this.peerStates.values()).filter((p) => p.reachable).length;
|
|
91
|
+
const consistencyLevel = this.calculateConsistencyLevel(indexName);
|
|
92
|
+
return {
|
|
93
|
+
indexName,
|
|
94
|
+
replicatedTo: state.replicatedPeers.size,
|
|
95
|
+
totalPeers,
|
|
96
|
+
reachablePeers,
|
|
97
|
+
pendingSyncs: state.pendingSync.length,
|
|
98
|
+
consistencyLevel,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Calculate consistency level for an index
|
|
103
|
+
*/
|
|
104
|
+
calculateConsistencyLevel(indexName) {
|
|
105
|
+
const state = this.replicationStates.get(indexName);
|
|
106
|
+
if (!state)
|
|
107
|
+
return 'local';
|
|
108
|
+
const totalPeers = this.peerStates.size;
|
|
109
|
+
const replicatedPeers = state.replicatedPeers.size;
|
|
110
|
+
if (replicatedPeers === totalPeers) {
|
|
111
|
+
return 'strong';
|
|
112
|
+
}
|
|
113
|
+
else if (replicatedPeers > totalPeers / 2) {
|
|
114
|
+
return 'causal';
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
return 'eventual';
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get replication targets for an index
|
|
122
|
+
*/
|
|
123
|
+
getReplicationTargets(indexName) {
|
|
124
|
+
const state = this.replicationStates.get(indexName);
|
|
125
|
+
if (!state)
|
|
126
|
+
return [];
|
|
127
|
+
return Array.from(this.peerStates.keys()).filter((peerId) => peerId !== this.localPeerId && !state.replicatedPeers.has(peerId));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Detect version conflicts
|
|
131
|
+
*/
|
|
132
|
+
detectConflicts(indexName) {
|
|
133
|
+
const state = this.replicationStates.get(indexName);
|
|
134
|
+
if (!state)
|
|
135
|
+
return [];
|
|
136
|
+
const conflicts = [];
|
|
137
|
+
for (const [peerId, peerVersion] of Object.entries(state.peerVersions)) {
|
|
138
|
+
if (this.isConcurrent(state.localVersion, peerVersion)) {
|
|
139
|
+
conflicts.push({
|
|
140
|
+
indexName,
|
|
141
|
+
localVersion: state.localVersion,
|
|
142
|
+
remotePeer: peerId,
|
|
143
|
+
remoteVersion: peerVersion,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return conflicts;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Merge versions using CRDT strategy
|
|
151
|
+
*/
|
|
152
|
+
mergeVersions(indexName) {
|
|
153
|
+
const state = this.replicationStates.get(indexName);
|
|
154
|
+
if (!state)
|
|
155
|
+
return;
|
|
156
|
+
for (const peerVersion of Object.values(state.peerVersions)) {
|
|
157
|
+
this.mergeClocks(state.localVersion, peerVersion);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Set peer reachability
|
|
162
|
+
*/
|
|
163
|
+
setPeerReachable(peerId, reachable) {
|
|
164
|
+
const peer = this.peerStates.get(peerId);
|
|
165
|
+
if (peer) {
|
|
166
|
+
peer.reachable = reachable;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get overall sync status
|
|
171
|
+
*/
|
|
172
|
+
getSyncStatus() {
|
|
173
|
+
const totalIndexes = this.replicationStates.size;
|
|
174
|
+
const fullyReplicated = Array.from(this.replicationStates.values()).filter((state) => state.replicatedPeers.size === this.peerStates.size).length;
|
|
175
|
+
const pendingOperations = Array.from(this.replicationStates.values()).reduce((sum, state) => sum + state.pendingSync.length, 0);
|
|
176
|
+
const unreachablePeers = Array.from(this.peerStates.values()).filter((p) => !p.reachable).length;
|
|
177
|
+
return {
|
|
178
|
+
totalIndexes,
|
|
179
|
+
fullyReplicated,
|
|
180
|
+
partiallyReplicated: totalIndexes - fullyReplicated,
|
|
181
|
+
pendingOperations,
|
|
182
|
+
unreachablePeers,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Vector clock utilities
|
|
187
|
+
*/
|
|
188
|
+
isConcurrent(clock1, clock2) {
|
|
189
|
+
return !this.happensBefore(clock1, clock2) && !this.happensBefore(clock2, clock1);
|
|
190
|
+
}
|
|
191
|
+
happensBefore(clock1, clock2) {
|
|
192
|
+
let less = false;
|
|
193
|
+
for (const [node, timestamp] of Object.entries(clock1.clock)) {
|
|
194
|
+
const other = clock2.clock[node] ?? 0;
|
|
195
|
+
if (timestamp > other) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
if (timestamp < other) {
|
|
199
|
+
less = true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return less;
|
|
203
|
+
}
|
|
204
|
+
mergeClocks(target, source) {
|
|
205
|
+
for (const [node, timestamp] of Object.entries(source.clock)) {
|
|
206
|
+
if (!target.clock[node] || target.clock[node] < timestamp) {
|
|
207
|
+
target.clock[node] = timestamp;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Synchronization coordinator for multi-node environments
|
|
214
|
+
*/
|
|
215
|
+
export class DistributedSyncCoordinator {
|
|
216
|
+
constructor(indexManager) {
|
|
217
|
+
this.syncInterval = null;
|
|
218
|
+
this.syncIntervalMs = 5000; // 5 seconds
|
|
219
|
+
this.indexManager = indexManager;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Start periodic synchronization
|
|
223
|
+
*/
|
|
224
|
+
startSync(intervalMs = 5000) {
|
|
225
|
+
this.syncIntervalMs = intervalMs;
|
|
226
|
+
this.syncInterval = setInterval(() => {
|
|
227
|
+
this.performSync();
|
|
228
|
+
}, intervalMs);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Stop synchronization
|
|
232
|
+
*/
|
|
233
|
+
stopSync() {
|
|
234
|
+
if (this.syncInterval) {
|
|
235
|
+
clearInterval(this.syncInterval);
|
|
236
|
+
this.syncInterval = null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Perform synchronization cycle
|
|
241
|
+
*/
|
|
242
|
+
performSync() {
|
|
243
|
+
const status = this.indexManager.getSyncStatus();
|
|
244
|
+
// Log sync status
|
|
245
|
+
if (status.pendingOperations > 0) {
|
|
246
|
+
console.debug(`[DistributedSync] Pending: ${status.pendingOperations}, Replicated: ${status.fullyReplicated}/${status.totalIndexes}`);
|
|
247
|
+
}
|
|
248
|
+
// Detect conflicts
|
|
249
|
+
// For each index, check for conflicts and attempt resolution
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Explicitly sync a specific index
|
|
253
|
+
*/
|
|
254
|
+
syncIndex(indexName) {
|
|
255
|
+
const status = this.indexManager.getReplicationStatus(indexName);
|
|
256
|
+
if (status && status.pendingSyncs > 0) {
|
|
257
|
+
console.debug(`[DistributedSync] Syncing ${indexName} to ${status.totalPeers - status.replicatedTo} peers`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
package/dist/flowspec.d.ts
CHANGED
|
@@ -55,6 +55,10 @@ export interface FlowMigrationOperation {
|
|
|
55
55
|
safety: 'safe' | 'requires_transform' | 'destructive';
|
|
56
56
|
detail: string;
|
|
57
57
|
}
|
|
58
|
+
import type { ApplicationManifest } from './application-manifest.js';
|
|
59
|
+
/** FlowSpec is a portable source format; the returned Rust manifest is authoritative only after server validation. */
|
|
60
|
+
export declare function flowSpecToManifest(spec: FlowSpec, tenantId: string, applicationId: string): ApplicationManifest;
|
|
61
|
+
export declare function manifestToFlowSpec(manifest: ApplicationManifest): FlowSpec;
|
|
58
62
|
export declare function parseFlowSpec(source: string): FlowSpec;
|
|
59
63
|
export declare function validateFlowSpec(spec: FlowSpec): FlowDiagnostic[];
|
|
60
64
|
export declare function formatFlowSpec(spec: FlowSpec): string;
|
package/dist/flowspec.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flowspec.d.ts","sourceRoot":"","sources":["../src/flowspec.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE;AAC5E,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AAC7E,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE;AAC3F,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE;AACjE,MAAM,WAAW,QAAS,SAAQ,SAAS;CAAG;AAC9C,MAAM,WAAW,YAAY;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAA;CAAE;AACrF,MAAM,WAAW,WAAW;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE;AACpE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,CAAC,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,SAAS,EAAE,SAAS,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAAG,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;AACjG,MAAM,WAAW,YAAY;IAAG,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE;AACvF,MAAM,WAAW,sBAAsB;IAAG,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;
|
|
1
|
+
{"version":3,"file":"flowspec.d.ts","sourceRoot":"","sources":["../src/flowspec.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE;AAC5E,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AAC7E,MAAM,WAAW,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,EAAE,CAAC;IAAC,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE;AAC3F,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE;AACjE,MAAM,WAAW,QAAS,SAAQ,SAAS;CAAG;AAC9C,MAAM,WAAW,YAAY;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAA;CAAE;AACrF,MAAM,WAAW,WAAW;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE;AACpE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,CAAC,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,SAAS,EAAE,SAAS,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAAG,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;AACjG,MAAM,WAAW,YAAY;IAAG,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE;AACvF,MAAM,WAAW,sBAAsB;IAAG,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,GAAG,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAEpK,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE,sHAAsH;AACtH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,mBAAmB,CAG/G;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,QAAQ,CAE1E;AAyFD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAA4C;AAEnG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,EAAE,CAWjE;AAGD,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAUrD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,YAAY,CAQ5E;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,sBAAsB,EAAE,CAsBjG;AAED,wBAAgB,aAAa,CAAC,GAAG,SAAU,GAAG,QAAQ,CAAyI"}
|
package/dist/flowspec.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/** FlowSpec is a portable source format; the returned Rust manifest is authoritative only after server validation. */
|
|
2
|
+
export function flowSpecToManifest(spec, tenantId, applicationId) {
|
|
3
|
+
const capabilities = spec.capabilities.map(value => ({ name: value.name }));
|
|
4
|
+
return { application_id: applicationId, tenant_id: tenantId, schema: 1, metadata: { name: spec.app, labels: {} }, collections: spec.collections.map(value => ({ name: value.name, fields: value.fields.map(field => ({ name: field.name, type: field.type, required: !field.optional })) })), indexes: spec.collections.flatMap(collection => collection.indexes.map(index => ({ name: index.name, collection: collection.name, fields: [index.expression], unique: index.kind === 'unique' }))), references: [], queries: [], actions: [], workflows: spec.workflows.map(value => ({ name: value.name, steps: value.steps.map(step => ({ name: step.name })) })), triggers: spec.triggers.map((value, index) => ({ name: `trigger-${index + 1}`, event: value.event, workflow: spec.workflows[0]?.name || '' })), schedules: spec.schedules.map(value => ({ name: value.name, expression: value.statements[0] || '', workflow: spec.workflows[0]?.name || '' })), agents: spec.agents.map(value => ({ name: value.name, capabilities: capabilities.map(capability => capability.name).filter(name => value.statements.some(statement => statement.includes(name))) })), capabilities, connections: [], policies: spec.policies.map(value => ({ name: value.name, resource: value.statements[0] || 'application', capabilities: [] })), ui: { routes: [], bindings: [], forms: [], dashboards: [] }, environments: ['development', 'preview', 'staging', 'production'].map(name => ({ name, configuration: {} })), artifacts: [], deployment: { environments: ['development', 'preview', 'staging', 'production'] }, runtime: { contract: 1, minimum_engine: '0.2.0', maximum_engine_exclusive: '2.0.0' } };
|
|
5
|
+
}
|
|
6
|
+
export function manifestToFlowSpec(manifest) {
|
|
7
|
+
return { version: 1, app: manifest.metadata.name, collections: manifest.collections.map(value => ({ name: value.name, fields: value.fields.map(field => ({ name: field.name, type: field.type, optional: !field.required })), indexes: manifest.indexes.filter(index => index.collection === value.name).map(index => ({ name: index.name, kind: index.unique ? 'unique' : 'index', expression: index.fields.join(', ') })) })), capabilities: manifest.capabilities.map(value => ({ name: value.name, statements: value.provider ? [`provider ${value.provider}`] : [] })), agents: manifest.agents.map(value => ({ name: value.name, statements: value.capabilities.map(capability => `capability ${capability}`) })), workflows: manifest.workflows.map(value => ({ name: value.name, parameters: '', steps: value.steps.map(step => ({ name: step.name, statements: step.capability ? [`capability ${step.capability}`] : [] })) })), triggers: manifest.triggers.map(value => ({ event: value.event, statements: [`run ${value.workflow}`] })), policies: manifest.policies.map(value => ({ name: value.name, statements: [value.resource, ...value.capabilities] })), schedules: manifest.schedules.map(value => ({ name: value.name, statements: [value.expression, `run ${value.workflow}`] })) };
|
|
8
|
+
}
|
|
1
9
|
function lex(source) {
|
|
2
10
|
const tokens = [];
|
|
3
11
|
let line = 1;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeltDB HTTP Client - Lightweight client for remote FeltDB servers
|
|
3
|
+
*
|
|
4
|
+
* Provides a simple interface for connecting to and querying remote FeltDB instances.
|
|
5
|
+
* For applications that only need HTTP access without the full core framework.
|
|
6
|
+
*/
|
|
7
|
+
export interface ClientOptions {
|
|
8
|
+
url: string;
|
|
9
|
+
token: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RemoteRecord<T> {
|
|
12
|
+
id: string;
|
|
13
|
+
key: string;
|
|
14
|
+
value: T;
|
|
15
|
+
version_ms: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class FeltDBClient {
|
|
18
|
+
private readonly url;
|
|
19
|
+
private readonly token;
|
|
20
|
+
constructor(options: ClientOptions);
|
|
21
|
+
private headers;
|
|
22
|
+
private request;
|
|
23
|
+
runtime(): Promise<Record<string, unknown>>;
|
|
24
|
+
list<T>(collection: string): Promise<Array<RemoteRecord<T>>>;
|
|
25
|
+
get<T>(collection: string, id: string | number): Promise<RemoteRecord<T>>;
|
|
26
|
+
insert<T extends object>(collection: string, value: T, id?: string | number): Promise<RemoteRecord<T>>;
|
|
27
|
+
update<T extends object>(collection: string, id: string | number, changes: Partial<T>): Promise<RemoteRecord<T>>;
|
|
28
|
+
delete(collection: string, id: string | number): Promise<void>;
|
|
29
|
+
getInfo(): {
|
|
30
|
+
runtime: 'remote';
|
|
31
|
+
url: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare function createClient(options: ClientOptions): FeltDBClient;
|
|
35
|
+
//# sourceMappingURL=http-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.d.ts","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,CAAC,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,EAAE,aAAa;IAMlC,OAAO,CAAC,OAAO;YAQD,OAAO;IAgBrB,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAI3C,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAI5D,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAIzE,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAOtG,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAOhH,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9D,OAAO,IAAI;QAAE,OAAO,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;CAG9C;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CAEjE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeltDB HTTP Client - Lightweight client for remote FeltDB servers
|
|
3
|
+
*
|
|
4
|
+
* Provides a simple interface for connecting to and querying remote FeltDB instances.
|
|
5
|
+
* For applications that only need HTTP access without the full core framework.
|
|
6
|
+
*/
|
|
7
|
+
export class FeltDBClient {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
if (!options.url || !options.token)
|
|
10
|
+
throw new Error('FeltDBClient requires url and token');
|
|
11
|
+
this.url = options.url.replace(/\/$/, '');
|
|
12
|
+
this.token = options.token;
|
|
13
|
+
}
|
|
14
|
+
headers(json = false) {
|
|
15
|
+
return {
|
|
16
|
+
Authorization: `Bearer ${this.token}`,
|
|
17
|
+
'FeltDB-Protocol': '1',
|
|
18
|
+
...(json ? { 'Content-Type': 'application/json' } : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async request(path, init = {}) {
|
|
22
|
+
const response = await fetch(`${this.url}${path}`, {
|
|
23
|
+
...init,
|
|
24
|
+
headers: { ...this.headers(init.body !== undefined), ...init.headers },
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
let message = `FeltDB request failed: HTTP ${response.status}`;
|
|
28
|
+
try {
|
|
29
|
+
const body = await response.json();
|
|
30
|
+
if (body.error)
|
|
31
|
+
message = body.error;
|
|
32
|
+
}
|
|
33
|
+
catch { /* non-JSON error */ }
|
|
34
|
+
throw new Error(message);
|
|
35
|
+
}
|
|
36
|
+
return (response.status === 204 ? undefined : response.json());
|
|
37
|
+
}
|
|
38
|
+
runtime() {
|
|
39
|
+
return this.request('/runtime');
|
|
40
|
+
}
|
|
41
|
+
list(collection) {
|
|
42
|
+
return this.request(`/collections/${encodeURIComponent(collection)}`);
|
|
43
|
+
}
|
|
44
|
+
get(collection, id) {
|
|
45
|
+
return this.request(`/collections/${encodeURIComponent(collection)}/${encodeURIComponent(String(id))}`);
|
|
46
|
+
}
|
|
47
|
+
insert(collection, value, id) {
|
|
48
|
+
return this.request(`/collections/${encodeURIComponent(collection)}`, {
|
|
49
|
+
method: 'POST',
|
|
50
|
+
body: JSON.stringify(id === undefined ? value : { ...value, id }),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
update(collection, id, changes) {
|
|
54
|
+
return this.request(`/collections/${encodeURIComponent(collection)}/${encodeURIComponent(String(id))}`, {
|
|
55
|
+
method: 'PATCH',
|
|
56
|
+
body: JSON.stringify(changes),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
delete(collection, id) {
|
|
60
|
+
return this.request(`/collections/${encodeURIComponent(collection)}/${encodeURIComponent(String(id))}`, {
|
|
61
|
+
method: 'DELETE',
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
getInfo() {
|
|
65
|
+
return { runtime: 'remote', url: this.url };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function createClient(options) {
|
|
69
|
+
return new FeltDBClient(options);
|
|
70
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type IdentityStatus = 'unverified' | 'active' | 'suspended' | 'locked' | 'revoked';
|
|
2
|
+
export interface Identity {
|
|
3
|
+
identityId: string;
|
|
4
|
+
subjectId: string;
|
|
5
|
+
provider: string;
|
|
6
|
+
providerSubject: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
displayName?: string;
|
|
9
|
+
status: IdentityStatus;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
metadata: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface IdentitySession {
|
|
14
|
+
sessionId: string;
|
|
15
|
+
identityId: string;
|
|
16
|
+
subjectId: string;
|
|
17
|
+
issuedAt: number;
|
|
18
|
+
expiresAt: number;
|
|
19
|
+
lastSeenAt: number;
|
|
20
|
+
device?: string;
|
|
21
|
+
provider: string;
|
|
22
|
+
status: string;
|
|
23
|
+
revocationReason?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class IdentityClient {
|
|
26
|
+
private readonly request;
|
|
27
|
+
constructor(request: (path: string, init?: RequestInit) => Promise<any>);
|
|
28
|
+
me(): Promise<any>;
|
|
29
|
+
sessions(): Promise<any>;
|
|
30
|
+
revokeSession(id: string): Promise<any>;
|
|
31
|
+
revokeAll(): Promise<any>;
|
|
32
|
+
normalize(input: {
|
|
33
|
+
provider: string;
|
|
34
|
+
providerSubject: string;
|
|
35
|
+
email?: string;
|
|
36
|
+
displayName?: string;
|
|
37
|
+
metadata?: unknown;
|
|
38
|
+
}): Promise<any>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,YAAY,GAAC,QAAQ,GAAC,WAAW,GAAC,QAAQ,GAAC,SAAS,CAAC;AAClF,MAAM,WAAW,QAAQ;IAAG,UAAU,EAAC,MAAM,CAAC;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,QAAQ,EAAC,MAAM,CAAC;IAAC,eAAe,EAAC,MAAM,CAAC;IAAC,KAAK,CAAC,EAAC,MAAM,CAAC;IAAC,WAAW,CAAC,EAAC,MAAM,CAAC;IAAC,MAAM,EAAC,cAAc,CAAC;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,QAAQ,EAAC,OAAO,CAAA;CAAE;AACzM,MAAM,WAAW,eAAe;IAAG,SAAS,EAAC,MAAM,CAAC;IAAC,UAAU,EAAC,MAAM,CAAC;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,QAAQ,EAAC,MAAM,CAAC;IAAC,SAAS,EAAC,MAAM,CAAC;IAAC,UAAU,EAAC,MAAM,CAAC;IAAC,MAAM,CAAC,EAAC,MAAM,CAAC;IAAC,QAAQ,EAAC,MAAM,CAAC;IAAC,MAAM,EAAC,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAC,MAAM,CAAA;CAAE;AAC1N,qBAAa,cAAc;IAAe,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAC,CAAC,IAAI,EAAC,MAAM,EAAC,IAAI,CAAC,EAAC,WAAW,KAAG,OAAO,CAAC,GAAG,CAAC;IAAI,EAAE;IAA2C,QAAQ;IAAiD,aAAa,CAAC,EAAE,EAAC,MAAM;IAAiG,SAAS;IAA4E,SAAS,CAAC,KAAK,EAAC;QAAC,QAAQ,EAAC,MAAM,CAAC;QAAA,eAAe,EAAC,MAAM,CAAC;QAAA,KAAK,CAAC,EAAC,MAAM,CAAC;QAAA,WAAW,CAAC,EAAC,MAAM,CAAC;QAAA,QAAQ,CAAC,EAAC,OAAO,CAAA;KAAC;CAAyI"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export class IdentityClient {
|
|
2
|
+
constructor(request) {
|
|
3
|
+
this.request = request;
|
|
4
|
+
}
|
|
5
|
+
me() { return this.request('/v1/identity/me'); }
|
|
6
|
+
sessions() { return this.request('/v1/identity/sessions'); }
|
|
7
|
+
revokeSession(id) { return this.request(`/v1/identity/sessions/${encodeURIComponent(id)}/revoke`, { method: 'POST' }); }
|
|
8
|
+
revokeAll() { return this.request('/v1/identity/sessions/revoke-all', { method: 'POST' }); }
|
|
9
|
+
normalize(input) { return this.request('/v1/identity/normalize', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(input) }); }
|
|
10
|
+
}
|