@ibgib/space-gib 0.0.2 → 0.0.4
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/CHANGELOG.md +4 -0
- package/IMPLEMENTATION.md +9 -13
- package/dist/client/bootstrap.mjs +1 -1
- package/dist/client/bootstrap.mjs.map +1 -1
- package/dist/client/chunk-NCXKCVYS.mjs +42 -0
- package/dist/client/chunk-NCXKCVYS.mjs.map +7 -0
- package/dist/client/chunk-ZUEU37Z5.mjs +1920 -0
- package/dist/client/chunk-ZUEU37Z5.mjs.map +7 -0
- package/dist/client/index.html +108 -8
- package/dist/client/index.mjs +1 -1
- package/dist/client/script.mjs +1 -1
- package/dist/client/style.css +466 -61
- package/dist/respec-gib.node.mjs +5 -0
- package/dist/server/server.mjs +815 -316
- package/dist/server/server.mjs.map +4 -4
- package/package.json +6 -6
- package/src/client/AUTO-GENERATED-version.mts +1 -1
- package/src/client/api/space-gib-api-bridge.mts +35 -0
- package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
- package/src/client/components/identity-header/identity-header.css +74 -0
- package/src/client/components/identity-header/identity-header.html +10 -0
- package/src/client/components/identity-header/identity-header.mts +361 -0
- package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
- package/src/client/components/identity-manager/identity-manager.css +467 -0
- package/src/client/components/identity-manager/identity-manager.html +113 -0
- package/src/client/components/identity-manager/identity-manager.mts +767 -0
- package/src/client/components/keystone-creator/keystone-creator.css +2 -76
- package/src/client/components/keystone-creator/keystone-creator.html +41 -26
- package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
- package/src/client/dev-tools/base-tools.mts +252 -0
- package/src/client/dev-tools/common.mts +217 -0
- package/src/client/dev-tools/phase-1.mts +156 -0
- package/src/client/dev-tools/phase-2.mts +143 -0
- package/src/client/dev-tools/phase-3.mts +189 -0
- package/src/client/dev-tools/phase-4-1.mts +197 -0
- package/src/client/dev-tools/phase-4-10.mts +884 -0
- package/src/client/dev-tools/phase-4-2.mts +388 -0
- package/src/client/dev-tools/phase-4-3.mts +391 -0
- package/src/client/dev-tools/phase-4-4.mts +374 -0
- package/src/client/dev-tools/phase-4-5.mts +376 -0
- package/src/client/dev-tools/phase-4-6.mts +273 -0
- package/src/client/dev-tools/phase-4-7.mts +399 -0
- package/src/client/dev-tools/phase-4-8.mts +430 -0
- package/src/client/dev-tools/phase-4-9.mts +398 -0
- package/src/client/dev-tools/phase-4.mts +1302 -0
- package/src/client/dev-tools.mts +55 -1096
- package/src/client/index.html +108 -8
- package/src/client/style.css +466 -61
- package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
- package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
- package/src/common/common-constants.mts +0 -0
- package/src/common/keystone-policies.json +40 -43
- package/src/common/keystone-policies.mts +4 -6
- package/src/server/path-helper.respec.mts +99 -94
- package/src/server/serve-gib/README.md +9 -0
- package/src/server/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +1 -1
- package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
- package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +4 -4
- package/src/server/serve-gib/handlers/api/keystone/keystone-post.handler.mts +1 -1
- package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +37 -5
- package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
- package/dist/client/chunk-BL2SGXS4.mjs +0 -18994
- package/dist/client/chunk-RDTAT5G4.mjs +0 -235
- package/dist/client/chunk-RDTAT5G4.mjs.map +0 -7
- package/dist/client/chunk-RE7XSMHH.mjs +0 -31
- package/dist/client/chunk-RE7XSMHH.mjs.map +0 -7
- package/dist/client/chunk-YUSGN3J4.mjs +0 -23119
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { extractErrorMsg, getUUID, getTimestamp } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
2
|
+
import { Factory_V1 as factory } from '@ibgib/ts-gib/dist/V1/factory.mjs';
|
|
3
|
+
import { ROOT } from '@ibgib/ts-gib/dist/V1/constants.mjs';
|
|
4
|
+
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
5
|
+
import { KeystoneIbGib_V1 } from '@ibgib/core-gib/dist/keystone/keystone-types.mjs';
|
|
6
|
+
import { KeystoneService_V1 } from '@ibgib/core-gib/dist/keystone/keystone-service-v1.mjs';
|
|
7
|
+
import { getGlobalMetaspace_waitIfNeeded } from "@ibgib/web-gib/dist/helpers.mjs";
|
|
8
|
+
import { mut8Timeline, appendToTimeline } from '@ibgib/core-gib/dist/timeline/timeline-api.mjs';
|
|
9
|
+
import { getTjpAddr } from '@ibgib/core-gib/dist/common/other/ibgib-helper.mjs';
|
|
10
|
+
import { SyncPeerWebSocketSender_V1 } from '@ibgib/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs';
|
|
11
|
+
import { SyncSagaCoordinator } from '@ibgib/core-gib/dist/sync/sync-saga-coordinator.mjs';
|
|
12
|
+
import { SyncConflictStrategy } from '@ibgib/core-gib/dist/sync/sync-constants.mjs';
|
|
13
|
+
import { GRAFT_BASE_REL8N_NAME, GRAFT_ORPHAN_REL8N_NAME, GRAFT_INFO_REL8N_NAME } from '@ibgib/core-gib/dist/sync/graft-info/graft-info-constants.mjs';
|
|
14
|
+
import { SESSION_KEYSTONE_POLICY, getSpaceGibPoolConfig } from "../../common/keystone-policies.mjs";
|
|
15
|
+
import { SpaceGibApiBridge } from '../api/space-gib-api-bridge.mjs';
|
|
16
|
+
|
|
17
|
+
import { debugState, devLog } from './common.mjs';
|
|
18
|
+
|
|
19
|
+
interface Phase48State {
|
|
20
|
+
domainI_latest?: KeystoneIbGib_V1;
|
|
21
|
+
testRoot?: any;
|
|
22
|
+
targetAlphaV3a?: any;
|
|
23
|
+
targetBetaV0?: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const state: Phase48State = {};
|
|
27
|
+
|
|
28
|
+
export function init4_8bSetupButton(): void {
|
|
29
|
+
const btn = document.getElementById('btn-4-8b-setup') as HTMLButtonElement | null;
|
|
30
|
+
if (!btn) { return; }
|
|
31
|
+
btn.addEventListener('click', async () => {
|
|
32
|
+
try {
|
|
33
|
+
btn.disabled = true;
|
|
34
|
+
devLog('4.8B Setup: Setting up identities, seeding history, and creating divergent branches in client and remote...');
|
|
35
|
+
|
|
36
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
37
|
+
const space = await metaspace.getLocalUserSpace({}) as any;
|
|
38
|
+
if (!space) { throw new Error("No default space."); }
|
|
39
|
+
|
|
40
|
+
const keystoneService = new KeystoneService_V1();
|
|
41
|
+
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
42
|
+
|
|
43
|
+
// 1. Generate Domain User Identity
|
|
44
|
+
const domainI = await keystoneService.genesis({
|
|
45
|
+
masterSecret: 'test-sender-secret-phase4-8b',
|
|
46
|
+
configs: [
|
|
47
|
+
getSpaceGibPoolConfig('sync', 'senderidentitysyncsaltphase4-8b'),
|
|
48
|
+
getSpaceGibPoolConfig('manage', 'senderidentitymanagesaltphase4-8b'),
|
|
49
|
+
],
|
|
50
|
+
metaspace,
|
|
51
|
+
space,
|
|
52
|
+
frameDetails: { client: 'space-gib-web-dev', timestamp: getTimestamp() }
|
|
53
|
+
});
|
|
54
|
+
state.domainI_latest = domainI;
|
|
55
|
+
let domainI_latest: any = domainI;
|
|
56
|
+
const domainAddr = getIbGibAddr({ ibGib: domainI });
|
|
57
|
+
devLog(`4.8B Setup: ✓ Created identity: ${domainAddr}`);
|
|
58
|
+
|
|
59
|
+
// Register on server
|
|
60
|
+
const apiBridge = new SpaceGibApiBridge();
|
|
61
|
+
const resGenesis = await apiBridge.postGenesisKeystone(domainI);
|
|
62
|
+
if (!resGenesis.success) {
|
|
63
|
+
throw new Error(`Server rejected genesis domain keystone: ${resGenesis.message}`);
|
|
64
|
+
}
|
|
65
|
+
devLog('4.8B Setup: ✓ Identity registered on server.');
|
|
66
|
+
|
|
67
|
+
// 2. Create the divergent "remote" space
|
|
68
|
+
devLog('4.8B Setup: Creating temporary remote space...');
|
|
69
|
+
const remoteSpace = await metaspace.createNewLocalSpace({
|
|
70
|
+
opts: {
|
|
71
|
+
allowCancel: false,
|
|
72
|
+
spaceName: 'remote_space_4_8b',
|
|
73
|
+
getFnPrompt: metaspace.getFnPrompt!
|
|
74
|
+
}
|
|
75
|
+
}) as any;
|
|
76
|
+
await remoteSpace.initialized;
|
|
77
|
+
|
|
78
|
+
// Copy user identity to remote space
|
|
79
|
+
await metaspace.put({ ibGib: domainI, space: remoteSpace });
|
|
80
|
+
await metaspace.registerNewIbGib({ ibGib: domainI, space: remoteSpace });
|
|
81
|
+
|
|
82
|
+
// 3. Seed common history root -> v1 locally
|
|
83
|
+
const resRoot = await factory.firstGen({
|
|
84
|
+
parentIbGib: ROOT,
|
|
85
|
+
ib: 'timeline_root_conflict_4_8b',
|
|
86
|
+
data: { type: 'root', label: 'CommonRoot', random: Math.random() },
|
|
87
|
+
dna: true,
|
|
88
|
+
nCounter: true,
|
|
89
|
+
tjp: { uuid: true, timestamp: true }
|
|
90
|
+
});
|
|
91
|
+
const testRoot = resRoot.newIbGib;
|
|
92
|
+
await metaspace.persistTransformResult({ resTransform: resRoot, space });
|
|
93
|
+
await metaspace.registerNewIbGib({ ibGib: testRoot, space });
|
|
94
|
+
state.testRoot = testRoot;
|
|
95
|
+
|
|
96
|
+
const v1_common = await mut8Timeline({
|
|
97
|
+
timeline: testRoot,
|
|
98
|
+
mut8Opts: { dataToAddOrPatch: { type: 'comment', label: 'V1Common' } },
|
|
99
|
+
metaspace,
|
|
100
|
+
space,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// 4. Copy common history to remote space
|
|
104
|
+
const graphRoot = await metaspace.getDependencyGraph({ ibGibAddr: getIbGibAddr({ ibGib: testRoot }), space });
|
|
105
|
+
const graphV1 = await metaspace.getDependencyGraph({ ibGibAddr: getIbGibAddr({ ibGib: v1_common }), space });
|
|
106
|
+
const commonDepGraph = { ...graphRoot, ...graphV1 };
|
|
107
|
+
await metaspace.put({ ibGibs: Object.values(commonDepGraph), space: remoteSpace });
|
|
108
|
+
await metaspace.registerNewIbGib({ ibGib: testRoot, space: remoteSpace });
|
|
109
|
+
await metaspace.registerNewIbGib({ ibGib: v1_common, space: remoteSpace });
|
|
110
|
+
|
|
111
|
+
// 5. Initial sync of v1_common to the server so server has it
|
|
112
|
+
devLog('4.8B Setup: Syncing v1_common to server...');
|
|
113
|
+
const senderPeerInit = new SyncPeerWebSocketSender_V1({
|
|
114
|
+
classname: 'SyncPeerWebSocketSender_V1',
|
|
115
|
+
httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
|
|
116
|
+
wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
|
|
117
|
+
});
|
|
118
|
+
const coordinatorInit = new SyncSagaCoordinator();
|
|
119
|
+
await senderPeerInit.initializeOpts({
|
|
120
|
+
localMetaspace: metaspace,
|
|
121
|
+
localSpace: space,
|
|
122
|
+
senderIdentity: domainI,
|
|
123
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
|
|
124
|
+
sagaId: await getUUID(),
|
|
125
|
+
sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
|
|
126
|
+
sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
|
|
127
|
+
targetAddrs: [domainAddr]
|
|
128
|
+
});
|
|
129
|
+
const syncSagaInit = await coordinatorInit.sync({
|
|
130
|
+
domainIbGibs: [v1_common],
|
|
131
|
+
senderIdentity: domainI,
|
|
132
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
|
|
133
|
+
peer: senderPeerInit,
|
|
134
|
+
localSpace: space,
|
|
135
|
+
metaspace,
|
|
136
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
137
|
+
});
|
|
138
|
+
await syncSagaInit.done;
|
|
139
|
+
devLog('4.8B Setup: ✓ Seeding complete on server.');
|
|
140
|
+
|
|
141
|
+
// Fetch evolved user identity from space (now at n=2)
|
|
142
|
+
const domainLatestAddr = await metaspace.getLatestAddr({ ibGib: domainI, space });
|
|
143
|
+
if (!domainLatestAddr) { throw new Error("Could not find latest evolved identity address in local space."); }
|
|
144
|
+
const resGetLatest = await metaspace.get({ addr: domainLatestAddr, space });
|
|
145
|
+
if (!resGetLatest.success || !resGetLatest.ibGibs || resGetLatest.ibGibs.length === 0) {
|
|
146
|
+
throw new Error("Could not find latest evolved identity in local space.");
|
|
147
|
+
}
|
|
148
|
+
domainI_latest = resGetLatest.ibGibs[0] as KeystoneIbGib_V1;
|
|
149
|
+
state.domainI_latest = domainI_latest;
|
|
150
|
+
devLog(`4.8B Setup: ✓ Fetched evolved identity: ${domainLatestAddr}`);
|
|
151
|
+
|
|
152
|
+
// Copy evolved user identity to remote space
|
|
153
|
+
await metaspace.put({ ibGib: domainI_latest, space: remoteSpace });
|
|
154
|
+
await metaspace.registerNewIbGib({ ibGib: domainI_latest, space: remoteSpace });
|
|
155
|
+
|
|
156
|
+
// 6. Create Divergence:
|
|
157
|
+
// Client (default space) gets V2a (fieldA edit + relates newly created independent timeline Beta)
|
|
158
|
+
const resBeta = await factory.firstGen({
|
|
159
|
+
parentIbGib: ROOT,
|
|
160
|
+
ib: 'beta_multitimelines_withid_4_8b',
|
|
161
|
+
data: { fieldA: 'beta field A created on source' },
|
|
162
|
+
dna: true,
|
|
163
|
+
nCounter: true,
|
|
164
|
+
tjp: { uuid: true, timestamp: true }
|
|
165
|
+
});
|
|
166
|
+
const beta_v0 = resBeta.newIbGib;
|
|
167
|
+
await metaspace.persistTransformResult({ resTransform: resBeta, space });
|
|
168
|
+
await metaspace.registerNewIbGib({ ibGib: beta_v0, space });
|
|
169
|
+
state.targetBetaV0 = beta_v0;
|
|
170
|
+
devLog(`4.8B Setup: ✓ Created client independent related timeline Beta: ${getIbGibAddr({ ibGib: beta_v0 })}`);
|
|
171
|
+
|
|
172
|
+
const alpha_v2_source_sansBeta = await mut8Timeline({
|
|
173
|
+
timeline: v1_common,
|
|
174
|
+
mut8Opts: { dataToAddOrPatch: { fieldA: 'source_edit' } },
|
|
175
|
+
metaspace,
|
|
176
|
+
space,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const alpha_v3_source_rel8beta = await appendToTimeline({
|
|
180
|
+
timeline: alpha_v2_source_sansBeta,
|
|
181
|
+
metaspace,
|
|
182
|
+
space,
|
|
183
|
+
rel8nInfos: [
|
|
184
|
+
{ rel8nName: 'testrel8n', ibGibs: [beta_v0] }
|
|
185
|
+
],
|
|
186
|
+
});
|
|
187
|
+
state.targetAlphaV3a = alpha_v3_source_rel8beta;
|
|
188
|
+
devLog(`4.8B Setup: ✓ Created client divergent edit V3a: ${getIbGibAddr({ ibGib: alpha_v3_source_rel8beta })}`);
|
|
189
|
+
|
|
190
|
+
// Remote Space gets V2b (fieldB edit)
|
|
191
|
+
const v2b = await mut8Timeline({
|
|
192
|
+
timeline: v1_common,
|
|
193
|
+
mut8Opts: { dataToAddOrPatch: { fieldB: 'dest_edit' } },
|
|
194
|
+
metaspace,
|
|
195
|
+
space: remoteSpace,
|
|
196
|
+
});
|
|
197
|
+
devLog(`4.8B Setup: ✓ Created remote divergent edit V2b: ${getIbGibAddr({ ibGib: v2b })}`);
|
|
198
|
+
|
|
199
|
+
// 7. Sync V2b from remote space to server, so server tip becomes V2b
|
|
200
|
+
devLog('4.8B Setup: Pushing V2b from remote space to server...');
|
|
201
|
+
const senderPeerRemote = new SyncPeerWebSocketSender_V1({
|
|
202
|
+
classname: 'SyncPeerWebSocketSender_V1',
|
|
203
|
+
httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
|
|
204
|
+
wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
|
|
205
|
+
});
|
|
206
|
+
const coordinatorRemote = new SyncSagaCoordinator();
|
|
207
|
+
await senderPeerRemote.initializeOpts({
|
|
208
|
+
localMetaspace: metaspace,
|
|
209
|
+
localSpace: remoteSpace,
|
|
210
|
+
senderIdentity: domainI_latest,
|
|
211
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
|
|
212
|
+
sagaId: await getUUID(),
|
|
213
|
+
sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
|
|
214
|
+
sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
|
|
215
|
+
targetAddrs: [domainAddr]
|
|
216
|
+
});
|
|
217
|
+
const syncSagaRemote = await coordinatorRemote.sync({
|
|
218
|
+
domainIbGibs: [v2b],
|
|
219
|
+
senderIdentity: domainI_latest,
|
|
220
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
|
|
221
|
+
peer: senderPeerRemote,
|
|
222
|
+
localSpace: remoteSpace,
|
|
223
|
+
metaspace,
|
|
224
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
225
|
+
});
|
|
226
|
+
await syncSagaRemote.done;
|
|
227
|
+
devLog('4.8B Setup: ✓ Server tip is now V2b.');
|
|
228
|
+
|
|
229
|
+
// Fetch evolved user identity from remote space (now at n=3)
|
|
230
|
+
const domainLatestAddrRemote = await metaspace.getLatestAddr({ ibGib: domainI, space: remoteSpace });
|
|
231
|
+
if (!domainLatestAddrRemote) { throw new Error("Could not find latest evolved identity address in remote space."); }
|
|
232
|
+
const resGetLatestRemote = await metaspace.get({ addr: domainLatestAddrRemote, space: remoteSpace });
|
|
233
|
+
if (!resGetLatestRemote.success || !resGetLatestRemote.ibGibs || resGetLatestRemote.ibGibs.length === 0) {
|
|
234
|
+
throw new Error("Could not find latest evolved identity in remote space.");
|
|
235
|
+
}
|
|
236
|
+
const domainI_latestRemote = resGetLatestRemote.ibGibs[0] as KeystoneIbGib_V1;
|
|
237
|
+
await metaspace.put({ ibGib: domainI_latestRemote, space });
|
|
238
|
+
await metaspace.registerNewIbGib({ ibGib: domainI_latestRemote, space });
|
|
239
|
+
state.domainI_latest = domainI_latestRemote;
|
|
240
|
+
devLog(`4.8B Setup: ✓ Copied evolved identity tip (n=3) back to default space: ${domainLatestAddrRemote}`);
|
|
241
|
+
|
|
242
|
+
devLog('✓ 4.8B Setup Complete! Ready for 4.8B Sync.');
|
|
243
|
+
btn.textContent = '✓ 4.8B Setup Complete';
|
|
244
|
+
|
|
245
|
+
const syncBtn = document.getElementById('btn-4-8b-sync') as HTMLButtonElement | null;
|
|
246
|
+
if (syncBtn) { syncBtn.disabled = false; }
|
|
247
|
+
|
|
248
|
+
} catch (error) {
|
|
249
|
+
devLog(`✗ 4.8B Setup FAILED: ${extractErrorMsg(error)}`);
|
|
250
|
+
console.error(error);
|
|
251
|
+
btn.disabled = false;
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function init4_8bSyncButton(): void {
|
|
257
|
+
const btn = document.getElementById('btn-4-8b-sync') as HTMLButtonElement | null;
|
|
258
|
+
if (!btn) { return; }
|
|
259
|
+
btn.addEventListener('click', async () => {
|
|
260
|
+
try {
|
|
261
|
+
btn.disabled = true;
|
|
262
|
+
devLog('4.8B Sync: Initiating WebSocket Sync for divergent edit V3a (with related timeline Beta)...');
|
|
263
|
+
|
|
264
|
+
const domainI = state.domainI_latest;
|
|
265
|
+
const targetAlphaV3a = state.targetAlphaV3a;
|
|
266
|
+
if (!domainI || !targetAlphaV3a) {
|
|
267
|
+
devLog('⚠ 4.8B Sync: Missing setup state. Please run Setup first.');
|
|
268
|
+
btn.disabled = false;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const domainAddr = getIbGibAddr({ ibGib: domainI });
|
|
273
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
274
|
+
const space = await metaspace.getLocalUserSpace({}) as any;
|
|
275
|
+
if (!space) { throw new Error("No default space."); }
|
|
276
|
+
|
|
277
|
+
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
278
|
+
|
|
279
|
+
const senderPeer = new SyncPeerWebSocketSender_V1({
|
|
280
|
+
classname: 'SyncPeerWebSocketSender_V1',
|
|
281
|
+
httpEvolveUrl: `${location.protocol}//${location.host}/api/keystone/evolve/${encodeURIComponent(domainAddr)}`,
|
|
282
|
+
wsUrl: `${protocol}//${location.host}/api/sync/ws/${encodeURIComponent(domainAddr)}`
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
const coordinator = new SyncSagaCoordinator();
|
|
286
|
+
const sagaId = await getUUID();
|
|
287
|
+
|
|
288
|
+
await senderPeer.initializeOpts({
|
|
289
|
+
localMetaspace: metaspace,
|
|
290
|
+
localSpace: space,
|
|
291
|
+
senderIdentity: domainI,
|
|
292
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
|
|
293
|
+
sagaId,
|
|
294
|
+
sessionConnectPoolConfig: SESSION_KEYSTONE_POLICY.CONNECT_POOL as any,
|
|
295
|
+
sessionSyncPoolConfig: SESSION_KEYSTONE_POLICY.DEFAULT_POOL as any,
|
|
296
|
+
targetAddrs: [domainAddr]
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// Run Sync. Client has V3a (with Beta), server has V2b. This will trigger optimistic graft merge!
|
|
300
|
+
const syncSaga = await coordinator.sync({
|
|
301
|
+
domainIbGibs: [targetAlphaV3a],
|
|
302
|
+
senderIdentity: domainI,
|
|
303
|
+
fnSenderSecret: async () => 'test-sender-secret-phase4-8b',
|
|
304
|
+
peer: senderPeer,
|
|
305
|
+
localSpace: space,
|
|
306
|
+
metaspace,
|
|
307
|
+
conflictStrategy: SyncConflictStrategy.optimisticWithLCS,
|
|
308
|
+
});
|
|
309
|
+
await syncSaga.done;
|
|
310
|
+
|
|
311
|
+
devLog('✓ 4.8B Sync Execution Complete! Ready for 4.8B Check.');
|
|
312
|
+
btn.textContent = '✓ 4.8B Sync Run';
|
|
313
|
+
|
|
314
|
+
const checkBtn = document.getElementById('btn-4-8b-check') as HTMLButtonElement | null;
|
|
315
|
+
if (checkBtn) { checkBtn.disabled = false; }
|
|
316
|
+
|
|
317
|
+
} catch (error) {
|
|
318
|
+
devLog(`✗ 4.8B Sync FAILED: ${extractErrorMsg(error)}`);
|
|
319
|
+
console.error(error);
|
|
320
|
+
btn.disabled = false;
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function init4_8bCheckButton(): void {
|
|
326
|
+
const btn = document.getElementById('btn-4-8b-check') as HTMLButtonElement | null;
|
|
327
|
+
if (!btn) { return; }
|
|
328
|
+
btn.addEventListener('click', async () => {
|
|
329
|
+
try {
|
|
330
|
+
btn.disabled = true;
|
|
331
|
+
devLog('4.8B Check: Verifying merged tip (V4) contains both edits on client and server...');
|
|
332
|
+
|
|
333
|
+
const domainI = state.domainI_latest;
|
|
334
|
+
const testRoot = state.testRoot;
|
|
335
|
+
const targetAlphaV3a = state.targetAlphaV3a;
|
|
336
|
+
const targetBetaV0 = state.targetBetaV0;
|
|
337
|
+
if (!domainI || !testRoot || !targetAlphaV3a || !targetBetaV0) {
|
|
338
|
+
devLog('⚠ 4.8B Check: Missing state. Did Setup and Sync run?');
|
|
339
|
+
btn.disabled = false;
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const domainAddr = getIbGibAddr({ ibGib: domainI });
|
|
344
|
+
const tjpAddr = getTjpAddr({ ibGib: testRoot, defaultIfNone: 'incomingAddr' }) ?? getIbGibAddr({ ibGib: testRoot });
|
|
345
|
+
const betaAddr = getIbGibAddr({ ibGib: targetBetaV0 });
|
|
346
|
+
|
|
347
|
+
const metaspace = await getGlobalMetaspace_waitIfNeeded();
|
|
348
|
+
const space = await metaspace.getLocalUserSpace({}) as any;
|
|
349
|
+
if (!space) { throw new Error("No default space."); }
|
|
350
|
+
|
|
351
|
+
// 1. Check client default space tip
|
|
352
|
+
const clientKV = await metaspace.getLocalUserSpace({}).then((space: any) => {
|
|
353
|
+
return new SyncSagaCoordinator().getKnowledgeMap({
|
|
354
|
+
space,
|
|
355
|
+
metaspace,
|
|
356
|
+
domainIbGibs: [testRoot]
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
const clientTipAddr = clientKV[tjpAddr];
|
|
360
|
+
devLog(`4.8B Check: Client tip address: ${clientTipAddr}`);
|
|
361
|
+
|
|
362
|
+
if (!clientTipAddr) {
|
|
363
|
+
throw new Error("Client default space is missing the timeline tip.");
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const resTip = await metaspace.get({ addr: clientTipAddr, space });
|
|
367
|
+
if (!resTip.success || !resTip.ibGibs || resTip.ibGibs.length === 0) {
|
|
368
|
+
throw new Error("Client tip not found in default local space.");
|
|
369
|
+
}
|
|
370
|
+
const clientTip = resTip.ibGibs[0];
|
|
371
|
+
|
|
372
|
+
if (!clientTip.data || !clientTip.data.fieldA || !clientTip.data.fieldB) {
|
|
373
|
+
throw new Error(`Merged client tip is missing expected data edits: fieldA: ${clientTip.data?.fieldA}, fieldB: ${clientTip.data?.fieldB}`);
|
|
374
|
+
}
|
|
375
|
+
devLog('4.8B Check: ✓ Client tip has both fieldA and fieldB edits.');
|
|
376
|
+
|
|
377
|
+
// Verify graftinfo rel8n exists
|
|
378
|
+
const graftInfoRel = clientTip.rel8ns?.[GRAFT_INFO_REL8N_NAME];
|
|
379
|
+
if (!graftInfoRel?.[0]) {
|
|
380
|
+
throw new Error("Client tip is missing graftinfo relations.");
|
|
381
|
+
}
|
|
382
|
+
const resGraft = await metaspace.get({ addr: graftInfoRel[0], space });
|
|
383
|
+
if (!resGraft.success || !resGraft.ibGibs || resGraft.ibGibs.length === 0) {
|
|
384
|
+
throw new Error("GraftInfo not found in local space.");
|
|
385
|
+
}
|
|
386
|
+
const graftInfo = resGraft.ibGibs[0];
|
|
387
|
+
const baseRel = graftInfo.rel8ns?.[GRAFT_BASE_REL8N_NAME];
|
|
388
|
+
const orphanRel = graftInfo.rel8ns?.[GRAFT_ORPHAN_REL8N_NAME];
|
|
389
|
+
|
|
390
|
+
if (!baseRel || !orphanRel) {
|
|
391
|
+
throw new Error("GraftInfo is missing graftbase or graftorphan relations.");
|
|
392
|
+
}
|
|
393
|
+
devLog('4.8B Check: ✓ Client graft base and orphan relations are correctly set.');
|
|
394
|
+
|
|
395
|
+
// 2. Check server tip
|
|
396
|
+
const apiBridge = new SpaceGibApiBridge();
|
|
397
|
+
devLog('4.8B Check: Fetching server timeline graph...');
|
|
398
|
+
const resServerGraph = await apiBridge.getIbGibGraph(domainAddr, clientTipAddr, true);
|
|
399
|
+
if (!resServerGraph.success || !resServerGraph.graph) {
|
|
400
|
+
throw new Error(`Failed to fetch merged graph from server: ${resServerGraph.message}`);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const serverTip = resServerGraph.graph[clientTipAddr];
|
|
404
|
+
if (!serverTip) {
|
|
405
|
+
throw new Error("Merged V4 tip is not present on the server!");
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (serverTip.data?.fieldA !== 'source_edit' || serverTip.data?.fieldB !== 'dest_edit') {
|
|
409
|
+
throw new Error("Server tip data edits do not match merged values.");
|
|
410
|
+
}
|
|
411
|
+
devLog('4.8B Check: ✓ Server tip has matching merged edits.');
|
|
412
|
+
|
|
413
|
+
// 3. Verify related timeline Beta exists on the server!
|
|
414
|
+
devLog('4.8B Check: Verifying related timeline Beta is present on the server...');
|
|
415
|
+
const resBetaGraph = await apiBridge.getIbGibGraph(domainAddr, betaAddr, true);
|
|
416
|
+
if (!resBetaGraph.success || !resBetaGraph.graph || !resBetaGraph.graph[betaAddr]) {
|
|
417
|
+
throw new Error(`Related timeline Beta (${betaAddr}) is missing from the server!`);
|
|
418
|
+
}
|
|
419
|
+
devLog('4.8B Check: ✓ Related timeline Beta successfully verified on the server.');
|
|
420
|
+
|
|
421
|
+
devLog('✓ 4.8B Check SUCCESS: Divergent branches merged successfully and related timeline synced on server!');
|
|
422
|
+
btn.textContent = '✓ 4.8B Check Success';
|
|
423
|
+
|
|
424
|
+
} catch (error) {
|
|
425
|
+
devLog(`✗ 4.8B Check FAILED: ${extractErrorMsg(error)}`);
|
|
426
|
+
console.error(error);
|
|
427
|
+
btn.disabled = false;
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|