@ibgib/web-gib 0.0.52 → 0.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/AUTO-GENERATED-version.d.mts +1 -1
  3. package/dist/AUTO-GENERATED-version.mjs +1 -1
  4. package/dist/api/commands/chat/hello-world.mjs.map +1 -1
  5. package/dist/api/commands/command-constants.d.mts +4 -4
  6. package/dist/api/commands/command-constants.d.mts.map +1 -1
  7. package/dist/api/commands/command-service-v1.d.mts.map +1 -1
  8. package/dist/api/commands/command-service-v1.mjs.map +1 -1
  9. package/dist/api/commands/ibgib/get-ibgibs.d.mts.map +1 -1
  10. package/dist/api/commands/ibgib/get-ibgibs.mjs.map +1 -1
  11. package/dist/api/ibgib-api-bridge.d.mts +81 -0
  12. package/dist/api/ibgib-api-bridge.d.mts.map +1 -0
  13. package/dist/api/ibgib-api-bridge.mjs +259 -0
  14. package/dist/api/ibgib-api-bridge.mjs.map +1 -0
  15. package/dist/app-bootstrap/init-orchestration.d.mts +1 -1
  16. package/dist/app-bootstrap/init-orchestration.d.mts.map +1 -1
  17. package/dist/app-bootstrap/init-orchestration.mjs +17 -3
  18. package/dist/app-bootstrap/init-orchestration.mjs.map +1 -1
  19. package/dist/assets/fullscreen-dialog.html +18 -0
  20. package/dist/assumptions.respec.mjs.map +1 -1
  21. package/dist/common/settings/settings-constants.d.mts.map +1 -1
  22. package/dist/helpers.d.mts.map +1 -1
  23. package/dist/helpers.mjs.map +1 -1
  24. package/dist/helpers.web.d.mts.map +1 -1
  25. package/dist/helpers.web.mjs.map +1 -1
  26. package/dist/helpers.web.respec.mjs.map +1 -1
  27. package/dist/identity/keystone-sync-service.d.mts +37 -0
  28. package/dist/identity/keystone-sync-service.d.mts.map +1 -0
  29. package/dist/identity/keystone-sync-service.mjs +211 -0
  30. package/dist/identity/keystone-sync-service.mjs.map +1 -0
  31. package/dist/identity/sso/sso-custodian-service.d.mts.map +1 -1
  32. package/dist/identity/sso/sso-custodian-service.mjs.map +1 -1
  33. package/dist/identity/sso/sso-custodian-service.respec.mjs.map +1 -1
  34. package/dist/index.d.mts +17 -1
  35. package/dist/index.d.mts.map +1 -1
  36. package/dist/index.mjs +21 -26
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/storage/storage-helpers.web.mjs.map +1 -1
  39. package/dist/ui/component/common-component-styles.css +270 -0
  40. package/dist/ui/component/ibgib-component-service.d.mts.map +1 -1
  41. package/dist/ui/component/ibgib-dynamic-component-bases.d.mts.map +1 -1
  42. package/dist/ui/component/ibgib-dynamic-component-bases.mjs.map +1 -1
  43. package/dist/ui/component/identity/add-device/add-device.css +133 -0
  44. package/dist/ui/component/identity/add-device/add-device.d.mts +49 -0
  45. package/dist/ui/component/identity/add-device/add-device.d.mts.map +1 -0
  46. package/dist/ui/component/identity/add-device/add-device.html +52 -0
  47. package/dist/ui/component/identity/add-device/add-device.mjs +321 -0
  48. package/dist/ui/component/identity/add-device/add-device.mjs.map +1 -0
  49. package/dist/ui/component/identity/identity-header/identity-header.css +317 -0
  50. package/dist/ui/component/identity/identity-header/identity-header.d.mts +85 -0
  51. package/dist/ui/component/identity/identity-header/identity-header.d.mts.map +1 -0
  52. package/dist/ui/component/identity/identity-header/identity-header.html +72 -0
  53. package/dist/ui/component/identity/identity-header/identity-header.mjs +546 -0
  54. package/dist/ui/component/identity/identity-header/identity-header.mjs.map +1 -0
  55. package/dist/ui/component/identity/identity-manager/identity-manager.css +178 -0
  56. package/dist/ui/component/identity/identity-manager/identity-manager.d.mts +76 -0
  57. package/dist/ui/component/identity/identity-manager/identity-manager.d.mts.map +1 -0
  58. package/dist/ui/component/identity/identity-manager/identity-manager.html +19 -0
  59. package/dist/ui/component/identity/identity-manager/identity-manager.mjs +591 -0
  60. package/dist/ui/component/identity/identity-manager/identity-manager.mjs.map +1 -0
  61. package/dist/ui/component/identity/index.d.mts +17 -0
  62. package/dist/ui/component/identity/index.d.mts.map +1 -0
  63. package/dist/ui/component/identity/index.mjs +34 -0
  64. package/dist/ui/component/identity/index.mjs.map +1 -0
  65. package/dist/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
  66. package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts +58 -0
  67. package/dist/ui/component/identity/keystone-creator/keystone-creator.d.mts.map +1 -0
  68. package/dist/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
  69. package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs +410 -0
  70. package/dist/ui/component/identity/keystone-creator/keystone-creator.mjs.map +1 -0
  71. package/dist/ui/component/identity/keystone-details/keystone-details.css +621 -0
  72. package/dist/ui/component/identity/keystone-details/keystone-details.d.mts +98 -0
  73. package/dist/ui/component/identity/keystone-details/keystone-details.d.mts.map +1 -0
  74. package/dist/ui/component/identity/keystone-details/keystone-details.html +154 -0
  75. package/dist/ui/component/identity/keystone-details/keystone-details.mjs +1377 -0
  76. package/dist/ui/component/identity/keystone-details/keystone-details.mjs.map +1 -0
  77. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
  78. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts +64 -0
  79. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.d.mts.map +1 -0
  80. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
  81. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs +300 -0
  82. package/dist/ui/component/identity/keystone-scrubber/keystone-scrubber.mjs.map +1 -0
  83. package/dist/ui/component/identity/remove-device/remove-device.css +118 -0
  84. package/dist/ui/component/identity/remove-device/remove-device.d.mts +50 -0
  85. package/dist/ui/component/identity/remove-device/remove-device.d.mts.map +1 -0
  86. package/dist/ui/component/identity/remove-device/remove-device.html +31 -0
  87. package/dist/ui/component/identity/remove-device/remove-device.mjs +188 -0
  88. package/dist/ui/component/identity/remove-device/remove-device.mjs.map +1 -0
  89. package/dist/ui/ui-constants.d.mts +1 -0
  90. package/dist/ui/ui-constants.d.mts.map +1 -1
  91. package/dist/ui/ui-constants.mjs +1 -0
  92. package/dist/ui/ui-constants.mjs.map +1 -1
  93. package/dist/ui/ui-types.d.mts +7 -0
  94. package/dist/ui/ui-types.d.mts.map +1 -1
  95. package/dist/witness/agent/agent-constants.d.mts.map +1 -1
  96. package/dist/witness/agent/agent-helpers.mjs.map +1 -1
  97. package/dist/witness/agent/agent-one-file.d.mts.map +1 -1
  98. package/dist/witness/agent/agent-one-file.mjs.map +1 -1
  99. package/dist/witness/agent/agents-service-v1.d.mts.map +1 -1
  100. package/dist/witness/agent/agents-service-v1.mjs.map +1 -1
  101. package/dist/witness/agent/gemini/agent-witness-gemini-v1.d.mts.map +1 -1
  102. package/dist/witness/agent/gemini/gemini-agent-factory.d.mts.map +1 -1
  103. package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.d.mts.map +1 -1
  104. package/dist/witness/live-proxy-ibgib/live-proxy-ibgib-one-file.mjs.map +1 -1
  105. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace-helper.mjs.map +1 -1
  106. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts +4 -0
  107. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.d.mts.map +1 -1
  108. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs +40 -1
  109. package/dist/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mjs.map +1 -1
  110. package/dist/witness/space/web-filesystem-space/web-filesystem-space-types.d.mts.map +1 -1
  111. package/dist/witness/space/web-filesystem-space/web-filesystem-space-v1.d.mts.map +1 -1
  112. package/package.json +2 -2
  113. package/src/AUTO-GENERATED-version.mts +1 -1
  114. package/src/api/ibgib-api-bridge.mts +292 -0
  115. package/src/app-bootstrap/init-orchestration.mts +17 -6
  116. package/src/custom.d.ts +11 -0
  117. package/src/identity/keystone-sync-service.mts +257 -0
  118. package/src/index.mts +24 -25
  119. package/src/ui/component/README.md +82 -5
  120. package/src/ui/component/common-component-styles.css +270 -0
  121. package/src/ui/component/identity/add-device/add-device.css +133 -0
  122. package/src/ui/component/identity/add-device/add-device.html +52 -0
  123. package/src/ui/component/identity/add-device/add-device.mts +397 -0
  124. package/src/ui/component/identity/identity-header/IMPLEMENTATION.md +45 -0
  125. package/src/ui/component/identity/identity-header/identity-header.css +317 -0
  126. package/src/ui/component/identity/identity-header/identity-header.html +72 -0
  127. package/src/ui/component/identity/identity-header/identity-header.mts +651 -0
  128. package/src/ui/component/identity/identity-manager/IMPLEMENTATION.md +100 -0
  129. package/src/ui/component/identity/identity-manager/identity-manager.css +178 -0
  130. package/src/ui/component/identity/identity-manager/identity-manager.html +19 -0
  131. package/src/ui/component/identity/identity-manager/identity-manager.mts +675 -0
  132. package/src/ui/component/identity/index.mts +36 -0
  133. package/src/ui/component/identity/keystone-creator/keystone-creator.css +97 -0
  134. package/src/ui/component/identity/keystone-creator/keystone-creator.html +51 -0
  135. package/src/ui/component/identity/keystone-creator/keystone-creator.mts +497 -0
  136. package/src/ui/component/identity/keystone-details/keystone-details.css +621 -0
  137. package/src/ui/component/identity/keystone-details/keystone-details.html +154 -0
  138. package/src/ui/component/identity/keystone-details/keystone-details.mts +1506 -0
  139. package/src/ui/component/identity/keystone-scrubber/SCRUBBER_IMPLEMENTATION.md +33 -0
  140. package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.css +46 -0
  141. package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.html +15 -0
  142. package/src/ui/component/identity/keystone-scrubber/keystone-scrubber.mts +355 -0
  143. package/src/ui/component/identity/remove-device/remove-device.css +118 -0
  144. package/src/ui/component/identity/remove-device/remove-device.html +31 -0
  145. package/src/ui/component/identity/remove-device/remove-device.mts +247 -0
  146. package/src/ui/ui-constants.mts +1 -0
  147. package/src/ui/ui-types.mts +8 -0
  148. package/src/witness/space/metaspace/metaspace-webspace/metaspace-webspace.mts +42 -1
  149. package/tools/auto-generated-agent-skills/skills/ibgib-dependency-graph/SKILL.md +209 -0
  150. package/tools/auto-generated-agent-skills/skills/ibgib-implementation-plan/SKILL.md +102 -0
