@ibgib/core-gib 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/.vscode/core-gib-snippets.code-snippets +189 -0
- package/.vscode/launch.json +24 -0
- package/.vscode/settings.json +56 -0
- package/.vscode/tasks.json +37 -0
- package/CHANGELOG.md +11 -0
- package/README.md +215 -0
- package/dist/common/aws-constants.d.mts +7 -0
- package/dist/common/aws-constants.d.mts.map +1 -0
- package/dist/common/aws-constants.mjs +7 -0
- package/dist/common/aws-constants.mjs.map +1 -0
- package/dist/common/bin/bin-types.d.mts +17 -0
- package/dist/common/bin/bin-types.d.mts.map +1 -0
- package/dist/common/bin/bin-types.mjs +3 -0
- package/dist/common/bin/bin-types.mjs.map +1 -0
- package/dist/common/cache/cache-types.d.mts +57 -0
- package/dist/common/cache/cache-types.d.mts.map +1 -0
- package/dist/common/cache/cache-types.mjs +2 -0
- package/dist/common/cache/cache-types.mjs.map +1 -0
- package/dist/common/comment/comment-constants.d.mts +11 -0
- package/dist/common/comment/comment-constants.d.mts.map +1 -0
- package/dist/common/comment/comment-constants.mjs +11 -0
- package/dist/common/comment/comment-constants.mjs.map +1 -0
- package/dist/common/comment/comment-helper.d.mts +59 -0
- package/dist/common/comment/comment-helper.d.mts.map +1 -0
- package/dist/common/comment/comment-helper.mjs +173 -0
- package/dist/common/comment/comment-helper.mjs.map +1 -0
- package/dist/common/comment/comment-types.d.mts +16 -0
- package/dist/common/comment/comment-types.d.mts.map +1 -0
- package/dist/common/comment/comment-types.mjs +2 -0
- package/dist/common/comment/comment-types.mjs.map +1 -0
- package/dist/common/display/display-helper.d.mts +19 -0
- package/dist/common/display/display-helper.d.mts.map +1 -0
- package/dist/common/display/display-helper.mjs +68 -0
- package/dist/common/display/display-helper.mjs.map +1 -0
- package/dist/common/display/display-types.d.mts +97 -0
- package/dist/common/display/display-types.d.mts.map +1 -0
- package/dist/common/display/display-types.mjs +37 -0
- package/dist/common/display/display-types.mjs.map +1 -0
- package/dist/common/encrypt/encrypt-constants.d.mts +27 -0
- package/dist/common/encrypt/encrypt-constants.d.mts.map +1 -0
- package/dist/common/encrypt/encrypt-constants.mjs +27 -0
- package/dist/common/encrypt/encrypt-constants.mjs.map +1 -0
- package/dist/common/encrypt/encrypt-types.d.mts +116 -0
- package/dist/common/encrypt/encrypt-types.d.mts.map +1 -0
- package/dist/common/encrypt/encrypt-types.mjs +9 -0
- package/dist/common/encrypt/encrypt-types.mjs.map +1 -0
- package/dist/common/error/error-constants.d.mts +9 -0
- package/dist/common/error/error-constants.d.mts.map +1 -0
- package/dist/common/error/error-constants.mjs +9 -0
- package/dist/common/error/error-constants.mjs.map +1 -0
- package/dist/common/error/error-helper.d.mts +43 -0
- package/dist/common/error/error-helper.d.mts.map +1 -0
- package/dist/common/error/error-helper.mjs +167 -0
- package/dist/common/error/error-helper.mjs.map +1 -0
- package/dist/common/error/error-types.d.mts +58 -0
- package/dist/common/error/error-types.d.mts.map +1 -0
- package/dist/common/error/error-types.mjs +2 -0
- package/dist/common/error/error-types.mjs.map +1 -0
- package/dist/common/form/form-helper.d.mts +97 -0
- package/dist/common/form/form-helper.d.mts.map +1 -0
- package/dist/common/form/form-helper.mjs +185 -0
- package/dist/common/form/form-helper.mjs.map +1 -0
- package/dist/common/form/form-items.d.mts +229 -0
- package/dist/common/form/form-items.d.mts.map +1 -0
- package/dist/common/form/form-items.mjs +63 -0
- package/dist/common/form/form-items.mjs.map +1 -0
- package/dist/common/import-export/import-export-types.d.mts +18 -0
- package/dist/common/import-export/import-export-types.d.mts.map +1 -0
- package/dist/common/import-export/import-export-types.mjs +2 -0
- package/dist/common/import-export/import-export-types.mjs.map +1 -0
- package/dist/common/legacy/legacy-types.d.mts +2 -0
- package/dist/common/legacy/legacy-types.d.mts.map +1 -0
- package/dist/common/legacy/legacy-types.mjs +2 -0
- package/dist/common/legacy/legacy-types.mjs.map +1 -0
- package/dist/common/link/link-constants.d.mts +2 -0
- package/dist/common/link/link-constants.d.mts.map +1 -0
- package/dist/common/link/link-constants.mjs +2 -0
- package/dist/common/link/link-constants.mjs.map +1 -0
- package/dist/common/link/link-helper.d.mts +37 -0
- package/dist/common/link/link-helper.d.mts.map +1 -0
- package/dist/common/link/link-helper.mjs +143 -0
- package/dist/common/link/link-helper.mjs.map +1 -0
- package/dist/common/link/link-types.d.mts +14 -0
- package/dist/common/link/link-types.d.mts.map +1 -0
- package/dist/common/link/link-types.mjs +2 -0
- package/dist/common/link/link-types.mjs.map +1 -0
- package/dist/common/other/graph-helper.d.mts +166 -0
- package/dist/common/other/graph-helper.d.mts.map +1 -0
- package/dist/common/other/graph-helper.mjs +710 -0
- package/dist/common/other/graph-helper.mjs.map +1 -0
- package/dist/common/other/ibgib-helper.d.mts +245 -0
- package/dist/common/other/ibgib-helper.d.mts.map +1 -0
- package/dist/common/other/ibgib-helper.mjs +641 -0
- package/dist/common/other/ibgib-helper.mjs.map +1 -0
- package/dist/common/other/other-constants.d.mts +53 -0
- package/dist/common/other/other-constants.d.mts.map +1 -0
- package/dist/common/other/other-constants.mjs +67 -0
- package/dist/common/other/other-constants.mjs.map +1 -0
- package/dist/common/other/other-types.d.mts +166 -0
- package/dist/common/other/other-types.d.mts.map +1 -0
- package/dist/common/other/other-types.mjs +30 -0
- package/dist/common/other/other-types.mjs.map +1 -0
- package/dist/common/other/svg-constants.d.mts +2 -0
- package/dist/common/other/svg-constants.d.mts.map +1 -0
- package/dist/common/other/svg-constants.mjs +2 -0
- package/dist/common/other/svg-constants.mjs.map +1 -0
- package/dist/common/other/svg-helper.d.mts +54 -0
- package/dist/common/other/svg-helper.d.mts.map +1 -0
- package/dist/common/other/svg-helper.mjs +170 -0
- package/dist/common/other/svg-helper.mjs.map +1 -0
- package/dist/common/pic/pic-constants.d.mts +13 -0
- package/dist/common/pic/pic-constants.d.mts.map +1 -0
- package/dist/common/pic/pic-constants.mjs +13 -0
- package/dist/common/pic/pic-constants.mjs.map +1 -0
- package/dist/common/pic/pic-helper.d.mts +70 -0
- package/dist/common/pic/pic-helper.d.mts.map +1 -0
- package/dist/common/pic/pic-helper.mjs +235 -0
- package/dist/common/pic/pic-helper.mjs.map +1 -0
- package/dist/common/pic/pic-types.d.mts +23 -0
- package/dist/common/pic/pic-types.d.mts.map +1 -0
- package/dist/common/pic/pic-types.mjs +2 -0
- package/dist/common/pic/pic-types.mjs.map +1 -0
- package/dist/common/root/root-constants.d.mts +40 -0
- package/dist/common/root/root-constants.d.mts.map +1 -0
- package/dist/common/root/root-constants.mjs +40 -0
- package/dist/common/root/root-constants.mjs.map +1 -0
- package/dist/common/root/root-types.d.mts +9 -0
- package/dist/common/root/root-types.d.mts.map +1 -0
- package/dist/common/root/root-types.mjs +2 -0
- package/dist/common/root/root-types.mjs.map +1 -0
- package/dist/common/tag/tag-constants.d.mts +21 -0
- package/dist/common/tag/tag-constants.d.mts.map +1 -0
- package/dist/common/tag/tag-constants.mjs +28 -0
- package/dist/common/tag/tag-constants.mjs.map +1 -0
- package/dist/common/tag/tag-types.d.mts +14 -0
- package/dist/common/tag/tag-types.d.mts.map +1 -0
- package/dist/common/tag/tag-types.mjs +2 -0
- package/dist/common/tag/tag-types.mjs.map +1 -0
- package/dist/core-constants.d.mts +89 -0
- package/dist/core-constants.d.mts.map +1 -0
- package/dist/core-constants.mjs +484 -0
- package/dist/core-constants.mjs.map +1 -0
- package/dist/core-helper.d.mts +6 -0
- package/dist/core-helper.d.mts.map +1 -0
- package/dist/core-helper.mjs +28 -0
- package/dist/core-helper.mjs.map +1 -0
- package/dist/core-types.d.mts +520 -0
- package/dist/core-types.d.mts.map +1 -0
- package/dist/core-types.mjs +2 -0
- package/dist/core-types.mjs.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -0
- package/dist/witness/app/app-base-v1.d.mts +130 -0
- package/dist/witness/app/app-base-v1.d.mts.map +1 -0
- package/dist/witness/app/app-base-v1.mjs +462 -0
- package/dist/witness/app/app-base-v1.mjs.map +1 -0
- package/dist/witness/app/app-constants.d.mts +10 -0
- package/dist/witness/app/app-constants.d.mts.map +1 -0
- package/dist/witness/app/app-constants.mjs +13 -0
- package/dist/witness/app/app-constants.mjs.map +1 -0
- package/dist/witness/app/app-helper.d.mts +85 -0
- package/dist/witness/app/app-helper.d.mts.map +1 -0
- package/dist/witness/app/app-helper.mjs +258 -0
- package/dist/witness/app/app-helper.mjs.map +1 -0
- package/dist/witness/app/app-types.d.mts +211 -0
- package/dist/witness/app/app-types.d.mts.map +1 -0
- package/dist/witness/app/app-types.mjs +49 -0
- package/dist/witness/app/app-types.mjs.map +1 -0
- package/dist/witness/app/chat-app/chat-app-types.d.mts +18 -0
- package/dist/witness/app/chat-app/chat-app-types.d.mts.map +1 -0
- package/dist/witness/app/chat-app/chat-app-types.mjs +25 -0
- package/dist/witness/app/chat-app/chat-app-types.mjs.map +1 -0
- package/dist/witness/app/flash-app/flash-app-types.d.mts +16 -0
- package/dist/witness/app/flash-app/flash-app-types.d.mts.map +1 -0
- package/dist/witness/app/flash-app/flash-app-types.mjs +23 -0
- package/dist/witness/app/flash-app/flash-app-types.mjs.map +1 -0
- package/dist/witness/app/raw-app/raw-app-types.d.mts +18 -0
- package/dist/witness/app/raw-app/raw-app-types.d.mts.map +1 -0
- package/dist/witness/app/raw-app/raw-app-types.mjs +25 -0
- package/dist/witness/app/raw-app/raw-app-types.mjs.map +1 -0
- package/dist/witness/app/todo-app/todo-app-types.d.ts +33 -0
- package/dist/witness/app/todo-app/todo-app-types.d.ts.map +1 -0
- package/dist/witness/app/todo-app/todo-app-types.js +31 -0
- package/dist/witness/app/todo-app/todo-app-types.js.map +1 -0
- package/dist/witness/robbot/robbot-base-v1.d.ts +432 -0
- package/dist/witness/robbot/robbot-base-v1.d.ts.map +1 -0
- package/dist/witness/robbot/robbot-base-v1.js +1407 -0
- package/dist/witness/robbot/robbot-base-v1.js.map +1 -0
- package/dist/witness/robbot/robbot-constants.d.mts +24 -0
- package/dist/witness/robbot/robbot-constants.d.mts.map +1 -0
- package/dist/witness/robbot/robbot-constants.mjs +24 -0
- package/dist/witness/robbot/robbot-constants.mjs.map +1 -0
- package/dist/witness/robbot/robbot-helper.d.mts +152 -0
- package/dist/witness/robbot/robbot-helper.d.mts.map +1 -0
- package/dist/witness/robbot/robbot-helper.mjs +609 -0
- package/dist/witness/robbot/robbot-helper.mjs.map +1 -0
- package/dist/witness/robbot/robbot-types.d.mts +539 -0
- package/dist/witness/robbot/robbot-types.d.mts.map +1 -0
- package/dist/witness/robbot/robbot-types.mjs +294 -0
- package/dist/witness/robbot/robbot-types.mjs.map +1 -0
- package/dist/witness/space/bootstrap/bootstrap-constants.d.mts +14 -0
- package/dist/witness/space/bootstrap/bootstrap-constants.d.mts.map +1 -0
- package/dist/witness/space/bootstrap/bootstrap-constants.mjs +15 -0
- package/dist/witness/space/bootstrap/bootstrap-constants.mjs.map +1 -0
- package/dist/witness/space/inner-space-v1.d.ts +63 -0
- package/dist/witness/space/inner-space-v1.d.ts.map +1 -0
- package/dist/witness/space/inner-space-v1.js +356 -0
- package/dist/witness/space/inner-space-v1.js.map +1 -0
- package/dist/witness/space/outer-space/outer-space-constants.d.mts +2 -0
- package/dist/witness/space/outer-space/outer-space-constants.d.mts.map +1 -0
- package/dist/witness/space/outer-space/outer-space-constants.mjs +2 -0
- package/dist/witness/space/outer-space/outer-space-constants.mjs.map +1 -0
- package/dist/witness/space/outer-space/outer-space-helper.d.mts +28 -0
- package/dist/witness/space/outer-space/outer-space-helper.d.mts.map +1 -0
- package/dist/witness/space/outer-space/outer-space-helper.mjs +87 -0
- package/dist/witness/space/outer-space/outer-space-helper.mjs.map +1 -0
- package/dist/witness/space/outer-space/outer-space-types.d.mts +548 -0
- package/dist/witness/space/outer-space/outer-space-types.d.mts.map +1 -0
- package/dist/witness/space/outer-space/outer-space-types.mjs +118 -0
- package/dist/witness/space/outer-space/outer-space-types.mjs.map +1 -0
- package/dist/witness/space/space-base-v1.d.mts +147 -0
- package/dist/witness/space/space-base-v1.d.mts.map +1 -0
- package/dist/witness/space/space-base-v1.mjs +350 -0
- package/dist/witness/space/space-base-v1.mjs.map +1 -0
- package/dist/witness/space/space-constants.d.mts +181 -0
- package/dist/witness/space/space-constants.d.mts.map +1 -0
- package/dist/witness/space/space-constants.mjs +192 -0
- package/dist/witness/space/space-constants.mjs.map +1 -0
- package/dist/witness/space/space-helper.d.mts +666 -0
- package/dist/witness/space/space-helper.d.mts.map +1 -0
- package/dist/witness/space/space-helper.mjs +2830 -0
- package/dist/witness/space/space-helper.mjs.map +1 -0
- package/dist/witness/space/space-types.d.mts +422 -0
- package/dist/witness/space/space-types.d.mts.map +1 -0
- package/dist/witness/space/space-types.mjs +52 -0
- package/dist/witness/space/space-types.mjs.map +1 -0
- package/dist/witness/witness-base-v1.d.ts +144 -0
- package/dist/witness/witness-base-v1.d.ts.map +1 -0
- package/dist/witness/witness-base-v1.js +300 -0
- package/dist/witness/witness-base-v1.js.map +1 -0
- package/dist/witness/witness-constants.d.mts +3 -0
- package/dist/witness/witness-constants.d.mts.map +1 -0
- package/dist/witness/witness-constants.mjs +3 -0
- package/dist/witness/witness-constants.mjs.map +1 -0
- package/dist/witness/witness-form-builder.d.mts +45 -0
- package/dist/witness/witness-form-builder.d.mts.map +1 -0
- package/dist/witness/witness-form-builder.mjs +95 -0
- package/dist/witness/witness-form-builder.mjs.map +1 -0
- package/dist/witness/witness-helper.d.mts +89 -0
- package/dist/witness/witness-helper.d.mts.map +1 -0
- package/dist/witness/witness-helper.mjs +229 -0
- package/dist/witness/witness-helper.mjs.map +1 -0
- package/dist/witness/witness-types.d.mts +211 -0
- package/dist/witness/witness-types.d.mts.map +1 -0
- package/dist/witness/witness-types.mjs +2 -0
- package/dist/witness/witness-types.mjs.map +1 -0
- package/jasmine-browser.json +18 -0
- package/jasmine.json +6 -0
- package/package.json +67 -0
- package/src/assumptions.spec.mts +45 -0
- package/src/common/aws-constants.mts +5 -0
- package/src/common/bin/bin-types.mts +17 -0
- package/src/common/cache/cache-types.mts +53 -0
- package/src/common/comment/comment-constants.mts +10 -0
- package/src/common/comment/comment-helper.mts +211 -0
- package/src/common/comment/comment-types.mts +19 -0
- package/src/common/display/display-helper.mts +88 -0
- package/src/common/display/display-types.mts +108 -0
- package/src/common/encrypt/encrypt-constants.mts +28 -0
- package/src/common/encrypt/encrypt-types.mts +130 -0
- package/src/common/error/error-constants.mts +8 -0
- package/src/common/error/error-helper.mts +155 -0
- package/src/common/error/error-types.mts +62 -0
- package/src/common/form/form-helper.mts +253 -0
- package/src/common/form/form-items.mts +236 -0
- package/src/common/import-export/import-export-types.mts +18 -0
- package/src/common/legacy/about-legacy.md +0 -0
- package/src/common/legacy/legacy-types.mts +0 -0
- package/src/common/link/link-constants.mts +1 -0
- package/src/common/link/link-helper.mts +155 -0
- package/src/common/link/link-types.mts +16 -0
- package/src/common/other/graph-helper.mts +853 -0
- package/src/common/other/ibgib-helper.mts +671 -0
- package/src/common/other/other-constants.mts +76 -0
- package/src/common/other/other-types.mts +186 -0
- package/src/common/other/svg-constants.mts +1 -0
- package/src/common/other/svg-helper.mts +238 -0
- package/src/common/pic/pic-constants.mts +13 -0
- package/src/common/pic/pic-helper.mts +295 -0
- package/src/common/pic/pic-types.mts +29 -0
- package/src/common/root/root-constants.mts +41 -0
- package/src/common/root/root-types.mts +8 -0
- package/src/common/tag/tag-constants.mts +34 -0
- package/src/common/tag/tag-types.mts +19 -0
- package/src/core-constants.mts +506 -0
- package/src/core-helper.mts +33 -0
- package/src/core-types.mts +519 -0
- package/src/helper.spec.mts +64 -0
- package/src/index.mts +1 -0
- package/src/witness/app/app-base-v1.mts +584 -0
- package/src/witness/app/app-constants.mts +16 -0
- package/src/witness/app/app-helper.mts +322 -0
- package/src/witness/app/app-types.mts +252 -0
- package/src/witness/app/chat-app/chat-app-types.mts +40 -0
- package/src/witness/app/flash-app/flash-app-types.mts +38 -0
- package/src/witness/app/raw-app/raw-app-types.mts +40 -0
- package/src/witness/app/todo-app/todo-app-types.ts +59 -0
- package/src/witness/robbot/robbot-base-v1.ts +1531 -0
- package/src/witness/robbot/robbot-constants.mts +25 -0
- package/src/witness/robbot/robbot-helper.mts +676 -0
- package/src/witness/robbot/robbot-helper.spec.mts +135 -0
- package/src/witness/robbot/robbot-types.mts +797 -0
- package/src/witness/space/bootstrap/bootstrap-constants.mts +15 -0
- package/src/witness/space/inner-space-v1.ts +372 -0
- package/src/witness/space/outer-space/outer-space-constants.mts +1 -0
- package/src/witness/space/outer-space/outer-space-helper.mts +91 -0
- package/src/witness/space/outer-space/outer-space-types.mts +627 -0
- package/src/witness/space/space-base-v1.mts +414 -0
- package/src/witness/space/space-constants.mts +208 -0
- package/src/witness/space/space-helper.mts +3242 -0
- package/src/witness/space/space-types.mts +476 -0
- package/src/witness/witness-base-v1.ts +325 -0
- package/src/witness/witness-constants.mts +2 -0
- package/src/witness/witness-form-builder.mts +128 -0
- package/src/witness/witness-helper.mts +256 -0
- package/src/witness/witness-types.mts +249 -0
- package/tsconfig.json +15 -0
- package/tsconfig.test.json +10 -0
|
@@ -0,0 +1,3242 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clone, delay, getExpirationUTCString, getTimestampInTicks, getUUID, isExpired, pretty
|
|
3
|
+
} from '@ibgib/helper-gib';
|
|
4
|
+
import {
|
|
5
|
+
Ib, IbGibAddr, TransformResult, V1, getIbAndGib, getIbGibAddr,
|
|
6
|
+
} from '@ibgib/ts-gib';
|
|
7
|
+
import { GIB, IbGib_V1, Rel8n, Factory_V1 as factory, IBGIB_DELIMITER, } from '@ibgib/ts-gib/dist/V1/index.mjs';
|
|
8
|
+
import { getGib, } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
|
|
9
|
+
import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
|
|
10
|
+
|
|
11
|
+
import { APP_REL8N_NAME, GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
|
|
12
|
+
import {
|
|
13
|
+
GetIbGibOpts, GetIbGibResult,
|
|
14
|
+
PutIbGibOpts, PutIbGibResult,
|
|
15
|
+
DeleteIbGibOpts, DeleteIbGibResult, SpecialIbGibType,
|
|
16
|
+
IbGibTimelineUpdateInfo,
|
|
17
|
+
} from '../../common/other/other-types.mjs';
|
|
18
|
+
import {
|
|
19
|
+
getRootIb,
|
|
20
|
+
getSpecialConfigKey, getSpecialIbGibIb, getSpecialTypeFromIb,
|
|
21
|
+
getTjpAddr, isSpecial, isTjp_Naive, tagTextToIb
|
|
22
|
+
} from '../../common/other/ibgib-helper.mjs';
|
|
23
|
+
import { TagData_V1, TagIbGib_V1 } from '../../common/tag/tag-types.mjs';
|
|
24
|
+
import { BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY, BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY, BOOTSTRAP_IBGIB_ADDR } from './bootstrap/bootstrap-constants.mjs';
|
|
25
|
+
import {
|
|
26
|
+
SpaceLockScope, IbGibSpaceLockIbGib, BootstrapIbGib, SpaceId,
|
|
27
|
+
IbGibSpaceLockOptions, BootstrapData, BootstrapRel8ns, TxId,
|
|
28
|
+
IbGibSpaceResultIbGib, IbGibSpaceResultData, IbGibSpaceResultRel8ns
|
|
29
|
+
} from './space-types.mjs';
|
|
30
|
+
import { getAppIb, } from '../app/app-helper.mjs';
|
|
31
|
+
import { AppIbGib_V1 } from '../app/app-types.mjs';
|
|
32
|
+
import { DEFAULT_CHAT_APP_DATA_V1, DEFAULT_CHAT_APP_REL8NS_V1 } from '../app/chat-app/chat-app-types.mjs';
|
|
33
|
+
import { DEFAULT_RAW_APP_DATA_V1, DEFAULT_RAW_APP_REL8NS_V1 } from '../app/raw-app/raw-app-types.mjs';
|
|
34
|
+
import { DEFAULT_TODO_APP_DATA_V1, DEFAULT_TODO_APP_REL8NS_V1 } from '../app/todo-app/todo-app-types.js';
|
|
35
|
+
import { IbGibSpaceAny } from './space-base-v1.mjs';
|
|
36
|
+
import { RootData } from '../../common/root/root-types.mjs';
|
|
37
|
+
import { IbGibCacheService } from '../../common/cache/cache-types.mjs';
|
|
38
|
+
import { DEFAULT_MAX_DELAY_MS_RETRY_LOCK_ACQUIRE, DEFAULT_MAX_DELAY_RETRY_LOCK_ACQUIRE_ATTEMPTS, DEFAULT_SECONDS_VALID_LOCAL, DEFAULT_TX_ID_LENGTH, IBGIB_SPACE_NAME_DEFAULT, SPACE_LOCK_IB_TERM, SYNC_SPACE_REL8N_NAME } from './space-constants.mjs';
|
|
39
|
+
import { DEFAULT_TAG_DESCRIPTION, DEFAULT_TAG_ICON, TAG_REL8N_NAME } from '../../common/tag/tag-constants.mjs';
|
|
40
|
+
import { DEFAULT_ROOT_DESCRIPTION, DEFAULT_ROOT_ICON, DEFAULT_ROOT_REL8N_NAME, DEFAULT_ROOT_TEXT, ROOT_REL8N_NAME } from '../../common/root/root-constants.mjs';
|
|
41
|
+
import { ARCHIVE_REL8N_NAME, TRASH_REL8N_NAME } from '../../common/other/other-constants.mjs';
|
|
42
|
+
|
|
43
|
+
const logalot = GLOBAL_LOG_A_LOT || false;
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Two spaces can be equivalent if they point to the same area.
|
|
48
|
+
*
|
|
49
|
+
* @returns true if the "same" space
|
|
50
|
+
*/
|
|
51
|
+
export function isSameSpace({
|
|
52
|
+
a,
|
|
53
|
+
b,
|
|
54
|
+
mustHaveSameData,
|
|
55
|
+
}: {
|
|
56
|
+
a: IbGibSpaceAny,
|
|
57
|
+
b: IbGibSpaceAny,
|
|
58
|
+
/**
|
|
59
|
+
* If true, then only same exact internal data will do.
|
|
60
|
+
* Be careful if they have last modified timestamps.
|
|
61
|
+
*/
|
|
62
|
+
mustHaveSameData?: boolean,
|
|
63
|
+
}): boolean {
|
|
64
|
+
const lc = `[${isSameSpace.name}]`;
|
|
65
|
+
|
|
66
|
+
if (!a) { throw new Error(`${lc} a is falsy`) };
|
|
67
|
+
if (!b) { throw new Error(`${lc} b is falsy`) };
|
|
68
|
+
|
|
69
|
+
// try by data
|
|
70
|
+
if (a.data && JSON.stringify(a.data) === JSON.stringify(b.data)) {
|
|
71
|
+
return true;
|
|
72
|
+
} else if (mustHaveSameData) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// try by uuid
|
|
77
|
+
if (a.data?.uuid && b.data?.uuid) { return a.data!.uuid === b.data!.uuid; }
|
|
78
|
+
|
|
79
|
+
// try by tjp
|
|
80
|
+
if (a.rel8ns?.tjp?.length === 1 && b.rel8ns?.tjp?.length === 1) {
|
|
81
|
+
return a.rel8ns.tjp[0] === b.rel8ns.tjp[0];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// try by gib (last resort), can't both be falsy or primitive (maybe overkill)
|
|
85
|
+
if (!a.gib && !b.gib) {
|
|
86
|
+
throw new Error(`${lc} Invalid spaces. both a.gib and b.gib are falsy, neither has uuid and neither has tjp.`);
|
|
87
|
+
}
|
|
88
|
+
if (a.gib === GIB && b.gib === GIB) { throw new Error(`${lc} both a and b are primitives`); }
|
|
89
|
+
return a.gib === b.gib;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* wrapper for dealing with a space.
|
|
94
|
+
*
|
|
95
|
+
* @returns legacy `GetIbGibResult`
|
|
96
|
+
*/
|
|
97
|
+
export async function getFromSpace({
|
|
98
|
+
addr,
|
|
99
|
+
addrs,
|
|
100
|
+
isMeta,
|
|
101
|
+
isDna,
|
|
102
|
+
space,
|
|
103
|
+
force,
|
|
104
|
+
}: GetIbGibOpts): Promise<GetIbGibResult> {
|
|
105
|
+
let lc = `[${getFromSpace.name}]`;
|
|
106
|
+
try {
|
|
107
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
108
|
+
if (!space) { throw new Error(`space required. (E: 4d188d6c863246f28aa575753a052304)`); }
|
|
109
|
+
if (!addr && (addrs ?? []).length === 0) { throw new Error(`addr or addrs required. (E: 1a0b92564ba942f1ba91a089ac1a2125)`); }
|
|
110
|
+
|
|
111
|
+
if (addr && (addrs?.length ?? 0) > 0) {
|
|
112
|
+
console.warn(`${lc} both addr and addrs provided, but supposed to be used one or the other. (W: 87226c2ac50e4ea28211334a7b58782f)`);
|
|
113
|
+
if (!addrs!.includes(addr)) { addrs!.push(addr); }
|
|
114
|
+
}
|
|
115
|
+
addrs = (addrs ?? []).length > 0 ? addrs : [addr!];
|
|
116
|
+
|
|
117
|
+
const argGet = await space.argy({
|
|
118
|
+
ibMetadata: getSpaceArgMetadata({ space }),
|
|
119
|
+
argData: {
|
|
120
|
+
cmd: 'get',
|
|
121
|
+
ibGibAddrs: addrs,
|
|
122
|
+
isMeta,
|
|
123
|
+
isDna,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
const result = await space.witness(argGet);
|
|
127
|
+
if (result?.data?.success) {
|
|
128
|
+
if (logalot) { console.log(`${lc} got.`) }
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
ibGibs: result.ibGibs,
|
|
132
|
+
rawResultIbGib: result,
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
if (logalot) { console.log(`${lc} didn't get.`) }
|
|
136
|
+
return {
|
|
137
|
+
success: false,
|
|
138
|
+
errorMsg: result.data?.errors?.join('|') || `${lc} something went wrong. addrs: ${addrs!.join('\n')} (E: b9e9d5ce0cde4122bfb74f7688db85e0)`,
|
|
139
|
+
rawResultIbGib: result,
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error(`${lc} ${error.message}`);
|
|
144
|
+
return { errorMsg: error.message, }
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Wrapper for saving ibgib in a given space.
|
|
150
|
+
*
|
|
151
|
+
* ## warnings
|
|
152
|
+
*
|
|
153
|
+
* The given space doesn't have to work this way.
|
|
154
|
+
* This is a convenience for me ATOW.
|
|
155
|
+
*/
|
|
156
|
+
export async function putInSpace({
|
|
157
|
+
ibGib,
|
|
158
|
+
ibGibs,
|
|
159
|
+
isMeta,
|
|
160
|
+
isDna,
|
|
161
|
+
force,
|
|
162
|
+
space,
|
|
163
|
+
}: PutIbGibOpts): Promise<PutIbGibResult> {
|
|
164
|
+
const lc = `[${putInSpace.name}]`;
|
|
165
|
+
try {
|
|
166
|
+
if (!ibGib && (ibGibs ?? []).length === 0) { throw new Error(`ibGib or ibGibs required. (E: e59c4de3695f4dd28c8fe82dbb9c4e90)`); }
|
|
167
|
+
if (!space) { throw new Error(`space required. (E: dd0b7189c67c43c586b905a8ed6f51c9)`); }
|
|
168
|
+
|
|
169
|
+
if (ibGib && (ibGibs ?? []).length > 0) {
|
|
170
|
+
console.warn(`${lc} Both ibGib and ibGibs is assigned, whereas this is intended to be exclusive one or the other. (W: 4c797835b620445f88e4cba6b5aa3460)`)
|
|
171
|
+
if (!ibGibs!.some(x => x.gib === ibGib.gib)) {
|
|
172
|
+
ibGibs = ibGibs!.concat([ibGib]);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
ibGibs = ibGibs ?? [ibGib!];
|
|
176
|
+
|
|
177
|
+
if (logalot) { console.log(`${lc} ibGibs.length: ${ibGibs.length}`) }
|
|
178
|
+
const argPutIbGibs = await space.argy({
|
|
179
|
+
ibMetadata: getSpaceArgMetadata({ space }),
|
|
180
|
+
argData: {
|
|
181
|
+
cmd: 'put', isMeta, force, isDna,
|
|
182
|
+
ibGibAddrs: ibGibs.map(x => getIbGibAddr({ ibGib: x })),
|
|
183
|
+
},
|
|
184
|
+
ibGibs: ibGibs.concat(),
|
|
185
|
+
});
|
|
186
|
+
const resPutIbGibs = await space.witness(argPutIbGibs);
|
|
187
|
+
if (resPutIbGibs.data?.success) {
|
|
188
|
+
if ((resPutIbGibs.data!.warnings ?? []).length > 0) {
|
|
189
|
+
resPutIbGibs.data!.warnings!.forEach((warning: string) => console.warn(`${lc} ${warning}`));
|
|
190
|
+
}
|
|
191
|
+
return { success: true }
|
|
192
|
+
} else {
|
|
193
|
+
const errorMsg = resPutIbGibs?.data?.errors?.length > 0 ?
|
|
194
|
+
`Error(s) putting in local space:\n${resPutIbGibs.data.errors.join('\n')}` :
|
|
195
|
+
'(UNEXPECTED) unknown error putting ibGibs (E: 3d7426d4527243b79c5e55eb25f3fa73)';
|
|
196
|
+
throw new Error(errorMsg);
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error(`${lc} ${error.message}`);
|
|
200
|
+
return { errorMsg: error.message, }
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Wrapper for removing ibgib from the a given space, else the current space.
|
|
206
|
+
*/
|
|
207
|
+
export async function deleteFromSpace({
|
|
208
|
+
addr,
|
|
209
|
+
isMeta,
|
|
210
|
+
isDna,
|
|
211
|
+
space,
|
|
212
|
+
}: DeleteIbGibOpts): Promise<DeleteIbGibResult> {
|
|
213
|
+
let lc = `[${deleteFromSpace.name}]`;
|
|
214
|
+
try {
|
|
215
|
+
if (!space) { throw new Error(`space required. (E: 40ab3b51e91c4b5eb4f215baeefbcef0)`); }
|
|
216
|
+
if (!space.data) { throw new Error(`space.data required. (E: 0d02c8e85ee143b8bd6a1a1db0d9af1b)`); }
|
|
217
|
+
lc = `${lc}[${space.data.name || 'noname?'}][${space.data.uuid || 'nouuid?'}]`;
|
|
218
|
+
|
|
219
|
+
const argDel = await space.argy({
|
|
220
|
+
ibMetadata: getSpaceArgMetadata({ space }),
|
|
221
|
+
argData: {
|
|
222
|
+
cmd: 'delete',
|
|
223
|
+
ibGibAddrs: [addr],
|
|
224
|
+
isMeta,
|
|
225
|
+
isDna,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
const result = await space.witness(argDel);
|
|
229
|
+
if (result.data?.success) {
|
|
230
|
+
return { success: true, }
|
|
231
|
+
} else {
|
|
232
|
+
if (result.data?.warnings?.length > 0) {
|
|
233
|
+
console.warn(`${lc} warnings with delete (${addr}): ${result.data!.warnings!.join('|')}`);
|
|
234
|
+
}
|
|
235
|
+
if (result.data?.addrs?.length > 0) {
|
|
236
|
+
console.warn(`${lc} partial addrs deleted: ${result.data!.addrs!.join('|')}`);
|
|
237
|
+
}
|
|
238
|
+
const errorMsg: string = result.data?.errors?.join('|') || `${lc} something went wrong (E: e397fd09b4a746a3ba3305d6ea0893cb)`;
|
|
239
|
+
if (errorMsg.includes('File does not exist')) {
|
|
240
|
+
if (logalot) { console.log(`${lc} tried to delete file that does not exist. (I: cb5d1348ccbc58bf0bfc95f3006f1e22)`); }
|
|
241
|
+
}
|
|
242
|
+
return { errorMsg }
|
|
243
|
+
}
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error(`${lc} ${error.message}`);
|
|
246
|
+
return { errorMsg: error.message };
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Convenience function for persisting a transform result, which has
|
|
252
|
+
* a newIbGib and optionally intermediate ibGibs and/or dnas.
|
|
253
|
+
*
|
|
254
|
+
* it persists these ibgibs into the given space, else the current space.
|
|
255
|
+
*/
|
|
256
|
+
export async function persistTransformResult({
|
|
257
|
+
resTransform,
|
|
258
|
+
space,
|
|
259
|
+
isMeta,
|
|
260
|
+
force,
|
|
261
|
+
}: {
|
|
262
|
+
resTransform: TransformResult<IbGib_V1>,
|
|
263
|
+
space: IbGibSpaceAny,
|
|
264
|
+
isMeta?: boolean,
|
|
265
|
+
force?: boolean,
|
|
266
|
+
}): Promise<void> {
|
|
267
|
+
const lc = `[${persistTransformResult.name}]`;
|
|
268
|
+
try {
|
|
269
|
+
if (!space) { throw new Error(`space required. (E: cf94f1d74f1c4561bb88025a2095965b)`); }
|
|
270
|
+
|
|
271
|
+
const { newIbGib, intermediateIbGibs, dnas } = resTransform;
|
|
272
|
+
const ibGibs = [newIbGib, ...(intermediateIbGibs || [])];
|
|
273
|
+
const argPutIbGibs = await space.argy({
|
|
274
|
+
ibMetadata: getSpaceArgMetadata({ space }),
|
|
275
|
+
argData: {
|
|
276
|
+
cmd: 'put', isMeta, force,
|
|
277
|
+
ibGibAddrs: ibGibs.map(x => getIbGibAddr({ ibGib: x })),
|
|
278
|
+
},
|
|
279
|
+
ibGibs: ibGibs.concat(),
|
|
280
|
+
});
|
|
281
|
+
const resPutIbGibs = await space.witness(argPutIbGibs);
|
|
282
|
+
if (resPutIbGibs.data?.success) {
|
|
283
|
+
if (resPutIbGibs.data!.warnings?.length > 0) {
|
|
284
|
+
resPutIbGibs.data!.warnings!.forEach((warning: string) => console.warn(`${lc} ${warning}`));
|
|
285
|
+
}
|
|
286
|
+
} else {
|
|
287
|
+
const errorMsg = resPutIbGibs?.data?.errors?.length > 0 ?
|
|
288
|
+
resPutIbGibs.data.errors.join('\n') :
|
|
289
|
+
'unknown error putting ibGibs';
|
|
290
|
+
throw new Error(errorMsg);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (dnas?.length ?? 0 > 0) {
|
|
294
|
+
const argPutDnas = await space.argy({
|
|
295
|
+
ibMetadata: getSpaceArgMetadata({ space }),
|
|
296
|
+
argData: {
|
|
297
|
+
cmd: 'put', isDna: true, force,
|
|
298
|
+
ibGibAddrs: dnas!.map(x => getIbGibAddr({ ibGib: x })),
|
|
299
|
+
},
|
|
300
|
+
ibGibs: dnas!.concat(),
|
|
301
|
+
});
|
|
302
|
+
const resPutDnas = await space.witness(argPutDnas);
|
|
303
|
+
if (resPutDnas.data?.success) {
|
|
304
|
+
if (resPutDnas.data!.warnings?.length > 0) {
|
|
305
|
+
resPutDnas.data!.warnings!.forEach((warning: string) => console.warn(`${lc} ${warning}`));
|
|
306
|
+
}
|
|
307
|
+
} else {
|
|
308
|
+
const errorMsg = resPutDnas?.data?.errors?.length > 0 ?
|
|
309
|
+
resPutDnas.data.errors.join('\n') :
|
|
310
|
+
'unknown error putting dna ibGibs';
|
|
311
|
+
throw new Error(errorMsg);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
} catch (error) {
|
|
315
|
+
console.error(`${lc} ${error.message}`);
|
|
316
|
+
throw error;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export async function getSyncSpaces({
|
|
321
|
+
space,
|
|
322
|
+
}: {
|
|
323
|
+
space: IbGibSpaceAny,
|
|
324
|
+
}): Promise<IbGibSpaceAny[]> {
|
|
325
|
+
const lc = `[${getSyncSpaces.name}]`;
|
|
326
|
+
try {
|
|
327
|
+
if (!space) { throw new Error(`space required. (E: c03f80eca6b045b9a73b0aafa44cdf26)`); }
|
|
328
|
+
let syncSpaces = await getSpecialRel8dIbGibs<IbGibSpaceAny>({
|
|
329
|
+
type: "outerspaces",
|
|
330
|
+
rel8nName: SYNC_SPACE_REL8N_NAME,
|
|
331
|
+
space,
|
|
332
|
+
});
|
|
333
|
+
return syncSpaces;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
console.error(`${lc} ${error.message}`);
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export async function getSpecialRel8dIbGibs<TIbGib extends IbGib_V1 = IbGib_V1>({
|
|
341
|
+
type,
|
|
342
|
+
rel8nName,
|
|
343
|
+
space,
|
|
344
|
+
}: {
|
|
345
|
+
type: SpecialIbGibType,
|
|
346
|
+
rel8nName: string,
|
|
347
|
+
space: IbGibSpaceAny,
|
|
348
|
+
}): Promise<TIbGib[]> {
|
|
349
|
+
const lc = `[${getSpecialRel8dIbGibs.name}]`;
|
|
350
|
+
try {
|
|
351
|
+
if (!space) { throw new Error(`space required. (E: f73868a952ac4181a4f90ee6d86cacf3)`); }
|
|
352
|
+
|
|
353
|
+
let special = await getSpecialIbGib({ type, space });
|
|
354
|
+
if (!special) { throw new Error(`couldn't get special (${type})`) };
|
|
355
|
+
const rel8dAddrs = special.rel8ns ? special.rel8ns[rel8nName] || [] : [];
|
|
356
|
+
const rel8dIbgibs: TIbGib[] = [];
|
|
357
|
+
for (let i = 0; i < rel8dAddrs.length; i++) {
|
|
358
|
+
const addr = rel8dAddrs[i];
|
|
359
|
+
let resGet = await getFromSpace({ addr, space });
|
|
360
|
+
if (resGet.success && resGet.ibGibs?.length === 1) {
|
|
361
|
+
rel8dIbgibs.push(resGet.ibGibs[0] as TIbGib);
|
|
362
|
+
} else {
|
|
363
|
+
throw new Error(`couldn't get addr: ${addr}`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return rel8dIbgibs;
|
|
367
|
+
} catch (error) {
|
|
368
|
+
console.error(`${lc} ${error.message}`);
|
|
369
|
+
throw error;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Gets one of the app's special ibGibs, e.g., TagsIbGib.
|
|
375
|
+
*
|
|
376
|
+
* When initializing tags, this will generate some boilerplate tags.
|
|
377
|
+
* I'm going to be doing roots here also, and who knows what else, but each
|
|
378
|
+
* one will have its own initialize specifics.
|
|
379
|
+
*
|
|
380
|
+
* @param initialize initialize (i.e. create) ONLY IF IbGib not found. Used for initializing app (first run).
|
|
381
|
+
*
|
|
382
|
+
* @see {@link createSpecial}
|
|
383
|
+
* @see {@link createSpecial_Tags}
|
|
384
|
+
*/
|
|
385
|
+
export async function getSpecialIbGib({
|
|
386
|
+
type,
|
|
387
|
+
initialize,
|
|
388
|
+
space,
|
|
389
|
+
zeroSpace,
|
|
390
|
+
fnUpdateBootstrap,
|
|
391
|
+
fnBroadcast,
|
|
392
|
+
fnGetInitializing,
|
|
393
|
+
fnSetInitializing,
|
|
394
|
+
}: {
|
|
395
|
+
type: SpecialIbGibType,
|
|
396
|
+
initialize?: boolean,
|
|
397
|
+
space: IbGibSpaceAny,
|
|
398
|
+
/**
|
|
399
|
+
* Only required if `initialize` is true.
|
|
400
|
+
*/
|
|
401
|
+
zeroSpace?: IbGibSpaceAny,
|
|
402
|
+
/**
|
|
403
|
+
* Only required if `initialize` is true.
|
|
404
|
+
*/
|
|
405
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
406
|
+
/**
|
|
407
|
+
* Only required if `initialize` is true.
|
|
408
|
+
*/
|
|
409
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
410
|
+
/**
|
|
411
|
+
* Initialization lock getter function.
|
|
412
|
+
*/
|
|
413
|
+
fnGetInitializing?: () => boolean,
|
|
414
|
+
/**
|
|
415
|
+
* Initialization lock setter function.
|
|
416
|
+
*
|
|
417
|
+
* Because we don't want to initialize while we're initializing.
|
|
418
|
+
*/
|
|
419
|
+
fnSetInitializing?: (x: boolean) => void,
|
|
420
|
+
}): Promise<IbGib_V1 | null> {
|
|
421
|
+
const lc = `[${getSpecialIbGib.name}]`;
|
|
422
|
+
try {
|
|
423
|
+
if (!space) { throw new Error(`space required. (E: d454b31d58764a9bb9c4e47fb5ef38b5)`); }
|
|
424
|
+
|
|
425
|
+
let key = getSpecialConfigKey({ type });
|
|
426
|
+
let addr = await getConfigAddr({ key, space });
|
|
427
|
+
|
|
428
|
+
if (!addr) {
|
|
429
|
+
if (initialize && (!fnGetInitializing || !fnSetInitializing)) { throw new Error(`if initialize, you must provide fnGetInitializeLock & fnSetInitializeLock. (E: 8eb322625d0c4538be089800882487de)`); }
|
|
430
|
+
if (initialize && !fnGetInitializing!()) {
|
|
431
|
+
fnSetInitializing!(true);
|
|
432
|
+
try {
|
|
433
|
+
if (!zeroSpace) { throw new Error(`zeroSpace required when 'initialize' truthy (E: 8582c92c637f90c9b2dbe0ec8355b523)`); }
|
|
434
|
+
addr = await createSpecial({ type, space, zeroSpace: zeroSpace!, fnBroadcast, fnUpdateBootstrap }) ?? undefined;
|
|
435
|
+
} catch (error) {
|
|
436
|
+
console.error(`${lc} error initializing: ${error.message}`);
|
|
437
|
+
} finally {
|
|
438
|
+
fnSetInitializing!(false);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (!addr) {
|
|
442
|
+
if (fnGetInitializing && fnGetInitializing()) {
|
|
443
|
+
console.warn(`${lc} couldn't get addr, but we're still initializing...`);
|
|
444
|
+
return null;
|
|
445
|
+
} else {
|
|
446
|
+
throw new Error(`Special address not in config and couldn't initialize it either.`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (logalot) { console.log(`${lc} getting addr: ${addr}`); }
|
|
452
|
+
|
|
453
|
+
let resSpecial = await getFromSpace({ addr, isMeta: true, space });
|
|
454
|
+
|
|
455
|
+
// I'm putting in this check in case we're getting a meta that wasn't
|
|
456
|
+
// saved into the meta folder.
|
|
457
|
+
if (!resSpecial.success) {
|
|
458
|
+
resSpecial = await getFromSpace({ addr, isMeta: false, space });
|
|
459
|
+
if (resSpecial.success) {
|
|
460
|
+
console.warn(`${lc} special ibgib was not stored in meta folder...putting in meta folder now for the future (W: e6f5571fd98c449bb2809359be5057cc)`);
|
|
461
|
+
const resPutInMeta = await putInSpace({ ibGib: resSpecial!.ibGibs![0], isMeta: true, space });
|
|
462
|
+
if (!resPutInMeta.success) {
|
|
463
|
+
console.warn(`${lc} (UNEXPECTED) tried to put special in meta but success was false? (W: b934b53571c24057af172c790e6a7240)`)
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (!resSpecial.success) { throw new Error(resSpecial.errorMsg); }
|
|
468
|
+
if (resSpecial.ibGibs?.length !== 1) { throw new Error(`no ibGib in result (E: 3a42abdddc3648e292d63dc45c560064)`); }
|
|
469
|
+
const specialIbGib = resSpecial.ibGibs[0];
|
|
470
|
+
|
|
471
|
+
// I'm putting this check in here because it's bad not to have the
|
|
472
|
+
// latest special associated with a space
|
|
473
|
+
if (type !== 'latest') {
|
|
474
|
+
let resLatest = await getLatestAddrs({ ibGibs: [specialIbGib], space });
|
|
475
|
+
if (resLatest?.data?.success && resLatest.data.addrs?.length === 1) {
|
|
476
|
+
let specialAddr = getIbGibAddr({ ibGib: specialIbGib });
|
|
477
|
+
let latestAddr = resLatest.data.addrs[0];
|
|
478
|
+
if (latestAddr !== specialAddr) {
|
|
479
|
+
console.warn(`${lc} latest addr is not the one associated with the local space.\nspecialAddr: ${specialAddr}\nlatestAddr: ${latestAddr} (W: 141b69dc3c414efc9645bb76fcf12df9)`)
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return specialIbGib;
|
|
485
|
+
} catch (error) {
|
|
486
|
+
console.error(`${lc} ${error.message}`);
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Gets a config addr from the current space via the given key
|
|
493
|
+
* as the space's rel8n name.
|
|
494
|
+
*
|
|
495
|
+
* For example, for `key = tags`, a space may look like:
|
|
496
|
+
*
|
|
497
|
+
* ```json
|
|
498
|
+
* {
|
|
499
|
+
* ib: space xyz,
|
|
500
|
+
* gib: e89ff8a1c4954db28432007615a78952,
|
|
501
|
+
* rel8ns: {
|
|
502
|
+
* past: [space xyz^21cb29cc353f45a491d2b49ff2f130db],
|
|
503
|
+
* ancestor: [space^gib],
|
|
504
|
+
* tags: [tags^99b388355f8f4a979ca30ba284d3a686], // <<< rel8n with name specified by key
|
|
505
|
+
* }
|
|
506
|
+
* }
|
|
507
|
+
* ```
|
|
508
|
+
*
|
|
509
|
+
* @param key config key
|
|
510
|
+
* @returns addr in config if exists, else undefined
|
|
511
|
+
*/
|
|
512
|
+
export async function getConfigAddr({
|
|
513
|
+
key,
|
|
514
|
+
space,
|
|
515
|
+
}: {
|
|
516
|
+
key: string,
|
|
517
|
+
space: IbGibSpaceAny,
|
|
518
|
+
}): Promise<string | undefined> {
|
|
519
|
+
const lc = `[${getConfigAddr.name}](${key})`;
|
|
520
|
+
try {
|
|
521
|
+
if (logalot) { console.log(`${lc} getting...`) }
|
|
522
|
+
|
|
523
|
+
if (!space) { throw new Error(`space required. (E: 4f135d4276e64054ba21aeb9c304ecec)`); }
|
|
524
|
+
|
|
525
|
+
if (!space.rel8ns) {
|
|
526
|
+
console.warn(`${lc} space.rel8ns falsy.`);
|
|
527
|
+
return undefined;
|
|
528
|
+
}
|
|
529
|
+
if (!space.rel8ns[key]) {
|
|
530
|
+
console.warn(`${lc} space.rel8ns[${key}] falsy.`);
|
|
531
|
+
return undefined;
|
|
532
|
+
}
|
|
533
|
+
if (space.rel8ns[key]!.length === 1) {
|
|
534
|
+
if (logalot) { console.log(`${lc} got`); }
|
|
535
|
+
return space.rel8ns![key]![0];
|
|
536
|
+
} else if (space.rel8ns[key]!.length > 1) {
|
|
537
|
+
console.warn(`${lc} more than one config addr with ${key} rel8n.`)
|
|
538
|
+
return space.rel8ns![key]![0];
|
|
539
|
+
} else {
|
|
540
|
+
if (logalot) { console.log(`${lc} didn't find`); }
|
|
541
|
+
// key not found or
|
|
542
|
+
return undefined;
|
|
543
|
+
}
|
|
544
|
+
} catch (error) {
|
|
545
|
+
console.error(`${lc} ${error.message}`);
|
|
546
|
+
return undefined;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export async function setConfigAddr({
|
|
551
|
+
key,
|
|
552
|
+
addr,
|
|
553
|
+
space,
|
|
554
|
+
zeroSpace,
|
|
555
|
+
fnUpdateBootstrap,
|
|
556
|
+
}: {
|
|
557
|
+
key: string,
|
|
558
|
+
addr: string,
|
|
559
|
+
space: IbGibSpaceAny,
|
|
560
|
+
zeroSpace: IbGibSpaceAny,
|
|
561
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
562
|
+
}): Promise<IbGibSpaceAny> {
|
|
563
|
+
const lc = `[${setConfigAddr.name}]`;
|
|
564
|
+
try {
|
|
565
|
+
if (!space) { throw new Error(`space required. (E: c28b663c991d44419aef1026cc689636)`); }
|
|
566
|
+
if (!zeroSpace) { throw new Error(`zeroSpace required. (E: d3707ae5265d464891ad216f64be6184)`); }
|
|
567
|
+
|
|
568
|
+
// rel8 the `addr` to the current space via rel8n named `key`
|
|
569
|
+
// note that since we are replacing the pointer, we include the key
|
|
570
|
+
// in `linkedRel8ns` which will keep only the most recent
|
|
571
|
+
const rel8nsToAddByAddr = { [key]: [addr] };
|
|
572
|
+
const resNewSpace = await V1.rel8({
|
|
573
|
+
src: space.toIbGibDto(),
|
|
574
|
+
dna: false,
|
|
575
|
+
linkedRel8ns: ["past", "ancestor", key], // we only want the most recent key address
|
|
576
|
+
rel8nsToAddByAddr,
|
|
577
|
+
nCounter: true,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
if (!resNewSpace.newIbGib) { throw new Error(`create new space failed.`); }
|
|
581
|
+
|
|
582
|
+
// persist the new space in both default space and its own space
|
|
583
|
+
// (will actually have the space witness its future self interestingly
|
|
584
|
+
// enough...perhaps should have the new space witness itself instead
|
|
585
|
+
|
|
586
|
+
// witness in the default zero space
|
|
587
|
+
// in refactoring, may have to make this optional...hmm
|
|
588
|
+
await persistTransformResult({ isMeta: true, resTransform: resNewSpace, space: zeroSpace });
|
|
589
|
+
|
|
590
|
+
// witness in the given space
|
|
591
|
+
await persistTransformResult({ isMeta: true, resTransform: resNewSpace, space });
|
|
592
|
+
|
|
593
|
+
// going to update the bootstrap^gib with the new space address, but first...
|
|
594
|
+
const newSpace = (resNewSpace.newIbGib as IbGibSpaceAny);
|
|
595
|
+
|
|
596
|
+
// ...must update the original space reference any time we change it.
|
|
597
|
+
// messy atm...
|
|
598
|
+
await space.loadIbGibDto(newSpace);
|
|
599
|
+
|
|
600
|
+
// ...now update so the proper space (config) loads on next app start
|
|
601
|
+
if (fnUpdateBootstrap) {
|
|
602
|
+
await fnUpdateBootstrap(newSpace);
|
|
603
|
+
} else {
|
|
604
|
+
console.warn(`${lc} fnUpdateBootstrap is falsy. (W: 9fb874de2b19454dac18645e61ac463f)`);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return newSpace;
|
|
608
|
+
} catch (error) {
|
|
609
|
+
console.error(`${lc} ${error.message}`);
|
|
610
|
+
throw error;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export async function getCurrentRoot({
|
|
615
|
+
space,
|
|
616
|
+
}: {
|
|
617
|
+
space: IbGibSpaceAny,
|
|
618
|
+
}): Promise<IbGib_V1<RootData> | undefined> {
|
|
619
|
+
const lc = `[${getCurrentRoot.name}]`;
|
|
620
|
+
|
|
621
|
+
try {
|
|
622
|
+
if (!space) { throw new Error(`space required. (E: f0d546101fba4c169256158114ab3c56)`); }
|
|
623
|
+
|
|
624
|
+
const roots = await getSpecialIbGib({ type: "roots", space });
|
|
625
|
+
if (!roots) { throw new Error(`Roots not initialized. (E: 89b1ba12ed12416aac41cef9fdaf1fc2)`); }
|
|
626
|
+
if (!roots.rel8ns) { throw new Error(`Roots not initialized properly. No rel8ns. (E: 8513a07cf530484db9521a2a3a27b7f6)`); }
|
|
627
|
+
if (!roots.rel8ns.current) { throw new Error(`Roots not initialized properly. No current root. (E: 459c3a007a30486d96fb8d83f696e239)`); }
|
|
628
|
+
if (roots.rel8ns.current.length === 0) { throw new Error(`Invalid Roots: empty current root rel8n. (E: bede5864090440bca01ea7ab7fd107d6)`); }
|
|
629
|
+
if (roots.rel8ns.current.length > 1) { throw new Error(`Invalid Roots: multiple current roots selected. (E: 97561acbf63a48ecaa037697bd26555a)`); }
|
|
630
|
+
|
|
631
|
+
const currentRootAddr = roots.rel8ns.current[0]!;
|
|
632
|
+
const resCurrentRoot =
|
|
633
|
+
await getFromSpace({ addr: currentRootAddr, isMeta: true, space });
|
|
634
|
+
if (resCurrentRoot.ibGibs?.length === 1) {
|
|
635
|
+
return resCurrentRoot.ibGibs![0] as IbGib_V1<RootData>;
|
|
636
|
+
} else {
|
|
637
|
+
throw new Error(`could not get current root. addr: ${currentRootAddr}`);
|
|
638
|
+
}
|
|
639
|
+
} catch (error) {
|
|
640
|
+
console.error(`${lc} ${error.message}`);
|
|
641
|
+
return undefined;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
export async function setCurrentRoot({
|
|
646
|
+
root,
|
|
647
|
+
space,
|
|
648
|
+
zeroSpace,
|
|
649
|
+
fnUpdateBootstrap,
|
|
650
|
+
fnBroadcast,
|
|
651
|
+
}: {
|
|
652
|
+
root: IbGib_V1<RootData>,
|
|
653
|
+
space: IbGibSpaceAny,
|
|
654
|
+
zeroSpace: IbGibSpaceAny,
|
|
655
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
656
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
657
|
+
}): Promise<void> {
|
|
658
|
+
const lc = `[${setCurrentRoot.name}]`;
|
|
659
|
+
try {
|
|
660
|
+
if (!root) { throw new Error(`root required.`); }
|
|
661
|
+
|
|
662
|
+
if (!space) { throw new Error(`space required. (E: 186af2731c5342a78b063a0a4346f3db)`); }
|
|
663
|
+
|
|
664
|
+
const rootAddr = getIbGibAddr({ ibGib: root });
|
|
665
|
+
|
|
666
|
+
// get the roots and update its "current" rel8n
|
|
667
|
+
const roots = await getSpecialIbGib({ type: "roots", space });
|
|
668
|
+
if (!roots) { throw new Error(`Roots not initialized.`); }
|
|
669
|
+
|
|
670
|
+
// we'll rel8 current with a linkedRel8n, thus ensuring a maximum of only
|
|
671
|
+
// one rel8d addr (the one we're adding here)
|
|
672
|
+
const rel8nsToAddByAddr = { current: [rootAddr] };
|
|
673
|
+
const resNewRoots = await V1.rel8({
|
|
674
|
+
src: roots,
|
|
675
|
+
dna: false,
|
|
676
|
+
linkedRel8ns: ["past", "ancestor", "current"], // current here ensures only 1 rel8n
|
|
677
|
+
rel8nsToAddByAddr,
|
|
678
|
+
nCounter: true,
|
|
679
|
+
});
|
|
680
|
+
await persistTransformResult({ isMeta: true, resTransform: resNewRoots, space });
|
|
681
|
+
|
|
682
|
+
const configKey = getSpecialConfigKey({ type: "roots" });
|
|
683
|
+
const newRoots = resNewRoots.newIbGib;
|
|
684
|
+
const newRootsAddr = getIbGibAddr({ ibGib: newRoots });
|
|
685
|
+
await setConfigAddr({ key: configKey, addr: newRootsAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
686
|
+
await registerNewIbGib({ ibGib: newRoots, space, fnBroadcast, zeroSpace, fnUpdateBootstrap });
|
|
687
|
+
|
|
688
|
+
// how to let others know roots has changed?
|
|
689
|
+
} catch (error) {
|
|
690
|
+
console.error(`${lc} ${error.message}`);
|
|
691
|
+
throw error;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Every tjp should be related to one of the roots in a space.
|
|
697
|
+
*
|
|
698
|
+
* You should NOT relate every ibgib frame of a given ibGib.
|
|
699
|
+
*/
|
|
700
|
+
export async function rel8ToCurrentRoot({
|
|
701
|
+
ibGib,
|
|
702
|
+
linked,
|
|
703
|
+
rel8nName,
|
|
704
|
+
space,
|
|
705
|
+
fnBroadcast,
|
|
706
|
+
zeroSpace,
|
|
707
|
+
fnUpdateBootstrap,
|
|
708
|
+
}: {
|
|
709
|
+
ibGib: IbGib_V1,
|
|
710
|
+
linked?: boolean,
|
|
711
|
+
rel8nName?: string,
|
|
712
|
+
space: IbGibSpaceAny,
|
|
713
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
714
|
+
zeroSpace: IbGibSpaceAny,
|
|
715
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
716
|
+
}): Promise<void> {
|
|
717
|
+
const lc = `[${rel8ToCurrentRoot.name}]`;
|
|
718
|
+
|
|
719
|
+
try {
|
|
720
|
+
if (!space) { throw new Error(`space required. (E: f2758eab3bb844d2b749515672d9e392)`); }
|
|
721
|
+
if (!ibGib) { throw new Error(`ibGib required (E: f1bfd67754a7271553f4af544d30bc22)`); }
|
|
722
|
+
|
|
723
|
+
let currentRoot = await getCurrentRoot({ space });
|
|
724
|
+
if (!currentRoot) { throw new Error('currentRoot undefined (E: 5c2d84dafc664808866008f6eb535750'); }
|
|
725
|
+
|
|
726
|
+
// only relate the tjp to roots and use the latest special index ibgib to
|
|
727
|
+
// have the reference to the latest ibgib in the space.
|
|
728
|
+
const tjpAddr = getTjpAddr({ ibGib, defaultIfNone: "incomingAddr" });
|
|
729
|
+
const ibGibAddr = getIbGibAddr({ ibGib });
|
|
730
|
+
|
|
731
|
+
// check to see if it's already rel8d. If so, we're done.
|
|
732
|
+
if (rel8nName && tjpAddr &&
|
|
733
|
+
currentRoot.rel8ns &&
|
|
734
|
+
currentRoot.rel8ns[rel8nName] &&
|
|
735
|
+
currentRoot.rel8ns[rel8nName]!.includes(tjpAddr)) {
|
|
736
|
+
// already rel8d
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
rel8nName = rel8nName || DEFAULT_ROOT_REL8N_NAME;
|
|
741
|
+
|
|
742
|
+
// we only need to add the ibgib itself to the root, not the tjp
|
|
743
|
+
// and not any dependent ibgibs. ...wakka doodle.
|
|
744
|
+
const resNewRoot = await V1.rel8({
|
|
745
|
+
src: currentRoot,
|
|
746
|
+
dna: false,
|
|
747
|
+
linkedRel8ns: linked ? ["past", "ancestor", rel8nName] : ["past", "ancestor"],
|
|
748
|
+
rel8nsToAddByAddr: { [rel8nName]: [ibGibAddr] },
|
|
749
|
+
nCounter: true,
|
|
750
|
+
});
|
|
751
|
+
await persistTransformResult({ isMeta: true, resTransform: resNewRoot, space });
|
|
752
|
+
const newRoot = resNewRoot.newIbGib as IbGib_V1<RootData>;
|
|
753
|
+
const newRootAddr = getIbGibAddr({ ibGib: newRoot });
|
|
754
|
+
if (logalot) { console.log(`${lc} updating _currentRoot root. newRootAddr: ${newRootAddr}`); }
|
|
755
|
+
await registerNewIbGib({ ibGib: newRoot, space, fnBroadcast, zeroSpace, fnUpdateBootstrap });
|
|
756
|
+
await setCurrentRoot({ root: newRoot, space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
|
|
757
|
+
|
|
758
|
+
} catch (error) {
|
|
759
|
+
console.error(`${lc} ${error.message}`);
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Used for tracking tjpAddr -> latest ibGibAddr.
|
|
766
|
+
*
|
|
767
|
+
* Call this when you create a new ibGib.
|
|
768
|
+
*
|
|
769
|
+
* Need to put this in another service at some point, but crunch crunch
|
|
770
|
+
* like pacman's lunch.
|
|
771
|
+
*/
|
|
772
|
+
export async function registerNewIbGib({
|
|
773
|
+
ibGib,
|
|
774
|
+
space,
|
|
775
|
+
fnBroadcast,
|
|
776
|
+
zeroSpace,
|
|
777
|
+
fnUpdateBootstrap,
|
|
778
|
+
}: {
|
|
779
|
+
ibGib: IbGib_V1,
|
|
780
|
+
space: IbGibSpaceAny,
|
|
781
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
782
|
+
zeroSpace: IbGibSpaceAny,
|
|
783
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
784
|
+
}): Promise<void> {
|
|
785
|
+
let lc = `[${registerNewIbGib.name}]`;
|
|
786
|
+
try {
|
|
787
|
+
const ibGibAddr: IbGibAddr = getIbGibAddr({ ibGib });
|
|
788
|
+
lc = `${lc}[${ibGibAddr}]`;
|
|
789
|
+
|
|
790
|
+
if (!space) { throw new Error(`space required. (E: ea0c03256f8a4062b460aa4de11f1e3e)`); }
|
|
791
|
+
|
|
792
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
793
|
+
|
|
794
|
+
// this is the latest index ibGib. It's just the mapping of tjp -> latestAddr.
|
|
795
|
+
// Other refs to "latest" in this function
|
|
796
|
+
// will refer to the actual/attempted latest of the ibGib arg.
|
|
797
|
+
let specialLatest = await getSpecialIbGib({ type: "latest", space });
|
|
798
|
+
if (!specialLatest) { throw new Error(`unable to get specialLatest (E: a24f785753e482085b49b74e367cff23)`); }
|
|
799
|
+
if (!specialLatest.rel8ns) { specialLatest.rel8ns = {}; }
|
|
800
|
+
|
|
801
|
+
// get the tjp for the rel8nName mapping, and also for some checking logic
|
|
802
|
+
let tjp = await getTjpIbGib({ ibGib, space });
|
|
803
|
+
if (!tjp) {
|
|
804
|
+
console.warn(`${lc} tjp not found for ${ibGibAddr}? Should at least just be the ibGib's address itself.`);
|
|
805
|
+
tjp = ibGib;
|
|
806
|
+
}
|
|
807
|
+
let tjpAddr = getIbGibAddr({ ibGib: tjp });
|
|
808
|
+
|
|
809
|
+
// either we're adding the given ibGib, replacing the existing with the ibGib,
|
|
810
|
+
// or doing nothing. We can do this with our current vars in a closure at this point.
|
|
811
|
+
const replaceLatest: () => Promise<void> = async () => {
|
|
812
|
+
if (logalot) { console.log(`${lc} adding/replacing latest. tjp: ${tjpAddr}`); }
|
|
813
|
+
await rel8ToSpecialIbGib({
|
|
814
|
+
type: "latest",
|
|
815
|
+
rel8nName: tjpAddr,
|
|
816
|
+
ibGibsToRel8: [ibGib],
|
|
817
|
+
linked: true, // this ensures only one latest ibGib mapped at a time
|
|
818
|
+
deletePreviousSpecialIbGib: true, // the latest mapping is ephemeral
|
|
819
|
+
severPast: true,
|
|
820
|
+
// skipRel8ToRoot: true,
|
|
821
|
+
space,
|
|
822
|
+
zeroSpace,
|
|
823
|
+
fnUpdateBootstrap,
|
|
824
|
+
fnBroadcast,
|
|
825
|
+
});
|
|
826
|
+
if (fnBroadcast) {
|
|
827
|
+
fnBroadcast({ tjpAddr, latestAddr: ibGibAddr, latestIbGib: ibGib });
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
let existingMapping = specialLatest.rel8ns[tjpAddr] || [];
|
|
832
|
+
if (existingMapping.length > 0) {
|
|
833
|
+
if (logalot) { console.log(`${lc} tjp mapping exists. Checking which is newer.`) }
|
|
834
|
+
let existingLatestAddr = existingMapping[0];
|
|
835
|
+
|
|
836
|
+
// check to see if ibgib is already the latest
|
|
837
|
+
if (existingLatestAddr === ibGibAddr) {
|
|
838
|
+
if (logalot) { console.log(`${lc} Neither is newer because ibGibAddr is already registered as latest, so returning without any further action. (I: 7f5bd5d3391be95919240f0e97976e22)`); }
|
|
839
|
+
return; /* <<<< returns early */
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// not the latest or not registered, so get the full existing latest
|
|
843
|
+
// ibgib analyze to see if the incoming ibgib is indeed newer
|
|
844
|
+
let resExistingLatest = await getFromSpace({ addr: existingLatestAddr, space });
|
|
845
|
+
if (!resExistingLatest.success || resExistingLatest.ibGibs?.length !== 1) {
|
|
846
|
+
console.error(`Didn't find existing latest ibGib (${existingLatestAddr}). I haven't implemented more robust multi-node/distributed strategies for this scenario yet. User chose YES to replace.`);
|
|
847
|
+
await replaceLatest();
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
const existingLatest = resExistingLatest.ibGibs![0];
|
|
851
|
+
|
|
852
|
+
// if there is an nCounter, then we can go by that. Otherwise, we'll
|
|
853
|
+
// try to brute force "latest" comparison
|
|
854
|
+
const ibGibHasNCounter =
|
|
855
|
+
ibGib.data?.n &&
|
|
856
|
+
typeof ibGib.data!.n! === 'number' &&
|
|
857
|
+
ibGib.data!.n! >= 0;
|
|
858
|
+
if (ibGibHasNCounter) {
|
|
859
|
+
// #region ibGib.data.n counter method
|
|
860
|
+
if (logalot) { console.log(`found ibGib.data.n (version counter), using this to determine latest ibGib: ${ibGib.data!.n!}`); }
|
|
861
|
+
const n_ibGib = (ibGib.data!.n! as number);
|
|
862
|
+
|
|
863
|
+
const existingLatestHasNCounter =
|
|
864
|
+
existingLatest.data?.n &&
|
|
865
|
+
typeof existingLatest.data!.n! === 'number' &&
|
|
866
|
+
existingLatest.data!.n! >= 0;
|
|
867
|
+
|
|
868
|
+
if (existingLatestHasNCounter) {
|
|
869
|
+
// both have counters, so compare by those.
|
|
870
|
+
const n_existingLatest = (existingLatest.data!.n! as number);
|
|
871
|
+
if (n_ibGib > n_existingLatest) {
|
|
872
|
+
// is newer
|
|
873
|
+
await replaceLatest();
|
|
874
|
+
} else {
|
|
875
|
+
// is not newer, so we don't need to do anything else.
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
} else {
|
|
879
|
+
// only the new one has the counter, so that wins by default
|
|
880
|
+
await replaceLatest();
|
|
881
|
+
}
|
|
882
|
+
// #endregion
|
|
883
|
+
|
|
884
|
+
} else {
|
|
885
|
+
if (logalot) { console.log(`${lc} no nCounter found. Trying brute force method.`); }
|
|
886
|
+
// #region brute force latest
|
|
887
|
+
let latestAddr = await getLatestAddr_Brute({
|
|
888
|
+
ibGib, ibGibAddr,
|
|
889
|
+
existingLatest, existingLatestAddr,
|
|
890
|
+
tjpAddr,
|
|
891
|
+
space,
|
|
892
|
+
});
|
|
893
|
+
if (latestAddr === ibGibAddr) {
|
|
894
|
+
await replaceLatest();
|
|
895
|
+
} else {
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
// #endregion
|
|
899
|
+
}
|
|
900
|
+
} else {
|
|
901
|
+
// no existing mapping, so go ahead and add.
|
|
902
|
+
if (logalot) { console.log(`${lc} no existing tjp mapping. ${tjpAddr} -> ${ibGibAddr}`); }
|
|
903
|
+
await replaceLatest();
|
|
904
|
+
}
|
|
905
|
+
} catch (error) {
|
|
906
|
+
console.error(`${lc} ${error.message}`);
|
|
907
|
+
throw error;
|
|
908
|
+
} finally {
|
|
909
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Performs a rel8 transform on the special ibgib corresponding to the incoming
|
|
915
|
+
* `type`.
|
|
916
|
+
*
|
|
917
|
+
* ## special ibgibs
|
|
918
|
+
*
|
|
919
|
+
* much metadata configuration is stored via "special" ibgibs. Most of these are
|
|
920
|
+
* tracked in a space's ibgib directly, and the space itself is tracked in the
|
|
921
|
+
* bootstrap. So when storing configuration data, I usually create a new special
|
|
922
|
+
* ibgib. this function performs the plumbing for the rel8 transform related to
|
|
923
|
+
* that special ibgib.
|
|
924
|
+
*
|
|
925
|
+
* ## notes
|
|
926
|
+
*
|
|
927
|
+
* * special ibgib must exist in the space, i.e. previously initialized
|
|
928
|
+
* * i'm using this atm for mainly the local ionic space, but sometimes
|
|
929
|
+
* might be good in sync space, i dunno at this point.
|
|
930
|
+
* * I've migrated a lot of local space behavior into this space-agnostic file.
|
|
931
|
+
*
|
|
932
|
+
* @returns new special ibgib addr
|
|
933
|
+
*/
|
|
934
|
+
export async function rel8ToSpecialIbGib({
|
|
935
|
+
type,
|
|
936
|
+
rel8nName,
|
|
937
|
+
ibGibsToRel8,
|
|
938
|
+
ibGibsToUnRel8,
|
|
939
|
+
linked,
|
|
940
|
+
severPast,
|
|
941
|
+
deletePreviousSpecialIbGib,
|
|
942
|
+
space,
|
|
943
|
+
zeroSpace,
|
|
944
|
+
fnUpdateBootstrap,
|
|
945
|
+
fnBroadcast,
|
|
946
|
+
}: {
|
|
947
|
+
/**
|
|
948
|
+
* the "name" of the special ibgib.
|
|
949
|
+
*
|
|
950
|
+
* This will drive deterministically what the special ibgib's `ib` will be,
|
|
951
|
+
* among other things.
|
|
952
|
+
*/
|
|
953
|
+
type: SpecialIbGibType,
|
|
954
|
+
/**
|
|
955
|
+
* The rel8nName by which to rel8 the target incoming `ibGibsToRel8`.
|
|
956
|
+
*/
|
|
957
|
+
rel8nName: string,
|
|
958
|
+
/**
|
|
959
|
+
* multiple ibgibs to rel8
|
|
960
|
+
*/
|
|
961
|
+
ibGibsToRel8?: IbGib_V1[],
|
|
962
|
+
/**
|
|
963
|
+
* multiple ibgibs to UNrel8
|
|
964
|
+
*/
|
|
965
|
+
ibGibsToUnRel8?: IbGib_V1[],
|
|
966
|
+
/**
|
|
967
|
+
* If linked, then the rel8nName will only contain one address, i.e. the
|
|
968
|
+
* last rel8d ibgib's address.
|
|
969
|
+
*
|
|
970
|
+
* This depends on your use case.
|
|
971
|
+
*/
|
|
972
|
+
linked?: boolean,
|
|
973
|
+
/**
|
|
974
|
+
* Clears out the special.rel8ns.past array to an empty array.
|
|
975
|
+
*
|
|
976
|
+
* {@see deletePreviousSpecialIbGib} for driving use case.
|
|
977
|
+
*/
|
|
978
|
+
severPast?: boolean,
|
|
979
|
+
/**
|
|
980
|
+
* Deletes the previous special ibGib.
|
|
981
|
+
*
|
|
982
|
+
* ## driving use case
|
|
983
|
+
*
|
|
984
|
+
* the latest ibGib is one that is completely ephemeral. It doesn't get attached
|
|
985
|
+
* to the current root, and it only has the current instance. So we don't want to
|
|
986
|
+
* keep around past incarnations.
|
|
987
|
+
*/
|
|
988
|
+
deletePreviousSpecialIbGib?: boolean,
|
|
989
|
+
/**
|
|
990
|
+
* The space in which the special ibgib resides.
|
|
991
|
+
*/
|
|
992
|
+
space: IbGibSpaceAny,
|
|
993
|
+
/**
|
|
994
|
+
* The default zero space that contains metaspace information, i.e.
|
|
995
|
+
* bootstrap ibgib, space ibgibs, etc.
|
|
996
|
+
*/
|
|
997
|
+
zeroSpace: IbGibSpaceAny,
|
|
998
|
+
/**
|
|
999
|
+
* The function by which to update the bootstrap ibgib.
|
|
1000
|
+
*
|
|
1001
|
+
* This is necessary, because when you update a special ibgib,
|
|
1002
|
+
* the address of that special ibgib must be updated in the given
|
|
1003
|
+
* `space`. This will require an update to the space's address, which
|
|
1004
|
+
* itself is tracked in the bootstrap ibgib.
|
|
1005
|
+
*/
|
|
1006
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1007
|
+
/**
|
|
1008
|
+
* Use this if you want to broadcast the new space's address after this
|
|
1009
|
+
* function performs the rel8 transform.
|
|
1010
|
+
*/
|
|
1011
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1012
|
+
}): Promise<IbGibAddr> {
|
|
1013
|
+
const lc = `[${rel8ToSpecialIbGib.name}](type:${type},rel8nName:${rel8nName})`;
|
|
1014
|
+
try {
|
|
1015
|
+
if (!space) { throw new Error(`space required. (E: 956192eea28047eba6dad81620bb96fb)`); }
|
|
1016
|
+
if ((ibGibsToRel8 ?? []).length === 0 && (ibGibsToUnRel8 ?? []).length === 0) {
|
|
1017
|
+
throw new Error(`either ibGibsToRel8 or ibGibsToUnRel8 required. (E: 5add49c8e46a54e2c6b057c22646a822)`);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
const addrsToRel8 = ibGibsToRel8?.map(ibGib => getIbGibAddr({ ibGib }));
|
|
1021
|
+
const addrsToUnRel8 = ibGibsToUnRel8?.map(ibGib => getIbGibAddr({ ibGib }));
|
|
1022
|
+
|
|
1023
|
+
// get the special ibgib
|
|
1024
|
+
const configKey = getSpecialConfigKey({ type });
|
|
1025
|
+
let specialAddr = await getConfigAddr({ key: configKey, space });
|
|
1026
|
+
if (!specialAddr) { throw new Error(`specialAddr not found`) };
|
|
1027
|
+
let resGetSpecial = await getFromSpace({ addr: specialAddr, isMeta: true, space });
|
|
1028
|
+
if (!resGetSpecial.success) { throw new Error(`couldn't get special`) }
|
|
1029
|
+
if (!resGetSpecial.ibGibs) { throw new Error(`resGetSpecial.ibGibs falsy`) }
|
|
1030
|
+
if (resGetSpecial.ibGibs!.length !== 1) { throw new Error(`resGetSpecial.ibGibs count is not 1 (${resGetSpecial.ibGibs!.length})`) }
|
|
1031
|
+
|
|
1032
|
+
// rel8 the new tag to the special ibgib.
|
|
1033
|
+
const resNewSpecial = await V1.rel8({
|
|
1034
|
+
src: resGetSpecial.ibGibs![0],
|
|
1035
|
+
rel8nsToAddByAddr: addrsToRel8 ? { [rel8nName]: addrsToRel8 } : undefined,
|
|
1036
|
+
rel8nsToRemoveByAddr: addrsToUnRel8 ? { [rel8nName]: addrsToUnRel8 } : undefined,
|
|
1037
|
+
dna: false,
|
|
1038
|
+
linkedRel8ns: linked ? [Rel8n.past, rel8nName] : [Rel8n.past],
|
|
1039
|
+
nCounter: true,
|
|
1040
|
+
});
|
|
1041
|
+
const newSpecialIbGib = resNewSpecial.newIbGib;
|
|
1042
|
+
|
|
1043
|
+
// sever
|
|
1044
|
+
if (severPast) {
|
|
1045
|
+
if (resNewSpecial.intermediateIbGibs) { throw new Error('new special creates intermediate ibgibs. so severing past is harder. (E: b580c0c56253494192e9c62212ee187d)'); }
|
|
1046
|
+
newSpecialIbGib.rel8ns!.past = [];
|
|
1047
|
+
newSpecialIbGib.gib = await getGib({ ibGib: newSpecialIbGib });
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
// persist
|
|
1051
|
+
await persistTransformResult({ resTransform: resNewSpecial, isMeta: true, space });
|
|
1052
|
+
|
|
1053
|
+
// return the new special address (not the incoming new ibGib)
|
|
1054
|
+
const newSpecialAddr = getIbGibAddr({ ibGib: newSpecialIbGib });
|
|
1055
|
+
// const specialTjpAddrs = getTjpAddrs({ ibGibs: [newSpecialIbGib] });
|
|
1056
|
+
// const specialTjpAddr = specialTjpAddrs?.length > 0 ? specialTjpAddrs[0] : null;
|
|
1057
|
+
const specialTjpAddr = getTjpAddr({ ibGib: newSpecialIbGib });
|
|
1058
|
+
|
|
1059
|
+
// update the space ibgib which contains the special/config information
|
|
1060
|
+
await setConfigAddr({ key: configKey, addr: newSpecialAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1061
|
+
|
|
1062
|
+
// delete if required, only after updating config with the new special addr.
|
|
1063
|
+
if (deletePreviousSpecialIbGib) {
|
|
1064
|
+
await deleteFromSpace({ addr: specialAddr, isMeta: true, space });
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// I'm thinking we also want to register the special ibgib in the latest index...
|
|
1068
|
+
if (type === 'latest') {
|
|
1069
|
+
// we're relating somethign to the latest index special ibgib (most
|
|
1070
|
+
// likely via registerNewIbgib), and we have a new latest index.
|
|
1071
|
+
// we already have updated our reference to space(?) so I'm
|
|
1072
|
+
// not sure what the problem is right now...
|
|
1073
|
+
} else {
|
|
1074
|
+
// we're relating something to a special ibgib that is NOT the
|
|
1075
|
+
// latest index, so our new special ibgib needs to be registered
|
|
1076
|
+
// with that latest index.
|
|
1077
|
+
await registerNewIbGib({
|
|
1078
|
+
ibGib: newSpecialIbGib,
|
|
1079
|
+
zeroSpace,
|
|
1080
|
+
fnBroadcast,
|
|
1081
|
+
fnUpdateBootstrap,
|
|
1082
|
+
space,
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (fnBroadcast && specialTjpAddr) {
|
|
1087
|
+
fnBroadcast({
|
|
1088
|
+
tjpAddr: specialTjpAddr,
|
|
1089
|
+
latestIbGib: newSpecialIbGib,
|
|
1090
|
+
latestAddr: newSpecialAddr,
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
return newSpecialAddr;
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
console.error(`${lc} ${error.message}`);
|
|
1097
|
+
throw error;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
export async function getTjpIbGib({
|
|
1102
|
+
ibGib,
|
|
1103
|
+
naive = true,
|
|
1104
|
+
space,
|
|
1105
|
+
}: {
|
|
1106
|
+
ibGib: IbGib_V1<any>,
|
|
1107
|
+
naive?: boolean,
|
|
1108
|
+
space: IbGibSpaceAny,
|
|
1109
|
+
}): Promise<IbGib_V1<any> | undefined> {
|
|
1110
|
+
const lc = `[${getTjpIbGib.name}]`;
|
|
1111
|
+
|
|
1112
|
+
try {
|
|
1113
|
+
if (!space) { throw new Error(`space required. (E: 941f973d50e84415b58724af173f52c2)`); }
|
|
1114
|
+
if (!ibGib) { throw new Error('ibGib required.'); }
|
|
1115
|
+
|
|
1116
|
+
let ibGibAddr = getIbGibAddr({ ibGib });
|
|
1117
|
+
const { gib } = getIbAndGib({ ibGibAddr });
|
|
1118
|
+
if (gib === GIB) { return ibGib; }
|
|
1119
|
+
let isTjp = await isTjp_Naive({ ibGib, naive });
|
|
1120
|
+
if (isTjp) { return ibGib; }
|
|
1121
|
+
|
|
1122
|
+
// the given ibGib arg isn't itself the tjp
|
|
1123
|
+
|
|
1124
|
+
// if no rel8ns, then there is no tjp ibgib, since this is not
|
|
1125
|
+
// intrinsically the tjp and there is no 'tjp' or 'past' rel8n to check
|
|
1126
|
+
if (!ibGib.rel8ns) {
|
|
1127
|
+
if (logalot) { console.log(`${lc} ibgib not tjp in data, and rel8ns is falsy. so tjp is undefined (I: acdadb76a7568807db7a68f6f866de22)`); }
|
|
1128
|
+
return undefined; // <<<< returns early
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// check explicitly listed tjp in rel8ns
|
|
1132
|
+
if (ibGib.rel8ns!.tjp && ibGib.rel8ns!.tjp.length > 0) {
|
|
1133
|
+
let firstTjpAddr = ibGib.rel8ns!.tjp[0];
|
|
1134
|
+
let resGetTjpIbGib = await getFromSpace({ addr: firstTjpAddr, space });
|
|
1135
|
+
if (resGetTjpIbGib.success && resGetTjpIbGib.ibGibs?.length === 1) {
|
|
1136
|
+
return resGetTjpIbGib.ibGibs[0]
|
|
1137
|
+
} else {
|
|
1138
|
+
const resErrorMsg = resGetTjpIbGib.errorMsg ?? '[unspecified error in get result]';
|
|
1139
|
+
throw new Error(`ibGib references tjp but could not retrieve from space. res error: ${resErrorMsg} (E: 94f0340706ad48c794c6a62c1b235a22)`);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
// couldn't get the tjp from the rel8ns.tjp, so look for manually in past.
|
|
1144
|
+
// but we can't just get the earliest in the 'past', because the tjp
|
|
1145
|
+
// may be one of the intermediates!
|
|
1146
|
+
// So, check the immediate past ibGib recursively.
|
|
1147
|
+
|
|
1148
|
+
const past = ibGib.rel8ns!.past || [];
|
|
1149
|
+
if (past.length === 0) {
|
|
1150
|
+
console.warn(`${lc} past.length === 0, so there is no tjp.`)
|
|
1151
|
+
if (logalot) { console.log(`${lc} ibgib is not tjp in data, not in tjp rel8n, and past is empty. so tjp is undefined (I: bf06f664917dcf4492fb9c4c106a6222)`); }
|
|
1152
|
+
return undefined; // <<<< returns early
|
|
1153
|
+
}
|
|
1154
|
+
const pastIbGibAddr = past[past.length - 1];
|
|
1155
|
+
const resGetPastIbGib = await getFromSpace({ addr: pastIbGibAddr, space });
|
|
1156
|
+
if (!resGetPastIbGib.success || resGetPastIbGib.ibGibs?.length !== 1) { throw new Error(`get past failed. addr: ${pastIbGibAddr}`); }
|
|
1157
|
+
const pastIbGib = resGetPastIbGib.ibGibs![0];
|
|
1158
|
+
|
|
1159
|
+
// call this method recursively!
|
|
1160
|
+
return await getTjpIbGib({ ibGib: pastIbGib, naive, space });
|
|
1161
|
+
} catch (error) {
|
|
1162
|
+
console.error(`${lc} ${error.message}`);
|
|
1163
|
+
throw error;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// #region creates
|
|
1168
|
+
|
|
1169
|
+
/**
|
|
1170
|
+
* Routing function to various `create_____` functions.
|
|
1171
|
+
*
|
|
1172
|
+
* @returns address of newly created special.
|
|
1173
|
+
*/
|
|
1174
|
+
export async function createSpecial({
|
|
1175
|
+
type,
|
|
1176
|
+
space,
|
|
1177
|
+
zeroSpace,
|
|
1178
|
+
fnUpdateBootstrap,
|
|
1179
|
+
fnBroadcast,
|
|
1180
|
+
}: {
|
|
1181
|
+
type: SpecialIbGibType,
|
|
1182
|
+
space: IbGibSpaceAny,
|
|
1183
|
+
zeroSpace: IbGibSpaceAny,
|
|
1184
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1185
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1186
|
+
}): Promise<IbGibAddr | null> {
|
|
1187
|
+
const lc = `[${createSpecial.name}]`;
|
|
1188
|
+
try {
|
|
1189
|
+
if (!space) { throw new Error(`space falsy and localUserSpace not initialized. (E: 66e7d3ff098248f0a5ddda51853c92e6)`); }
|
|
1190
|
+
|
|
1191
|
+
switch (type) {
|
|
1192
|
+
case "roots": return createSpecial_Roots({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1193
|
+
case "tags": return createSpecial_Tags({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1194
|
+
case "latest": return createSpecial_Latest({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1195
|
+
case "secrets": return createSpecial_Secrets({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1196
|
+
case "encryptions": return createSpecial_Encryptions({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1197
|
+
case "outerspaces": return createSpecial_OuterSpaces({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1198
|
+
case "autosyncs": return createSpecial_Autosyncs({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1199
|
+
case "robbots": return createSpecial_Robbots({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1200
|
+
case "apps": return createSpecial_Apps({ space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1201
|
+
default: return createSpecial_Default({ type, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1202
|
+
}
|
|
1203
|
+
} catch (error) {
|
|
1204
|
+
console.error(`${lc} ${error.message}`);
|
|
1205
|
+
throw error;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
/**
|
|
1210
|
+
* Creates a new special ibgib, persists it and if not skipped, relates
|
|
1211
|
+
* it to the current root.
|
|
1212
|
+
*
|
|
1213
|
+
* @returns newly created ibgib (not just address)
|
|
1214
|
+
*/
|
|
1215
|
+
export async function createSpecialIbGib({
|
|
1216
|
+
type,
|
|
1217
|
+
skipRel8ToRoot,
|
|
1218
|
+
space,
|
|
1219
|
+
zeroSpace,
|
|
1220
|
+
fnUpdateBootstrap,
|
|
1221
|
+
fnBroadcast,
|
|
1222
|
+
}: {
|
|
1223
|
+
type: SpecialIbGibType,
|
|
1224
|
+
skipRel8ToRoot?: boolean,
|
|
1225
|
+
space: IbGibSpaceAny,
|
|
1226
|
+
zeroSpace: IbGibSpaceAny,
|
|
1227
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1228
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1229
|
+
}): Promise<IbGib_V1> {
|
|
1230
|
+
const lc = `[${createSpecialIbGib.name}][${type || 'falsy type?'}]`;
|
|
1231
|
+
try {
|
|
1232
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
1233
|
+
const specialIb = getSpecialIbGibIb({ type });
|
|
1234
|
+
const src = factory.primitive({ ib: specialIb });
|
|
1235
|
+
const resNewSpecial = await V1.fork({
|
|
1236
|
+
src,
|
|
1237
|
+
destIb: specialIb,
|
|
1238
|
+
linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
|
|
1239
|
+
tjp: { uuid: true, timestamp: true },
|
|
1240
|
+
dna: false,
|
|
1241
|
+
nCounter: true,
|
|
1242
|
+
});
|
|
1243
|
+
await persistTransformResult({ resTransform: resNewSpecial, isMeta: true, space });
|
|
1244
|
+
if (type !== 'roots' && !skipRel8ToRoot) {
|
|
1245
|
+
await rel8ToCurrentRoot({
|
|
1246
|
+
ibGib: resNewSpecial.newIbGib,
|
|
1247
|
+
linked: true,
|
|
1248
|
+
space,
|
|
1249
|
+
zeroSpace,
|
|
1250
|
+
fnBroadcast,
|
|
1251
|
+
fnUpdateBootstrap,
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
1255
|
+
return resNewSpecial.newIbGib;
|
|
1256
|
+
} catch (error) {
|
|
1257
|
+
console.error(`${lc} ${error.message}`);
|
|
1258
|
+
throw error;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* Creates a new tags^gib instance (unique to current space), as well as
|
|
1264
|
+
* default initial tags, e.g. "home", "favorites", etc., and relates these
|
|
1265
|
+
* individual tags to the tags ibGib itself.
|
|
1266
|
+
*
|
|
1267
|
+
* Stores the tags ibGib's addr in config.
|
|
1268
|
+
*/
|
|
1269
|
+
export async function createSpecial_Tags({
|
|
1270
|
+
space,
|
|
1271
|
+
zeroSpace,
|
|
1272
|
+
fnUpdateBootstrap,
|
|
1273
|
+
fnBroadcast,
|
|
1274
|
+
}: {
|
|
1275
|
+
space: IbGibSpaceAny,
|
|
1276
|
+
zeroSpace: IbGibSpaceAny,
|
|
1277
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1278
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1279
|
+
}): Promise<IbGibAddr | null> {
|
|
1280
|
+
const lc = `[${createSpecial_Tags.name}]`;
|
|
1281
|
+
try {
|
|
1282
|
+
if (!space) { throw new Error(`space required. (E: 9c05b9bd355943a39ca47afef67a50eb)`); }
|
|
1283
|
+
|
|
1284
|
+
const configKey = getSpecialConfigKey({ type: "tags" });
|
|
1285
|
+
const special = await createSpecialIbGib({
|
|
1286
|
+
type: "tags",
|
|
1287
|
+
space,
|
|
1288
|
+
zeroSpace,
|
|
1289
|
+
fnBroadcast,
|
|
1290
|
+
fnUpdateBootstrap,
|
|
1291
|
+
});
|
|
1292
|
+
let addr = getIbGibAddr({ ibGib: special });
|
|
1293
|
+
await setConfigAddr({ key: configKey, addr: addr, space, zeroSpace, fnUpdateBootstrap });
|
|
1294
|
+
|
|
1295
|
+
// at this point, our tags ibGib has no associated tag ibGibs.
|
|
1296
|
+
// add home, favorite tags
|
|
1297
|
+
const initialTagDatas: TagData_V1[] = [
|
|
1298
|
+
{ text: 'home', icon: 'home-outline' },
|
|
1299
|
+
{ text: 'favorite', icon: 'heart-outline' },
|
|
1300
|
+
];
|
|
1301
|
+
for (const data of initialTagDatas) {
|
|
1302
|
+
const resCreate = await createTagIbGibAndSundry({ ...data, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1303
|
+
addr = resCreate.newTagsAddr;
|
|
1304
|
+
await setConfigAddr({ key: configKey, addr: addr, space, zeroSpace, fnUpdateBootstrap });
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
return addr;
|
|
1308
|
+
} catch (error) {
|
|
1309
|
+
console.error(`${lc} ${error.message}`);
|
|
1310
|
+
return null;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
/**
|
|
1315
|
+
* 1. Creates a new tag ibgib with the given properties.
|
|
1316
|
+
* 2. Persists graph in given {@link space}
|
|
1317
|
+
* 3. Registers the new tag ibgib in that space, using the given
|
|
1318
|
+
* {@link fnUpdateBootstrap} and {@link fnBroadcast} functions.
|
|
1319
|
+
* 4. Relates the new tag to the special tags ibgib.
|
|
1320
|
+
*
|
|
1321
|
+
* @returns the new tag ibgib and new tags address.
|
|
1322
|
+
*/
|
|
1323
|
+
export async function createTagIbGibAndSundry({
|
|
1324
|
+
text,
|
|
1325
|
+
icon,
|
|
1326
|
+
description,
|
|
1327
|
+
space,
|
|
1328
|
+
zeroSpace,
|
|
1329
|
+
fnUpdateBootstrap,
|
|
1330
|
+
fnBroadcast,
|
|
1331
|
+
}: {
|
|
1332
|
+
text: string,
|
|
1333
|
+
icon?: string,
|
|
1334
|
+
description?: string,
|
|
1335
|
+
space: IbGibSpaceAny,
|
|
1336
|
+
zeroSpace: IbGibSpaceAny,
|
|
1337
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1338
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1339
|
+
}): Promise<{ newTagIbGib: TagIbGib_V1, newTagsAddr: string }> {
|
|
1340
|
+
const lc = `[${createTagIbGibAndSundry.name}]`;
|
|
1341
|
+
try {
|
|
1342
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
1343
|
+
if (!space) { throw new Error(`space required. (E: 5def0b1afab74b0c9286e3ac5060cb8f)`); }
|
|
1344
|
+
|
|
1345
|
+
if (!text) { throw new Error(`${lc} text required`); }
|
|
1346
|
+
icon = icon || DEFAULT_TAG_ICON;
|
|
1347
|
+
description = description || DEFAULT_TAG_DESCRIPTION;
|
|
1348
|
+
const tagIb = tagTextToIb(text);
|
|
1349
|
+
const tagPrimitive = factory.primitive({ ib: "tag" });
|
|
1350
|
+
const resNewTag = await factory.firstGen({
|
|
1351
|
+
parentIbGib: tagPrimitive,
|
|
1352
|
+
ib: tagIb,
|
|
1353
|
+
data: { text, icon, description },
|
|
1354
|
+
linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
|
|
1355
|
+
tjp: { uuid: true, timestamp: true },
|
|
1356
|
+
dna: true,
|
|
1357
|
+
nCounter: true,
|
|
1358
|
+
});
|
|
1359
|
+
const newTag = resNewTag.newIbGib as TagIbGib_V1;
|
|
1360
|
+
await persistTransformResult({ resTransform: resNewTag, isMeta: true, space });
|
|
1361
|
+
await registerNewIbGib({ ibGib: newTag, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1362
|
+
const newTagsAddr = await rel8TagToTagsIbGib({
|
|
1363
|
+
tagIbGib: newTag, space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
|
|
1364
|
+
});
|
|
1365
|
+
return { newTagIbGib: newTag, newTagsAddr };
|
|
1366
|
+
} catch (error) {
|
|
1367
|
+
console.error(`${lc} ${error.message}`);
|
|
1368
|
+
throw error;
|
|
1369
|
+
} finally {
|
|
1370
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
export async function createSpecial_Roots({
|
|
1375
|
+
space,
|
|
1376
|
+
zeroSpace,
|
|
1377
|
+
fnUpdateBootstrap,
|
|
1378
|
+
fnBroadcast,
|
|
1379
|
+
}: {
|
|
1380
|
+
space: IbGibSpaceAny,
|
|
1381
|
+
zeroSpace: IbGibSpaceAny,
|
|
1382
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1383
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1384
|
+
}): Promise<IbGibAddr | null> {
|
|
1385
|
+
const lc = `[${createSpecial_Roots.name}]`;
|
|
1386
|
+
try {
|
|
1387
|
+
if (!space) { throw new Error(`space required. (E: d12a8ea31163429fb6e53ff8e7579c57)`); }
|
|
1388
|
+
|
|
1389
|
+
const configKey = getSpecialConfigKey({ type: "roots" });
|
|
1390
|
+
// const rootsIbGib = await createSpecialIbGib({type: "roots", space});
|
|
1391
|
+
const rootsIbGib = await createSpecialIbGib({
|
|
1392
|
+
type: "roots",
|
|
1393
|
+
space,
|
|
1394
|
+
zeroSpace,
|
|
1395
|
+
fnBroadcast,
|
|
1396
|
+
fnUpdateBootstrap,
|
|
1397
|
+
});
|
|
1398
|
+
let rootsAddr: IbGibAddr | undefined = getIbGibAddr({ ibGib: rootsIbGib });
|
|
1399
|
+
await setConfigAddr({ key: configKey, addr: rootsAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1400
|
+
|
|
1401
|
+
// at this point, our ibGib has no associated ibGibs.
|
|
1402
|
+
// so we add initial roots
|
|
1403
|
+
const rootNames = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
|
|
1404
|
+
|
|
1405
|
+
const initialDatas: RootData[] = rootNames.map(n => {
|
|
1406
|
+
return {
|
|
1407
|
+
text: `${n}root`,
|
|
1408
|
+
icon: DEFAULT_ROOT_ICON,
|
|
1409
|
+
description: DEFAULT_ROOT_DESCRIPTION
|
|
1410
|
+
};
|
|
1411
|
+
});
|
|
1412
|
+
let firstRoot: IbGib_V1<RootData> | undefined = undefined;
|
|
1413
|
+
for (let i = 0; i < initialDatas.length; i++) {
|
|
1414
|
+
const data = initialDatas[i];
|
|
1415
|
+
const resCreate = await createRootIbGib({
|
|
1416
|
+
...data,
|
|
1417
|
+
space,
|
|
1418
|
+
zeroSpace,
|
|
1419
|
+
fnUpdateBootstrap,
|
|
1420
|
+
fnBroadcast,
|
|
1421
|
+
});
|
|
1422
|
+
if (!firstRoot) { firstRoot = resCreate.newRootIbGib; }
|
|
1423
|
+
if (!resCreate.newRootIbGib) { throw new Error(`(UNEXPECTED) resCreate.newRootIbGib falsy? (E: c9fb2c94a9c1d762c1699b41a4d5ad23)`); }
|
|
1424
|
+
rootsAddr = resCreate.newRootsAddr;
|
|
1425
|
+
// update the config for the updated **roots** ibgib.
|
|
1426
|
+
// that roots ibgib is what points to the just created new root.
|
|
1427
|
+
await setConfigAddr({ key: configKey, addr: rootsAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1428
|
+
}
|
|
1429
|
+
if (!firstRoot) { throw new Error(`(UNEXPECTED) firstRoot still falsy? (E: b2e2c926d242966e7ed7159e4b129e23)`); }
|
|
1430
|
+
|
|
1431
|
+
// initialize current root
|
|
1432
|
+
await setCurrentRoot({ root: firstRoot, space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
|
|
1433
|
+
// hack: the above line updates the roots in config. so get **that** addr.
|
|
1434
|
+
|
|
1435
|
+
rootsAddr = await getConfigAddr({ key: configKey, space });
|
|
1436
|
+
if (!rootsAddr) { throw new Error('(UNEXPECTED) no roots address in config? (E: 76345340699a4738a195e48803ef0d31)'); }
|
|
1437
|
+
return rootsAddr;
|
|
1438
|
+
} catch (error) {
|
|
1439
|
+
console.error(`${lc} ${error.message}`);
|
|
1440
|
+
return null;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
async function createRootIbGib({
|
|
1445
|
+
text,
|
|
1446
|
+
icon,
|
|
1447
|
+
description,
|
|
1448
|
+
space,
|
|
1449
|
+
zeroSpace,
|
|
1450
|
+
fnUpdateBootstrap,
|
|
1451
|
+
fnBroadcast,
|
|
1452
|
+
}: {
|
|
1453
|
+
text: string,
|
|
1454
|
+
icon?: string,
|
|
1455
|
+
description?: string,
|
|
1456
|
+
space: IbGibSpaceAny,
|
|
1457
|
+
zeroSpace: IbGibSpaceAny,
|
|
1458
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1459
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1460
|
+
}): Promise<{ newRootIbGib: IbGib_V1<RootData>, newRootsAddr: string }> {
|
|
1461
|
+
const lc = `[${createRootIbGib.name}]`;
|
|
1462
|
+
try {
|
|
1463
|
+
if (!space) { throw new Error(`space required. (E: cfa876e5c8c64a53a463ca7a645571c8)`); }
|
|
1464
|
+
|
|
1465
|
+
text = text || DEFAULT_ROOT_TEXT;
|
|
1466
|
+
icon = icon || DEFAULT_ROOT_ICON;
|
|
1467
|
+
description = description || DEFAULT_ROOT_DESCRIPTION;
|
|
1468
|
+
const ib = getRootIb(text);
|
|
1469
|
+
const parentIbGib = factory.primitive({ ib: "root" });
|
|
1470
|
+
const resNewIbGib = await factory.firstGen({
|
|
1471
|
+
parentIbGib,
|
|
1472
|
+
ib,
|
|
1473
|
+
data: { text, icon, description },
|
|
1474
|
+
linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
|
|
1475
|
+
tjp: { uuid: true, timestamp: true },
|
|
1476
|
+
dna: true,
|
|
1477
|
+
});
|
|
1478
|
+
const { newIbGib } = resNewIbGib;
|
|
1479
|
+
await persistTransformResult({
|
|
1480
|
+
resTransform: resNewIbGib,
|
|
1481
|
+
isMeta: true,
|
|
1482
|
+
space,
|
|
1483
|
+
});
|
|
1484
|
+
const newRootsAddr = await rel8ToSpecialIbGib({
|
|
1485
|
+
type: "roots",
|
|
1486
|
+
rel8nName: ROOT_REL8N_NAME,
|
|
1487
|
+
ibGibsToRel8: [newIbGib],
|
|
1488
|
+
// isMeta: true,
|
|
1489
|
+
space,
|
|
1490
|
+
zeroSpace,
|
|
1491
|
+
fnUpdateBootstrap,
|
|
1492
|
+
fnBroadcast,
|
|
1493
|
+
});
|
|
1494
|
+
return { newRootIbGib: newIbGib as IbGib_V1<RootData>, newRootsAddr };
|
|
1495
|
+
} catch (error) {
|
|
1496
|
+
console.error(`${lc} ${error.message}`);
|
|
1497
|
+
throw error;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
async function createSpecial_Latest({
|
|
1502
|
+
space,
|
|
1503
|
+
zeroSpace,
|
|
1504
|
+
fnUpdateBootstrap,
|
|
1505
|
+
fnBroadcast,
|
|
1506
|
+
}: {
|
|
1507
|
+
space: IbGibSpaceAny,
|
|
1508
|
+
zeroSpace: IbGibSpaceAny,
|
|
1509
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1510
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1511
|
+
}): Promise<IbGibAddr | null> {
|
|
1512
|
+
const lc = `[${createSpecial_Latest.name}]`;
|
|
1513
|
+
try {
|
|
1514
|
+
if (!space) { throw new Error(`space required. (E: 173b08d7eb114238b32280c3efce9d1a)`); }
|
|
1515
|
+
|
|
1516
|
+
const configKey = getSpecialConfigKey({ type: "latest" });
|
|
1517
|
+
// const special =
|
|
1518
|
+
// await createSpecialIbGib({type: "latest", skipRel8ToRoot: true, space});
|
|
1519
|
+
const special = await createSpecialIbGib({
|
|
1520
|
+
type: "latest",
|
|
1521
|
+
space,
|
|
1522
|
+
skipRel8ToRoot: true,
|
|
1523
|
+
zeroSpace,
|
|
1524
|
+
fnBroadcast,
|
|
1525
|
+
fnUpdateBootstrap,
|
|
1526
|
+
});
|
|
1527
|
+
let specialAddr = getIbGibAddr({ ibGib: special });
|
|
1528
|
+
await setConfigAddr({ key: configKey, addr: specialAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1529
|
+
|
|
1530
|
+
// right now, the latest ibgib doesn't have any more initialization,
|
|
1531
|
+
// since it is supposed to be as ephemeral and non-tracked as possible.
|
|
1532
|
+
|
|
1533
|
+
return specialAddr;
|
|
1534
|
+
} catch (error) {
|
|
1535
|
+
console.error(`${lc} ${error.message}`);
|
|
1536
|
+
return null;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
async function createSpecial_Secrets({
|
|
1541
|
+
space,
|
|
1542
|
+
zeroSpace,
|
|
1543
|
+
fnUpdateBootstrap,
|
|
1544
|
+
fnBroadcast,
|
|
1545
|
+
}: {
|
|
1546
|
+
space: IbGibSpaceAny,
|
|
1547
|
+
zeroSpace: IbGibSpaceAny,
|
|
1548
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1549
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1550
|
+
}): Promise<IbGibAddr | null> {
|
|
1551
|
+
const lc = `[${createSpecial_Secrets.name}]`;
|
|
1552
|
+
try {
|
|
1553
|
+
if (!space) { throw new Error(`space required. (E: 340960cd5ad24addb300b23d9722e30a)`); }
|
|
1554
|
+
|
|
1555
|
+
let secretsAddr: IbGibAddr;
|
|
1556
|
+
const configKey = getSpecialConfigKey({ type: "secrets" });
|
|
1557
|
+
|
|
1558
|
+
// special ibgib doesn't exist, so create it (empty)
|
|
1559
|
+
// const secretsIbgib = await createSpecialIbGib({type: "secrets", space});
|
|
1560
|
+
const secretsIbgib = await createSpecialIbGib({
|
|
1561
|
+
type: "secrets",
|
|
1562
|
+
space,
|
|
1563
|
+
zeroSpace,
|
|
1564
|
+
fnBroadcast,
|
|
1565
|
+
fnUpdateBootstrap,
|
|
1566
|
+
});
|
|
1567
|
+
secretsAddr = getIbGibAddr({ ibGib: secretsIbgib });
|
|
1568
|
+
await setConfigAddr({ key: configKey, addr: secretsAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1569
|
+
|
|
1570
|
+
return secretsAddr;
|
|
1571
|
+
} catch (error) {
|
|
1572
|
+
console.error(`${lc} ${error.message}`);
|
|
1573
|
+
return null;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
async function createSpecial_Encryptions({
|
|
1578
|
+
space,
|
|
1579
|
+
zeroSpace,
|
|
1580
|
+
fnUpdateBootstrap,
|
|
1581
|
+
fnBroadcast,
|
|
1582
|
+
}: {
|
|
1583
|
+
space: IbGibSpaceAny,
|
|
1584
|
+
zeroSpace: IbGibSpaceAny,
|
|
1585
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1586
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1587
|
+
}): Promise<IbGibAddr | null> {
|
|
1588
|
+
const lc = `[${createSpecial_Encryptions.name}]`;
|
|
1589
|
+
try {
|
|
1590
|
+
if (!space) { throw new Error(`space required. (E: 5084e698b6924e7090697ca50075ca59)`); }
|
|
1591
|
+
|
|
1592
|
+
let addr: IbGibAddr;
|
|
1593
|
+
const configKey = getSpecialConfigKey({ type: "encryptions" });
|
|
1594
|
+
|
|
1595
|
+
// special ibgib doesn't exist, so create it (empty)
|
|
1596
|
+
// const encryptionsIbgib = await createSpecialIbGib({type: "encryptions", space});
|
|
1597
|
+
const encryptionsIbgib = await createSpecialIbGib({
|
|
1598
|
+
type: "encryptions",
|
|
1599
|
+
space,
|
|
1600
|
+
zeroSpace,
|
|
1601
|
+
fnBroadcast,
|
|
1602
|
+
fnUpdateBootstrap,
|
|
1603
|
+
});
|
|
1604
|
+
addr = getIbGibAddr({ ibGib: encryptionsIbgib });
|
|
1605
|
+
await setConfigAddr({ key: configKey, addr: addr, space, zeroSpace, fnUpdateBootstrap });
|
|
1606
|
+
|
|
1607
|
+
return addr;
|
|
1608
|
+
} catch (error) {
|
|
1609
|
+
console.error(`${lc} ${error.message}`);
|
|
1610
|
+
return null;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
async function createSpecial_OuterSpaces({
|
|
1615
|
+
space,
|
|
1616
|
+
zeroSpace,
|
|
1617
|
+
fnUpdateBootstrap,
|
|
1618
|
+
fnBroadcast,
|
|
1619
|
+
}: {
|
|
1620
|
+
space: IbGibSpaceAny,
|
|
1621
|
+
zeroSpace: IbGibSpaceAny,
|
|
1622
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1623
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1624
|
+
}): Promise<IbGibAddr | null> {
|
|
1625
|
+
const lc = `[${createSpecial_OuterSpaces.name}]`;
|
|
1626
|
+
try {
|
|
1627
|
+
if (!space) { throw new Error(`space required. (E: 99dd9e92535c470482eb9f6625a33831)`); }
|
|
1628
|
+
|
|
1629
|
+
let outerSpacesAddr: IbGibAddr;
|
|
1630
|
+
const configKey = getSpecialConfigKey({ type: "outerspaces" });
|
|
1631
|
+
|
|
1632
|
+
// special outerspaces ibgib doesn't exist, so create it (empty)
|
|
1633
|
+
// const outerSpacesIbGib = await createSpecialIbGib({type: "outerspaces", space});
|
|
1634
|
+
const outerSpacesIbGib = await createSpecialIbGib({
|
|
1635
|
+
type: "outerspaces",
|
|
1636
|
+
space,
|
|
1637
|
+
zeroSpace,
|
|
1638
|
+
fnBroadcast,
|
|
1639
|
+
fnUpdateBootstrap,
|
|
1640
|
+
});
|
|
1641
|
+
outerSpacesAddr = getIbGibAddr({ ibGib: outerSpacesIbGib });
|
|
1642
|
+
await setConfigAddr({ key: configKey, addr: outerSpacesAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1643
|
+
|
|
1644
|
+
return outerSpacesAddr;
|
|
1645
|
+
} catch (error) {
|
|
1646
|
+
console.error(`${lc} ${error.message}`);
|
|
1647
|
+
return null;
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
async function createSpecial_Autosyncs({
|
|
1652
|
+
space,
|
|
1653
|
+
zeroSpace,
|
|
1654
|
+
fnUpdateBootstrap,
|
|
1655
|
+
fnBroadcast,
|
|
1656
|
+
}: {
|
|
1657
|
+
space: IbGibSpaceAny,
|
|
1658
|
+
zeroSpace: IbGibSpaceAny,
|
|
1659
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1660
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1661
|
+
}): Promise<IbGibAddr | null> {
|
|
1662
|
+
const lc = `[${createSpecial_Autosyncs.name}]`;
|
|
1663
|
+
try {
|
|
1664
|
+
if (!space) { throw new Error(`space required. (E: f01cf6a4a460486796e16d505d629522)`); }
|
|
1665
|
+
|
|
1666
|
+
let autosyncsAddr: IbGibAddr;
|
|
1667
|
+
const configKey = getSpecialConfigKey({ type: "autosyncs" });
|
|
1668
|
+
|
|
1669
|
+
const autosyncsIbGib = await createSpecialIbGib({
|
|
1670
|
+
type: "autosyncs",
|
|
1671
|
+
space,
|
|
1672
|
+
zeroSpace,
|
|
1673
|
+
fnBroadcast,
|
|
1674
|
+
fnUpdateBootstrap,
|
|
1675
|
+
});
|
|
1676
|
+
autosyncsAddr = getIbGibAddr({ ibGib: autosyncsIbGib });
|
|
1677
|
+
await setConfigAddr({ key: configKey, addr: autosyncsAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1678
|
+
|
|
1679
|
+
return autosyncsAddr;
|
|
1680
|
+
} catch (error) {
|
|
1681
|
+
console.error(`${lc} ${error.message}`);
|
|
1682
|
+
return null;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
export async function createSpecial_Robbots({
|
|
1687
|
+
space,
|
|
1688
|
+
zeroSpace,
|
|
1689
|
+
fnUpdateBootstrap,
|
|
1690
|
+
fnBroadcast,
|
|
1691
|
+
}: {
|
|
1692
|
+
space: IbGibSpaceAny,
|
|
1693
|
+
zeroSpace: IbGibSpaceAny,
|
|
1694
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1695
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1696
|
+
}): Promise<IbGibAddr | null> {
|
|
1697
|
+
const lc = `[${createSpecial_Robbots.name}]`;
|
|
1698
|
+
try {
|
|
1699
|
+
if (!space) { throw new Error(`space required. (E: f01cf6a4a460486796e16d505d629522)`); }
|
|
1700
|
+
|
|
1701
|
+
let robbotsAddr: IbGibAddr;
|
|
1702
|
+
const configKey = getSpecialConfigKey({ type: "robbots" });
|
|
1703
|
+
|
|
1704
|
+
const robbotsIbGib = await createSpecialIbGib({
|
|
1705
|
+
type: "robbots",
|
|
1706
|
+
space,
|
|
1707
|
+
zeroSpace,
|
|
1708
|
+
fnBroadcast,
|
|
1709
|
+
fnUpdateBootstrap,
|
|
1710
|
+
});
|
|
1711
|
+
robbotsAddr = getIbGibAddr({ ibGib: robbotsIbGib });
|
|
1712
|
+
await setConfigAddr({ key: configKey, addr: robbotsAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1713
|
+
|
|
1714
|
+
return robbotsAddr;
|
|
1715
|
+
} catch (error) {
|
|
1716
|
+
console.error(`${lc} ${error.message}`);
|
|
1717
|
+
return null;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
export async function createSpecial_Apps({
|
|
1722
|
+
space,
|
|
1723
|
+
zeroSpace,
|
|
1724
|
+
fnUpdateBootstrap,
|
|
1725
|
+
fnBroadcast,
|
|
1726
|
+
}: {
|
|
1727
|
+
space: IbGibSpaceAny,
|
|
1728
|
+
zeroSpace: IbGibSpaceAny,
|
|
1729
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1730
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1731
|
+
}): Promise<IbGibAddr | null> {
|
|
1732
|
+
const lc = `[${createSpecial_Apps.name}]`;
|
|
1733
|
+
try {
|
|
1734
|
+
if (!space) { throw new Error(`space required. (E: f01cf6a4a460486796e16d505d629522)`); }
|
|
1735
|
+
|
|
1736
|
+
let appsAddr: IbGibAddr | undefined | null;
|
|
1737
|
+
const configKey = getSpecialConfigKey({ type: "apps" });
|
|
1738
|
+
|
|
1739
|
+
const appsIbGib = await createSpecialIbGib({
|
|
1740
|
+
type: "apps",
|
|
1741
|
+
space,
|
|
1742
|
+
zeroSpace,
|
|
1743
|
+
fnBroadcast,
|
|
1744
|
+
fnUpdateBootstrap,
|
|
1745
|
+
});
|
|
1746
|
+
appsAddr = getIbGibAddr({ ibGib: appsIbGib });
|
|
1747
|
+
await setConfigAddr({ key: configKey, addr: appsAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1748
|
+
|
|
1749
|
+
// at this point, our apps ibGib has no associated app ibGibs.
|
|
1750
|
+
// so create our initial apps.
|
|
1751
|
+
// appsAddr = await createApps_Chat({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
|
|
1752
|
+
appsAddr = await createApp({
|
|
1753
|
+
defaultAppData: DEFAULT_CHAT_APP_DATA_V1,
|
|
1754
|
+
defaultAppRel8ns: DEFAULT_CHAT_APP_REL8NS_V1,
|
|
1755
|
+
space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
|
|
1756
|
+
});
|
|
1757
|
+
// appsAddr = await createApps_Raw({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
|
|
1758
|
+
appsAddr = await createApp({
|
|
1759
|
+
defaultAppData: DEFAULT_RAW_APP_DATA_V1,
|
|
1760
|
+
defaultAppRel8ns: DEFAULT_RAW_APP_REL8NS_V1,
|
|
1761
|
+
space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
|
|
1762
|
+
});
|
|
1763
|
+
// appsAddr = await createApps_Todo({ space, zeroSpace, fnUpdateBootstrap, fnBroadcast });
|
|
1764
|
+
appsAddr = await createApp({
|
|
1765
|
+
defaultAppData: DEFAULT_TODO_APP_DATA_V1,
|
|
1766
|
+
defaultAppRel8ns: DEFAULT_TODO_APP_REL8NS_V1,
|
|
1767
|
+
space, zeroSpace, fnUpdateBootstrap, fnBroadcast,
|
|
1768
|
+
});
|
|
1769
|
+
|
|
1770
|
+
return appsAddr;
|
|
1771
|
+
} catch (error) {
|
|
1772
|
+
console.error(`${lc} ${error.message}`);
|
|
1773
|
+
return null;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
export async function createApp({
|
|
1778
|
+
defaultAppData,
|
|
1779
|
+
defaultAppRel8ns,
|
|
1780
|
+
space,
|
|
1781
|
+
zeroSpace,
|
|
1782
|
+
fnUpdateBootstrap,
|
|
1783
|
+
fnBroadcast,
|
|
1784
|
+
}: {
|
|
1785
|
+
/**
|
|
1786
|
+
* object that contains all of the default "data" for the app. Data here
|
|
1787
|
+
* does not mean an app's data like other apps. In ibgib, data is
|
|
1788
|
+
* everywhere. This means particularly the defalut app ibGib's data, i.e.
|
|
1789
|
+
* `ibGib.data`.
|
|
1790
|
+
*/
|
|
1791
|
+
defaultAppData: any,
|
|
1792
|
+
defaultAppRel8ns: any,
|
|
1793
|
+
space: IbGibSpaceAny,
|
|
1794
|
+
zeroSpace: IbGibSpaceAny,
|
|
1795
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1796
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1797
|
+
}): Promise<IbGibAddr | null> {
|
|
1798
|
+
const lc = `[${createApp.name}]`;
|
|
1799
|
+
try {
|
|
1800
|
+
if (logalot) { console.log(`${lc} starting... (I: 677f68789abdc7316887e8f38c764e22)`); }
|
|
1801
|
+
|
|
1802
|
+
// #region torn from chat-app-v1.ts because of circular dependency...eesh
|
|
1803
|
+
|
|
1804
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
1805
|
+
let data = clone(defaultAppData);
|
|
1806
|
+
let rel8ns = defaultAppRel8ns ? clone(defaultAppRel8ns) : undefined;
|
|
1807
|
+
data.uuid = data.uuid ?? await getUUID();
|
|
1808
|
+
let { classname } = data;
|
|
1809
|
+
|
|
1810
|
+
const ib = getAppIb({ appData: data, classname });
|
|
1811
|
+
|
|
1812
|
+
const resNewApp = await factory.firstGen({
|
|
1813
|
+
ib,
|
|
1814
|
+
parentIbGib: factory.primitive({ ib: `app ${classname}` }),
|
|
1815
|
+
data: data,
|
|
1816
|
+
rel8ns,
|
|
1817
|
+
dna: true,
|
|
1818
|
+
linkedRel8ns: [Rel8n.ancestor, Rel8n.past],
|
|
1819
|
+
nCounter: true,
|
|
1820
|
+
tjp: { timestamp: true },
|
|
1821
|
+
}) as TransformResult<AppIbGib_V1>;
|
|
1822
|
+
|
|
1823
|
+
// #endregion torn from chat-app-v1.ts because of circular dependency...eesh
|
|
1824
|
+
|
|
1825
|
+
await persistTransformResult({ resTransform: resNewApp, space });
|
|
1826
|
+
await registerNewIbGib({
|
|
1827
|
+
ibGib: resNewApp.newIbGib,
|
|
1828
|
+
fnBroadcast, fnUpdateBootstrap,
|
|
1829
|
+
space, zeroSpace
|
|
1830
|
+
});
|
|
1831
|
+
let appsAddr = await rel8ToSpecialIbGib({
|
|
1832
|
+
type: "apps",
|
|
1833
|
+
rel8nName: APP_REL8N_NAME,
|
|
1834
|
+
ibGibsToRel8: [resNewApp.newIbGib],
|
|
1835
|
+
fnBroadcast, fnUpdateBootstrap,
|
|
1836
|
+
space, zeroSpace,
|
|
1837
|
+
});
|
|
1838
|
+
|
|
1839
|
+
return appsAddr;
|
|
1840
|
+
|
|
1841
|
+
} catch (error) {
|
|
1842
|
+
console.error(`${lc} ${error.message}`);
|
|
1843
|
+
throw error;
|
|
1844
|
+
} finally {
|
|
1845
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
async function createSpecial_Default({
|
|
1850
|
+
type,
|
|
1851
|
+
space,
|
|
1852
|
+
zeroSpace,
|
|
1853
|
+
fnUpdateBootstrap,
|
|
1854
|
+
fnBroadcast,
|
|
1855
|
+
}: {
|
|
1856
|
+
type: SpecialIbGibType,
|
|
1857
|
+
space: IbGibSpaceAny,
|
|
1858
|
+
zeroSpace: IbGibSpaceAny,
|
|
1859
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1860
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1861
|
+
}): Promise<IbGibAddr | null> {
|
|
1862
|
+
const lc = `[${createSpecial_Autosyncs.name}]`;
|
|
1863
|
+
try {
|
|
1864
|
+
if (!space) { throw new Error(`space required. (E: c7bbafcbe901418db4c6048f17f53091)`); }
|
|
1865
|
+
|
|
1866
|
+
if (logalot) { console.log(`${lc} creating special of type: ${type} (I: 283c8bb30ed6f9698b74b886c6078622)`); }
|
|
1867
|
+
|
|
1868
|
+
let specialAddr: IbGibAddr;
|
|
1869
|
+
const configKey = getSpecialConfigKey({ type });
|
|
1870
|
+
|
|
1871
|
+
const specialIbGib = await createSpecialIbGib({
|
|
1872
|
+
type,
|
|
1873
|
+
space,
|
|
1874
|
+
zeroSpace,
|
|
1875
|
+
fnBroadcast,
|
|
1876
|
+
fnUpdateBootstrap,
|
|
1877
|
+
});
|
|
1878
|
+
specialAddr = getIbGibAddr({ ibGib: specialIbGib });
|
|
1879
|
+
await setConfigAddr({ key: configKey, addr: specialAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
1880
|
+
|
|
1881
|
+
return specialAddr;
|
|
1882
|
+
} catch (error) {
|
|
1883
|
+
console.error(`${lc} ${error.message}`);
|
|
1884
|
+
return null;
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
/**
|
|
1889
|
+
* 1. Creates a new robbot ibgib with the given properties.
|
|
1890
|
+
* 2. Persists graph in given {@link space}
|
|
1891
|
+
* 3. Registers the new robbot ibgib in that space, using the given
|
|
1892
|
+
* {@link fnUpdateBootstrap} and {@link fnBroadcast} functions.
|
|
1893
|
+
* 4. Relates the new robbot to the special robbots ibgib.
|
|
1894
|
+
*
|
|
1895
|
+
* @returns the new robbot ibgib and new robbots address.
|
|
1896
|
+
*/
|
|
1897
|
+
// export async function createRobbotIbGib({
|
|
1898
|
+
// robbotData,
|
|
1899
|
+
// space,
|
|
1900
|
+
// zeroSpace,
|
|
1901
|
+
// fnUpdateBootstrap,
|
|
1902
|
+
// fnBroadcast,
|
|
1903
|
+
// }: {
|
|
1904
|
+
// robbotData: RobbotData_V1,
|
|
1905
|
+
// space: IbGibSpaceAny,
|
|
1906
|
+
// zeroSpace: IbGibSpaceAny,
|
|
1907
|
+
// fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
1908
|
+
// fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
1909
|
+
// }): Promise<{ newRobbotIbGib: RobbotIbGib_V1, newRobbotsAddr: string }> {
|
|
1910
|
+
// const lc = `[${createRobbotIbGib.name}]`;
|
|
1911
|
+
// try {
|
|
1912
|
+
// if (logalot) { console.log(`${lc} starting...`); }
|
|
1913
|
+
// if (!space) { throw new Error(`space required. (E: 5def0b1afab74b0c9286e3ac5060cb8f)`); }
|
|
1914
|
+
// if (!robbotData) { throw new Error(`robbotData required (E: cd0304401a2f5a63d86dd71f76f31222)`); }
|
|
1915
|
+
|
|
1916
|
+
// const ib = getRobbotIb({ robbotData });
|
|
1917
|
+
// const resNewRobbot = await factory.firstGen({
|
|
1918
|
+
// parentIbGib: factory.primitive({ ib: "robbot" }),
|
|
1919
|
+
// ib,
|
|
1920
|
+
// data: robbotData,
|
|
1921
|
+
// linkedRel8ns: [Rel8n.past, Rel8n.ancestor],
|
|
1922
|
+
// tjp: { uuid: true, timestamp: true },
|
|
1923
|
+
// dna: true,
|
|
1924
|
+
// nCounter: true,
|
|
1925
|
+
// });
|
|
1926
|
+
// const newRobbot = (resNewRobbot.newIbGib as RobbotIbGib_V1);
|
|
1927
|
+
// await persistTransformResult({ resTransform: resNewRobbot, isMeta: true, space });
|
|
1928
|
+
// await registerNewIbGib({ ibGib: newRobbot, space, zeroSpace, fnBroadcast, fnUpdateBootstrap });
|
|
1929
|
+
// const newRobbotsAddr = await rel8ToSpecialIbGib({
|
|
1930
|
+
// type: "robbots",
|
|
1931
|
+
// rel8nName: ROBBOT_REL8N_NAME,
|
|
1932
|
+
// ibGibsToRel8: [newRobbot],
|
|
1933
|
+
// space,
|
|
1934
|
+
// zeroSpace,
|
|
1935
|
+
// fnUpdateBootstrap,
|
|
1936
|
+
// fnBroadcast,
|
|
1937
|
+
// });
|
|
1938
|
+
// return { newRobbotIbGib: newRobbot, newRobbotsAddr };
|
|
1939
|
+
// } catch (error) {
|
|
1940
|
+
// console.error(`${lc} ${error.message}`);
|
|
1941
|
+
// throw error;
|
|
1942
|
+
// } finally {
|
|
1943
|
+
// if (logalot) { console.log(`${lc} complete.`); }
|
|
1944
|
+
// }
|
|
1945
|
+
// }
|
|
1946
|
+
|
|
1947
|
+
|
|
1948
|
+
/**
|
|
1949
|
+
* We are NOT searching through all of our data looking for a needle in a haystack.
|
|
1950
|
+
* What we ARE doing is we are looking through the past of the existing latest and
|
|
1951
|
+
* the prospective latest (the given ibGib param) and comparing between the two.
|
|
1952
|
+
*
|
|
1953
|
+
* Since `past` rel8n is usually a linked rel8n now, we may have to traverse it all
|
|
1954
|
+
* the way to its beginning for each possibility.
|
|
1955
|
+
*
|
|
1956
|
+
* @returns either {@param ibGibAddr} or {@param existingLatestAddr}
|
|
1957
|
+
*/
|
|
1958
|
+
async function getLatestAddr_Brute({
|
|
1959
|
+
ibGib, ibGibAddr,
|
|
1960
|
+
existingLatest, existingLatestAddr,
|
|
1961
|
+
tjpAddr,
|
|
1962
|
+
space,
|
|
1963
|
+
}: {
|
|
1964
|
+
ibGib: IbGib_V1<any>, ibGibAddr: string,
|
|
1965
|
+
existingLatest: IbGib_V1<any>, existingLatestAddr: string,
|
|
1966
|
+
tjpAddr: string,
|
|
1967
|
+
space: IbGibSpaceAny,
|
|
1968
|
+
}): Promise<string> {
|
|
1969
|
+
const lc = `[${getLatestAddr_Brute.name}][${ibGibAddr}]`;
|
|
1970
|
+
try {
|
|
1971
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
1972
|
+
|
|
1973
|
+
if (!space) { throw new Error(`space required. (E: 64eb9a271f5d43deadec30b9638746c8)`); }
|
|
1974
|
+
|
|
1975
|
+
// no nCounter, so we need to brute force.
|
|
1976
|
+
// The easiest way is to check each's past, as the most common
|
|
1977
|
+
// scenario would be registering a newer one, or less likely, a timing issue
|
|
1978
|
+
// with registering a previous ibGib frame.
|
|
1979
|
+
|
|
1980
|
+
let ibGibPast = ibGib.rel8ns?.past || [];
|
|
1981
|
+
let existingLatestPast = existingLatest.rel8ns?.past || [];
|
|
1982
|
+
|
|
1983
|
+
// going to check a bunch of specific, easy cases to narrow things down.
|
|
1984
|
+
|
|
1985
|
+
if (ibGibPast.length === 1 && existingLatestPast.length === 0) {
|
|
1986
|
+
if (logalot) { console.log(`prospective has a past, so it "must" be newer. (won't quote "must" anymore)`); }
|
|
1987
|
+
return ibGibAddr;
|
|
1988
|
+
} else if (existingLatestPast.length === 1 && ibGibPast.length === 0) {
|
|
1989
|
+
if (logalot) { console.log(`existing has a past, so it must be newer.`); }
|
|
1990
|
+
return existingLatestAddr;
|
|
1991
|
+
} else if (existingLatestPast.length === 0 && ibGibPast.length === 0) {
|
|
1992
|
+
console.warn(`${lc} neither existing latest nor prospective new ibGib has a past, so keeping existing.`);
|
|
1993
|
+
return existingLatestAddr;
|
|
1994
|
+
} else if (existingLatestPast.includes(ibGibAddr)) {
|
|
1995
|
+
if (logalot) { console.log(`existing by definition is newer`); }
|
|
1996
|
+
return existingLatestAddr;
|
|
1997
|
+
} else if (ibGibPast.includes(existingLatestAddr)) {
|
|
1998
|
+
if (logalot) { console.log(`ibGib by definition is newer`); }
|
|
1999
|
+
return ibGibAddr;
|
|
2000
|
+
} else if (existingLatestAddr === ibGibAddr) {
|
|
2001
|
+
if (logalot) { console.log(`they're the same!`); }
|
|
2002
|
+
return existingLatestAddr;
|
|
2003
|
+
} else if (existingLatestAddr === tjpAddr && existingLatest.rel8ns?.tjp?.length === 1) {
|
|
2004
|
+
if (logalot) { console.log(`ibGib must be newer because the existingLatestAddr is the tjp, which is by definition first in unique past.`); }
|
|
2005
|
+
return ibGibAddr;
|
|
2006
|
+
} else if (ibGibAddr === tjpAddr && ibGib.rel8ns?.tjp?.length === 1) {
|
|
2007
|
+
if (logalot) { console.log(`existing must be newer because the ibGibAddr is the tjp, which is by definition first in unique past.`); }
|
|
2008
|
+
return existingLatestAddr;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
// well, neither one really gives us any indicator alone
|
|
2012
|
+
// so load each one in the past
|
|
2013
|
+
if (logalot) { console.log(`${lc} brute forcing through iterating the pasts.`); }
|
|
2014
|
+
let newerAddr: string | undefined;
|
|
2015
|
+
let firstIterationCount = -1; // klugy hack, but is an ugly method anyway (brute after all!)
|
|
2016
|
+
|
|
2017
|
+
let getPastCount: (x: IbGib_V1<any>, n: number, otherAddr: string) => Promise<number> =
|
|
2018
|
+
async (x, n, otherAddr) => {
|
|
2019
|
+
let xPast = x.rel8ns?.past || [];
|
|
2020
|
+
if (xPast.includes(otherAddr)) {
|
|
2021
|
+
// no need to proceed further, since the other is found in the past of x, so x is newer
|
|
2022
|
+
newerAddr = getIbGibAddr({ ibGib: x });
|
|
2023
|
+
return -1;
|
|
2024
|
+
}
|
|
2025
|
+
if (xPast.length === 0) { return n; } // no more past to increment
|
|
2026
|
+
let newCount = n + xPast.length;
|
|
2027
|
+
if (firstIterationCount !== -1 && newCount > firstIterationCount) {
|
|
2028
|
+
// we've determined that the second iteration has a longer past,
|
|
2029
|
+
// so we don't need to look further
|
|
2030
|
+
newerAddr = getIbGibAddr({ ibGib: x });
|
|
2031
|
+
return -1;
|
|
2032
|
+
}
|
|
2033
|
+
// load up the earliest one and call recursively
|
|
2034
|
+
let resNextX = await getFromSpace({ addr: xPast[0], space });
|
|
2035
|
+
if (!resNextX.success || resNextX.ibGibs?.length !== 1) { throw new Error(`Couldn't load past addr (xPast[0]): ${xPast[0]}`); }
|
|
2036
|
+
return getPastCount(resNextX.ibGibs![0], n + xPast.length, otherAddr);
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
if (logalot) { console.log(`${lc} doing ibGibPastCount`); }
|
|
2040
|
+
let ibGibPastCount = await getPastCount(ibGib, 0, existingLatestAddr);
|
|
2041
|
+
if (newerAddr) { return newerAddr; }
|
|
2042
|
+
|
|
2043
|
+
// we didn't hit upon it, so set the firstIterationCount so we don't spend unnecessary cycles
|
|
2044
|
+
if (logalot) { console.log(`${lc} Doing existingPastCount`); }
|
|
2045
|
+
firstIterationCount = ibGibPastCount;
|
|
2046
|
+
let existingPastCount = await getPastCount(existingLatest, 0, ibGibAddr);
|
|
2047
|
+
if (newerAddr) { return newerAddr; }
|
|
2048
|
+
|
|
2049
|
+
// we didn't yet determine it, so whichever has the longer past is newer
|
|
2050
|
+
if (ibGibPastCount > existingPastCount) {
|
|
2051
|
+
if (logalot) { console.log(`${lc} ibGibPastCount (${ibGibPastCount}) is longer than existingPastCount (${existingPastCount}), so ibGib is newer.`); }
|
|
2052
|
+
newerAddr = ibGibAddr;
|
|
2053
|
+
} else {
|
|
2054
|
+
if (logalot) { console.log(`${lc} existingPastCount (${existingPastCount}) is longer than ibGibPastCount (${ibGibPastCount}), so ibGib is newer.`); }
|
|
2055
|
+
newerAddr = existingLatestAddr;
|
|
2056
|
+
}
|
|
2057
|
+
return newerAddr;
|
|
2058
|
+
|
|
2059
|
+
} catch (error) {
|
|
2060
|
+
console.error(`${lc} ${error.message}`);
|
|
2061
|
+
throw error;
|
|
2062
|
+
} finally {
|
|
2063
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
// #endregion
|
|
2068
|
+
|
|
2069
|
+
|
|
2070
|
+
/**
|
|
2071
|
+
* Relates the given tag to the TagsIbGib, saves the generated
|
|
2072
|
+
* TagsIbGib and updates the settings to point to the new TagsIbGib.
|
|
2073
|
+
*
|
|
2074
|
+
* @param tagIbGib to add to Tags
|
|
2075
|
+
*/
|
|
2076
|
+
export function rel8TagToTagsIbGib({
|
|
2077
|
+
tagIbGib,
|
|
2078
|
+
space,
|
|
2079
|
+
zeroSpace,
|
|
2080
|
+
fnUpdateBootstrap,
|
|
2081
|
+
fnBroadcast,
|
|
2082
|
+
}: {
|
|
2083
|
+
tagIbGib: IbGib_V1,
|
|
2084
|
+
space: IbGibSpaceAny,
|
|
2085
|
+
zeroSpace: IbGibSpaceAny,
|
|
2086
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
2087
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
2088
|
+
}): Promise<IbGibAddr> {
|
|
2089
|
+
return rel8ToSpecialIbGib({
|
|
2090
|
+
type: "tags",
|
|
2091
|
+
rel8nName: TAG_REL8N_NAME,
|
|
2092
|
+
ibGibsToRel8: [tagIbGib],
|
|
2093
|
+
space,
|
|
2094
|
+
zeroSpace,
|
|
2095
|
+
fnUpdateBootstrap,
|
|
2096
|
+
fnBroadcast,
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
/**
|
|
2102
|
+
* Throws an error if any duplicates found in either array.
|
|
2103
|
+
*
|
|
2104
|
+
* ## notes
|
|
2105
|
+
*
|
|
2106
|
+
* Only pass in ibGib or ibGibAddrs, not both. Warns if both are passed in though.
|
|
2107
|
+
*
|
|
2108
|
+
* @throws if both params are falsy or if addrs || mapped addrs contains duplicates.
|
|
2109
|
+
*/
|
|
2110
|
+
export function throwIfDuplicates({
|
|
2111
|
+
ibGibs,
|
|
2112
|
+
ibGibAddrs,
|
|
2113
|
+
}: {
|
|
2114
|
+
ibGibs?: IbGib_V1[],
|
|
2115
|
+
ibGibAddrs?: IbGibAddr[],
|
|
2116
|
+
}): void {
|
|
2117
|
+
const lc = `[${throwIfDuplicates.name}]`;
|
|
2118
|
+
try {
|
|
2119
|
+
if (!ibGibs && !ibGibAddrs) { throw new Error(`either ibGibs or ibGibAddrs required. (E: 37776788620f4966b0964945ce181fc6)`); }
|
|
2120
|
+
if (ibGibs && ibGibAddrs) { console.warn(`${lc} both ibGibs and ibGibAddrs provided. You should only provide one. Only ibGibAddrs will be checked. (W: dc13f9e197834e2daaba3bcfd08418db)`); }
|
|
2121
|
+
|
|
2122
|
+
const addrs = ibGibAddrs ? ibGibAddrs.concat() : ibGibs!.map(x => getIbGibAddr({ ibGib: x }));
|
|
2123
|
+
for (let i = 0; i < addrs.length; i++) {
|
|
2124
|
+
const addr = addrs[i];
|
|
2125
|
+
if (addrs.filter(x => x === addr).length > 1) { throw new Error(`duplicate addr found: ${addr} (E: 70fbef040dd449c38c667d53b8092053)`); }
|
|
2126
|
+
}
|
|
2127
|
+
} catch (error) {
|
|
2128
|
+
console.error(`${lc} ${error.message}`);
|
|
2129
|
+
throw error;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
export function getSpaceLockAddr({
|
|
2134
|
+
space,
|
|
2135
|
+
scope,
|
|
2136
|
+
}: {
|
|
2137
|
+
space: IbGibSpaceAny,
|
|
2138
|
+
scope: SpaceLockScope,
|
|
2139
|
+
}): IbGibAddr {
|
|
2140
|
+
const lc = `[${getSpaceLockAddr.name}]`;
|
|
2141
|
+
try {
|
|
2142
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
2143
|
+
|
|
2144
|
+
if (!space) { throw new Error(`space required. (E: 3ba16e6c3e5e47948b0e63448da11752)`); }
|
|
2145
|
+
if (!space.data?.uuid) { throw new Error(`invalid space (space.data.uuid falsy) (E: 273262b32f2ef27b2e690bc699f33822)`); }
|
|
2146
|
+
if (!scope) { throw new Error(`scope required. (E: f47801d6c45e2247b42a53d9b604b522)`); }
|
|
2147
|
+
while (scope.includes(IBGIB_DELIMITER)) {
|
|
2148
|
+
if (logalot) { console.log(`${lc} scope contains ibgib delimiter...replacing... (I: 0f456fd7cc6552a799673a0c5b4a7d22)`); }
|
|
2149
|
+
scope = scope.replace(IBGIB_DELIMITER, '_');
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
const spaceId = space.data!.uuid;
|
|
2153
|
+
const ib = `${SPACE_LOCK_IB_TERM} ${spaceId} ${scope}`;
|
|
2154
|
+
const gib = GIB;
|
|
2155
|
+
return getIbGibAddr({ ib, gib });
|
|
2156
|
+
} catch (error) {
|
|
2157
|
+
console.error(`${lc} ${error.message}`);
|
|
2158
|
+
throw error;
|
|
2159
|
+
} finally {
|
|
2160
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
/**
|
|
2165
|
+
* Executes some function `fn` against/in a given `space` while
|
|
2166
|
+
* performing lock plumbing in that space.
|
|
2167
|
+
*
|
|
2168
|
+
* By this, I mean that this function takes care of acquiring the lock,
|
|
2169
|
+
* attempting retries according to the parameters, and then unlocking
|
|
2170
|
+
* the space regardless of result/error.
|
|
2171
|
+
*
|
|
2172
|
+
* @returns result of inner `fn` with `TResult`
|
|
2173
|
+
*/
|
|
2174
|
+
export async function execInSpaceWithLocking<TResult>({
|
|
2175
|
+
space,
|
|
2176
|
+
scope,
|
|
2177
|
+
secondsValid,
|
|
2178
|
+
maxDelayMs,
|
|
2179
|
+
fn,
|
|
2180
|
+
callerInstanceId,
|
|
2181
|
+
maxLockAttempts,
|
|
2182
|
+
}: {
|
|
2183
|
+
space: IbGibSpaceAny,
|
|
2184
|
+
scope: string,
|
|
2185
|
+
secondsValid: number,
|
|
2186
|
+
/**
|
|
2187
|
+
* If resource locked, will delay at max this ms.
|
|
2188
|
+
*/
|
|
2189
|
+
maxDelayMs?: number,
|
|
2190
|
+
fn: () => Promise<TResult>,
|
|
2191
|
+
/**
|
|
2192
|
+
* for use differentiating among tabs.
|
|
2193
|
+
*
|
|
2194
|
+
* ## intent
|
|
2195
|
+
* the idea is the ibgibs service has an instance id and passes it in here.
|
|
2196
|
+
*/
|
|
2197
|
+
callerInstanceId?: string,
|
|
2198
|
+
/**
|
|
2199
|
+
* if given, will try to acquire lock at most this many times, else
|
|
2200
|
+
* will default to {@link DEFAULT_MAX_DELAY_RETRY_LOCK_ACQUIRE_ATTEMPTS}.
|
|
2201
|
+
*/
|
|
2202
|
+
maxLockAttempts?: number,
|
|
2203
|
+
}): Promise<TResult> {
|
|
2204
|
+
const lc = `[${execInSpaceWithLocking.name}]`;
|
|
2205
|
+
try {
|
|
2206
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
2207
|
+
|
|
2208
|
+
// #region validation
|
|
2209
|
+
|
|
2210
|
+
if (!space) { throw new Error(`space required. (E: 66fd8f21a5b2b572d18cdeb9472a7722)`); }
|
|
2211
|
+
if (!secondsValid) { throw new Error(`secondsValid required. (E: 92c5610e57ceede5ce83cff86d5c2a22)`); }
|
|
2212
|
+
if (secondsValid < 0) { throw new Error(`secondsValid must be positive. (E: 970a7510c517235d7a355a843d18d222)`); }
|
|
2213
|
+
// if (secondsValid > MAX_LOCK_SECONDS_VALID) { throw new Error(`secondsValid arg (${secondsValid}) exceeds max secondsValid (${MAX_LOCK_SECONDS_VALID}) (E: 4cffe49a23c8f1698bf7c78eaccbb722)`); }
|
|
2214
|
+
if (!fn) { throw new Error(`fnGet required (E: 7022e280252ec2faf756b6db05c56e22)`); }
|
|
2215
|
+
|
|
2216
|
+
// #endregion validation
|
|
2217
|
+
|
|
2218
|
+
let resultFn: TResult;
|
|
2219
|
+
|
|
2220
|
+
if (logalot) { console.log(`${lc} attempting to acquire lock with scope ${scope} (I: fed36d42a975b1c52897a4df804ac722)`); }
|
|
2221
|
+
let lockIbGib: IbGibSpaceLockIbGib;
|
|
2222
|
+
maxDelayMs =
|
|
2223
|
+
(maxDelayMs ?? 0) > 0 ? maxDelayMs : DEFAULT_MAX_DELAY_MS_RETRY_LOCK_ACQUIRE
|
|
2224
|
+
let attempts = 0;
|
|
2225
|
+
maxLockAttempts =
|
|
2226
|
+
maxLockAttempts ?? -1 > 0 ?
|
|
2227
|
+
maxLockAttempts :
|
|
2228
|
+
DEFAULT_MAX_DELAY_RETRY_LOCK_ACQUIRE_ATTEMPTS;
|
|
2229
|
+
do {
|
|
2230
|
+
lockIbGib = await lockSpace({
|
|
2231
|
+
space,
|
|
2232
|
+
scope,
|
|
2233
|
+
secondsValid,
|
|
2234
|
+
instanceId: callerInstanceId,
|
|
2235
|
+
});
|
|
2236
|
+
if (lockIbGib?.data?.success) { break; }
|
|
2237
|
+
/** Delay a small random amount of time before trying again. */
|
|
2238
|
+
let delayMs = Math.ceil(Math.random() * maxDelayMs!);
|
|
2239
|
+
await delay(delayMs);
|
|
2240
|
+
} while (attempts < maxLockAttempts!);
|
|
2241
|
+
if (lockIbGib?.data?.success) {
|
|
2242
|
+
if (logalot) { console.log(`${lc} lock acquired. (I: d847fa953ee131a57e1a89c537342722)`); }
|
|
2243
|
+
} else {
|
|
2244
|
+
throw new Error(`could not acquire lock after ${attempts} attempts with intermittent delays of ${maxDelayMs} ms (E: 898c559dbd0c9bf20c14cf87a8f1e222)`);
|
|
2245
|
+
}
|
|
2246
|
+
|
|
2247
|
+
// execute the actual get inside an additional try..catch..finally
|
|
2248
|
+
// to ensure (attempted) unlockSpace call.
|
|
2249
|
+
const lc2 = `${lc}[fn]`;
|
|
2250
|
+
try {
|
|
2251
|
+
if (logalot) { console.log(`${lc2} starting... (I: c2f7bedf95d3f1dd1f76de34a68d3f22)`); }
|
|
2252
|
+
resultFn = await fn();
|
|
2253
|
+
} catch (error) {
|
|
2254
|
+
console.error(`${lc2} ${error.message}`);
|
|
2255
|
+
throw error;
|
|
2256
|
+
} finally {
|
|
2257
|
+
if (logalot) { console.log(`${lc2} unlocking space with scope: ${scope} (I: 21034d9c3395499756e9000e40417d22)`); }
|
|
2258
|
+
await unlockSpace({ space: space, scope: scope, instanceId: callerInstanceId });
|
|
2259
|
+
if (logalot) { console.log(`${lc2} complete. (I: 79d8ac03714a4d429c7e6c2ac6e18d22)`); }
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
return resultFn;
|
|
2263
|
+
} catch (error) {
|
|
2264
|
+
console.error(`${lc} ${error.message}`);
|
|
2265
|
+
throw error;
|
|
2266
|
+
} finally {
|
|
2267
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
/**
|
|
2272
|
+
* Gets the bootstrap ibgib in the given `zeroSpace`.
|
|
2273
|
+
*
|
|
2274
|
+
* @example
|
|
2275
|
+
*
|
|
2276
|
+
* ```json
|
|
2277
|
+
* {
|
|
2278
|
+
* "ib":"bootstrap",
|
|
2279
|
+
* "gib":"gib",
|
|
2280
|
+
* "data":{
|
|
2281
|
+
* "defaultSpaceId":"d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33",
|
|
2282
|
+
* "spaceIds":["d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33"]
|
|
2283
|
+
* },
|
|
2284
|
+
* "rel8ns":{
|
|
2285
|
+
* "d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33":[
|
|
2286
|
+
* "witness space IonicSpace_V1 oij d455d9a72807617634ccbf1e532b71037c45762f824ec85fcd9a4c2275562f33^B336251655E8C56B38E9E86F20E0E42E6C153785F1A0A798ADE6916E71CF055B"
|
|
2287
|
+
* ]
|
|
2288
|
+
* }
|
|
2289
|
+
* }
|
|
2290
|
+
* ```
|
|
2291
|
+
*
|
|
2292
|
+
* @returns bootstrapIbGib if found
|
|
2293
|
+
*/
|
|
2294
|
+
export async function getValidatedBootstrapIbGib({
|
|
2295
|
+
zeroSpace,
|
|
2296
|
+
}: {
|
|
2297
|
+
zeroSpace: IbGibSpaceAny,
|
|
2298
|
+
}): Promise<BootstrapIbGib | null> {
|
|
2299
|
+
const lc = `[${getValidatedBootstrapIbGib.name}]`;
|
|
2300
|
+
try {
|
|
2301
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
2302
|
+
|
|
2303
|
+
if (!zeroSpace) { throw new Error(`zeroSpace required. (E: 66fd8f21a5b2b572d18cdeb9472a7722)`); }
|
|
2304
|
+
|
|
2305
|
+
const bootstrapAddr = BOOTSTRAP_IBGIB_ADDR;
|
|
2306
|
+
|
|
2307
|
+
if (logalot) { console.log(`${lc} getting from zeroSpace...`); }
|
|
2308
|
+
const argGet = await zeroSpace.argy({
|
|
2309
|
+
ibMetadata: getSpaceArgMetadata({ space: zeroSpace }),
|
|
2310
|
+
argData: {
|
|
2311
|
+
cmd: 'get',
|
|
2312
|
+
ibGibAddrs: [bootstrapAddr],
|
|
2313
|
+
isMeta: true,
|
|
2314
|
+
},
|
|
2315
|
+
});
|
|
2316
|
+
const resGetBootstrapIbGib = await zeroSpace.witness(argGet);
|
|
2317
|
+
|
|
2318
|
+
if (resGetBootstrapIbGib?.data?.success && resGetBootstrapIbGib.ibGibs?.length === 1) {
|
|
2319
|
+
// bootstrap found
|
|
2320
|
+
const bootstrapIbGib = resGetBootstrapIbGib!.ibGibs![0]!;
|
|
2321
|
+
if (logalot) { console.log(`${lc} bootstrapibGib found: ${pretty(bootstrapIbGib)}`); }
|
|
2322
|
+
if (await validateBootstrapIbGib(bootstrapIbGib)) {
|
|
2323
|
+
return (bootstrapIbGib as BootstrapIbGib);
|
|
2324
|
+
} else {
|
|
2325
|
+
if (logalot) { console.log(`${lc} bootstrapIbGib was invalid. (I: cce66b26805404fc85525d565e1f8b22)`); }
|
|
2326
|
+
return null;
|
|
2327
|
+
}
|
|
2328
|
+
} else {
|
|
2329
|
+
if (logalot) { console.log(`${lc} bootstrapIbGib NOT found. (I: 421562993bf3464eb507d2967d311e22)`); }
|
|
2330
|
+
return null;
|
|
2331
|
+
}
|
|
2332
|
+
} catch (error) {
|
|
2333
|
+
console.error(`${lc} ${error.message}`);
|
|
2334
|
+
throw error;
|
|
2335
|
+
} finally {
|
|
2336
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
|
|
2341
|
+
/**
|
|
2342
|
+
* So when loading the local user space, even if the class changes or default
|
|
2343
|
+
* constructors change, the internal `data` is loaded from file.
|
|
2344
|
+
*/
|
|
2345
|
+
export async function getLocalSpace<TSpace extends IbGibSpaceAny>({
|
|
2346
|
+
zeroSpace,
|
|
2347
|
+
bootstrapIbGib,
|
|
2348
|
+
localSpaceId,
|
|
2349
|
+
lock,
|
|
2350
|
+
callerInstanceId,
|
|
2351
|
+
fnDtoToSpace,
|
|
2352
|
+
localSpaceCacheSvc,
|
|
2353
|
+
}: {
|
|
2354
|
+
/**
|
|
2355
|
+
* A zero space is a space that is built with default settings that
|
|
2356
|
+
* is not specific to a user.
|
|
2357
|
+
*
|
|
2358
|
+
* This is the foundational space that all spaces share, out of which
|
|
2359
|
+
* a bootstrap ibgib can be found that will itself have rel8ns to other
|
|
2360
|
+
* spaces.
|
|
2361
|
+
*
|
|
2362
|
+
* ## notes
|
|
2363
|
+
*
|
|
2364
|
+
* This is what I was calling a zeroSpace, but that will in the future
|
|
2365
|
+
* mean a default space among a group of spaces.
|
|
2366
|
+
*/
|
|
2367
|
+
zeroSpace: IbGibSpaceAny,
|
|
2368
|
+
/**
|
|
2369
|
+
* bootstrap ibGib, if provided, which was found in the zero space.
|
|
2370
|
+
* The bootstrap ibgib should have a rel8n entry to the local space.
|
|
2371
|
+
*
|
|
2372
|
+
* ## future
|
|
2373
|
+
*
|
|
2374
|
+
* We will have multiple local spaces to choose from, with a default
|
|
2375
|
+
* being the one that we're referring to atow.
|
|
2376
|
+
*/
|
|
2377
|
+
bootstrapIbGib?: BootstrapIbGib,
|
|
2378
|
+
/**
|
|
2379
|
+
* If provided, will look for the space via this id in the bootstrap ibgib.
|
|
2380
|
+
* If not provided, will use the bootstrap ibgib's default spaceId.
|
|
2381
|
+
*/
|
|
2382
|
+
localSpaceId?: SpaceId,
|
|
2383
|
+
/**
|
|
2384
|
+
* If true, we will lock on getting the bootstrap ibgib (if needed), as
|
|
2385
|
+
* well as getting the user space.
|
|
2386
|
+
*/
|
|
2387
|
+
lock?: boolean,
|
|
2388
|
+
/**
|
|
2389
|
+
* for use differentiating among tabs.
|
|
2390
|
+
*
|
|
2391
|
+
* ## intent
|
|
2392
|
+
* the idea is the ibgibs service has an instance id and passes it in here.
|
|
2393
|
+
*/
|
|
2394
|
+
callerInstanceId: string,
|
|
2395
|
+
/**
|
|
2396
|
+
* function that turns the space dto into the space witness.
|
|
2397
|
+
*
|
|
2398
|
+
* ## intent
|
|
2399
|
+
*
|
|
2400
|
+
* When loading a space, the only part stored is the ibgib data. You still
|
|
2401
|
+
* need a function that hydrates a witness class with that data.
|
|
2402
|
+
*/
|
|
2403
|
+
fnDtoToSpace: (spaceDto: IbGib_V1) => Promise<TSpace>,
|
|
2404
|
+
/**
|
|
2405
|
+
* Optional caching service
|
|
2406
|
+
*/
|
|
2407
|
+
localSpaceCacheSvc?: IbGibCacheService,
|
|
2408
|
+
}): Promise<TSpace> {
|
|
2409
|
+
const lc = `[${getLocalSpace.name}]`;
|
|
2410
|
+
try {
|
|
2411
|
+
if (!zeroSpace) { throw new Error(`zeroSpace required. (E: 0793781a98c456a666cfa9eb960bcd22)`); }
|
|
2412
|
+
|
|
2413
|
+
if (!bootstrapIbGib) {
|
|
2414
|
+
if (logalot) { console.log(`${lc} bootstrap falsy, so loading it... (I: f2366e38283495a38b5501297aa34422)`); }
|
|
2415
|
+
if (lock) {
|
|
2416
|
+
const bootstrapAddr = BOOTSTRAP_IBGIB_ADDR;
|
|
2417
|
+
if (logalot) { console.log(`${lc} using locked version of loading bootstrap... (I: 52b9b11999674e586d051c2b23f59b22)`); }
|
|
2418
|
+
bootstrapIbGib = await execInSpaceWithLocking<BootstrapIbGib>({
|
|
2419
|
+
space: zeroSpace,
|
|
2420
|
+
scope: bootstrapAddr,
|
|
2421
|
+
fn: async () => {
|
|
2422
|
+
let validatedBootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace });
|
|
2423
|
+
if (validatedBootstrapIbGib) {
|
|
2424
|
+
return validatedBootstrapIbGib;
|
|
2425
|
+
} else {
|
|
2426
|
+
throw new Error(`(UNEXPECTED) unable to get bootstrap ibgib? (E: c111dc7627acbfb992134ddf4064ea23)`);
|
|
2427
|
+
}
|
|
2428
|
+
},
|
|
2429
|
+
callerInstanceId,
|
|
2430
|
+
secondsValid: DEFAULT_SECONDS_VALID_LOCAL,
|
|
2431
|
+
});
|
|
2432
|
+
} else {
|
|
2433
|
+
if (logalot) { console.log(`${lc} lock is false, so just getting the bootstrap ibgib (I: 49d55e5a824510bb3ee0ccd9f5ec3322)`); }
|
|
2434
|
+
bootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace }) ?? undefined;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
if (!bootstrapIbGib) { throw new Error(`bootstrapIbGib falsy. not initialized? (E: 91f5c82b5e124178d958701ebcb09822)`); }
|
|
2439
|
+
|
|
2440
|
+
if (!bootstrapIbGib.data) { throw new Error(`(UNEXPECTED) bootstrapIbGib.data required. invalid bootstrap? (E: 568c6b837c1a39f7a25d188a90167423)`); }
|
|
2441
|
+
|
|
2442
|
+
localSpaceId = localSpaceId ?? bootstrapIbGib!.data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY];
|
|
2443
|
+
const localSpaceAddr = bootstrapIbGib.rel8ns![localSpaceId]![0]; // guaranteed b/c bootstrap was validated
|
|
2444
|
+
|
|
2445
|
+
const fnGet: () => Promise<TSpace> = async () => {
|
|
2446
|
+
|
|
2447
|
+
const argGet = await zeroSpace.argy({
|
|
2448
|
+
ibMetadata: getSpaceArgMetadata({ space: zeroSpace }),
|
|
2449
|
+
argData: {
|
|
2450
|
+
cmd: 'get',
|
|
2451
|
+
ibGibAddrs: [localSpaceAddr],
|
|
2452
|
+
isMeta: true,
|
|
2453
|
+
},
|
|
2454
|
+
});
|
|
2455
|
+
const resLocalSpace = await zeroSpace.witness(argGet);
|
|
2456
|
+
if (resLocalSpace?.data?.success && resLocalSpace.ibGibs?.length === 1) {
|
|
2457
|
+
const localSpaceDto = resLocalSpace.ibGibs[0] as TSpace;
|
|
2458
|
+
const localSpace = await fnDtoToSpace(localSpaceDto);
|
|
2459
|
+
if (localSpaceCacheSvc) { localSpace.cacheSvc = localSpaceCacheSvc; }
|
|
2460
|
+
return localSpace;
|
|
2461
|
+
} else {
|
|
2462
|
+
throw new Error(`Could not get local space addr (${localSpaceAddr}) specified in bootstrap space (${getIbGibAddr({ ibGib: bootstrapIbGib })}). (E: 6d6b45e7eae4472697ddc971438e4922)`);
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2466
|
+
if (lock) {
|
|
2467
|
+
if (logalot) { console.log(`${lc} getting localSpaceId (${localSpaceId}) WITH locking (I: c48a0e4ac5971cdbc57273dd35f8a522)`); }
|
|
2468
|
+
return await execInSpaceWithLocking({
|
|
2469
|
+
space: zeroSpace,
|
|
2470
|
+
scope: localSpaceId,
|
|
2471
|
+
fn: () => { return fnGet(); },
|
|
2472
|
+
callerInstanceId,
|
|
2473
|
+
secondsValid: DEFAULT_SECONDS_VALID_LOCAL,
|
|
2474
|
+
});
|
|
2475
|
+
} else {
|
|
2476
|
+
if (logalot) { console.log(`${lc} getting localSpaceId (${localSpaceId}) WITHOUT locking (I: 48e504835dee4006839df8820d860b22)`); }
|
|
2477
|
+
return fnGet();
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
} catch (error) {
|
|
2481
|
+
console.error(`${lc} ${error.message}`);
|
|
2482
|
+
throw error;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
export async function lockSpace({
|
|
2487
|
+
space,
|
|
2488
|
+
scope,
|
|
2489
|
+
secondsValid,
|
|
2490
|
+
instanceId,
|
|
2491
|
+
}: IbGibSpaceLockOptions): Promise<IbGibSpaceLockIbGib> {
|
|
2492
|
+
const lc = `[${lockSpace.name}]`;
|
|
2493
|
+
try {
|
|
2494
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
2495
|
+
|
|
2496
|
+
if (!space) { throw new Error(`space required. (E: 5c0a7197a75f483a82d74e5eea60df37)`); }
|
|
2497
|
+
if (!scope) { throw new Error(`scope required. (E: c7f1dde9570f4df3b450faa2c2f85122)`); }
|
|
2498
|
+
if (!secondsValid) { throw new Error(`secondsValid required and positive (E: b42b6733638b46c06c9aff59a6c49822)`); }
|
|
2499
|
+
if (secondsValid < 0) { throw new Error(`secondsValid must be positive (E: bbe3b6d567583bfb35a1c0825eb29622)`); }
|
|
2500
|
+
|
|
2501
|
+
/** what we will return */
|
|
2502
|
+
let resLockIbGib: IbGibSpaceLockIbGib;
|
|
2503
|
+
|
|
2504
|
+
/** space lock address is deterministic ibgib primitive (gib === 'gib') */
|
|
2505
|
+
const spaceLockAddr = getSpaceLockAddr({ space, scope });
|
|
2506
|
+
|
|
2507
|
+
// check for existing lock...
|
|
2508
|
+
let existingLock: IbGibSpaceLockIbGib | undefined;
|
|
2509
|
+
|
|
2510
|
+
// ...in space's backing store (file, IndexedDB entry, DB, etc.)
|
|
2511
|
+
|
|
2512
|
+
let getLock = await getFromSpace({
|
|
2513
|
+
addr: spaceLockAddr, isMeta: true, space, force: true
|
|
2514
|
+
});
|
|
2515
|
+
if (getLock.success && getLock.ibGibs?.length === 1) {
|
|
2516
|
+
existingLock = getLock.ibGibs[0] as IbGibSpaceLockIbGib;
|
|
2517
|
+
if (existingLock?.data?.expirationUTC) {
|
|
2518
|
+
if (isExpired({ expirationTimestampUTC: existingLock.data.expirationUTC })) {
|
|
2519
|
+
// lock expired, so log only. skipping delete atow because should be overwritten
|
|
2520
|
+
// when the new lock is in place.
|
|
2521
|
+
if (logalot) { console.log(`${lc} ignoring expired existing lock in space at ${spaceLockAddr}. Should be overwritten (I: 7421c5b051724b189f88cecbbd449b22)`); }
|
|
2522
|
+
existingLock = undefined;
|
|
2523
|
+
}
|
|
2524
|
+
} else {
|
|
2525
|
+
console.error(`${lc} exisingLock.data.expirationUTC falsy? (E: 218dc0e935534a149d0be153c532cf25)`);
|
|
2526
|
+
existingLock = undefined;
|
|
2527
|
+
}
|
|
2528
|
+
} else {
|
|
2529
|
+
if (logalot) { console.log(`${lc} existing lock not found for ${spaceLockAddr} (I: 191af56ec4e2db3d19084e46bf949222)`); }
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
// populate resLockIbGib if/else existingLock
|
|
2533
|
+
if (existingLock && existingLock.data) {
|
|
2534
|
+
if (!existingLock.data) { throw new Error(`(UNEXPECTED) existingLock.data falsy? (E: 00069b4662e5566d971760d15e293723)`); }
|
|
2535
|
+
// valid lock already exists, so return informing caller. this includes
|
|
2536
|
+
// the existing lock's info, i.e. its expiration
|
|
2537
|
+
resLockIbGib = clone(existingLock) as IbGibSpaceLockIbGib;
|
|
2538
|
+
resLockIbGib.data!.alreadyLocked = true;
|
|
2539
|
+
resLockIbGib.data!.success = false;
|
|
2540
|
+
} else {
|
|
2541
|
+
// not yet locked so immediately lock in memory for space, then via
|
|
2542
|
+
// `space.put(lock)`
|
|
2543
|
+
const { ib, gib } = getIbAndGib({ ibGibAddr: spaceLockAddr });
|
|
2544
|
+
resLockIbGib = {
|
|
2545
|
+
ib, gib,
|
|
2546
|
+
data: {
|
|
2547
|
+
scope,
|
|
2548
|
+
secondsValid,
|
|
2549
|
+
instanceId,
|
|
2550
|
+
expirationUTC: getExpirationUTCString({ seconds: secondsValid }),
|
|
2551
|
+
}
|
|
2552
|
+
} as IbGibSpaceLockIbGib;
|
|
2553
|
+
const resPut = await putInSpace({ ibGib: resLockIbGib, isMeta: true, force: true, space });
|
|
2554
|
+
if (resPut.success) {
|
|
2555
|
+
resLockIbGib.data!.success = true;
|
|
2556
|
+
} else {
|
|
2557
|
+
const emsg = `${lc} there was an error putting the lock in the space: ${resPut.errorMsg}`;
|
|
2558
|
+
resLockIbGib.data!.success = false;
|
|
2559
|
+
resLockIbGib.data!.errorMsg = emsg;
|
|
2560
|
+
console.error(emsg);
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
|
|
2564
|
+
return resLockIbGib;
|
|
2565
|
+
} catch (error) {
|
|
2566
|
+
console.error(`${lc} ${error.message}`);
|
|
2567
|
+
throw error;
|
|
2568
|
+
} finally {
|
|
2569
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
export async function unlockSpace({
|
|
2574
|
+
space,
|
|
2575
|
+
scope,
|
|
2576
|
+
instanceId,
|
|
2577
|
+
}: IbGibSpaceLockOptions): Promise<IbGibSpaceLockIbGib | undefined> {
|
|
2578
|
+
const lc = `[${unlockSpace.name}]`;
|
|
2579
|
+
try {
|
|
2580
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
2581
|
+
|
|
2582
|
+
if (!space) { throw new Error(`space required. (E: 5c0a7197a75f483a82d74e5eea60df37)`); }
|
|
2583
|
+
if (!scope) { throw new Error(`scope required. (E: c7f1dde9570f4df3b450faa2c2f85122)`); }
|
|
2584
|
+
|
|
2585
|
+
/** space lock address is deterministic ibgib primitive (gib === 'gib') */
|
|
2586
|
+
const spaceLockAddr = getSpaceLockAddr({ space, scope });
|
|
2587
|
+
|
|
2588
|
+
// delete in file if it exists
|
|
2589
|
+
let resDelete = await deleteFromSpace({ addr: spaceLockAddr, isMeta: true, space, force: true });
|
|
2590
|
+
if (resDelete.success) {
|
|
2591
|
+
const { ib, gib } = getIbAndGib({ ibGibAddr: spaceLockAddr });
|
|
2592
|
+
return {
|
|
2593
|
+
ib, gib,
|
|
2594
|
+
data: {
|
|
2595
|
+
// action: 'unlock',
|
|
2596
|
+
success: true,
|
|
2597
|
+
instanceId,
|
|
2598
|
+
scope,
|
|
2599
|
+
}
|
|
2600
|
+
} as IbGibSpaceLockIbGib;
|
|
2601
|
+
} else {
|
|
2602
|
+
/** May NOT be an error, just setting this here is convenient to code. */
|
|
2603
|
+
const emsg = `Delete lock in space failed. delete errorMsg: ${resDelete.errorMsg}`;
|
|
2604
|
+
if (emsg.includes('not implemented')) {
|
|
2605
|
+
// rethrow error if space has not implemented a delete command handler
|
|
2606
|
+
throw new Error(emsg);
|
|
2607
|
+
} else if (
|
|
2608
|
+
emsg.toLowerCase().includes(`does not exist`) ||
|
|
2609
|
+
emsg.toLowerCase().includes(`doesn't exist`) ||
|
|
2610
|
+
emsg.toLowerCase().includes(`not found`)
|
|
2611
|
+
) {
|
|
2612
|
+
// don't want to warn if just file didn't exist
|
|
2613
|
+
if (logalot) { console.log(`${lc} ${emsg} (I: b647916fd0f3e5366e9387131be21c22)`); }
|
|
2614
|
+
const { ib, gib } = getIbAndGib({ ibGibAddr: spaceLockAddr });
|
|
2615
|
+
return {
|
|
2616
|
+
ib, gib,
|
|
2617
|
+
data: {
|
|
2618
|
+
action: 'unlock',
|
|
2619
|
+
success: true,
|
|
2620
|
+
instanceId,
|
|
2621
|
+
scope,
|
|
2622
|
+
}
|
|
2623
|
+
} as IbGibSpaceLockIbGib;
|
|
2624
|
+
} else {
|
|
2625
|
+
console.warn(`${lc} ${emsg} (W: 14c84fcac15944bd9a417099964d5d9d)`);
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
} catch (error) {
|
|
2629
|
+
console.error(`${lc} ${error.message}`);
|
|
2630
|
+
throw error;
|
|
2631
|
+
} finally {
|
|
2632
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
|
|
2636
|
+
/**
|
|
2637
|
+
* Updates the bootstrap^gib record in the default space data store
|
|
2638
|
+
* with the 'space' rel8n set to the `newSpaceAddr`.
|
|
2639
|
+
*
|
|
2640
|
+
* This way, if the app closes at this point, it will know to look at this
|
|
2641
|
+
* space when it loads.
|
|
2642
|
+
*
|
|
2643
|
+
* ## notes
|
|
2644
|
+
*
|
|
2645
|
+
* I'm probably typing this all over, but the bootstrap^gib is the
|
|
2646
|
+
* first record that the app looks at to know what space to load.
|
|
2647
|
+
* The space itself has configuration and has a proper gib hash
|
|
2648
|
+
* so it's verifiable. But the initial bootstrap^gib record is
|
|
2649
|
+
* NOT, since it only has 'gib' as its address (and thus its not hashed).
|
|
2650
|
+
*
|
|
2651
|
+
* In the future, this could be alleviated by asking other witnesses
|
|
2652
|
+
* "Hey what was my last bootstrap^gib hash", but there's no way to
|
|
2653
|
+
* do it beyond this without using some kind of authentication/secret(s)
|
|
2654
|
+
* that generate the record, i.e. encrypting bootstrap^gib cleverly.
|
|
2655
|
+
*/
|
|
2656
|
+
export async function updateBootstrapIbGib({
|
|
2657
|
+
space,
|
|
2658
|
+
zeroSpace,
|
|
2659
|
+
setSpaceAsDefault,
|
|
2660
|
+
createIfNotFound,
|
|
2661
|
+
}: {
|
|
2662
|
+
/**
|
|
2663
|
+
* space to add/replace in the bootstrap^gib ibgib.
|
|
2664
|
+
*/
|
|
2665
|
+
space: IbGibSpaceAny,
|
|
2666
|
+
/**
|
|
2667
|
+
* default "zero" space which contains a bootstrap^gib ibgib.
|
|
2668
|
+
*/
|
|
2669
|
+
zeroSpace?: IbGibSpaceAny,
|
|
2670
|
+
/**
|
|
2671
|
+
* set the space as the default local space in the bootstrap^gib ibgib.
|
|
2672
|
+
*/
|
|
2673
|
+
setSpaceAsDefault?: boolean,
|
|
2674
|
+
/**
|
|
2675
|
+
* If bootstrap not found, create a new one
|
|
2676
|
+
*/
|
|
2677
|
+
createIfNotFound?: boolean,
|
|
2678
|
+
}): Promise<void> {
|
|
2679
|
+
const lc = `[${updateBootstrapIbGib.name}]`;
|
|
2680
|
+
try {
|
|
2681
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
2682
|
+
|
|
2683
|
+
if (!space) { throw new Error(`space required. (E: 6fc19548fa7d1d5219e19871f280a322)`); }
|
|
2684
|
+
if (!space.data?.uuid) { throw new Error(`space.data.uuid required (E: 6483188ca6f2ed2085fd355595f3ab22)`); }
|
|
2685
|
+
if (!zeroSpace) { throw new Error(`zeroSpace required. (E: abbf156e18b1018d96273e22a260f122)`); }
|
|
2686
|
+
|
|
2687
|
+
const spaceId = space.data.uuid;
|
|
2688
|
+
const newSpaceAddr = getIbGibAddr({ ibGib: space });
|
|
2689
|
+
|
|
2690
|
+
/** validated bootstrap ibgib or null */
|
|
2691
|
+
let bootstrapIbGib = await getValidatedBootstrapIbGib({ zeroSpace });
|
|
2692
|
+
if (!bootstrapIbGib) {
|
|
2693
|
+
if (!createIfNotFound) {
|
|
2694
|
+
if (logalot) { console.log(`${lc} bootstrapIbGib not found but createIfNotFound falsy, so returning early. (I: 5c67d85a8599a5ba4a6780f26a66ea22)`); }
|
|
2695
|
+
return; /* <<<< returns early */
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
// create the bootstrap^gib space that points to user space
|
|
2699
|
+
if (logalot) { console.log(`${lc} creating new bootstrap ibgib for spaceId (${spaceId}) with address of (${newSpaceAddr}) (I: 651959c27bf2ebc5be1f7f44e2b9e422)`); }
|
|
2700
|
+
const { ib: bootstrapIb, gib } = getIbAndGib({ ibGibAddr: BOOTSTRAP_IBGIB_ADDR });
|
|
2701
|
+
bootstrapIbGib = (factory.primitive as any)({ ib: bootstrapIb });
|
|
2702
|
+
bootstrapIbGib!.gib = gib;
|
|
2703
|
+
bootstrapIbGib!.data = {
|
|
2704
|
+
/**
|
|
2705
|
+
* first space is automatically set as default, regardless of
|
|
2706
|
+
* `setSpaceAsDefault` value
|
|
2707
|
+
*/
|
|
2708
|
+
[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]: spaceId,
|
|
2709
|
+
[BOOTSTRAP_DATA_KNOWN_SPACE_IDS_KEY]: [spaceId],
|
|
2710
|
+
} as BootstrapData;
|
|
2711
|
+
bootstrapIbGib!.rel8ns = {
|
|
2712
|
+
/**
|
|
2713
|
+
* individual spaces indexed by spaceId, should be length === 1
|
|
2714
|
+
* with the value being the most recent.
|
|
2715
|
+
*/
|
|
2716
|
+
[spaceId]: [newSpaceAddr],
|
|
2717
|
+
} as BootstrapRel8ns;
|
|
2718
|
+
} else {
|
|
2719
|
+
// at this point, we have a validated bootstrap.
|
|
2720
|
+
// update existing bootstrap with newSpaceAddr for given spaceId
|
|
2721
|
+
if (logalot) { console.log(`${lc} updating existing bootstrap (I: 977d4aa7ed47bef73b35743c05ce0722)`); }
|
|
2722
|
+
if (bootstrapIbGib.data!.spaceIds.includes(spaceId)) {
|
|
2723
|
+
if (logalot) { console.log(`${lc} space already rel8d to bootstrap, possibly updating its addr (I: b5e2c515ef732d4bbcf02625a9e7c722)`); }
|
|
2724
|
+
const existingSpaceAddr = bootstrapIbGib.rel8ns![spaceId]![0];
|
|
2725
|
+
if (existingSpaceAddr === newSpaceAddr) {
|
|
2726
|
+
if (logalot) { console.log(`${lc} bootstrap already rel8d to space (I: c1be027b23e7350c64790a631cae2822)`); }
|
|
2727
|
+
} else {
|
|
2728
|
+
if (logalot) { console.log(`${lc} updating rel8ns[${spaceId}] with newSpaceAddr (${newSpaceAddr}). (Old address: ${existingSpaceAddr})(I: 297a9b0061fd471b8d28a06e04a6ad22)`); }
|
|
2729
|
+
bootstrapIbGib.rel8ns![spaceId] = [newSpaceAddr];
|
|
2730
|
+
}
|
|
2731
|
+
} else {
|
|
2732
|
+
// new space being rel8d to bootstrap
|
|
2733
|
+
if (logalot) { console.log(`${lc} new space being rel8d. adding spaceId to data.spaceIds and amending rel8ns (I: 40903d71719aa1d56e498299f5699a22)`); }
|
|
2734
|
+
bootstrapIbGib.data!.spaceIds.push(spaceId);
|
|
2735
|
+
bootstrapIbGib.rel8ns![spaceId] = [newSpaceAddr];
|
|
2736
|
+
}
|
|
2737
|
+
if (setSpaceAsDefault) {
|
|
2738
|
+
if (logalot) { console.log(`${lc} setting spaceId (${spaceId}) as default space (I: f85eda6c6ad2b0bec9750ce3c7795b22)`); }
|
|
2739
|
+
bootstrapIbGib.data![BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY] = spaceId;
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
if (!bootstrapIbGib) { throw new Error(`(UNEXPECTED) bootstrapIbGib still falsy? (E: cf21d7f1756710a66aa0e6a28d762723)`); }
|
|
2744
|
+
|
|
2745
|
+
if (logalot) { console.log(`${lc} saving bootstrapIbGib: ${pretty(bootstrapIbGib)} (I: 3cceca0b98dde90e4a58a734be252322)`); }
|
|
2746
|
+
|
|
2747
|
+
// save the bootstrap^gib in the zero space for future space loadings,
|
|
2748
|
+
// especially when the app first starts up
|
|
2749
|
+
const argPutBootstrap = await zeroSpace.argy({
|
|
2750
|
+
ibMetadata: bootstrapIbGib!.ib,
|
|
2751
|
+
argData: {
|
|
2752
|
+
cmd: 'put', isMeta: true, force: true,
|
|
2753
|
+
ibGibAddrs: [getIbGibAddr({ ibGib: bootstrapIbGib })],
|
|
2754
|
+
},
|
|
2755
|
+
ibGibs: [bootstrapIbGib],
|
|
2756
|
+
});
|
|
2757
|
+
if (logalot) { console.log(`${lc} zeroSpace will witness/put... (I: 1be9aca22ffc4951b6690965a7aeae5b)`); }
|
|
2758
|
+
const resPutBootstrap = await zeroSpace.witness(argPutBootstrap);
|
|
2759
|
+
if (resPutBootstrap?.data?.success) {
|
|
2760
|
+
if (logalot) { console.log(`${lc} zero space put complete. (I: ac3056d655e841f1a3c442bcc64942f9)`); }
|
|
2761
|
+
} else {
|
|
2762
|
+
throw new Error(`${resPutBootstrap?.data?.errors?.join('|') || "There was a problem with zeroSpace witnessing the bootstrap^gib primitive pointing to the new user space"}`);
|
|
2763
|
+
}
|
|
2764
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2765
|
+
} catch (error) {
|
|
2766
|
+
console.error(`${lc} ${error.message}`);
|
|
2767
|
+
throw error;
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
}
|
|
2771
|
+
|
|
2772
|
+
export function getSpaceArgMetadata({ space }: { space: IbGibSpaceAny }): string {
|
|
2773
|
+
return `${space.ib} ${getTimestampInTicks()}`;
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2776
|
+
export function getSpaceResultMetadata({ space }: { space: IbGibSpaceAny }): string {
|
|
2777
|
+
return `${space.ib} ${getTimestampInTicks()}`;
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
export function getSpaceIb({
|
|
2781
|
+
space,
|
|
2782
|
+
classname,
|
|
2783
|
+
}: {
|
|
2784
|
+
space: IbGibSpaceAny,
|
|
2785
|
+
classname: string,
|
|
2786
|
+
}): Ib {
|
|
2787
|
+
const lc = `[${getSpaceIb.name}]`;
|
|
2788
|
+
try {
|
|
2789
|
+
if (!space) { throw new Error(`space required (E: 4dabec34ee77d67c9cc30ee3c3049622)`); }
|
|
2790
|
+
if (!space.data) { throw new Error(`space.data required (E: 058d298876ebbeada7bbddb9e3da2f23)`); }
|
|
2791
|
+
if (!classname) { throw new Error(`classname required (E: fa3af4613ad56742dab51d1b0d839322)`); }
|
|
2792
|
+
if (classname.includes(' ')) { throw new Error(`invalid classname. cannot contain spaces (E: 243adbf720dcce7904e2665933208b22)`); }
|
|
2793
|
+
const name = space.data?.name || IBGIB_SPACE_NAME_DEFAULT;
|
|
2794
|
+
if (name.includes(' ')) { throw new Error(`invalid space name. cannot contain spaces (E: a8450e1651081412c8ac018520182422)`); }
|
|
2795
|
+
const id = space.data?.uuid || undefined;
|
|
2796
|
+
if (!id) { throw new Error(`invalid space, space.data.uuid falsy (E: 50ae723a9ab24f4fc7132613e65faf23)`); }
|
|
2797
|
+
if (id.includes(' ')) { throw new Error(`invalid space id. cannot contain spaces (E: 8696830fe7f54bfa85e670a063f3e089)`); }
|
|
2798
|
+
let ib = `witness space ${classname} ${name} ${id}`;
|
|
2799
|
+
return ib;
|
|
2800
|
+
} catch (error) {
|
|
2801
|
+
console.error(`${lc} ${error.message}`);
|
|
2802
|
+
throw error;
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2806
|
+
export function isSpaceIb({
|
|
2807
|
+
ib
|
|
2808
|
+
}: {
|
|
2809
|
+
ib: Ib
|
|
2810
|
+
}): boolean {
|
|
2811
|
+
const lc = `[${isSpaceIb.name}]`;
|
|
2812
|
+
try {
|
|
2813
|
+
if (logalot) { console.log(`${lc} starting... (I: 53ad337f8148616a77caca5dff0f8722)`); }
|
|
2814
|
+
return ib.startsWith('witness space ') || ib.startsWith('outerspace sync ');
|
|
2815
|
+
} catch (error) {
|
|
2816
|
+
console.error(`${lc} ${error.message}`);
|
|
2817
|
+
throw error;
|
|
2818
|
+
} finally {
|
|
2819
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
/**
|
|
2824
|
+
* ## current schema FOR LOCAL (IONIC) SPACES:
|
|
2825
|
+
*
|
|
2826
|
+
* `witness space [classname] [spaceName] [spaceId]`
|
|
2827
|
+
*
|
|
2828
|
+
* ## current schema FOR SYNC (AWS) OUTERSPACES:
|
|
2829
|
+
*
|
|
2830
|
+
* `outerspace sync [spaceName]
|
|
2831
|
+
*
|
|
2832
|
+
* ## I need to fix this somehow...
|
|
2833
|
+
*
|
|
2834
|
+
* This is why I'm working on streamlining space management
|
|
2835
|
+
*
|
|
2836
|
+
* (To start with, I just had to get the ball rolling and tried my best.)
|
|
2837
|
+
*
|
|
2838
|
+
* ## NOTES
|
|
2839
|
+
*
|
|
2840
|
+
* * both schemas are space-delimited
|
|
2841
|
+
*/
|
|
2842
|
+
export function getInfoFromSpaceIb({
|
|
2843
|
+
spaceIb,
|
|
2844
|
+
}: {
|
|
2845
|
+
spaceIb: Ib,
|
|
2846
|
+
}): {
|
|
2847
|
+
/**
|
|
2848
|
+
* currently this can be SpaceId OR undefined.
|
|
2849
|
+
*/
|
|
2850
|
+
spaceClassname: string | undefined,
|
|
2851
|
+
/**
|
|
2852
|
+
* non-unique spaceName of the given space (i.e. most likely space.data.name)
|
|
2853
|
+
*/
|
|
2854
|
+
spaceName: string,
|
|
2855
|
+
/**
|
|
2856
|
+
* currently this returns EITHER SpaceId OR undefined.
|
|
2857
|
+
*
|
|
2858
|
+
* This is because of my using different schemas for local/outer spaces...
|
|
2859
|
+
*
|
|
2860
|
+
* (for better or worse)
|
|
2861
|
+
*/
|
|
2862
|
+
spaceId: SpaceId | undefined,
|
|
2863
|
+
spaceType: 'outer' | 'local' | 'inner',
|
|
2864
|
+
} {
|
|
2865
|
+
const lc = `[${getInfoFromSpaceIb.name}]`;
|
|
2866
|
+
try {
|
|
2867
|
+
if (!spaceIb) { throw new Error(`spaceIb required (E: fa5424cfb7e846e2851562f2f417944f)`); }
|
|
2868
|
+
|
|
2869
|
+
if (spaceIb.startsWith('witness space ')) {
|
|
2870
|
+
const pieces = spaceIb.split(' ');
|
|
2871
|
+
return {
|
|
2872
|
+
spaceClassname: pieces[2],
|
|
2873
|
+
spaceName: pieces[3],
|
|
2874
|
+
spaceId: pieces[4],
|
|
2875
|
+
spaceType: 'local',
|
|
2876
|
+
};
|
|
2877
|
+
} else if (spaceIb.startsWith('outerspace sync ')) {
|
|
2878
|
+
const pieces = spaceIb.split(' ');
|
|
2879
|
+
return {
|
|
2880
|
+
spaceClassname: undefined,
|
|
2881
|
+
spaceName: pieces[2],
|
|
2882
|
+
spaceId: undefined,
|
|
2883
|
+
spaceType: 'outer',
|
|
2884
|
+
};
|
|
2885
|
+
} else {
|
|
2886
|
+
throw new Error(`unknown spaceIb schema (spaceIb: ${spaceIb}) (E: a6d361be85d5f25d6a464a5896186322)`);
|
|
2887
|
+
}
|
|
2888
|
+
} catch (error) {
|
|
2889
|
+
console.error(`${lc} ${error.message}`);
|
|
2890
|
+
throw error;
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
/**
|
|
2894
|
+
* Helper function that generates a unique-ish id.
|
|
2895
|
+
*
|
|
2896
|
+
* atow this is just `return (await getUUID()).slice(0, DEFAULT_TX_ID_LENGTH);`
|
|
2897
|
+
*
|
|
2898
|
+
* ## notes
|
|
2899
|
+
*
|
|
2900
|
+
* The thinking is that it only has to be a couple characters in length
|
|
2901
|
+
* because this is supposed to only be a unique id within the scope of
|
|
2902
|
+
* a tx which has its own tjp (gib) used as the id for the entire communication
|
|
2903
|
+
* saga.
|
|
2904
|
+
*
|
|
2905
|
+
* @returns txId
|
|
2906
|
+
*/
|
|
2907
|
+
export async function getNewTxId({
|
|
2908
|
+
length,
|
|
2909
|
+
}: {
|
|
2910
|
+
/**
|
|
2911
|
+
* length of txId
|
|
2912
|
+
*
|
|
2913
|
+
* @default DEFAULT_TX_ID_LENGTH
|
|
2914
|
+
*/
|
|
2915
|
+
length?: number,
|
|
2916
|
+
} = { length: DEFAULT_TX_ID_LENGTH }): Promise<TxId> {
|
|
2917
|
+
const lc = `[${getNewTxId.name}]`;
|
|
2918
|
+
try {
|
|
2919
|
+
length = length || DEFAULT_TX_ID_LENGTH;
|
|
2920
|
+
return (await getUUID()).slice(0, length) as TxId;
|
|
2921
|
+
} catch (error) {
|
|
2922
|
+
console.error(`${lc} ${error.message}`);
|
|
2923
|
+
throw error;
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
/**
|
|
2928
|
+
* wrapper for dealing with a space.
|
|
2929
|
+
*
|
|
2930
|
+
* convenience function for creating an arg ibgib to send to the given space
|
|
2931
|
+
* using Cmd/CmdModifiers for getting latest addrs.
|
|
2932
|
+
*
|
|
2933
|
+
* @returns space result ibgib from the given `space.witness` call.
|
|
2934
|
+
*/
|
|
2935
|
+
export async function getLatestAddrs({
|
|
2936
|
+
ibGibs,
|
|
2937
|
+
addrs,
|
|
2938
|
+
tjps,
|
|
2939
|
+
tjpAddrs,
|
|
2940
|
+
space,
|
|
2941
|
+
}: {
|
|
2942
|
+
ibGibs?: IbGib_V1[],
|
|
2943
|
+
addrs?: IbGibAddr[],
|
|
2944
|
+
tjps?: IbGib_V1[],
|
|
2945
|
+
tjpAddrs?: IbGibAddr[],
|
|
2946
|
+
space: IbGibSpaceAny,
|
|
2947
|
+
}): Promise<IbGibSpaceResultIbGib<IbGib_V1, IbGibSpaceResultData, IbGibSpaceResultRel8ns>> {
|
|
2948
|
+
let lc = `[${getLatestAddrs.name}]`;
|
|
2949
|
+
try {
|
|
2950
|
+
if (logalot) { console.log(`${lc} starting...`); }
|
|
2951
|
+
|
|
2952
|
+
if (!space) { throw new Error(`space required. (E: 4d188d6c863246f28aa575753a052304)`); }
|
|
2953
|
+
|
|
2954
|
+
// so we don't have to do a bunch of conditional checks all over
|
|
2955
|
+
ibGibs = ibGibs ?? []; addrs = addrs ?? [];
|
|
2956
|
+
tjps = tjps ?? []; tjpAddrs = tjpAddrs ?? [];
|
|
2957
|
+
|
|
2958
|
+
if (
|
|
2959
|
+
addrs.length === 0 && ibGibs.length === 0 &&
|
|
2960
|
+
tjps.length === 0 && tjpAddrs.length === 0
|
|
2961
|
+
) {
|
|
2962
|
+
throw new Error(`Either addrs, ibGibs, tjps, or tjpAddrs required. (E: 7c6ebfbab98d4d21a431b144457fd991)`);
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
/**
|
|
2966
|
+
* Addrs that we'll ultimately send to the space. They start off as
|
|
2967
|
+
* tjpAddrs (and derived from `tjps` if any), and then add the incoming
|
|
2968
|
+
* ibgibs/addrs if we don't already have their corresponding tjpAddrs
|
|
2969
|
+
* being queried.
|
|
2970
|
+
* */
|
|
2971
|
+
const addrsToQuery = new Set<IbGibAddr>(
|
|
2972
|
+
tjpAddrs.concat(tjps.map(ibGib => getIbGibAddr({ ibGib })))
|
|
2973
|
+
);
|
|
2974
|
+
|
|
2975
|
+
// add ibgibs/addrs only if they do not already have their corresponding
|
|
2976
|
+
// tjpAddr in the query addrs. We can do this by checking if the tjpGib
|
|
2977
|
+
// is located in the ibGibAddr.gib, which has the form
|
|
2978
|
+
// [punctiliarHash].[tjpGib]
|
|
2979
|
+
const tjpGibs = Array.from(addrsToQuery).map(x => getIbAndGib({ ibGibAddr: x }).gib);
|
|
2980
|
+
ibGibs.map(ibGib => getIbGibAddr({ ibGib }))
|
|
2981
|
+
.concat(addrs)
|
|
2982
|
+
.forEach(ibGibAddr => {
|
|
2983
|
+
const { gib } = getIbAndGib({ ibGibAddr });
|
|
2984
|
+
const addrHasExistingTjpGib =
|
|
2985
|
+
tjpGibs.some(tjpGib => gib.includes(tjpGib));
|
|
2986
|
+
if (!addrHasExistingTjpGib) { addrsToQuery.add(ibGibAddr); }
|
|
2987
|
+
});
|
|
2988
|
+
|
|
2989
|
+
if (logalot) { console.log(`${lc}[testing] ${space.data?.name || space.ib} (${space.data?.uuid || '[space.data.uuid falsy]'}) addrsToQuery: ${Array.from(addrsToQuery)} (I: 8a2202912c364238b6d6eb09577bc246)`); }
|
|
2990
|
+
|
|
2991
|
+
// construct the arg and execute
|
|
2992
|
+
const argGet = await space.argy({
|
|
2993
|
+
ibMetadata: getSpaceArgMetadata({ space }),
|
|
2994
|
+
argData: {
|
|
2995
|
+
cmd: 'get',
|
|
2996
|
+
cmdModifiers: ['latest', 'addrs'],
|
|
2997
|
+
ibGibAddrs: Array.from(addrsToQuery),
|
|
2998
|
+
},
|
|
2999
|
+
});
|
|
3000
|
+
return await space.witness(argGet);
|
|
3001
|
+
} catch (error) {
|
|
3002
|
+
console.error(`${lc} ${error.message}`);
|
|
3003
|
+
throw error;
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
|
|
3007
|
+
/**
|
|
3008
|
+
* I'm making this because i want to archive on a special tags index ibgib.
|
|
3009
|
+
* But we can't allow archiving on any old special ibgib, like the 'latest' index.
|
|
3010
|
+
* so this checks to see if it's on the forbidden list (winging that atm), and if it
|
|
3011
|
+
* is then this throws.
|
|
3012
|
+
*
|
|
3013
|
+
* use this function inside of commands that act on ibgibs that are special.
|
|
3014
|
+
*/
|
|
3015
|
+
export function throwIfContextIsSpecial({
|
|
3016
|
+
ibGib_Context,
|
|
3017
|
+
}: {
|
|
3018
|
+
ibGib_Context: IbGib_V1,
|
|
3019
|
+
}): void {
|
|
3020
|
+
const lc = `[${throwIfContextIsSpecial.name}]`;
|
|
3021
|
+
try {
|
|
3022
|
+
if (logalot) { console.log(`${lc} starting... (I: 5f583fd94d27731a65d514e731b8aa22)`); }
|
|
3023
|
+
|
|
3024
|
+
if (!isSpecial({ ibGib: ibGib_Context })) { return; /* <<<< returns early */; }
|
|
3025
|
+
|
|
3026
|
+
const FORBIDDEN_MANUAL_SPECIAL_TYPES: SpecialIbGibType[] = [
|
|
3027
|
+
'latest', 'roots', 'autosyncs'
|
|
3028
|
+
];
|
|
3029
|
+
if (FORBIDDEN_MANUAL_SPECIAL_TYPES.some(x => ibGib_Context.ib.includes(x))) {
|
|
3030
|
+
throw new Error(`cannot perform a modification of this type on this special ibgib (E: b8fb718a7323fc54454464b973412722)`);
|
|
3031
|
+
}
|
|
3032
|
+
} catch (error) {
|
|
3033
|
+
console.error(`${lc} ${error.message}`);
|
|
3034
|
+
throw error;
|
|
3035
|
+
} finally {
|
|
3036
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
export async function trash({
|
|
3041
|
+
ibGib_Context,
|
|
3042
|
+
rel8nName_Context,
|
|
3043
|
+
addr,
|
|
3044
|
+
space,
|
|
3045
|
+
zeroSpace,
|
|
3046
|
+
fnUpdateBootstrap,
|
|
3047
|
+
fnBroadcast,
|
|
3048
|
+
}: {
|
|
3049
|
+
ibGib_Context: IbGib_V1,
|
|
3050
|
+
rel8nName_Context: string,
|
|
3051
|
+
addr: IbGibAddr,
|
|
3052
|
+
space: IbGibSpaceAny,
|
|
3053
|
+
zeroSpace: IbGibSpaceAny,
|
|
3054
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
3055
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
3056
|
+
}): Promise<void> {
|
|
3057
|
+
const lc = `[${trash.name}]`;
|
|
3058
|
+
try {
|
|
3059
|
+
if (logalot) { console.log(`${lc} starting... (I: 2dc486bb2d516e4534f437aaf5ec7f22)`); }
|
|
3060
|
+
if (!ibGib_Context) { throw new Error(`ibGib_Context required (E: 75f7bfa93145d6dffe85d488443ca722)`); }
|
|
3061
|
+
if (!rel8nName_Context) { throw new Error(`rel8nName_Context required (E: 12aaa43de9e34b68b25dc9a2a68ad6b9)`); }
|
|
3062
|
+
if (!addr) { throw new Error(`addr required (E: e27df3bdc5a2554697cc9597afc4e422)`); }
|
|
3063
|
+
if (!space) { throw new Error(`space required (E: 2e3562486ed2956a770ed9e8d77a3f22)`); }
|
|
3064
|
+
|
|
3065
|
+
const contextIsSpecialIbGib = isSpecial({ ibGib: ibGib_Context });
|
|
3066
|
+
if (contextIsSpecialIbGib) { throwIfContextIsSpecial({ ibGib_Context }); }
|
|
3067
|
+
|
|
3068
|
+
const resNewContext = await V1.rel8({
|
|
3069
|
+
src: ibGib_Context,
|
|
3070
|
+
rel8nsToAddByAddr: { [TRASH_REL8N_NAME]: [addr] },
|
|
3071
|
+
rel8nsToRemoveByAddr: { [rel8nName_Context]: [addr] },
|
|
3072
|
+
dna: true,
|
|
3073
|
+
nCounter: true,
|
|
3074
|
+
});
|
|
3075
|
+
|
|
3076
|
+
await persistTransformResult({ resTransform: resNewContext, isMeta: contextIsSpecialIbGib, space });
|
|
3077
|
+
|
|
3078
|
+
if (contextIsSpecialIbGib) {
|
|
3079
|
+
const newSpecialAddr = getIbGibAddr({ ibGib: resNewContext.newIbGib });
|
|
3080
|
+
const specialType = getSpecialTypeFromIb({ ib: ibGib_Context.ib });
|
|
3081
|
+
const configKey = getSpecialConfigKey({ type: specialType });
|
|
3082
|
+
await setConfigAddr({ key: configKey, addr: newSpecialAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
// if (fnBroadcast && fnUpdateBootstrap) {
|
|
3086
|
+
await registerNewIbGib({
|
|
3087
|
+
ibGib: resNewContext.newIbGib,
|
|
3088
|
+
fnBroadcast,
|
|
3089
|
+
fnUpdateBootstrap,
|
|
3090
|
+
zeroSpace,
|
|
3091
|
+
space,
|
|
3092
|
+
});
|
|
3093
|
+
// };
|
|
3094
|
+
} catch (error) {
|
|
3095
|
+
console.error(`${lc} ${error.message}`);
|
|
3096
|
+
throw error;
|
|
3097
|
+
} finally {
|
|
3098
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
|
|
3103
|
+
export async function archive({
|
|
3104
|
+
ibGib_Context,
|
|
3105
|
+
rel8nName_Context,
|
|
3106
|
+
addr,
|
|
3107
|
+
space,
|
|
3108
|
+
zeroSpace,
|
|
3109
|
+
fnUpdateBootstrap,
|
|
3110
|
+
fnBroadcast,
|
|
3111
|
+
}: {
|
|
3112
|
+
ibGib_Context: IbGib_V1,
|
|
3113
|
+
rel8nName_Context: string,
|
|
3114
|
+
addr: IbGibAddr,
|
|
3115
|
+
space: IbGibSpaceAny,
|
|
3116
|
+
zeroSpace: IbGibSpaceAny,
|
|
3117
|
+
fnUpdateBootstrap?: (newSpace: IbGibSpaceAny) => Promise<void>,
|
|
3118
|
+
fnBroadcast?: (info: IbGibTimelineUpdateInfo) => void,
|
|
3119
|
+
}): Promise<void> {
|
|
3120
|
+
const lc = `[${archive.name}]`;
|
|
3121
|
+
try {
|
|
3122
|
+
if (logalot) { console.log(`${lc} starting... (I: 38098552b830495187299bb24fcddff0)`); }
|
|
3123
|
+
if (!ibGib_Context) { throw new Error(`ibGib_Context required (E: d819e8c4db5b4c0bb721300ba434cd40)`); }
|
|
3124
|
+
if (!rel8nName_Context) { throw new Error(`rel8nName_Context required (E: de061adff8c04429a211aa09116a532d)`); }
|
|
3125
|
+
if (!addr) { throw new Error(`addr required (E: 7059ebb8ef6149ea94e22f961d6b5c81)`); }
|
|
3126
|
+
if (!space) { throw new Error(`space required (E: e19566f2d42347798621447edcae312e)`); }
|
|
3127
|
+
|
|
3128
|
+
const contextIsSpecialIbGib = isSpecial({ ibGib: ibGib_Context });
|
|
3129
|
+
if (contextIsSpecialIbGib) { throwIfContextIsSpecial({ ibGib_Context }); }
|
|
3130
|
+
|
|
3131
|
+
const resNewContext = await V1.rel8({
|
|
3132
|
+
src: ibGib_Context,
|
|
3133
|
+
rel8nsToAddByAddr: { [ARCHIVE_REL8N_NAME]: [addr] },
|
|
3134
|
+
rel8nsToRemoveByAddr: { [rel8nName_Context]: [addr] },
|
|
3135
|
+
dna: true,
|
|
3136
|
+
nCounter: true,
|
|
3137
|
+
});
|
|
3138
|
+
|
|
3139
|
+
await persistTransformResult({ resTransform: resNewContext, isMeta: contextIsSpecialIbGib, space });
|
|
3140
|
+
|
|
3141
|
+
if (contextIsSpecialIbGib) {
|
|
3142
|
+
const newSpecialAddr = getIbGibAddr({ ibGib: resNewContext.newIbGib });
|
|
3143
|
+
const specialType = getSpecialTypeFromIb({ ib: ibGib_Context.ib });
|
|
3144
|
+
const configKey = getSpecialConfigKey({ type: specialType });
|
|
3145
|
+
await setConfigAddr({ key: configKey, addr: newSpecialAddr, space, zeroSpace, fnUpdateBootstrap });
|
|
3146
|
+
}
|
|
3147
|
+
|
|
3148
|
+
// if (fnBroadcast && fnUpdateBootstrap) {
|
|
3149
|
+
await registerNewIbGib({
|
|
3150
|
+
ibGib: resNewContext.newIbGib,
|
|
3151
|
+
fnBroadcast,
|
|
3152
|
+
fnUpdateBootstrap,
|
|
3153
|
+
zeroSpace,
|
|
3154
|
+
space,
|
|
3155
|
+
});
|
|
3156
|
+
// } else {
|
|
3157
|
+
// console.warn(`${lc} fnBroadcast or fnUpdateBootstrap falsy, so we can't register `)
|
|
3158
|
+
// };
|
|
3159
|
+
} catch (error) {
|
|
3160
|
+
console.error(`${lc} ${error.message}`);
|
|
3161
|
+
throw error;
|
|
3162
|
+
} finally {
|
|
3163
|
+
if (logalot) { console.log(`${lc} complete.`); }
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
|
|
3167
|
+
export function spaceNameIsValid(name: string): boolean {
|
|
3168
|
+
const lc = `[${spaceNameIsValid.name}]`;
|
|
3169
|
+
try {
|
|
3170
|
+
// non-falsy
|
|
3171
|
+
if (!name) {
|
|
3172
|
+
console.error(`${lc} name is falsy`)
|
|
3173
|
+
return false;
|
|
3174
|
+
}
|
|
3175
|
+
|
|
3176
|
+
// valid characters are alphanumerics, numbers, underscores, hyphens
|
|
3177
|
+
const regexOnlyIncluded = /[\w-]+/;
|
|
3178
|
+
const matchOnlyIncluded = name.match(regexOnlyIncluded);
|
|
3179
|
+
if (matchOnlyIncluded?.length !== 1 || matchOnlyIncluded[0].length !== name.length) {
|
|
3180
|
+
console.error(`${lc} name can only contain letters, numbers, underscores, hyphens`);
|
|
3181
|
+
return false;
|
|
3182
|
+
}
|
|
3183
|
+
|
|
3184
|
+
// start with alphanumeric
|
|
3185
|
+
const regexStart = /[a-zA-Z\d]/;
|
|
3186
|
+
const matchStart = name[0].match(regexStart);
|
|
3187
|
+
if (!matchStart) {
|
|
3188
|
+
console.error(`${lc} name must start with a letter or number`);
|
|
3189
|
+
return false;
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
return true;
|
|
3193
|
+
} catch (error) {
|
|
3194
|
+
console.error(`${lc} ${error.message}`);
|
|
3195
|
+
return false;
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
|
|
3199
|
+
export async function validateBootstrapIbGib(bootstrapSpace: IbGib_V1): Promise<boolean> {
|
|
3200
|
+
const lc = `[${validateBootstrapIbGib.name}]`;
|
|
3201
|
+
const errors: string[] = [];
|
|
3202
|
+
try {
|
|
3203
|
+
const addr = getIbGibAddr({ ibGib: bootstrapSpace });
|
|
3204
|
+
if (addr !== BOOTSTRAP_IBGIB_ADDR) {
|
|
3205
|
+
errors.push(`invalid bootstrapSpace addr. Should equal "${BOOTSTRAP_IBGIB_ADDR}" (E: ecfdbed719284db7a1aa3f867f706fe9)`);
|
|
3206
|
+
}
|
|
3207
|
+
let intrinsicErrors = await validateIbGibIntrinsically({ ibGib: bootstrapSpace });
|
|
3208
|
+
if (intrinsicErrors?.length ?? -1 > 0) { intrinsicErrors!.forEach(e => errors.push(e)); }
|
|
3209
|
+
|
|
3210
|
+
const data = (bootstrapSpace.data as BootstrapData);
|
|
3211
|
+
const rel8ns = (bootstrapSpace.rel8ns as BootstrapRel8ns);
|
|
3212
|
+
|
|
3213
|
+
if (Object.keys(data || {}).length === 0) {
|
|
3214
|
+
errors.push(`invalid bootstrapSpace data. data required (E: 5a9bd15dd0644f9b93cafbbba660cfdf)`);
|
|
3215
|
+
}
|
|
3216
|
+
if ((data.spaceIds ?? []).length === 0) {
|
|
3217
|
+
errors.push(`invalid bootstrapSpace, data.spaceIds required. (E: 6b91ddc12cfd41e59ded7d7502c1909f)`);
|
|
3218
|
+
}
|
|
3219
|
+
if (Object.keys(bootstrapSpace.rel8ns || {}).length === 0) {
|
|
3220
|
+
errors.push(`invalid bootstrapSpace rel8ns (empty). Should have at least one rel8n, with rel8nName corresponding to the spaceId (E: b188ce4ae25e49f794f35e141bc2ecde)`);
|
|
3221
|
+
}
|
|
3222
|
+
data.spaceIds.forEach((spaceId: string) => {
|
|
3223
|
+
if ((rel8ns[spaceId] ?? []).length === 0) {
|
|
3224
|
+
errors.push(`invalid bootstrap. Each spaceId listed in data should have a corresponding address in rel8ns. spaceId (${spaceId}) missing. (E: 62dd0d76e29a415a98b4b27deb8db17e)`);
|
|
3225
|
+
}
|
|
3226
|
+
});
|
|
3227
|
+
if (!data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]) {
|
|
3228
|
+
errors.push(`invalid bootstrap. data.${BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY} required. (E: f763af2e275f445cbf1db5801bacafad)`);
|
|
3229
|
+
} else if ((rel8ns[data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]] ?? []).length === 0) {
|
|
3230
|
+
errors.push(`invalid bootstrap. data.${BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY} (${data[BOOTSTRAP_DATA_DEFAULT_SPACE_ID_KEY]}) not found in rel8ns. (E: 44d0799d232f4a51a0b0019ebebe019f)`);
|
|
3231
|
+
}
|
|
3232
|
+
if (errors.length === 0) {
|
|
3233
|
+
return true;
|
|
3234
|
+
} else {
|
|
3235
|
+
console.error(`${lc} errors: ${errors.join('|')}`);
|
|
3236
|
+
return false;
|
|
3237
|
+
}
|
|
3238
|
+
} catch (error) {
|
|
3239
|
+
console.error(`${lc} ${error.message}`);
|
|
3240
|
+
return false;
|
|
3241
|
+
}
|
|
3242
|
+
}
|