@fireproof/core-gateways-base 0.22.0-keybag → 0.23.1-dev-issue-1057

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.
@@ -1,208 +0,0 @@
1
- import { exception2Result, Result, URI } from "@adviser/cement";
2
- import type {
3
- CarClockLink,
4
- DbMeta,
5
- DbMetaBinary,
6
- DbMetaEvent,
7
- FPDecoder,
8
- FPEncoder,
9
- LinkOrCid,
10
- SerializedMeta,
11
- SerializedWAL,
12
- WALState,
13
- } from "@fireproof/core-types-blockstore";
14
- import {
15
- FPEnvelope,
16
- FPEnvelopeCar,
17
- FPEnvelopeFile,
18
- FPEnvelopeMeta,
19
- FPEnvelopeType,
20
- FPEnvelopeTypes,
21
- FPEnvelopeWAL,
22
- } from "@fireproof/core-types-blockstore";
23
- import { PARAM, PromiseToUInt8, SuperThis } from "@fireproof/core-types-base";
24
- import { decodeEventBlock, EventBlock } from "@web3-storage/pail/clock";
25
- import { base64pad } from "multiformats/bases/base64";
26
- import { CID, Link } from "multiformats";
27
- import { fromJSON } from "multiformats/link";
28
- import { format, parse } from "@ipld/dag-json";
29
- import { EventView } from "@web3-storage/pail/clock/api";
30
- import { coercePromiseIntoUint8 } from "@fireproof/core-runtime";
31
-
32
- export async function dbMetaEvent2Serialized(
33
- sthis: SuperThis,
34
- dbEvents: Omit<DbMetaEvent, "eventCid">[],
35
- ): Promise<SerializedMeta[]> {
36
- return await Promise.all(
37
- dbEvents.map(async (dbEvent) => {
38
- const event = await EventBlock.create<DbMetaBinary>(
39
- {
40
- dbMeta: sthis.txt.encode(format(dbEvent.dbMeta)),
41
- },
42
- dbEvent.parents as unknown as Link<EventView<DbMetaBinary>, number, number, 1>[],
43
- );
44
- return {
45
- cid: event.cid.toString(),
46
- parents: dbEvent.parents.map((i) => i.toString()),
47
- data: base64pad.encode(event.bytes),
48
- } satisfies SerializedMeta;
49
- }),
50
- );
51
- }
52
-
53
- function WALState2Serialized(sthis: SuperThis, wal: WALState): SerializedWAL {
54
- const serializedWAL: SerializedWAL = {
55
- fileOperations: wal.fileOperations.map((fop) => ({
56
- cid: fop.cid.toString(),
57
- public: fop.public,
58
- })),
59
- noLoaderOps: wal.noLoaderOps.map((nop) => ({
60
- cars: nop.cars.map((i) => i.toString()),
61
- })),
62
- operations: wal.operations.map((op) => ({
63
- cars: op.cars.map((i) => i.toString()),
64
- })),
65
- };
66
- return serializedWAL;
67
- }
68
-
69
- const defaultEncoder: FPEncoder = {
70
- car: async (sthis: SuperThis, payload: Uint8Array) => Result.Ok(payload),
71
- file: async (sthis: SuperThis, payload: Uint8Array) => Result.Ok(payload),
72
- meta: async (sthis: SuperThis, payload: SerializedMeta[]) => Result.Ok(sthis.txt.encode(JSON.stringify(payload))),
73
- wal: async (sthis: SuperThis, payload: SerializedWAL) => Result.Ok(sthis.txt.encode(JSON.stringify(payload))),
74
- };
75
-
76
- export async function fpSerialize<T>(
77
- sthis: SuperThis,
78
- env: FPEnvelope<T>,
79
- pencoder?: Partial<FPEncoder>,
80
- ): Promise<Result<Uint8Array>> {
81
- const encoder = {
82
- ...defaultEncoder,
83
- ...pencoder,
84
- };
85
- switch (env.type) {
86
- case FPEnvelopeTypes.FILE:
87
- return encoder.file(sthis, (env as FPEnvelopeFile).payload);
88
- case FPEnvelopeTypes.CAR:
89
- return encoder.car(sthis, (env as FPEnvelopeCar).payload);
90
- case FPEnvelopeTypes.WAL:
91
- return encoder.wal(sthis, WALState2Serialized(sthis, (env as FPEnvelopeWAL).payload));
92
- case FPEnvelopeTypes.META:
93
- return encoder.meta(sthis, await dbMetaEvent2Serialized(sthis, (env as FPEnvelopeMeta).payload));
94
- default:
95
- throw sthis.logger.Error().Str("type", env.type).Msg("unsupported store").AsError();
96
- }
97
- }
98
-
99
- export async function decode2DbMetaEvents(
100
- sthis: SuperThis,
101
- rserializedMeta: Result<SerializedMeta[]>,
102
- ): Promise<Result<DbMetaEvent[]>> {
103
- if (rserializedMeta.isErr()) {
104
- return Result.Err(rserializedMeta.Err());
105
- }
106
- const serializedMeta = rserializedMeta.unwrap();
107
- if (!Array.isArray(serializedMeta)) {
108
- return sthis.logger.Debug().Any("metaEntries", serializedMeta).Msg("No data in MetaEntries").ResultError();
109
- }
110
- // if (!serializedMeta.length) {
111
- // return sthis.logger.Debug().Msg("No MetaEntries found").ResultError();
112
- // }
113
- return Result.Ok(
114
- await Promise.all(
115
- serializedMeta.map(async (metaEntry) => {
116
- const eventBlock = await decodeEventBlock<DbMetaBinary>(base64pad.decode(metaEntry.data));
117
- const dbMeta = parse<DbMeta>(sthis.txt.decode(eventBlock.value.data.dbMeta));
118
- return {
119
- eventCid: eventBlock.cid as CarClockLink,
120
- parents: metaEntry.parents.map((i: string) => CID.parse(i)),
121
- dbMeta,
122
- } satisfies DbMetaEvent;
123
- }),
124
- ),
125
- );
126
- }
127
-
128
- function toCid(sthis: SuperThis, link: LinkOrCid): CID {
129
- if (typeof link === "string") {
130
- return CID.parse(link);
131
- }
132
- return fromJSON(link);
133
- }
134
-
135
- async function decode2WalState(sthis: SuperThis, rserializedWAL: Result<SerializedWAL>): Promise<Result<WALState>> {
136
- if (rserializedWAL.isErr()) {
137
- return Result.Err(rserializedWAL.Err());
138
- }
139
- const serializedWAL = rserializedWAL.unwrap();
140
- return Result.Ok({
141
- fileOperations: (serializedWAL.fileOperations || []).map((fop) => ({
142
- cid: toCid(sthis, fop.cid),
143
- public: fop.public,
144
- })),
145
- noLoaderOps: (serializedWAL.noLoaderOps || []).map((nop) => ({
146
- cars: (nop.cars || []).map((i) => toCid(sthis, i)),
147
- })),
148
- operations: (serializedWAL.operations || []).map((op) => ({
149
- cars: (op.cars || []).map((i) => toCid(sthis, i)),
150
- })),
151
- });
152
- }
153
- // export type CARDecodeEnvelopeBase = (sthis: SuperThis, payload: Uint8Array) => Promise<Result<Uint8Array>>;
154
- // export type FILEDecodeEnvelopeBase = (sthis: SuperThis, payload: Uint8Array) => Promise<Result<Uint8Array>>;
155
- // export type WALDecodeEnvelopeBase = (sthis: SuperThis, payload: SerializedWAL) => Promise<Result<SerializedWAL>>;
156
- // export type METADecodeEnvelopeBase = (sthis: SuperThis, payload: SerializedMeta[]) => Promise<Result<SerializedMeta[]>>;
157
-
158
- const defaultDecoder = {
159
- car: async (sthis: SuperThis, payload: Uint8Array) => Result.Ok(payload),
160
- file: async (sthis: SuperThis, payload: Uint8Array) => Result.Ok(payload),
161
- meta: async (sthis: SuperThis, payload: Uint8Array) =>
162
- exception2Result(() => JSON.parse(sthis.txt.decode(payload)) as SerializedMeta[]),
163
- wal: async (sthis: SuperThis, payload: Uint8Array) =>
164
- exception2Result(() => JSON.parse(sthis.txt.decode(payload)) as SerializedWAL),
165
- };
166
-
167
- function makeFPEnvelope<S>(type: FPEnvelopeType, payload: Result<S>): Result<FPEnvelope<S>> {
168
- if (payload.isErr()) {
169
- return Result.Err(payload.Err());
170
- }
171
- return Result.Ok({
172
- type,
173
- payload: payload.unwrap(),
174
- });
175
- }
176
-
177
- export async function fpDeserialize<S>(
178
- sthis: SuperThis,
179
- url: URI,
180
- intoRaw: PromiseToUInt8,
181
- pdecoder?: Partial<FPDecoder>,
182
- ): Promise<Result<FPEnvelope<S>>> {
183
- const rraw = await coercePromiseIntoUint8(intoRaw);
184
- if (rraw.isErr()) {
185
- return Result.Err(rraw.Err());
186
- }
187
- const raw = rraw.unwrap();
188
- const decoder = {
189
- ...defaultDecoder,
190
- ...pdecoder,
191
- };
192
- switch (url.getParam(PARAM.STORE)) {
193
- case "car":
194
- return makeFPEnvelope(FPEnvelopeTypes.CAR, await decoder.car(sthis, raw)) as Result<FPEnvelope<S>>;
195
- case "file":
196
- return makeFPEnvelope(FPEnvelopeTypes.FILE, await decoder.file(sthis, raw)) as Result<FPEnvelope<S>>;
197
- case "wal":
198
- return makeFPEnvelope(FPEnvelopeTypes.WAL, await decode2WalState(sthis, await decoder.wal(sthis, raw))) as Result<
199
- FPEnvelope<S>
200
- >;
201
- case "meta":
202
- return makeFPEnvelope(FPEnvelopeTypes.META, await decode2DbMetaEvents(sthis, await decoder.meta(sthis, raw))) as Result<
203
- FPEnvelope<S>
204
- >;
205
- default:
206
- return sthis.logger.Error().Str("store", url.getParam(PARAM.STORE)).Msg("unsupported store").ResultError();
207
- }
208
- }
package/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export * from "./fp-envelope-serialize.js";
2
- export * from "./def-serde-gateway.js";
3
- export * from "./interceptor-gateway.js";
4
- export * from "./uri-interceptor.js";
5
- export * from "./utils.js";
6
- export * from "./indexeddb-version.js";
7
- export * from "./meta-key-hack.js";
@@ -1 +0,0 @@
1
- export const INDEXEDDB_VERSION = "v0.19-indexeddb";
@@ -1,174 +0,0 @@
1
- import { Result, URI } from "@adviser/cement";
2
- import type {
3
- FPEnvelope,
4
- FPEnvelopeMeta,
5
- SerdeGateway,
6
- SerdeGatewayBuildUrlReturn,
7
- SerdeGatewayCloseReturn,
8
- SerdeGatewayCtx,
9
- SerdeGatewayDeleteReturn,
10
- SerdeGatewayDestroyReturn,
11
- SerdeGatewayGetReturn,
12
- SerdeGatewayInterceptor,
13
- SerdeGatewayPutReturn,
14
- SerdeGatewayStartReturn,
15
- SerdeGatewaySubscribeReturn,
16
- SerdeGetResult,
17
- UnsubscribeResult,
18
- VoidResult,
19
- } from "@fireproof/core-types-blockstore";
20
- import type { SuperThis } from "@fireproof/core-types-base";
21
-
22
- export class PassThroughGateway implements SerdeGatewayInterceptor {
23
- async buildUrl(ctx: SerdeGatewayCtx, url: URI, key: string): Promise<Result<SerdeGatewayBuildUrlReturn>> {
24
- const op = { url, key };
25
- return Result.Ok({ op });
26
- }
27
- async start(ctx: SerdeGatewayCtx, url: URI): Promise<Result<SerdeGatewayStartReturn>> {
28
- const op = { url };
29
- return Result.Ok({ op });
30
- }
31
- async close(ctx: SerdeGatewayCtx, url: URI): Promise<Result<SerdeGatewayCloseReturn>> {
32
- const op = { url };
33
- return Result.Ok({ op });
34
- }
35
- async delete(ctx: SerdeGatewayCtx, url: URI): Promise<Result<SerdeGatewayDeleteReturn>> {
36
- const op = { url };
37
- return Result.Ok({ op });
38
- }
39
- async destroy(ctx: SerdeGatewayCtx, url: URI): Promise<Result<SerdeGatewayDestroyReturn>> {
40
- const op = { url };
41
- return Result.Ok({ op });
42
- }
43
- async put<T>(ctx: SerdeGatewayCtx, url: URI, body: FPEnvelope<T>): Promise<Result<SerdeGatewayPutReturn<T>>> {
44
- const op = { url, body };
45
- return Result.Ok({ op });
46
- }
47
- async get<S>(ctx: SerdeGatewayCtx, url: URI): Promise<Result<SerdeGatewayGetReturn<S>>> {
48
- const op = { url };
49
- return Result.Ok({ op });
50
- }
51
- async subscribe(
52
- ctx: SerdeGatewayCtx,
53
- url: URI,
54
- callback: (meta: FPEnvelopeMeta) => Promise<void>,
55
- ): Promise<Result<SerdeGatewaySubscribeReturn>> {
56
- const op = { url, callback };
57
- return Result.Ok({ op });
58
- }
59
- }
60
-
61
- const passThrougthGateway = new PassThroughGateway();
62
-
63
- export class InterceptorGateway implements SerdeGateway {
64
- readonly innerGW: SerdeGateway;
65
- readonly interceptor: SerdeGatewayInterceptor;
66
-
67
- constructor(sthis: SuperThis, innerGW: SerdeGateway, interceptor: SerdeGatewayInterceptor | undefined) {
68
- this.innerGW = innerGW;
69
- this.interceptor = interceptor || passThrougthGateway;
70
- }
71
-
72
- async buildUrl(ctx: SerdeGatewayCtx, baseUrl: URI, key: string): Promise<Result<URI>> {
73
- const rret = await this.interceptor.buildUrl(ctx, baseUrl, key);
74
- if (rret.isErr()) {
75
- return Result.Err(rret.Err());
76
- }
77
- const ret = rret.unwrap();
78
- if (ret.stop && ret.value) {
79
- return ret.value;
80
- }
81
- return this.innerGW.buildUrl(ctx, ret.op.url, ret.op.key);
82
- }
83
-
84
- async destroy(ctx: SerdeGatewayCtx, iurl: URI): Promise<Result<void>> {
85
- const rret = await this.interceptor.destroy(ctx, iurl);
86
- if (rret.isErr()) {
87
- return Result.Err(rret.Err());
88
- }
89
- const ret = rret.unwrap();
90
- if (ret.stop && ret.value) {
91
- return ret.value;
92
- }
93
- return this.innerGW.destroy(ctx, ret.op.url);
94
- }
95
-
96
- async start(ctx: SerdeGatewayCtx, url: URI): Promise<Result<URI>> {
97
- const rret = await this.interceptor.start(ctx, url);
98
- if (rret.isErr()) {
99
- return Result.Err(rret.Err());
100
- }
101
- const ret = rret.unwrap();
102
- if (ret.stop && ret.value) {
103
- return ret.value;
104
- }
105
- return await this.innerGW.start(ctx, ret.op.url);
106
- }
107
-
108
- async close(ctx: SerdeGatewayCtx, url: URI): Promise<VoidResult> {
109
- const rret = await this.interceptor.close(ctx, url);
110
- if (rret.isErr()) {
111
- return Result.Err(rret.Err());
112
- }
113
- const ret = rret.unwrap();
114
- if (ret.stop && ret.value) {
115
- return ret.value;
116
- }
117
- return await this.innerGW.close(ctx, ret.op.url);
118
- }
119
-
120
- async put<T>(ctx: SerdeGatewayCtx, url: URI, fpEnv: FPEnvelope<T>): Promise<VoidResult> {
121
- const rret = await this.interceptor.put(ctx, url, fpEnv);
122
- if (rret.isErr()) {
123
- return Result.Err(rret.Err());
124
- }
125
- const ret = rret.unwrap();
126
- if (ret.stop && ret.value) {
127
- return ret.value;
128
- }
129
- return this.innerGW.put(ctx, ret.op.url, ret.op.body);
130
- }
131
-
132
- async get<S>(ctx: SerdeGatewayCtx, url: URI): Promise<SerdeGetResult<S>> {
133
- const rret = await this.interceptor.get<S>(ctx, url);
134
- if (rret.isErr()) {
135
- return Result.Err(rret.Err());
136
- }
137
- const ret = rret.unwrap();
138
- if (ret.stop && ret.value) {
139
- return ret.value;
140
- }
141
- return this.innerGW.get(ctx, ret.op.url);
142
- }
143
-
144
- async subscribe(ctx: SerdeGatewayCtx, url: URI, callback: (msg: FPEnvelopeMeta) => Promise<void>): Promise<UnsubscribeResult> {
145
- if (!this.innerGW.subscribe) {
146
- return Result.Err(ctx.loader.sthis.logger.Error().Url(url).Msg("subscribe not supported").AsError());
147
- }
148
- const rret = await this.interceptor.subscribe(ctx, url, callback);
149
- if (rret.isErr()) {
150
- return Result.Err(rret.Err());
151
- }
152
- const ret = rret.unwrap();
153
- if (ret.stop && ret.value) {
154
- return ret.value;
155
- }
156
- return this.innerGW.subscribe(ctx, ret.op.url, ret.op.callback);
157
- }
158
-
159
- async delete(ctx: SerdeGatewayCtx, url: URI): Promise<VoidResult> {
160
- const rret = await this.interceptor.delete(ctx, url);
161
- if (rret.isErr()) {
162
- return Result.Err(rret.Err());
163
- }
164
- const ret = rret.unwrap();
165
- if (ret.stop && ret.value) {
166
- return ret.value;
167
- }
168
- return this.innerGW.delete(ctx, url);
169
- }
170
-
171
- async getPlain(ctx: SerdeGatewayCtx, url: URI, key: string): Promise<Result<Uint8Array>> {
172
- return this.innerGW.getPlain(ctx, url, key);
173
- }
174
- }
package/meta-key-hack.ts DELETED
@@ -1,260 +0,0 @@
1
- import { exception2Result, Result, URI } from "@adviser/cement";
2
- import {
3
- FPEnvelopeMeta,
4
- SerializedMeta,
5
- V2SerializedMetaKey,
6
- Gateway,
7
- Loadable,
8
- FPEnvelope,
9
- SerdeGateway,
10
- SerdeGatewayCtx,
11
- } from "@fireproof/core-types-blockstore";
12
-
13
- import { PARAM, SuperThis, NotFoundError } from "@fireproof/core-types-base";
14
- import { DefSerdeGateway } from "./def-serde-gateway.js";
15
-
16
- type V1SerializedMetaKey = SerializedMeta & {
17
- // old version
18
- readonly key?: string | string[];
19
- // new version
20
- readonly keys?: string[];
21
- };
22
-
23
- // type SerializedMetaWithKey = V1SerializedMetaKey[] | V2SerializedMetaKey;
24
-
25
- function fromV1toV2SerializedMetaKey(v1s: unknown[], keys: string[] = []): V2SerializedMetaKey {
26
- const res = (v1s as Partial<V1SerializedMetaKey>[]).reduce(
27
- (acc, v1) => {
28
- const keys: string[] = [];
29
- if (v1.key) {
30
- if (typeof v1.key === "string") {
31
- acc.keys.add(v1.key);
32
- } else {
33
- keys.push(...v1.key);
34
- }
35
- }
36
- if (v1.keys) {
37
- keys.push(...v1.keys);
38
- }
39
- for (const key of keys) {
40
- acc.keys.add(key);
41
- }
42
- if (typeof v1.cid === "string" && (!v1.data || typeof v1.data === "string") && (!v1.parents || Array.isArray(v1.parents))) {
43
- acc.metas.set(v1.cid, {
44
- data: v1.data ?? "",
45
- parents: v1.parents ?? [],
46
- cid: v1.cid,
47
- });
48
- }
49
- return acc;
50
- },
51
- {
52
- metas: new Map<string, SerializedMeta>(),
53
- keys: new Set<string>(keys),
54
- },
55
- );
56
- return {
57
- metas: Array.from(res.metas.values()),
58
- keys: Array.from(res.keys),
59
- };
60
- }
61
-
62
- function isV2SerializedMetaKey(or: NonNullable<unknown>): or is Partial<V2SerializedMetaKey> {
63
- const my = or as Partial<V2SerializedMetaKey>;
64
- return my !== null && (!my.keys || Array.isArray(my.keys)) && (!my.metas || Array.isArray(my.metas));
65
- }
66
-
67
- function toV2SerializedMetaKey(or: NonNullable<unknown>): V2SerializedMetaKey {
68
- if (Array.isArray(or)) {
69
- return fromV1toV2SerializedMetaKey(or);
70
- }
71
- if (isV2SerializedMetaKey(or)) {
72
- return fromV1toV2SerializedMetaKey(or.metas ?? [], or.keys ?? []);
73
- }
74
- throw new Error("not a valid serialized meta key");
75
- }
76
-
77
- export async function V2SerializedMetaKeyExtractKey(
78
- ctx: SerdeGatewayCtx,
79
- v2: V2SerializedMetaKey,
80
- ): Promise<Result<SerializedMeta[]>> {
81
- const kb = await ctx.loader.keyBag();
82
- if (!kb) {
83
- return Promise.resolve(Result.Err(new Error("missing keybag")));
84
- }
85
- const dataUrl = await ctx.loader.attachedStores.local().active.car.url();
86
- const keyName = dataUrl.getParam(PARAM.STORE_KEY);
87
- if (!keyName) {
88
- ctx.loader.sthis.logger.Warn().Url(dataUrl).Msg("missing store key");
89
- } else {
90
- const rKey = await kb.getNamedKey(keyName);
91
- if (rKey.isErr()) {
92
- ctx.loader.sthis.logger.Warn().Str("keyName", keyName).Msg("did not found a extractable key");
93
- } else {
94
- for (const keyStr of v2.keys) {
95
- // side effect: in the keybag
96
- // this is the key gossip protocol
97
- // it basically collects all the keys that are used distributed metas
98
- const res = await rKey.Ok().upsert(keyStr, false);
99
- if (res.isErr()) {
100
- ctx.loader.sthis.logger.Warn().Str("keyStr", keyStr).Msg("failed to upsert key");
101
- }
102
- }
103
- }
104
- }
105
- return Promise.resolve(Result.Ok(v2.metas));
106
- }
107
-
108
- export async function decodeAsToSerializedMeta(ctx: SerdeGatewayCtx, raw: Uint8Array): Promise<Result<V2SerializedMetaKey>> {
109
- const rJsObj = exception2Result(() => JSON.parse(ctx.loader.sthis.txt.decode(raw))) as Result<NonNullable<unknown>>;
110
- if (rJsObj.isErr()) {
111
- return Result.Err(rJsObj);
112
- }
113
- const v2 = toV2SerializedMetaKey(rJsObj.unwrap());
114
- const metas = await V2SerializedMetaKeyExtractKey(ctx, v2);
115
- if (metas.isErr()) {
116
- return Result.Err(metas);
117
- }
118
- return Result.Ok({
119
- metas: metas.Ok(),
120
- keys: v2.keys,
121
- });
122
- }
123
-
124
- export function addKeyToDbMetaDecoder(
125
- ctx: SerdeGatewayCtx & { readonly lastDecodedMetas?: V2SerializedMetaKey[] },
126
- ): SerdeGatewayCtx & { lastDecodedMetas: V2SerializedMetaKey[] } {
127
- const lastDecodedMetas: V2SerializedMetaKey[] = ctx.lastDecodedMetas ?? [];
128
- return {
129
- ...ctx,
130
- lastDecodedMetas,
131
- decoder: {
132
- meta: async (sthis: SuperThis, raw: Uint8Array): Promise<Result<SerializedMeta[]>> => {
133
- const r = await decodeAsToSerializedMeta(ctx, raw);
134
- if (r.isErr()) {
135
- return Promise.resolve(Result.Err(r));
136
- }
137
- // we only want to keep the last 2 metas
138
- if (lastDecodedMetas.length > 2) {
139
- lastDecodedMetas.shift();
140
- }
141
- lastDecodedMetas.push(r.Ok());
142
- return Promise.resolve(Result.Ok(r.Ok().metas));
143
- },
144
- },
145
- };
146
- }
147
-
148
- async function wrapEncode<T extends V1SerializedMetaKey[] | V2SerializedMetaKey>(
149
- ctx: SerdeGatewayCtx,
150
- payload: SerializedMeta[],
151
- fn: (payload: SerializedMeta[], keyM: string[]) => T,
152
- ): Promise<Result<T>> {
153
- const carStore = ctx.loader.attachedStores.local().active.car;
154
- const kb = await ctx.loader.keyBag();
155
- if (!kb) {
156
- return Promise.resolve(Result.Err(new Error("missing keybag")));
157
- }
158
- const keyName = carStore.url().getParam(PARAM.STORE_KEY) ?? "";
159
- const rKex = await kb.getNamedKey(keyName);
160
- if (rKex.isErr()) {
161
- return Promise.resolve(Result.Err(rKex.Err()));
162
- }
163
- /* security: we don't want to log the key */
164
- const keyMaterials = await rKex
165
- .Ok()
166
- .asV2KeysItem()
167
- .then((i) => Object.values(i.keys).map((i) => i.key));
168
-
169
- return Promise.resolve(Result.Ok(fn(payload, keyMaterials)));
170
- }
171
-
172
- export function encodeAsV1SerializedMetaKey(
173
- ctx: SerdeGatewayCtx,
174
- payload: SerializedMeta[],
175
- ): Promise<Result<V1SerializedMetaKey[]>> {
176
- return wrapEncode(ctx, payload, (payload, keyM) => payload.map((p) => ({ ...p, key: keyM }) satisfies V1SerializedMetaKey));
177
- }
178
-
179
- export function encodeAsV2SerializedMetaKey(ctx: SerdeGatewayCtx, payload: SerializedMeta[]): Promise<Result<V2SerializedMetaKey>> {
180
- return wrapEncode(
181
- ctx,
182
- payload,
183
- (payload, keyM) =>
184
- ({
185
- metas: payload,
186
- keys: keyM,
187
- }) satisfies V2SerializedMetaKey,
188
- );
189
- }
190
-
191
- export function addKeyToDbMetaEncoder(ctx: SerdeGatewayCtx, version: "v1" | "v2"): SerdeGatewayCtx {
192
- return {
193
- ...ctx,
194
- encoder: {
195
- meta: async (sthis: SuperThis, payload: SerializedMeta[]): Promise<Result<Uint8Array>> => {
196
- let obj: Result<V1SerializedMetaKey[] | V2SerializedMetaKey>;
197
- switch (version) {
198
- case "v1":
199
- obj = await encodeAsV1SerializedMetaKey(ctx, payload);
200
- break;
201
- case "v2":
202
- obj = await encodeAsV2SerializedMetaKey(ctx, payload);
203
- break;
204
- default:
205
- return Promise.resolve(Result.Err(`unknown version:[${version}]`));
206
- }
207
- if (obj.isErr()) {
208
- return Promise.resolve(Result.Err(obj));
209
- }
210
- try {
211
- return Promise.resolve(Result.Ok(sthis.txt.encode(JSON.stringify(obj.Ok()))));
212
- } catch (e) {
213
- return Promise.resolve(Result.Err(e as Error));
214
- }
215
- },
216
- },
217
- };
218
- }
219
-
220
- export class AddKeyToDbMetaGateway implements SerdeGateway {
221
- private readonly sdGw: DefSerdeGateway;
222
- readonly version: "v1" | "v2";
223
- constructor(gw: Gateway, version: "v1" | "v2") {
224
- this.sdGw = new DefSerdeGateway(gw);
225
- this.version = version;
226
- }
227
-
228
- buildUrl(ctx: SerdeGatewayCtx, baseUrl: URI, key: string): Promise<Result<URI>> {
229
- return this.sdGw.buildUrl(ctx, baseUrl, key);
230
- }
231
- start(ctx: SerdeGatewayCtx, baseUrl: URI): Promise<Result<URI>> {
232
- return this.sdGw.start(ctx, baseUrl);
233
- }
234
- close(ctx: SerdeGatewayCtx, baseUrl: URI): Promise<Result<void, Error>> {
235
- return this.sdGw.close(ctx, baseUrl);
236
- }
237
- async put<T>(ctx: SerdeGatewayCtx, url: URI, body: FPEnvelope<T>): Promise<Result<void, Error>> {
238
- return this.sdGw.put(addKeyToDbMetaEncoder(ctx, this.version), url, body);
239
- }
240
- async get<S>(ctx: SerdeGatewayCtx, url: URI): Promise<Result<FPEnvelope<S>, Error | NotFoundError>> {
241
- return this.sdGw.get(addKeyToDbMetaDecoder({ ...ctx, lastDecodedMetas: this.lastDecodedMetas }), url);
242
- }
243
-
244
- // only for tests
245
- readonly lastDecodedMetas: V2SerializedMetaKey[] = [];
246
-
247
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
248
- delete(ctx: SerdeGatewayCtx, url: URI, loader?: Loadable): Promise<Result<void, Error>> {
249
- return this.sdGw.delete(ctx, url);
250
- }
251
- subscribe(ctx: SerdeGatewayCtx, url: URI, callback: (meta: FPEnvelopeMeta) => Promise<void>): Promise<Result<() => void, Error>> {
252
- return this.sdGw.subscribe(addKeyToDbMetaDecoder({ ...ctx, lastDecodedMetas: this.lastDecodedMetas }), url, callback);
253
- }
254
- getPlain(ctx: SerdeGatewayCtx, url: URI, key: string): Promise<Result<Uint8Array>> {
255
- return this.sdGw.getPlain(ctx, url, key);
256
- }
257
- destroy(ctx: SerdeGatewayCtx, baseUrl: URI): Promise<Result<void, Error>> {
258
- return this.sdGw.destroy(ctx, baseUrl);
259
- }
260
- }
package/tsconfig.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "extends": [
3
- "/home/runner/work/fireproof/fireproof/tsconfig.dist.json"
4
- ],
5
- "compilerOptions": {
6
- "noEmit": false,
7
- "outDir": "./"
8
- },
9
- "include": [
10
- "**/*"
11
- ],
12
- "exclude": [
13
- "node_modules",
14
- "dist",
15
- ".git",
16
- ".vscode"
17
- ]
18
- }