@@ -0,0 +1,292 @@
1
+ /**
2
+ * @module api/ibgib-api-bridge
3
+ *
4
+ * Base REST API bridge class for interacting with serve-gib endpoints from browser clients.
5
+ */
6
+
7
+ import { extractErrorMsg } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
8
+ import { IbGib_V1 } from "@ibgib/ts-gib/dist/V1/types.mjs";
9
+
10
+ const logalot = false;
11
+
12
+ export class IbGibApiBridge {
13
+ protected lc: string = `[${IbGibApiBridge.name}]`;
14
+
15
+ protected async parseResponseJson<T = any>(response: Response, url: string): Promise<T> {
16
+ const contentType = response.headers.get('content-type') || '';
17
+ if (!contentType.includes('application/json')) {
18
+ const text = await response.text();
19
+ if (text.trim().toLowerCase().startsWith('<!doctype html') || text.includes('<html')) {
20
+ throw new Error(`API request to '${url}' failed (${response.status} ${response.statusText}): Received HTML fallback instead of JSON. Check API route matching and parameters.`);
21
+ }
22
+ throw new Error(`API request to '${url}' failed (${response.status} ${response.statusText}): Returned non-JSON content type '${contentType}': ${text.slice(0, 150)}`);
23
+ }
24
+ return await response.json();
25
+ }
26
+
27
+ /**
28
+ * Posts a single genesis keystone ibgib to the server to create a new domain.
29
+ */
30
+ public async postGenesisKeystone(keystoneIbGib: IbGib_V1): Promise<{ success: boolean; message?: string; addr?: string }> {
31
+ const lc = `${this.lc}[${this.postGenesisKeystone.name}]`;
32
+ try {
33
+ if (logalot) { console.log(`${lc} starting... (I: eecd082fc4a4381c8857928e8b090826)`); }
34
+
35
+ const url = '/api/keystone/genesis';
36
+ const response = await fetch(url, {
37
+ method: 'POST',
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ },
41
+ body: JSON.stringify({ keystoneIbGib }),
42
+ });
43
+
44
+ const data = await this.parseResponseJson(response, url);
45
+
46
+ if (!response.ok) {
47
+ const errorMsg = data.message || data.error || 'Unknown error';
48
+ console.error(`${lc} server rejected genesis keystone: ${errorMsg}`);
49
+ return { success: false, message: errorMsg, addr: data.addr };
50
+ }
51
+
52
+ if (logalot) { console.log(`${lc} genesis keystone posted successfully.`); }
53
+ return { success: true, addr: data.addr };
54
+
55
+ } catch (error) {
56
+ const errorMsg = extractErrorMsg(error);
57
+ console.error(`${lc} error: ${errorMsg}`);
58
+ return { success: false, message: errorMsg };
59
+ }
60
+ }
61
+
62
+ /**
63
+ * PUTs an evolved domain keystone and any related keystones to the server.
64
+ */
65
+ public async putEvolveKeystone({
66
+ domainAddr,
67
+ keystoneIbGib,
68
+ relatedKeystoneIbGibs = [],
69
+ revokeTokens
70
+ }: {
71
+ domainAddr: string;
72
+ keystoneIbGib: IbGib_V1;
73
+ relatedKeystoneIbGibs?: IbGib_V1[];
74
+ revokeTokens?: Record<string, string>;
75
+ }): Promise<{ success: boolean; message?: string }> {
76
+ const lc = `${this.lc}[${this.putEvolveKeystone.name}]`;
77
+ try {
78
+ if (logalot) { console.log(`${lc} posting evolved keystone...`); }
79
+
80
+ const url = `/api/keystone/evolve/${encodeURIComponent(domainAddr)}`;
81
+ const response = await fetch(url, {
82
+ method: 'PUT',
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ body: JSON.stringify({
87
+ keystoneIbGib,
88
+ relatedKeystoneIbGibs,
89
+ revokeTokens
90
+ }),
91
+ });
92
+
93
+ const data = await this.parseResponseJson(response, url);
94
+
95
+ if (!response.ok) {
96
+ const errorMsg = data.message || data.error || 'Unknown error';
97
+ console.error(`${lc} server rejected keystone evolution: ${errorMsg}`);
98
+ return { success: false, message: errorMsg };
99
+ }
100
+
101
+ if (logalot) { console.log(`${lc} keystone evolution accepted by server.`); }
102
+ return { success: true };
103
+
104
+ } catch (error) {
105
+ const errorMsg = extractErrorMsg(error);
106
+ console.error(`${lc} fetch error: ${errorMsg}`);
107
+ return { success: false, message: errorMsg };
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Looks up a primary identity keystone on the server by username or email.
113
+ */
114
+ public async lookupPrimaryKeystone({ identifier }: { identifier: string }): Promise<{ success: boolean; message?: string; tjpAddr?: string; primaryKeystoneIbGib?: IbGib_V1 }> {
115
+ const lc = `${this.lc}[${this.lookupPrimaryKeystone.name}]`;
116
+ try {
117
+ const url = '/api/keystone/lookup';
118
+ const response = await fetch(url, {
119
+ method: 'POST',
120
+ headers: {
121
+ 'Content-Type': 'application/json',
122
+ },
123
+ body: JSON.stringify({ identifier }),
124
+ });
125
+
126
+ const data = await this.parseResponseJson(response, url);
127
+
128
+ if (!response.ok) {
129
+ const errorMsg = data.message || data.error || 'Identity not found';
130
+ console.error(`${lc} server lookup failed: ${errorMsg}`);
131
+ return { success: false, message: errorMsg };
132
+ }
133
+
134
+ return {
135
+ success: true,
136
+ tjpAddr: data.tjpAddr,
137
+ primaryKeystoneIbGib: data.primaryKeystoneIbGib
138
+ };
139
+ } catch (error) {
140
+ const errorMsg = extractErrorMsg(error);
141
+ console.error(`${lc} lookup fetch error: ${errorMsg}`);
142
+ return { success: false, message: errorMsg };
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Checks if an email address is available on the server before local genesis.
148
+ */
149
+ public async checkEmailAvailability({ email }: { email: string }): Promise<{ available: boolean; message?: string }> {
150
+ const lc = `${this.lc}[${this.checkEmailAvailability.name}]`;
151
+ try {
152
+ const url = `/api/keystone/check-email?email=${encodeURIComponent(email)}`;
153
+ const response = await fetch(url, {
154
+ method: 'GET',
155
+ headers: {
156
+ 'Content-Type': 'application/json',
157
+ },
158
+ });
159
+
160
+ const data = await this.parseResponseJson(response, url);
161
+
162
+ if (!response.ok) {
163
+ const errorMsg = data.message || data.error || 'Server check failed';
164
+ console.error(`${lc} email check failed: ${errorMsg}`);
165
+ return { available: false, message: errorMsg };
166
+ }
167
+
168
+ return {
169
+ available: data.available ?? true,
170
+ message: data.message
171
+ };
172
+ } catch (error) {
173
+ const errorMsg = extractErrorMsg(error);
174
+ console.error(`${lc} check email error: ${errorMsg}`);
175
+ return { available: true }; // network error fallback
176
+ }
177
+ }
178
+ public async getKeystoneGraph(domainAddr: string): Promise<{ success: boolean; message?: string; graph?: Record<string, any> }> {
179
+ const lc = `${this.lc}[${this.getKeystoneGraph.name}]`;
180
+ try {
181
+ if (logalot) { console.log(`${lc} fetching keystone graph...`); }
182
+
183
+ const url = `/api/keystone/${encodeURIComponent(domainAddr)}?getLatest=true&getGraph=true`;
184
+ const response = await fetch(url, {
185
+ method: 'GET',
186
+ headers: {
187
+ 'Accept': 'application/json',
188
+ }
189
+ });
190
+
191
+ const data = await this.parseResponseJson(response, url);
192
+
193
+ if (!response.ok) {
194
+ const errorMsg = data.message || data.error || 'Unknown error';
195
+ console.error(`${lc} server rejected keystone graph get: ${errorMsg}`);
196
+ return { success: false, message: errorMsg };
197
+ }
198
+
199
+ return { success: true, graph: data.domainGraph };
200
+
201
+ } catch (error) {
202
+ const errorMsg = extractErrorMsg(error);
203
+ console.error(`${lc} fetch error: ${errorMsg}`);
204
+ return { success: false, message: errorMsg };
205
+ }
206
+ }
207
+
208
+ /**
209
+ * GETs a single ibGib frame from the server's domain space.
210
+ */
211
+ public async getIbGib(domainAddr: string, ibGibAddr: string, getLatest = false): Promise<{ success: boolean; message?: string; ibGib?: IbGib_V1 }> {
212
+ const lc = `${this.lc}[${this.getIbGib.name}]`;
213
+ try {
214
+ if (logalot) { console.log(`${lc} fetching single ibGib frame...`); }
215
+
216
+ const url = `/api/ibgib/${encodeURIComponent(domainAddr)}/${encodeURIComponent(ibGibAddr)}?getLatest=${getLatest}&getGraph=false`;
217
+ const response = await fetch(url, {
218
+ method: 'GET',
219
+ headers: {
220
+ 'Accept': 'application/json',
221
+ }
222
+ });
223
+
224
+ const data = await this.parseResponseJson(response, url);
225
+
226
+ if (!response.ok) {
227
+ const errorMsg = data.message || data.error || 'Unknown error';
228
+ console.error(`${lc} server rejected ibGib get: ${errorMsg}`);
229
+ return { success: false, message: errorMsg };
230
+ }
231
+
232
+ return { success: true, ibGib: data };
233
+
234
+ } catch (error) {
235
+ const errorMsg = extractErrorMsg(error);
236
+ console.error(`${lc} fetch error: ${errorMsg}`);
237
+ return { success: false, message: errorMsg };
238
+ }
239
+ }
240
+
241
+ /**
242
+ * GETs the full dependency graph of an ibGib from the server's domain space.
243
+ */
244
+ public async getIbGibGraph(domainAddr: string, ibGibAddr: string, getLatest = false): Promise<{ success: boolean; message?: string; graph?: Record<string, IbGib_V1>; addr?: string }> {
245
+ const lc = `${this.lc}[${this.getIbGibGraph.name}]`;
246
+ try {
247
+ if (logalot) { console.log(`${lc} fetching ibGib graph...`); }
248
+
249
+ const url = `/api/ibgib/${encodeURIComponent(domainAddr)}/${encodeURIComponent(ibGibAddr)}?getLatest=${getLatest}&getGraph=true`;
250
+ const response = await fetch(url, {
251
+ method: 'GET',
252
+ headers: {
253
+ 'Accept': 'application/json',
254
+ }
255
+ });
256
+
257
+ const data = await response.json();
258
+
259
+ if (!response.ok) {
260
+ const errorMsg = data.message || data.error || 'Unknown error';
261
+ console.error(`${lc} server rejected ibGib graph get: ${errorMsg}`);
262
+ return { success: false, message: errorMsg };
263
+ }
264
+
265
+ return { success: true, graph: data.graph, addr: data.addr };
266
+
267
+ } catch (error) {
268
+ const errorMsg = extractErrorMsg(error);
269
+ console.error(`${lc} fetch error: ${errorMsg}`);
270
+ return { success: false, message: errorMsg };
271
+ }
272
+ }
273
+ }
274
+
275
+ let _apiBridge: IbGibApiBridge | undefined;
276
+
277
+ /**
278
+ * Returns the global API bridge instance, creating a default IbGibApiBridge if not set.
279
+ */
280
+ export function getApiBridge(): IbGibApiBridge {
281
+ if (!_apiBridge) {
282
+ _apiBridge = new IbGibApiBridge();
283
+ }
284
+ return _apiBridge;
285
+ }
286
+
287
+ /**
288
+ * Registers a custom API bridge instance (e.g. SpaceGibApiBridge or app-specific subclass).
289
+ */
290
+ export function setApiBridge(bridge: IbGibApiBridge): void {
291
+ _apiBridge = bridge;
292
+ }
@@ -213,7 +213,7 @@ export async function dynamicallyLoadBootstrapScript(
213
213
  * @param globalThisKey The per-app namespace key used to find the bootstrap
214
214
  * promise on globalThis.
215
215
  */
216
- export function getComponentCtorArg(globalThisKey: string): IbGibDynamicComponentMetaCtorOpts {
216
+ export function getComponentCtorArg(globalThisKey?: string): IbGibDynamicComponentMetaCtorOpts {
217
217
  const fnGetMetaspace = async () => getGlobalMetaspace_waitIfNeeded();
218
218
 
219
219
  const bootstrapPromiseWrapper = new Promise<void>(async (resolve, reject) => {
@@ -222,16 +222,27 @@ export function getComponentCtorArg(globalThisKey: string): IbGibDynamicComponen
222
222
  let counter = 0;
223
223
  let bootstrapPromise: Promise<void> | undefined;
224
224
  do {
225
- bootstrapPromise =
226
- getIbGibGlobalThis_IbGibApp(globalThisKey)?.bootstrapPromise;
225
+ if (globalThisKey) {
226
+ bootstrapPromise = getIbGibGlobalThis_IbGibApp(globalThisKey)?.bootstrapPromise;
227
+ } else {
228
+ bootstrapPromise = (globalThis as any).ibgib?.bootstrapPromise;
229
+ if (!bootstrapPromise && (globalThis as any).ibgib) {
230
+ const keys = Object.keys((globalThis as any).ibgib);
231
+ for (const k of keys) {
232
+ if ((globalThis as any).ibgib[k]?.bootstrapPromise) {
233
+ bootstrapPromise = (globalThis as any).ibgib[k].bootstrapPromise;
234
+ break;
235
+ }
236
+ }
237
+ }
238
+ }
227
239
  counter++;
228
240
  if (counter > maxTries) { break; }
229
241
  await delay(10);
230
242
  } while (bootstrapPromise === undefined);
231
243
  if (!bootstrapPromise) {
232
- throw new Error(
233
- `Timed out waiting for bootstrapPromise on key '${globalThisKey}'. (E: 4c48ce92ibgib-common26)`
234
- );
244
+ resolve();
245
+ return;
235
246
  }
236
247
  await bootstrapPromise;
237
248
  resolve();
@@ -0,0 +1,11 @@
1
+ // Tell TypeScript that importing a .html file will return a string.
2
+ declare module '*.html' {
3
+ const value: string;
4
+ export default value;
5
+ }
6
+
7
+ // Tell TypeScript that importing a .css file will return a string.
8
+ declare module '*.css' {
9
+ const value: string;
10
+ export default value;
11
+ }
@@ -0,0 +1,257 @@
1
+ /**
2
+ * @module identity/keystone-sync-service
3
+ *
4
+ * On-Demand Keystone Sync Service.
5
+ * Provides functions to check for keystone updates on the server and sync updated keystone DAG graphs locally.
6
+ */
7
+
8
+ import { extractErrorMsg } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs";
9
+ import { getIbAndGib, getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs";
10
+ import { getGibInfo } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs";
11
+ import { KeystoneIbGib_V1 } from "@ibgib/core-gib/dist/keystone/keystone-types.mjs";
12
+ import { getTimelinesGroupedByTjp, getTjpAddr, toDto } from "@ibgib/core-gib/dist/common/other/ibgib-helper.mjs";
13
+ import { updateSpecialIndex } from "@ibgib/core-gib/dist/timeline/timeline-api.mjs";
14
+ import { getApiBridge } from "../api/ibgib-api-bridge.mjs";
15
+ import { getGlobalMetaspace_waitIfNeeded } from "../helpers.mjs";
16
+ import { EVENT_IBGIB_IDENTITY_UPDATE_AVAILABLE } from "../ui/ui-constants.mjs";
17
+ import { EventIbGibIdentityUpdateAvailableDetail } from "../ui/ui-types.mjs";
18
+
19
+ export interface KeystoneUpdateCheckResult {
20
+ hasUpdate: boolean;
21
+ serverN: number;
22
+ localN: number;
23
+ serverLatestAddr: string;
24
+ graph: Record<string, KeystoneIbGib_V1>;
25
+ }
26
+
27
+ export class KeystoneSyncService {
28
+ protected lc: string = `[KeystoneSyncService]`;
29
+
30
+ private dispatchUpdateAvailableEvent(detail: EventIbGibIdentityUpdateAvailableDetail): void {
31
+ if (typeof window !== 'undefined') {
32
+ window.dispatchEvent(new CustomEvent(EVENT_IBGIB_IDENTITY_UPDATE_AVAILABLE, {
33
+ detail,
34
+ bubbles: true,
35
+ composed: true,
36
+ }));
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Checks if a server update exists for the given active primary keystone address.
42
+ */
43
+ public async checkForKeystoneUpdate({
44
+ activePrimaryAddr,
45
+ metaspace,
46
+ space
47
+ }: {
48
+ activePrimaryAddr: string;
49
+ metaspace?: any;
50
+ space?: any;
51
+ }): Promise<KeystoneUpdateCheckResult> {
52
+ const lc = `${this.lc}[${this.checkForKeystoneUpdate.name}]`;
53
+ try {
54
+ if (!metaspace) {
55
+ metaspace = await getGlobalMetaspace_waitIfNeeded();
56
+ }
57
+ if (!metaspace) {
58
+ throw new Error("Metaspace not available.");
59
+ }
60
+ if (!space) {
61
+ space = await metaspace.getLocalUserSpace({ lock: false });
62
+ }
63
+ if (!space) {
64
+ throw new Error("Local user space not available.");
65
+ }
66
+
67
+ // Determine local latest address & frame
68
+ const localLatestAddr = (await metaspace.getLatestAddr({ addr: activePrimaryAddr, space })) || activePrimaryAddr;
69
+ const resLocal = await metaspace.get({ addrs: [localLatestAddr], space });
70
+ const localFrame = (resLocal.success && resLocal.ibGibs && resLocal.ibGibs.length > 0)
71
+ ? (resLocal.ibGibs[0] as KeystoneIbGib_V1)
72
+ : undefined;
73
+
74
+ const localN = localFrame?.data?.n ?? 0;
75
+
76
+ // Fetch server graph using activePrimaryAddr (resolving to full domain TJP address, e.g. "keystone^hash")
77
+ const { ib } = getIbAndGib({ ibGibAddr: activePrimaryAddr });
78
+ const info = getGibInfo({ ibGibAddr: activePrimaryAddr });
79
+ const fallbackTjp = info.tjpGib ? `${ib}^${info.tjpGib}` : activePrimaryAddr;
80
+ const domainTjpAddr = (localFrame ? getTjpAddr({ ibGib: localFrame }) : undefined) || fallbackTjp;
81
+ const resGraph = await getApiBridge().getKeystoneGraph(domainTjpAddr);
82
+
83
+ if (!resGraph.success || !resGraph.graph) {
84
+ const res: KeystoneUpdateCheckResult = {
85
+ hasUpdate: false,
86
+ serverN: localN,
87
+ localN,
88
+ serverLatestAddr: localLatestAddr,
89
+ graph: {}
90
+ };
91
+ this.dispatchUpdateAvailableEvent({
92
+ activePrimaryAddr,
93
+ hasUpdate: res.hasUpdate,
94
+ serverN: res.serverN,
95
+ localN: res.localN,
96
+ serverLatestAddr: res.serverLatestAddr,
97
+ });
98
+ return res;
99
+ }
100
+
101
+ const graph = resGraph.graph as Record<string, KeystoneIbGib_V1>;
102
+ const graphIbGibs = Object.values(graph);
103
+
104
+ // Group timelines by TJP to isolate primary domain timeline
105
+ const timelinesMap = getTimelinesGroupedByTjp({ ibGibs: graphIbGibs });
106
+ // Look for timeline under domainTjpAddr or activePrimaryAddr or first available
107
+ const domainTimeline = timelinesMap[domainTjpAddr] || timelinesMap[activePrimaryAddr] || timelinesMap[Object.keys(timelinesMap)[0]] || [];
108
+
109
+ if (domainTimeline.length === 0) {
110
+ const res: KeystoneUpdateCheckResult = {
111
+ hasUpdate: false,
112
+ serverN: localN,
113
+ localN,
114
+ serverLatestAddr: localLatestAddr,
115
+ graph
116
+ };
117
+ this.dispatchUpdateAvailableEvent({
118
+ activePrimaryAddr,
119
+ hasUpdate: res.hasUpdate,
120
+ serverN: res.serverN,
121
+ localN: res.localN,
122
+ serverLatestAddr: res.serverLatestAddr,
123
+ });
124
+ return res;
125
+ }
126
+
127
+ // Domain timeline sorted ascending by n
128
+ const sortedDomainTimeline = [...domainTimeline].sort((a, b) => (a.data?.n ?? 0) - (b.data?.n ?? 0));
129
+ const serverLatestFrame = sortedDomainTimeline[sortedDomainTimeline.length - 1] as KeystoneIbGib_V1;
130
+ const serverN = serverLatestFrame.data?.n ?? 0;
131
+ const serverLatestAddr = getIbGibAddr({ ibGib: serverLatestFrame });
132
+
133
+ const hasUpdate = serverN > localN;
134
+
135
+ const res: KeystoneUpdateCheckResult = {
136
+ hasUpdate,
137
+ serverN,
138
+ localN,
139
+ serverLatestAddr,
140
+ graph
141
+ };
142
+ this.dispatchUpdateAvailableEvent({
143
+ activePrimaryAddr,
144
+ hasUpdate: res.hasUpdate,
145
+ serverN: res.serverN,
146
+ localN: res.localN,
147
+ serverLatestAddr: res.serverLatestAddr,
148
+ });
149
+ return res;
150
+ } catch (error) {
151
+ console.error(`${lc} ${extractErrorMsg(error)}`);
152
+ const res: KeystoneUpdateCheckResult = {
153
+ hasUpdate: false,
154
+ serverN: 0,
155
+ localN: 0,
156
+ serverLatestAddr: activePrimaryAddr,
157
+ graph: {}
158
+ };
159
+ this.dispatchUpdateAvailableEvent({
160
+ activePrimaryAddr,
161
+ hasUpdate: false,
162
+ serverN: 0,
163
+ localN: 0,
164
+ serverLatestAddr: activePrimaryAddr,
165
+ });
166
+ return res;
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Checks for updates and registers any missing server keystone frames into local space.
172
+ * Returns the updated (or current) primary keystone frame.
173
+ */
174
+ public async updateActiveKeystone({
175
+ activePrimaryAddr,
176
+ metaspace,
177
+ space
178
+ }: {
179
+ activePrimaryAddr: string;
180
+ metaspace?: any;
181
+ space?: any;
182
+ }): Promise<KeystoneIbGib_V1 | undefined> {
183
+ const lc = `${this.lc}[${this.updateActiveKeystone.name}]`;
184
+ try {
185
+ if (!metaspace) {
186
+ metaspace = await getGlobalMetaspace_waitIfNeeded();
187
+ }
188
+ if (!metaspace) {
189
+ throw new Error("Metaspace not available.");
190
+ }
191
+ if (!space) {
192
+ space = await metaspace.getLocalUserSpace({ lock: false });
193
+ }
194
+ if (!space) {
195
+ throw new Error("Local user space not available.");
196
+ }
197
+
198
+ const updateInfo = await this.checkForKeystoneUpdate({ activePrimaryAddr, metaspace, space });
199
+
200
+ if (updateInfo.hasUpdate && Object.keys(updateInfo.graph).length > 0) {
201
+ const graphIbGibs = Object.values(updateInfo.graph);
202
+ // Put all graph ibgibs into space
203
+ await metaspace.put({ ibGibs: graphIbGibs, space });
204
+
205
+ // Group by TJP and register each frame ascending by n
206
+ const timelinesMap = getTimelinesGroupedByTjp({ ibGibs: graphIbGibs });
207
+ for (const tjpKey of Object.keys(timelinesMap)) {
208
+ const timeline = timelinesMap[tjpKey];
209
+ const sorted = [...timeline].sort((a, b) => (a.data?.n ?? 0) - (b.data?.n ?? 0));
210
+ for (const frame of sorted) {
211
+ await metaspace.registerNewIbGib({ ibGib: frame, space });
212
+ }
213
+ }
214
+
215
+ // Get updated latest primary frame
216
+ const domainTjp = getGibInfo({ ibGibAddr: activePrimaryAddr }).tjpGib ?? activePrimaryAddr;
217
+ const domainTimeline = timelinesMap[domainTjp] || timelinesMap[activePrimaryAddr] || timelinesMap[Object.keys(timelinesMap)[0]];
218
+ const sortedDomain = [...domainTimeline].sort((a, b) => (a.data?.n ?? 0) - (b.data?.n ?? 0));
219
+ const updatedLatestFrame = sortedDomain[sortedDomain.length - 1] as KeystoneIbGib_V1;
220
+
221
+ if (updatedLatestFrame) {
222
+ // Update special index locally
223
+ await updateSpecialIndex({
224
+ type: "keystones",
225
+ rel8nInfos: [{
226
+ rel8nName: "keystone",
227
+ ibGibs: [toDto({ ibGib: updatedLatestFrame })]
228
+ }],
229
+ metaspace,
230
+ space
231
+ });
232
+ return updatedLatestFrame;
233
+ }
234
+ }
235
+
236
+ // If no update or update failed, return current local frame
237
+ const localLatestAddr = (await metaspace.getLatestAddr({ addr: activePrimaryAddr, space })) || activePrimaryAddr;
238
+ const resLocal = await metaspace.get({ addrs: [localLatestAddr], space });
239
+ if (resLocal.success && resLocal.ibGibs && resLocal.ibGibs.length > 0) {
240
+ return resLocal.ibGibs[0] as KeystoneIbGib_V1;
241
+ }
242
+ return undefined;
243
+ } catch (error) {
244
+ console.error(`${lc} ${extractErrorMsg(error)}`);
245
+ throw error;
246
+ }
247
+ }
248
+ }
249
+
250
+ let _keystoneSyncSvc: KeystoneSyncService | undefined;
251
+
252
+ export function getKeystoneSyncService(): KeystoneSyncService {
253
+ if (!_keystoneSyncSvc) {
254
+ _keystoneSyncSvc = new KeystoneSyncService();
255
+ }
256
+ return _keystoneSyncSvc;
257
+ }
package/src/index.mts CHANGED
@@ -1,29 +1,28 @@
1
- // /**
2
- // * @ibgib/web-gib
3
- // *
4
- // * Front Door: Streamlined App Bootstrapping
5
- // */
1
+ /**
2
+ * @module @ibgib/web-gib
3
+ *
4
+ * Front Door: Streamlined App Bootstrapping & Web Components
5
+ */
6
6
 
7
- // export {
8
- // bootstrapIbGibApp
9
- // } from "./app-bootstrap/bootstrap.mjs";
7
+ export * from "./app-bootstrap/bootstrap.mjs";
8
+ export * from "./app-bootstrap/types.mjs";
9
+ export * from "./app-bootstrap/init-orchestration.mjs";
10
10
 
11
- // export {
12
- // IbGibAmbientContextConfig,
13
- // IbGibGlobalThis_IbGibApp
14
- // } from "./app-bootstrap/types.mjs";
11
+ export * from "./constants.mjs";
12
+ export * from "./types.mjs";
13
+ export * from "./helpers.web.mjs";
14
+ export * from "./helpers.mjs";
15
15
 
16
- // export {
17
- // initIbGibStorage,
18
- // dynamicallyLoadBootstrapScript,
19
- // getComponentCtorArg
20
- // } from "./app-bootstrap/init-orchestration.mjs";
16
+ // REST API bridge
17
+ export * from "./api/ibgib-api-bridge.mjs";
18
+
19
+ // Identity & Sync services
20
+ export * from "./identity/keystone-sync-service.mjs";
21
+
22
+ // Identity UI components
23
+ export * from "./ui/component/identity/index.mjs";
24
+
25
+ // UI constants & types
26
+ export * from "./ui/ui-constants.mjs";
27
+ export * from "./ui/ui-types.mjs";
21
28
 
22
- // /**
23
- // * Toolbox: Library Internals
24
- // * (Only export what's necessary for advanced users)
25
- // */
26
- // export * from "./constants.mjs";
27
- // export * from "./types.mjs";
28
- // export * from "./helpers.web.mjs";
29
- // export * from "./helpers.mjs";