@ibgib/ts-gib 0.4.9
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/launch.json +24 -0
- package/.vscode/settings.json +34 -0
- package/.vscode/tasks.json +37 -0
- package/CHANGELOG.md +159 -0
- package/README.md +502 -0
- package/dist/V1/constants.d.mts +22 -0
- package/dist/V1/constants.d.mts.map +1 -0
- package/dist/V1/constants.mjs +21 -0
- package/dist/V1/constants.mjs.map +1 -0
- package/dist/V1/factory.d.mts +23 -0
- package/dist/V1/factory.d.mts.map +1 -0
- package/dist/V1/factory.mjs +78 -0
- package/dist/V1/factory.mjs.map +1 -0
- package/dist/V1/index.d.mts +6 -0
- package/dist/V1/index.d.mts.map +1 -0
- package/dist/V1/index.mjs +6 -0
- package/dist/V1/index.mjs.map +1 -0
- package/dist/V1/sha256v1.d.mts +19 -0
- package/dist/V1/sha256v1.d.mts.map +1 -0
- package/dist/V1/sha256v1.mjs +86 -0
- package/dist/V1/sha256v1.mjs.map +1 -0
- package/dist/V1/transforms/fork.d.mts +16 -0
- package/dist/V1/transforms/fork.d.mts.map +1 -0
- package/dist/V1/transforms/fork.mjs +111 -0
- package/dist/V1/transforms/fork.mjs.map +1 -0
- package/dist/V1/transforms/index.d.mts +5 -0
- package/dist/V1/transforms/index.d.mts.map +1 -0
- package/dist/V1/transforms/index.mjs +5 -0
- package/dist/V1/transforms/index.mjs.map +1 -0
- package/dist/V1/transforms/mut8.d.mts +50 -0
- package/dist/V1/transforms/mut8.d.mts.map +1 -0
- package/dist/V1/transforms/mut8.mjs +246 -0
- package/dist/V1/transforms/mut8.mjs.map +1 -0
- package/dist/V1/transforms/rel8.d.mts +14 -0
- package/dist/V1/transforms/rel8.d.mts.map +1 -0
- package/dist/V1/transforms/rel8.mjs +176 -0
- package/dist/V1/transforms/rel8.mjs.map +1 -0
- package/dist/V1/transforms/transform-helper.d.mts +92 -0
- package/dist/V1/transforms/transform-helper.d.mts.map +1 -0
- package/dist/V1/transforms/transform-helper.mjs +189 -0
- package/dist/V1/transforms/transform-helper.mjs.map +1 -0
- package/dist/V1/types.d.mts +79 -0
- package/dist/V1/types.d.mts.map +1 -0
- package/dist/V1/types.mjs +12 -0
- package/dist/V1/types.mjs.map +1 -0
- package/dist/helper.d.mts +77 -0
- package/dist/helper.d.mts.map +1 -0
- package/dist/helper.mjs +179 -0
- package/dist/helper.mjs.map +1 -0
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types.d.mts +242 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/jasmine-browser.json +18 -0
- package/jasmine.json +6 -0
- package/package.json +61 -0
- package/src/V1/constants.mts +23 -0
- package/src/V1/factory.mts +110 -0
- package/src/V1/factory.spec.mts +162 -0
- package/src/V1/index.mts +5 -0
- package/src/V1/sha256v1.mts +85 -0
- package/src/V1/sha256v1.spec.mts +221 -0
- package/src/V1/transforms/fork.mts +100 -0
- package/src/V1/transforms/fork.spec.mts +410 -0
- package/src/V1/transforms/index.mts +4 -0
- package/src/V1/transforms/mut8.mts +239 -0
- package/src/V1/transforms/mut8.spec.mts +656 -0
- package/src/V1/transforms/rel8.mts +173 -0
- package/src/V1/transforms/rel8.spec.mts +556 -0
- package/src/V1/transforms/transform-helper.mts +263 -0
- package/src/V1/transforms/transform-helper.spec.mts +45 -0
- package/src/V1/types.mts +84 -0
- package/src/helper.mts +192 -0
- package/src/helper.spec.mts +127 -0
- package/src/index.cts +3 -0
- package/src/index.mts +3 -0
- package/src/types.mts +242 -0
- package/tsconfig.json +15 -0
- package/tsconfig.test.json +10 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { TransformOpts, IbGib, Gib, Ib, IbGibAddr, } from "../../types.mjs";
|
|
2
|
+
import { clone, getIbGibAddr, getIbAndGib, HashAlgorithm, extractErrorMsg, } from "../../helper.mjs";
|
|
3
|
+
import { sha256v1, } from "../sha256v1.mjs";
|
|
4
|
+
import { GibInfo, IbGib_V1, } from "../types.mjs";
|
|
5
|
+
import { IBGIB_DELIMITER, GIB, GIB_DELIMITER } from "../constants.mjs";
|
|
6
|
+
|
|
7
|
+
export async function buildDna<TSrc extends IbGib_V1, TOpts extends TransformOpts<TSrc>>(
|
|
8
|
+
opts: TOpts,
|
|
9
|
+
): Promise<IbGib_V1> {
|
|
10
|
+
const transformData: TOpts = clone(opts);
|
|
11
|
+
let lc = `[${buildDna.name}]`;
|
|
12
|
+
|
|
13
|
+
// remove references to the srcAddr, as this will be captured
|
|
14
|
+
// by the ibGib's `past` rel8n. This way, we can reapply dna
|
|
15
|
+
// to different src's more easily, as well as have less unique dna
|
|
16
|
+
if (transformData.srcAddr) { delete transformData.srcAddr; }
|
|
17
|
+
|
|
18
|
+
// remove all references to actual objects in this, we just
|
|
19
|
+
// want the data. ATOW, src is a reference to the src object
|
|
20
|
+
// and we only want the srcAddr
|
|
21
|
+
delete transformData.src;
|
|
22
|
+
|
|
23
|
+
// dna is never timestamped or uniquely identified hmm...
|
|
24
|
+
// or rel8d to anything...hmmm
|
|
25
|
+
// so much dna, best to minimize though of course we dont
|
|
26
|
+
// want to prematurely optimize...but there's a looooot of dna.
|
|
27
|
+
// best to share/reuse as much as possible.
|
|
28
|
+
const result: IbGib_V1 = {
|
|
29
|
+
ib: transformData.type!,
|
|
30
|
+
data: transformData,
|
|
31
|
+
rel8ns: {
|
|
32
|
+
ancestor: [
|
|
33
|
+
`${transformData.type!.toString()}${IBGIB_DELIMITER}${GIB}` // e.g. fork^gib
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
result.gib = await sha256v1(result);
|
|
39
|
+
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function isDna({ ibGib }: { ibGib: IbGib }): boolean {
|
|
44
|
+
const lc = `[${isDna.name}]`;
|
|
45
|
+
try {
|
|
46
|
+
if (!ibGib) { throw new Error(`ibGib required.`); }
|
|
47
|
+
|
|
48
|
+
// console.log(`${lc} ibGib: ${pretty(ibGib)}`);
|
|
49
|
+
|
|
50
|
+
// ancestor is known transform is the best way for v1 ATOW
|
|
51
|
+
const knownTransformPrimitiveAddrs =
|
|
52
|
+
['fork', 'mut8', 'rel8', 'plan'].map(x => `${x}^${GIB}`); // plan from prev versions
|
|
53
|
+
const hasTransformAncestor =
|
|
54
|
+
((ibGib as any).rel8ns) &&
|
|
55
|
+
((ibGib as any).rel8ns.ancestor) &&
|
|
56
|
+
(Array.isArray((ibGib as any).rel8ns.ancestor)) &&
|
|
57
|
+
((((ibGib as any).rel8ns.ancestor) as any) as any).
|
|
58
|
+
some((x: any) => knownTransformPrimitiveAddrs.includes(x));
|
|
59
|
+
|
|
60
|
+
return hasTransformAncestor || false;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function isPrimitive({ ibGib, gib }: { ibGib?: IbGib_V1, gib?: Gib }): boolean {
|
|
68
|
+
if (ibGib) {
|
|
69
|
+
return isPrimitive({ gib: ibGib.gib });
|
|
70
|
+
} else if (gib) {
|
|
71
|
+
return gib === GIB;
|
|
72
|
+
} else {
|
|
73
|
+
// falsy gib means it's primitive or a programming error...hmm
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Generates the gib of a given `ibGib` depending on
|
|
80
|
+
* @returns gib - either bare hash for those with no tjp; or tjp-scoped hash; or 'gib' for primitives
|
|
81
|
+
*/
|
|
82
|
+
export async function getGib({
|
|
83
|
+
ibGib,
|
|
84
|
+
hasTjp,
|
|
85
|
+
tjpAddr,
|
|
86
|
+
gibDelimiter,
|
|
87
|
+
isPrimitive,
|
|
88
|
+
hashAlgorithm,
|
|
89
|
+
}: {
|
|
90
|
+
/**
|
|
91
|
+
* We'll take the `ib`, `data`, and `rel8ns` from this
|
|
92
|
+
*/
|
|
93
|
+
ibGib: IbGib_V1,
|
|
94
|
+
/**
|
|
95
|
+
* If true, then we'll treat this as having a tjp.
|
|
96
|
+
* If falsy, then we'll check the internals of the ibGib to see if it has a tjp.
|
|
97
|
+
*/
|
|
98
|
+
hasTjp?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* @deprecated
|
|
101
|
+
*
|
|
102
|
+
* IGNORED
|
|
103
|
+
*
|
|
104
|
+
* This is now always searched for in the ibGib itself.
|
|
105
|
+
*/
|
|
106
|
+
tjpAddr?: IbGibAddr,
|
|
107
|
+
/**
|
|
108
|
+
* What to use as the delimiter for the `gib`.
|
|
109
|
+
*
|
|
110
|
+
* @default GIB_DELIMITER
|
|
111
|
+
*
|
|
112
|
+
* ## notes
|
|
113
|
+
*
|
|
114
|
+
* This is not the same thing necessarily as the ib^gib delimiter.
|
|
115
|
+
* In fact the default gibDelimiter ATOW ('.') is different than the
|
|
116
|
+
* default ib^gib delimiter ('^').
|
|
117
|
+
*/
|
|
118
|
+
gibDelimiter?: string,
|
|
119
|
+
/**
|
|
120
|
+
* If this is primitive, then the `gib` is always GIB ("gib" string literal).
|
|
121
|
+
*/
|
|
122
|
+
isPrimitive?: boolean,
|
|
123
|
+
/**
|
|
124
|
+
* Hash algorithm to use when calculating the gib hash of the ibgib datum.
|
|
125
|
+
*
|
|
126
|
+
* ## notes
|
|
127
|
+
*
|
|
128
|
+
* * I'm just including this now to show where we will expand when working with
|
|
129
|
+
* multiple hash algorithms. For now though, in all of V1, we use 'SHA-256'
|
|
130
|
+
* when calculating the gib hashes. This is why I'm hard-coding the type
|
|
131
|
+
* here instead of using this lib's `HashAlgorithm` type.
|
|
132
|
+
* * This param is actually ignored ATOW.
|
|
133
|
+
* * In my current consuming use case (ionic-gib), though,
|
|
134
|
+
* I am indeed using SHA-512 when encrypting using encrypt-gib. I only note
|
|
135
|
+
* this in case someone sees "SHA-512" code somewhere and is confused.
|
|
136
|
+
*/
|
|
137
|
+
hashAlgorithm?: 'SHA-256',
|
|
138
|
+
}): Promise<string> {
|
|
139
|
+
const lc = `[${getGib.name}]`;
|
|
140
|
+
try {
|
|
141
|
+
if (!ibGib) { throw new Error(`ibGib required. (E: 17d073226b9d42fd841e5a94b065ef21)`); }
|
|
142
|
+
if (isPrimitive) { return GIB; }
|
|
143
|
+
const ibGibHash = await sha256v1(ibGib, '');
|
|
144
|
+
const rel8ns = ibGib.rel8ns ?? {};
|
|
145
|
+
const data = ibGib.data ?? {};
|
|
146
|
+
gibDelimiter = gibDelimiter || GIB_DELIMITER;
|
|
147
|
+
if (!hasTjp) { hasTjp = (rel8ns.tjp?.length ?? []) > 0 || data.isTjp || false; }
|
|
148
|
+
if (hasTjp) {
|
|
149
|
+
let tjpAddrGib: string | undefined;
|
|
150
|
+
if (rel8ns.tjp) {
|
|
151
|
+
if (rel8ns.tjp.length === 1) {
|
|
152
|
+
if (rel8ns.tjp[0]) { // checking for empty string
|
|
153
|
+
tjpAddr = rel8ns.tjp[0];
|
|
154
|
+
} else {
|
|
155
|
+
throw new Error(`rel8ns.tjp[0] is falsy. (E: ed879d2b039543f8b1902e8b7b5a5a7b)`);
|
|
156
|
+
}
|
|
157
|
+
} else if (rel8ns.tjp.length > 1) {
|
|
158
|
+
if (rel8ns.tjp[rel8ns.tjp.length - 1]) {
|
|
159
|
+
console.warn(`${lc} found more than one tjp addr...only expecting 1 ATOW. (W: 10ed43f716e743e0afd1954f1ab46789)`);
|
|
160
|
+
tjpAddr = rel8ns.tjp[rel8ns.tjp.length - 1];
|
|
161
|
+
} else {
|
|
162
|
+
throw new Error(`multiple tjp addrs, and the last (most recent) one is falsy. (E: bc835dc89be24075bba8b2b6616ea069)`);
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
// empty rel8ns.tjp array?
|
|
166
|
+
throw new Error(`hasTjp is true but rel8ns.tjp is empty array. (E: d08b2f9e86494814b5e7d7b4602b2ab7)`);
|
|
167
|
+
}
|
|
168
|
+
} else if (data.isTjp) {
|
|
169
|
+
// the ibGib itself is the tjp
|
|
170
|
+
tjpAddr = getIbGibAddr({ ib: ibGib.ib, gib: ibGibHash });
|
|
171
|
+
} else {
|
|
172
|
+
throw new Error(`hasTjp is true, but both ibGib.rel8ns.tjp and ibGib.data.isTjp are falsy. (E: 4e246897e52044789594d853bb5b66ee)`)
|
|
173
|
+
}
|
|
174
|
+
tjpAddrGib = tjpAddr ? getIbAndGib({ ibGibAddr: tjpAddr }).gib : undefined;
|
|
175
|
+
|
|
176
|
+
if (tjpAddrGib) {
|
|
177
|
+
// if the ibGib IS the tjp, then the gib is only the hash
|
|
178
|
+
|
|
179
|
+
// if the ibGib is NOT the tjp, then the gib is the hash plus
|
|
180
|
+
// tjpGib. note in the future, if multiple tjps are going, then
|
|
181
|
+
// tjpAddrGib itself may have another delim inside it, so we
|
|
182
|
+
// will end up with a gib with multiple delimiters.
|
|
183
|
+
return data.isTjp ? ibGibHash : `${ibGibHash}${GIB_DELIMITER}${tjpAddrGib}`;
|
|
184
|
+
} else {
|
|
185
|
+
throw new Error(`hasTjp is true but could not find tjpAddrGib. (E: 1863df626b754744a1d431a683cb0ba0)`);
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
// no tjp, so gib is just the hash
|
|
189
|
+
return ibGibHash;
|
|
190
|
+
}
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Parses gib (either via `gib` param or `ibGibAddr.gib`) and returns information
|
|
200
|
+
* about it.
|
|
201
|
+
*
|
|
202
|
+
* @returns Information about the given `gib` (or `gib` extracted from `ibGibAddr`)
|
|
203
|
+
*/
|
|
204
|
+
export function getGibInfo({
|
|
205
|
+
ibGibAddr,
|
|
206
|
+
gib,
|
|
207
|
+
gibDelimiter,
|
|
208
|
+
}: {
|
|
209
|
+
/**
|
|
210
|
+
* If given, will extract `gib` from this.
|
|
211
|
+
*/
|
|
212
|
+
ibGibAddr?: IbGibAddr,
|
|
213
|
+
/**
|
|
214
|
+
* `gib` to analyze.
|
|
215
|
+
*/
|
|
216
|
+
gib?: Gib,
|
|
217
|
+
/**
|
|
218
|
+
* Delimiter among pieces of gib, if applicable.
|
|
219
|
+
*
|
|
220
|
+
* @default GIB_DELIMITER (ATOW '.')
|
|
221
|
+
*
|
|
222
|
+
* ## notes
|
|
223
|
+
*
|
|
224
|
+
* Some `gib` values will include tjp information, while others
|
|
225
|
+
* are just the hash.
|
|
226
|
+
*/
|
|
227
|
+
gibDelimiter?: string,
|
|
228
|
+
}): GibInfo {
|
|
229
|
+
const lc = `[${getGibInfo.name}]`;
|
|
230
|
+
try {
|
|
231
|
+
if (!ibGibAddr && !gib) { throw new Error(`Either ibGibAddr or gib required. (E: 25e3dcbe63cd44909032df12af9df75e)`); }
|
|
232
|
+
gib = gib || getIbAndGib({ ibGibAddr }).gib;
|
|
233
|
+
|
|
234
|
+
if (gib === GIB) { return { isPrimitive: true } }
|
|
235
|
+
|
|
236
|
+
gibDelimiter = gibDelimiter ?? GIB_DELIMITER;
|
|
237
|
+
|
|
238
|
+
if (gib.includes(gibDelimiter)) {
|
|
239
|
+
const pieces = gib.split(gibDelimiter);
|
|
240
|
+
if (pieces.some(p => p === '')) { throw new Error(`unexpected gib that contains gibDelimiter (${gibDelimiter}) but has at least one piece with empty string. (E: 75a94280045541009ee68182d12d3449)`); }
|
|
241
|
+
|
|
242
|
+
const piecesCount = pieces.length;
|
|
243
|
+
if (piecesCount > 2) { console.warn(`${lc} gib only expected to have two pieces ATOW. re-examine please. (W: aa4283ac5a5747a386a69966ecdad39d)`); }
|
|
244
|
+
|
|
245
|
+
const punctiliarHashPiece = pieces.splice(0, 1);
|
|
246
|
+
return {
|
|
247
|
+
punctiliarHash: punctiliarHashPiece[0],
|
|
248
|
+
tjpGib: pieces.join(gibDelimiter), // after splice, piece/s is/are tjp
|
|
249
|
+
piecesCount,
|
|
250
|
+
delimiter: gibDelimiter,
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
return {
|
|
254
|
+
punctiliarHash: gib,
|
|
255
|
+
piecesCount: 1,
|
|
256
|
+
delimiter: gibDelimiter,
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} catch (error) {
|
|
260
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test transform-helper.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import { IbGib_V1, IbGibRel8ns_V1, Rel8n } from '../types.mjs';
|
|
7
|
+
import { TransformOpts_Rel8, IbGibAddr, IbGibRel8ns } from '../../types.mjs';
|
|
8
|
+
import { pretty, clone, delay, getIbGibAddr } from '../../helper.mjs';
|
|
9
|
+
import { ROOT, ROOT_ADDR } from '../constants.mjs';
|
|
10
|
+
import { fork } from './fork.mjs';
|
|
11
|
+
// import { mut8 } from './mut8.mjs';
|
|
12
|
+
import { rel8 } from './rel8.mjs';
|
|
13
|
+
import { Factory_V1 as factory } from '../factory.mjs';
|
|
14
|
+
import { isDna } from './transform-helper.mjs';
|
|
15
|
+
|
|
16
|
+
const PRIMITIVE_IBGIBS = [
|
|
17
|
+
factory.root(),
|
|
18
|
+
...factory.primitives({
|
|
19
|
+
ibs: [
|
|
20
|
+
'a', '7', 'tag',
|
|
21
|
+
'any string/value that isnt hashed with a gib is a primitive',
|
|
22
|
+
// e.g. 6 -> 6^ -> 6^gib are all equivalent ib^gib addresses,
|
|
23
|
+
]
|
|
24
|
+
}),
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
describe(`isDna`, () => {
|
|
28
|
+
for (const src of PRIMITIVE_IBGIBS) {
|
|
29
|
+
|
|
30
|
+
it(`should return true for dna ibgibs`, async () => {
|
|
31
|
+
const resFork = await fork({ src, dna: true });
|
|
32
|
+
resFork.dnas?.every(x => {
|
|
33
|
+
const resIsDna = isDna({ ibGib: x });
|
|
34
|
+
expect(resIsDna).toBeTrue()
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it(`should return false for non-dna ibgibs`, async () => {
|
|
39
|
+
const resFork = await fork({ src, dna: true });
|
|
40
|
+
const resIsDna = isDna({ ibGib: resFork.newIbGib });
|
|
41
|
+
expect(resIsDna).toBeFalse();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
});
|
package/src/V1/types.mts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The core of the simplicity of the ibGib protocol is that you are
|
|
3
|
+
* taking two (or more) ibGibs and producing other ibGibs.
|
|
4
|
+
*
|
|
5
|
+
* There are three primary functions: mut8, rel8, fork
|
|
6
|
+
*
|
|
7
|
+
* These are actually different aspects of the single function of
|
|
8
|
+
* relationship and time, either:
|
|
9
|
+
* 1) Creating a 'new' timeline, or...
|
|
10
|
+
* 2) Extending an existing one.
|
|
11
|
+
*
|
|
12
|
+
* Mut8 is intrinsic, rel8 is extrinsic, fork is a new timeline.
|
|
13
|
+
* Mut8 changes a timeline, rel8 changes a timeline's link(s),
|
|
14
|
+
* fork creates a new timeline.
|
|
15
|
+
*/
|
|
16
|
+
import {
|
|
17
|
+
IbGibRel8ns, IbGibAddr, IbGibWithDataAndRel8ns, Gib,
|
|
18
|
+
} from '../types.mjs';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Need to see if I can remove this...
|
|
22
|
+
*/
|
|
23
|
+
export declare type IbGibData_V1 = {
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
isTjp?: boolean;
|
|
26
|
+
n?: number;
|
|
27
|
+
timestamp?: string;
|
|
28
|
+
uuid?: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Convenience enum to avoid spelling mistakes. (optional)
|
|
33
|
+
*/
|
|
34
|
+
export enum Rel8n {
|
|
35
|
+
past = 'past',
|
|
36
|
+
ancestor = 'ancestor',
|
|
37
|
+
dna = 'dna',
|
|
38
|
+
identity = 'identity',
|
|
39
|
+
tjp = 'tjp',
|
|
40
|
+
}
|
|
41
|
+
export interface IbGibRel8ns_V1 extends IbGibRel8ns {
|
|
42
|
+
[Rel8n.past]?: IbGibAddr[];
|
|
43
|
+
[Rel8n.identity]?: IbGibAddr[];
|
|
44
|
+
[Rel8n.ancestor]?: IbGibAddr[];
|
|
45
|
+
[Rel8n.dna]?: IbGibAddr[];
|
|
46
|
+
[Rel8n.tjp]?: IbGibAddr[];
|
|
47
|
+
}
|
|
48
|
+
export interface IbGib_V1<TData = IbGibData_V1, TRel8ns extends IbGibRel8ns_V1 = IbGibRel8ns_V1>
|
|
49
|
+
extends IbGibWithDataAndRel8ns<TData, TRel8ns> {
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface GibInfo {
|
|
53
|
+
/**
|
|
54
|
+
* Hash for this ibgib frame in time.
|
|
55
|
+
*/
|
|
56
|
+
punctiliarHash?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The gib for this ibgib's most recent tjp.
|
|
59
|
+
*
|
|
60
|
+
* ## notes
|
|
61
|
+
*
|
|
62
|
+
* ATOW, only one tjp expected really, though I've been coding
|
|
63
|
+
* with the possibility of having multiple tjp's similar to
|
|
64
|
+
* checkpoints.
|
|
65
|
+
*/
|
|
66
|
+
tjpGib?: Gib;
|
|
67
|
+
/**
|
|
68
|
+
* If
|
|
69
|
+
*/
|
|
70
|
+
piecesCount?: number;
|
|
71
|
+
/**
|
|
72
|
+
* If a delimiter is used in this gib, this is the delimiter.
|
|
73
|
+
*
|
|
74
|
+
* ## notes
|
|
75
|
+
*
|
|
76
|
+
* ATOW, the caller already knows the delimiter. But I'm thinking that
|
|
77
|
+
* I may be persisting this at some point and it would be good to include.
|
|
78
|
+
*/
|
|
79
|
+
delimiter?: string;
|
|
80
|
+
/**
|
|
81
|
+
* True the gib is just 'gib' (GIB constant), else falsy.
|
|
82
|
+
*/
|
|
83
|
+
isPrimitive?: boolean;
|
|
84
|
+
}
|
package/src/helper.mts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Ib, Gib, IbGib, IbGibAddr, IbAndGib } from './types.mjs';
|
|
2
|
+
let crypto: any = globalThis.crypto;
|
|
3
|
+
let { subtle } = crypto;
|
|
4
|
+
|
|
5
|
+
export type HashAlgorithm = 'SHA-256' | 'SHA-512';
|
|
6
|
+
export const HashAlgorithm: { [key: string]: HashAlgorithm } = {
|
|
7
|
+
'sha_256': 'SHA-256' as HashAlgorithm,
|
|
8
|
+
'sha_512': 'SHA-512' as HashAlgorithm,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function clone(obj: any) {
|
|
12
|
+
return JSON.parse(JSON.stringify(obj));
|
|
13
|
+
}
|
|
14
|
+
export function getTimestamp() {
|
|
15
|
+
return (new Date()).toUTCString();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Gets the ib^gib address from the given ib and gib or
|
|
19
|
+
* from the ibGib object.
|
|
20
|
+
*
|
|
21
|
+
* Need to refactor to getIbGibAddr
|
|
22
|
+
*/
|
|
23
|
+
export function getIbGibAddr({
|
|
24
|
+
ib, gib, ibGib, delimiter = '^'
|
|
25
|
+
}: {
|
|
26
|
+
ib?: Ib,
|
|
27
|
+
gib?: Gib,
|
|
28
|
+
ibGib?: IbGib,
|
|
29
|
+
delimiter?: string
|
|
30
|
+
}) {
|
|
31
|
+
ib = ib || ibGib?.ib || '';
|
|
32
|
+
gib = gib || ibGib?.gib || '';
|
|
33
|
+
return ib + delimiter + gib;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get the ib and gib fields from an ibGib object or ibGibAddr
|
|
38
|
+
* with the given `delimiter`.
|
|
39
|
+
*/
|
|
40
|
+
export function getIbAndGib({
|
|
41
|
+
ibGib,
|
|
42
|
+
ibGibAddr,
|
|
43
|
+
delimiter = '^'
|
|
44
|
+
}: {
|
|
45
|
+
ibGibAddr?: IbGibAddr,
|
|
46
|
+
ibGib?: IbGib,
|
|
47
|
+
delimiter?: string
|
|
48
|
+
}): IbAndGib {
|
|
49
|
+
const lc = '[getIbAndGib]';
|
|
50
|
+
if (!ibGibAddr) {
|
|
51
|
+
if (ibGib) {
|
|
52
|
+
ibGibAddr = getIbGibAddr({ ibGib });
|
|
53
|
+
} else {
|
|
54
|
+
throw new Error(`${lc} We need either an address or an ibGib object`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (!ibGibAddr) { throw new Error(`${lc} Couldn't get ibGibAddr. ibGib invalid?`); }
|
|
58
|
+
|
|
59
|
+
if (!delimiter) { delimiter = '^'; }
|
|
60
|
+
|
|
61
|
+
const pieces = ibGibAddr.split(delimiter);
|
|
62
|
+
if (pieces.length === 2) {
|
|
63
|
+
// normal v1 case, e.g. 'ib^gib' or 'tag home^ABC123'
|
|
64
|
+
return { ib: pieces[0], gib: pieces[1] };
|
|
65
|
+
} else if (pieces.length === 1 && ibGibAddr.endsWith(delimiter)) {
|
|
66
|
+
// normal v1 primitive, e.g. '7^' or 'name^'
|
|
67
|
+
return { ib: pieces[0], gib: '' };
|
|
68
|
+
} else if (pieces.length === 1 && ibGibAddr.startsWith(delimiter)) {
|
|
69
|
+
// only gib/hash is provided like maybe a binary file
|
|
70
|
+
// e.g. ^ABC123 or ^XYZ456 or ^some_gib_that_isnt_a_hash
|
|
71
|
+
return { ib: '', gib: pieces[0] };
|
|
72
|
+
} else if (pieces.length === 2 && pieces[0] === '' && pieces[1] === '') {
|
|
73
|
+
// edge case of address is only the delimiter.
|
|
74
|
+
// So it's the primitive for that delimiter
|
|
75
|
+
return { ib: delimiter, gib: '' };
|
|
76
|
+
// } else if (pieces.length === 0 ) {
|
|
77
|
+
// ibGibAddr is falsy, so would have thrown earlier in this function
|
|
78
|
+
// I'm just noting this case for intent ATOW
|
|
79
|
+
} else {
|
|
80
|
+
console.warn(`${lc} multiple delimiters found in ibGibAddr. Considering last delimiter as the demarcation of gib hash`);
|
|
81
|
+
// e.g. 'ib^ABC123^gib'
|
|
82
|
+
// ib: 'ib^ABC123'
|
|
83
|
+
// gib: 'gib'
|
|
84
|
+
return {
|
|
85
|
+
ib: pieces.slice(0, pieces.length - 1).join(delimiter),
|
|
86
|
+
gib: pieces.slice(pieces.length - 1)[0],
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Simple hash function.
|
|
93
|
+
*
|
|
94
|
+
* NOTE:
|
|
95
|
+
* This is not used for ibGib.gib values (ATOW)
|
|
96
|
+
* but rather as a helper function for generating random UUIDs.
|
|
97
|
+
*
|
|
98
|
+
* @param s string to hash
|
|
99
|
+
* @param algorithm to use, currently only 'SHA-256'
|
|
100
|
+
*/
|
|
101
|
+
export async function hash({
|
|
102
|
+
s,
|
|
103
|
+
algorithm = 'SHA-256',
|
|
104
|
+
}: {
|
|
105
|
+
s: string,
|
|
106
|
+
algorithm?: HashAlgorithm,
|
|
107
|
+
}): Promise<string> {
|
|
108
|
+
if (!s) { return ''; }
|
|
109
|
+
|
|
110
|
+
const validAlgorithms = Object.values(HashAlgorithm);
|
|
111
|
+
if (!validAlgorithms.includes(algorithm)) {
|
|
112
|
+
console.error(`Only ${validAlgorithms} implemented`); return '';
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
const msgUint8 = new TextEncoder().encode(s);
|
|
116
|
+
const buffer = await subtle.digest(algorithm, msgUint8);
|
|
117
|
+
const asArray = Array.from(new Uint8Array(buffer));
|
|
118
|
+
return asArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
119
|
+
} catch (e) {
|
|
120
|
+
console.error(extractErrorMsg(e.message));
|
|
121
|
+
return '';
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Simple func to generate UUID (sha-256 hash basically).
|
|
127
|
+
*
|
|
128
|
+
* @param seedSize size of seed for UUID generation
|
|
129
|
+
*/
|
|
130
|
+
export async function getUUID(seedSize = 64): Promise<string> {
|
|
131
|
+
let uuid: string = '';
|
|
132
|
+
if (seedSize < 32) { throw new Error(`Seed size must be at least 32`); }
|
|
133
|
+
if (!globalThis.crypto) { throw new Error(`Cannot create UUID, as unknown crypto library version. If using node.js, v19+ is required. (E: c02cee3fd8a94f678d3f4ebe9dc49797)`); }
|
|
134
|
+
|
|
135
|
+
const values = crypto.getRandomValues(new Uint8Array(16));
|
|
136
|
+
uuid = await hash({ s: values.join('') });
|
|
137
|
+
|
|
138
|
+
if (!uuid) { throw new Error(`Did not create UUID...hmm...`); }
|
|
139
|
+
|
|
140
|
+
return uuid;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Syntactic sugar for JSON.stringify(obj, null, 2);
|
|
145
|
+
*
|
|
146
|
+
* @param obj to pretty stringify
|
|
147
|
+
*/
|
|
148
|
+
export function pretty(obj: any): string {
|
|
149
|
+
return JSON.stringify(obj, null, 2);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Just delays given number of ms.
|
|
154
|
+
*
|
|
155
|
+
* @param ms milliseconds to delay
|
|
156
|
+
*/
|
|
157
|
+
export async function delay(ms: number): Promise<void> {
|
|
158
|
+
return new Promise<void>(resolve => {
|
|
159
|
+
setTimeout(() => {
|
|
160
|
+
resolve();
|
|
161
|
+
}, ms);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* extracts the error message from an error object/string/falsy arg.
|
|
167
|
+
*
|
|
168
|
+
* ## notes
|
|
169
|
+
*
|
|
170
|
+
* * some libs throw errors, some throw just strings.
|
|
171
|
+
* * who knows what else it could be.
|
|
172
|
+
*
|
|
173
|
+
* ## todo
|
|
174
|
+
*
|
|
175
|
+
* * extract inner errors/causes if we ever use this function extensively.
|
|
176
|
+
*
|
|
177
|
+
* @param error the error object in the catch area of the try..catch block.
|
|
178
|
+
* @returns error.message if it's a string, error itself if it's a string, or canned error messages if it's falsy or none of the above.
|
|
179
|
+
*/
|
|
180
|
+
export function extractErrorMsg(error: any): string {
|
|
181
|
+
if (!error && error !== 0) {
|
|
182
|
+
return '[error is falsy]';
|
|
183
|
+
} else if (typeof error === 'string') {
|
|
184
|
+
return error;
|
|
185
|
+
} else if (typeof error.message === 'string') {
|
|
186
|
+
return error.message;
|
|
187
|
+
} else if (typeof error === 'number') {
|
|
188
|
+
return JSON.stringify(error);
|
|
189
|
+
} else {
|
|
190
|
+
return `[error is not a string and error.message is not a string. typeof error: ${typeof error}]`;
|
|
191
|
+
}
|
|
192
|
+
}
|