@wovin/connect-nftstorage 0.0.1-RC15

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.
@@ -0,0 +1,69 @@
1
+ // src/retrieve.ts
2
+ import { CarReader } from "@ipld/car";
3
+ import { sortApplogsByTs } from "@wovin/core/applog";
4
+ import { decodeCarToApplogs } from "@wovin/core/ipfs";
5
+ import { ApplogStreamInMemory } from "@wovin/core/stream";
6
+ import { Logger } from "besonders-logger";
7
+ import { CID } from "multiformats/cid";
8
+ var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.DEBUG);
9
+ async function retrievePubStream(pubID, pinnedCID) {
10
+ let cid;
11
+ if (pinnedCID) {
12
+ cid = CID.parse(pinnedCID);
13
+ } else {
14
+ try {
15
+ cid = await resolveIPNS(
16
+ /* parseW3Name( */
17
+ pubID
18
+ /* ) */
19
+ );
20
+ DEBUG(`Resolved pub to CID`, cid.toString());
21
+ } catch (err) {
22
+ throw ERROR(`Failed to resolve IPNS ${pubID}:`, err);
23
+ }
24
+ }
25
+ const car = await retrieveCar(cid);
26
+ const { applogs: maybeEncrypted } = await decodeCarToApplogs(car);
27
+ const encrypted = maybeEncrypted.filter((log) => log instanceof Uint8Array);
28
+ if (encrypted.length)
29
+ WARN(`Found ${encrypted.length} encrypted logs - skipping`);
30
+ const applogs = maybeEncrypted.filter((log) => !(log instanceof Uint8Array));
31
+ sortApplogsByTs(applogs);
32
+ const dataStream = new ApplogStreamInMemory(applogs, [], `preview-${pubID}`, true);
33
+ return { cid, dataStream };
34
+ }
35
+ async function resolveIPNS(name) {
36
+ const response = await fetch(`https://name.web3.storage/name/${name}`);
37
+ const result = await response.json();
38
+ if (!result.value.startsWith("/ipfs/")) {
39
+ console.warn("IPNS value is not ipfs:", result);
40
+ }
41
+ return CID.parse(result.value.replace("/ipfs/", ""));
42
+ }
43
+ async function retrieveCar(cid) {
44
+ DEBUG("Retrieving:", cid);
45
+ const response = await fetch(`https://cloudflare-ipfs.com/ipfs/${cid}?format=car&dag-scope=all`);
46
+ if (!response?.ok || !response?.body) {
47
+ throw new Error(`unexpected response ${response?.statusText}`);
48
+ }
49
+ const data = streamToIterable(response.body.getReader());
50
+ return await CarReader.fromIterable(data);
51
+ }
52
+ function streamToIterable(bodyReader) {
53
+ return async function* () {
54
+ while (true) {
55
+ const { done, value } = await bodyReader.read();
56
+ if (done) {
57
+ break;
58
+ }
59
+ yield value;
60
+ }
61
+ }();
62
+ }
63
+
64
+ export {
65
+ retrievePubStream,
66
+ resolveIPNS,
67
+ retrieveCar
68
+ };
69
+ //# sourceMappingURL=chunk-BVBXK7QG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/retrieve.ts"],"sourcesContent":["import { CarReader } from '@ipld/car'\nimport { Applog, CidString, sortApplogsByTs } from '@wovin/core/applog'\nimport { decodeCarToApplogs } from '@wovin/core/ipfs'\nimport { ApplogStreamInMemory } from '@wovin/core/stream'\nimport { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats/cid'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.DEBUG) // eslint-disable-line no-unused-vars\n\nexport async function retrievePubStream(pubID: CidString, pinnedCID?: CidString) {\n\tlet cid: CID\n\tif (pinnedCID) {\n\t\tcid = CID.parse(pinnedCID)\n\t} else {\n\t\ttry {\n\t\t\tcid = await resolveIPNS(/* parseW3Name( */ pubID /* ) */)\n\t\t\tDEBUG(`Resolved pub to CID`, cid.toString())\n\t\t} catch (err) {\n\t\t\tthrow ERROR(`Failed to resolve IPNS ${pubID}:`, err)\n\t\t}\n\t}\n\tconst car = await retrieveCar(cid)\n\tconst { applogs: maybeEncrypted } = await decodeCarToApplogs(car)\n\tconst encrypted = maybeEncrypted.filter(log => log instanceof Uint8Array) as Uint8Array[]\n\tif (encrypted.length) WARN(`Found ${encrypted.length} encrypted logs - skipping`) // TODO: decryption\n\tconst applogs = maybeEncrypted.filter(log => !(log instanceof Uint8Array)) as Applog[]\n\tsortApplogsByTs(applogs)\n\tconst dataStream = new ApplogStreamInMemory(applogs, [], `preview-${pubID}`, true)\n\treturn { cid, dataStream }\n\t// return dataStream\n}\n\nexport async function resolveIPNS(name: CidString): Promise<CID> {\n\tconst response = await fetch(`https://name.web3.storage/name/${name}`)\n\tconst result = await response.json()\n\tif (!result.value.startsWith('/ipfs/')) {\n\t\tconsole.warn('IPNS value is not ipfs:', result)\n\t}\n\treturn CID.parse(result.value.replace('/ipfs/', ''))\n}\n\nexport async function retrieveCar(cid: CID): Promise<CarReader> {\n\tDEBUG('Retrieving:', cid)\n\t// const response = await fetch(`https://saturn.ms/ipfs/${cid}?format=car&dag-scope=all`)\n\tconst response = await fetch(`https://cloudflare-ipfs.com/ipfs/${cid}?format=car&dag-scope=all`) // HACK: workaround for https://github.com/web3-storage/freeway/issues/94\n\tif (!response?.ok || !response?.body) {\n\t\tthrow new Error(`unexpected response ${response?.statusText}`)\n\t}\n\n\t// The data is an AsyncIterable<Uint8Array>, convert it to an AsyncIterable for the CarReader\n\tconst data: AsyncIterable<Uint8Array> = streamToIterable(response!.body.getReader())\n\n\t// return a CarReader from the CAR data\n\treturn await CarReader.fromIterable(data)\n}\n\nfunction streamToIterable(bodyReader: any): AsyncIterable<Uint8Array> {\n\treturn (async function*() {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await bodyReader.read()\n\t\t\tif (done) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tyield value\n\t\t}\n\t})()\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAC1B,SAA4B,uBAAuB;AACnD,SAAS,0BAA0B;AACnC,SAAS,4BAA4B;AACrC,SAAS,cAAc;AACvB,SAAS,WAAW;AAEpB,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM,OAAO,KAAK;AAEtE,eAAsB,kBAAkB,OAAkB,WAAuB;AAChF,MAAI;AACJ,MAAI,WAAW;AACd,UAAM,IAAI,MAAM,SAAS;AAAA,EAC1B,OAAO;AACN,QAAI;AACH,YAAM,MAAM;AAAA;AAAA,QAA+B;AAAA;AAAA,MAAa;AACxD,YAAM,uBAAuB,IAAI,SAAS,CAAC;AAAA,IAC5C,SAAS,KAAK;AACb,YAAM,MAAM,0BAA0B,KAAK,KAAK,GAAG;AAAA,IACpD;AAAA,EACD;AACA,QAAM,MAAM,MAAM,YAAY,GAAG;AACjC,QAAM,EAAE,SAAS,eAAe,IAAI,MAAM,mBAAmB,GAAG;AAChE,QAAM,YAAY,eAAe,OAAO,SAAO,eAAe,UAAU;AACxE,MAAI,UAAU;AAAQ,SAAK,SAAS,UAAU,MAAM,4BAA4B;AAChF,QAAM,UAAU,eAAe,OAAO,SAAO,EAAE,eAAe,WAAW;AACzE,kBAAgB,OAAO;AACvB,QAAM,aAAa,IAAI,qBAAqB,SAAS,CAAC,GAAG,WAAW,KAAK,IAAI,IAAI;AACjF,SAAO,EAAE,KAAK,WAAW;AAE1B;AAEA,eAAsB,YAAY,MAA+B;AAChE,QAAM,WAAW,MAAM,MAAM,kCAAkC,IAAI,EAAE;AACrE,QAAM,SAAS,MAAM,SAAS,KAAK;AACnC,MAAI,CAAC,OAAO,MAAM,WAAW,QAAQ,GAAG;AACvC,YAAQ,KAAK,2BAA2B,MAAM;AAAA,EAC/C;AACA,SAAO,IAAI,MAAM,OAAO,MAAM,QAAQ,UAAU,EAAE,CAAC;AACpD;AAEA,eAAsB,YAAY,KAA8B;AAC/D,QAAM,eAAe,GAAG;AAExB,QAAM,WAAW,MAAM,MAAM,oCAAoC,GAAG,2BAA2B;AAC/F,MAAI,CAAC,UAAU,MAAM,CAAC,UAAU,MAAM;AACrC,UAAM,IAAI,MAAM,uBAAuB,UAAU,UAAU,EAAE;AAAA,EAC9D;AAGA,QAAM,OAAkC,iBAAiB,SAAU,KAAK,UAAU,CAAC;AAGnF,SAAO,MAAM,UAAU,aAAa,IAAI;AACzC;AAEA,SAAS,iBAAiB,YAA4C;AACrE,SAAQ,mBAAkB;AACzB,WAAO,MAAM;AACZ,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,WAAW,KAAK;AAC9C,UAAI,MAAM;AACT;AAAA,MACD;AACA,YAAM;AAAA,IACP;AAAA,EACD,EAAG;AACJ;","names":[]}
@@ -0,0 +1,68 @@
1
+ // src/store.ts
2
+ import { ucan } from "@oddjs/odd";
3
+ import * as ucans from "@ucans/ucans";
4
+ import { Logger } from "besonders-logger";
5
+ import { CID } from "multiformats";
6
+ var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.DEBUG);
7
+ async function storeCar(car, encodedUcan) {
8
+ const ucanInfo = await ucans.validate(encodedUcan);
9
+ const result = await (await fetch("https://api.nft.storage/upload", {
10
+ method: "POST",
11
+ headers: {
12
+ "Authorization": `Bearer ${encodedUcan}`,
13
+ "Content-Type": `application/car`,
14
+ "x-agent-did": ucanInfo.payload.iss
15
+ },
16
+ body: car
17
+ })).json();
18
+ LOG("[storeCar] result", result);
19
+ if (!result.ok)
20
+ throw new Error(`Failed to register DID ` + result.error);
21
+ return CID.parse(result.value.cid);
22
+ }
23
+ async function createRequestToken(keypair, serviceDID, ucanToken) {
24
+ DEBUG(`[createRequestToken] `, { keypair, ucanToken });
25
+ const payload = ucanToken.payload;
26
+ return ucans.build({
27
+ issuer: keypair,
28
+ audience: serviceDID,
29
+ capabilities: payload.att.map((att) => ucans.capability.parse(att)),
30
+ proofs: [ucan.encode(ucanToken)]
31
+ });
32
+ }
33
+ async function registerDid(apiKey, did2) {
34
+ DEBUG(`Registering`, { did: did2 });
35
+ const result = await (await fetch("https://api.nft.storage/user/did", {
36
+ method: "POST",
37
+ headers: {
38
+ "Authorization": `Bearer ${apiKey}`
39
+ },
40
+ body: JSON.stringify({
41
+ did: did2
42
+ })
43
+ })).json();
44
+ DEBUG(`Register DID result`, result);
45
+ if (!result.ok)
46
+ throw new Error(`Failed to register DID ` + result.error);
47
+ }
48
+ async function getRootUcan(apiKey) {
49
+ DEBUG(`Get root UCAN`, { apiKey });
50
+ const result = await (await fetch("https://api.nft.storage/ucan/token", {
51
+ method: "POST",
52
+ headers: {
53
+ "Authorization": `Bearer ${apiKey}`
54
+ }
55
+ })).json();
56
+ DEBUG(`Get root UCAN result`, result);
57
+ if (!result.ok)
58
+ throw new Error(`Failed get root UCAN ` + result.error);
59
+ return ucan.decode(result.value);
60
+ }
61
+
62
+ export {
63
+ storeCar,
64
+ createRequestToken,
65
+ registerDid,
66
+ getRootUcan
67
+ };
68
+ //# sourceMappingURL=chunk-IXVGCOBN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store.ts"],"sourcesContent":["import { Crypto, did, namespace, ucan } from '@oddjs/odd'\nimport * as ucans from '@ucans/ucans'\nimport { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.DEBUG) // eslint-disable-line no-unused-vars\n\nexport async function storeCar(car: Blob, encodedUcan: string /* ucan.Ucan */): Promise<CID> {\n\tconst ucanInfo = await ucans.validate(encodedUcan)\n\n\t// Docs: https://nft.storage/api-docs/#operations-NFT_Storage-upload\n\tconst result = await (await fetch('https://api.nft.storage/upload', {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Authorization': `Bearer ${encodedUcan}`,\n\t\t\t'Content-Type': `application/car`,\n\t\t\t'x-agent-did': ucanInfo.payload.iss,\n\t\t},\n\t\tbody: car,\n\t})).json()\n\tLOG('[storeCar] result', result)\n\tif (!result.ok) throw new Error(`Failed to register DID ` + result.error)\n\treturn CID.parse(result.value.cid)\n}\n\n// export async function createRequestToken(oddCrypto: Crypto.Implementation, serviceDID: string, ucanToken: ucans.Ucan) {\n// \t// export async function createRequestToken(ucan: string, issuerKeyPair: KeyPair, serviceDID: string) {\n// \tDEBUG(`[createRequestToken] `, { ucanToken, jwtAlg: await oddCrypto.keystore.getUcanAlgorithm() })\n\n// \tconst payload = ucanToken.payload\n\n// \tconst myDid = await getDid(oddCrypto)\n// \tconst didable = {\n// \t\tdid: () => myDid,\n// \t\tjwtAlg: 'EdDSA', // await oddCrypto.keystore.getUcanAlgorithm(),\n// \t\tsign: async (msg) => {\n// \t\t\tDEBUG(`Signing`, msg)\n// \t\t\tconst result = await oddCrypto.keystore.sign(msg)\n// \t\t\tDEBUG(`Signed`, result)\n// \t\t\treturn result\n// \t\t},\n// \t}\n// \treturn build({\n// \t\tissuer: didable,\n// \t\taudience: serviceDID,\n// \t\tcapabilities: payload.att,\n// \t\tproofs: [ucan],\n// \t})\n// }\nexport async function createRequestToken(\n\tkeypair: ucans.DidableKey,\n\t// oddCrypto: Crypto.Implementation,\n\tserviceDID: string,\n\tucanToken: ucan.Ucan,\n) {\n\tDEBUG(`[createRequestToken] `, { keypair, ucanToken })\n\t// we want to include the capabilities of the parent token in our request token\n\t// so we validate the parent token to extract the payload and copy over the capabilities\n\t// // the `att` field contains the capabilities we need for uploading\n\tconst payload = ucanToken.payload\n\t// const myDid = await getDid(oddCrypto)\n\t// DEBUG(`[createRequestToken]`, {myDid})\n\n\t// const didable = {\n\t// \tdid: () => myDid,\n\t// \tjwtAlg: 'EdDSA', // await oddCrypto.keystore.getUcanAlgorithm(),\n\t// \tsign: async (msg) => {\n\t// \t\tDEBUG(`Signing`, msg)\n\t// \t\tconst result = await oddCrypto.keystore.sign(msg)\n\t// \t\tDEBUG(`Signed`, result)\n\t// \t\treturn result\n\t// \t},\n\t// }\n\treturn ucans.build({\n\t\tissuer: keypair,\n\t\taudience: serviceDID,\n\t\tcapabilities: (payload as any).att.map(att => ucans.capability.parse(att)),\n\t\tproofs: [ucan.encode(ucanToken)],\n\t})\n}\nexport async function registerDid(apiKey: string, did: string) {\n\tDEBUG(`Registering`, { did })\n\tconst result = await (await fetch('https://api.nft.storage/user/did', {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Authorization': `Bearer ${apiKey}`,\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tdid,\n\t\t}),\n\t})).json()\n\tDEBUG(`Register DID result`, result)\n\tif (!result.ok) throw new Error(`Failed to register DID ` + result.error)\n}\nexport async function getRootUcan(apiKey: string) {\n\tDEBUG(`Get root UCAN`, { apiKey })\n\tconst result = await (await fetch('https://api.nft.storage/ucan/token', {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Authorization': `Bearer ${apiKey}`,\n\t\t},\n\t})).json()\n\tDEBUG(`Get root UCAN result`, result)\n\tif (!result.ok) throw new Error(`Failed get root UCAN ` + result.error)\n\treturn ucan.decode(result.value)\n}\n\n// import { build } from 'ucan-storage/ucan-storage'\n\n// // The DID for the storage service. In real code, you should obtain this from the service you're targetting.\n// const serviceDID = 'did:key:a-fake-service-did'\n\n// async function createRequestToken(parentUCAN, issuerKeyPair) {\n// \t// we want to include the capabilities of the parent token in our request token\n// \t// so we validate the parent token to extract the payload and copy over the capabilities\n// \tconst { payload } = await validate(parentUCAN)\n\n// \t// the `att` field contains the capabilities we need for uploading\n// \tconst { att } = payload\n\n// \treturn build({\n// \t\tissuer: issuerKeyPair,\n// \t\taudience: serviceDID,\n// \t\tcapabilities: att,\n// \t\tproofs: [parentUcan],\n// \t})\n// }\n"],"mappings":";AAAA,SAAiC,YAAY;AAC7C,YAAY,WAAW;AACvB,SAAS,cAAc;AACvB,SAAS,WAAW;AAEpB,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM,OAAO,KAAK;AAEtE,eAAsB,SAAS,KAAW,aAAmD;AAC5F,QAAM,WAAW,MAAY,eAAS,WAAW;AAGjD,QAAM,SAAS,OAAO,MAAM,MAAM,kCAAkC;AAAA,IACnE,QAAQ;AAAA,IACR,SAAS;AAAA,MACR,iBAAiB,UAAU,WAAW;AAAA,MACtC,gBAAgB;AAAA,MAChB,eAAe,SAAS,QAAQ;AAAA,IACjC;AAAA,IACA,MAAM;AAAA,EACP,CAAC,GAAG,KAAK;AACT,MAAI,qBAAqB,MAAM;AAC/B,MAAI,CAAC,OAAO;AAAI,UAAM,IAAI,MAAM,4BAA4B,OAAO,KAAK;AACxE,SAAO,IAAI,MAAM,OAAO,MAAM,GAAG;AAClC;AA0BA,eAAsB,mBACrB,SAEA,YACA,WACC;AACD,QAAM,yBAAyB,EAAE,SAAS,UAAU,CAAC;AAIrD,QAAM,UAAU,UAAU;AAc1B,SAAa,YAAM;AAAA,IAClB,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,cAAe,QAAgB,IAAI,IAAI,SAAa,iBAAW,MAAM,GAAG,CAAC;AAAA,IACzE,QAAQ,CAAC,KAAK,OAAO,SAAS,CAAC;AAAA,EAChC,CAAC;AACF;AACA,eAAsB,YAAY,QAAgBA,MAAa;AAC9D,QAAM,eAAe,EAAE,KAAAA,KAAI,CAAC;AAC5B,QAAM,SAAS,OAAO,MAAM,MAAM,oCAAoC;AAAA,IACrE,QAAQ;AAAA,IACR,SAAS;AAAA,MACR,iBAAiB,UAAU,MAAM;AAAA,IAClC;AAAA,IACA,MAAM,KAAK,UAAU;AAAA,MACpB,KAAAA;AAAA,IACD,CAAC;AAAA,EACF,CAAC,GAAG,KAAK;AACT,QAAM,uBAAuB,MAAM;AACnC,MAAI,CAAC,OAAO;AAAI,UAAM,IAAI,MAAM,4BAA4B,OAAO,KAAK;AACzE;AACA,eAAsB,YAAY,QAAgB;AACjD,QAAM,iBAAiB,EAAE,OAAO,CAAC;AACjC,QAAM,SAAS,OAAO,MAAM,MAAM,sCAAsC;AAAA,IACvE,QAAQ;AAAA,IACR,SAAS;AAAA,MACR,iBAAiB,UAAU,MAAM;AAAA,IAClC;AAAA,EACD,CAAC,GAAG,KAAK;AACT,QAAM,wBAAwB,MAAM;AACpC,MAAI,CAAC,OAAO;AAAI,UAAM,IAAI,MAAM,0BAA0B,OAAO,KAAK;AACtE,SAAO,KAAK,OAAO,OAAO,KAAK;AAChC;","names":["did"]}
@@ -0,0 +1,20 @@
1
+ import { Crypto, ucan } from '@oddjs/odd';
2
+ import * as ucans from '@ucans/ucans';
3
+ import { type StorageConnector } from '@wovin/core/pubsub';
4
+ import { CID } from 'multiformats';
5
+ export * from './retrieve';
6
+ export declare class NftStorageConnector implements StorageConnector {
7
+ private keypair;
8
+ serviceDID: string;
9
+ apiKey: string;
10
+ rootUcan: ucan.Ucan;
11
+ static init({ apiKey }: {
12
+ oddCrypto: Crypto.Implementation;
13
+ apiKey?: string;
14
+ rootUcan?: ucan.Ucan;
15
+ }): Promise<NftStorageConnector>;
16
+ constructor(keypair: ucans.DidableKey, serviceDID: string, apiKey: string, rootUcan: ucan.Ucan);
17
+ storeCar(car: Blob): Promise<CID<unknown, number, number, import("multiformats").Version>>;
18
+ retrieveCar(cid: CID): Promise<import("@ipld/car").CarReader>;
19
+ }
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAO,IAAI,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAOlC,cAAc,YAAY,CAAA;AAG1B,qBAAa,mBAAoB,YAAW,gBAAgB;IAoB1D,OAAO,CAAC,OAAO;IACR,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,IAAI,CAAC,IAAI;WAtBd,IAAI,CAAC,EAAE,MAAM,EACzB,EAAE;QACF,SAAS,EAAE,MAAM,CAAC,cAAc,CAAA;QAChC,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAA;KACpB;gBAcQ,OAAO,EAAE,KAAK,CAAC,UAAU,EAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,IAAI,CAAC,IAAI;IAGrB,QAAQ,CAAC,GAAG,EAAE,IAAI;IAiBlB,WAAW,CAAC,GAAG,EAAE,GAAG;CAG1B"}
package/dist/index.js ADDED
@@ -0,0 +1,66 @@
1
+ import {
2
+ resolveIPNS,
3
+ retrieveCar,
4
+ retrievePubStream
5
+ } from "./chunk-BVBXK7QG.js";
6
+ import {
7
+ createRequestToken,
8
+ getRootUcan,
9
+ registerDid,
10
+ storeCar
11
+ } from "./chunk-IXVGCOBN.js";
12
+
13
+ // src/index.ts
14
+ import * as ucans from "@ucans/ucans";
15
+ import { Logger } from "besonders-logger";
16
+ var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.DEBUG);
17
+ var NftStorageConnector = class _NftStorageConnector {
18
+ constructor(keypair, serviceDID, apiKey, rootUcan) {
19
+ this.keypair = keypair;
20
+ this.serviceDID = serviceDID;
21
+ this.apiKey = apiKey;
22
+ this.rootUcan = rootUcan;
23
+ }
24
+ static async init({
25
+ apiKey
26
+ /* rootUcan, oddCrypto*/
27
+ }) {
28
+ const { value: serviceDID } = await (await fetch("https://api.nft.storage/did")).json();
29
+ const keypair = await ucans.EdKeypair.create();
30
+ LOG(`Service DID:`, serviceDID);
31
+ return new _NftStorageConnector(
32
+ keypair,
33
+ serviceDID,
34
+ apiKey,
35
+ null
36
+ /* rootUcan */
37
+ );
38
+ }
39
+ async storeCar(car) {
40
+ for (let attempt = 0; attempt < 3; attempt++) {
41
+ try {
42
+ if (!this.rootUcan) {
43
+ await registerDid(this.apiKey, this.keypair.did());
44
+ this.rootUcan = await getRootUcan(this.apiKey);
45
+ }
46
+ const requestUcan = await createRequestToken(this.keypair, this.serviceDID, this.rootUcan);
47
+ return storeCar(car, ucans.encode(requestUcan));
48
+ } catch (err) {
49
+ if (err.message?.contains("ERROR_TOKEN_NOT_FOUND")) {
50
+ WARN(`Token not found (might be a race condition), retrying...`, err);
51
+ } else
52
+ throw err;
53
+ }
54
+ }
55
+ }
56
+ async retrieveCar(cid) {
57
+ return retrieveCar(cid);
58
+ }
59
+ };
60
+ export {
61
+ NftStorageConnector,
62
+ resolveIPNS,
63
+ retrieveCar,
64
+ retrievePubStream
65
+ };
66
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Crypto, did, ucan } from '@oddjs/odd'\nimport * as ucans from '@ucans/ucans'\nimport { CidString } from '@wovin/core'\nimport { type StorageConnector } from '@wovin/core/pubsub'\nimport { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats'\nimport { retrieveCar, retrievePubStream } from './retrieve'\nimport { createRequestToken, getRootUcan, registerDid, storeCar } from './store'\nimport { getDid } from './utils'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.DEBUG) // eslint-disable-line no-unused-vars\n\nexport * from './retrieve'\n// export * from './store'\n\nexport class NftStorageConnector implements StorageConnector {\n\tstatic async init({ apiKey /* rootUcan, oddCrypto*/\n\t}: {\n\t\toddCrypto: Crypto.Implementation\n\t\tapiKey?: string\n\t\trootUcan?: ucan.Ucan\n\t}) {\n\t\tconst { value: serviceDID } = await (await fetch('https://api.nft.storage/did')).json()\n\t\t// const myDid = await getDid(oddCrypto)\n\t\tconst keypair = await ucans.EdKeypair.create()\n\t\tLOG(`Service DID:`, serviceDID)\n\t\t// LOG(`My DID:`, myDid, keypair)\n\t\t// if (!rootUcan) {\n\t\t// await registerDid(apiKey, myDid)\n\t\t// rootUcan = await getRootUcan(apiKey)\n\t\t// }\n\t\treturn new NftStorageConnector(keypair, serviceDID, apiKey, null /* rootUcan */)\n\t}\n\tconstructor(\n\t\t// private oddCrypto: Crypto.Implementation,\n\t\tprivate keypair: ucans.DidableKey,\n\t\tpublic serviceDID: string,\n\t\tpublic apiKey: string,\n\t\tpublic rootUcan: ucan.Ucan,\n\t) {}\n\n\tasync storeCar(car: Blob) {\n\t\tfor (let attempt = 0; attempt < 3; attempt++) {\n\t\t\ttry {\n\t\t\t\tif (!this.rootUcan) {\n\t\t\t\t\tawait registerDid(this.apiKey, this.keypair.did())\n\t\t\t\t\tthis.rootUcan = await getRootUcan(this.apiKey)\n\t\t\t\t}\n\t\t\t\tconst requestUcan = await createRequestToken(this.keypair, this.serviceDID, this.rootUcan)\n\t\t\t\treturn storeCar(car, ucans.encode(requestUcan))\n\t\t\t} catch (err) {\n\t\t\t\tif ((err as any).message?.contains('ERROR_TOKEN_NOT_FOUND')) {\n\t\t\t\t\tWARN(`Token not found (might be a race condition), retrying...`, err)\n\t\t\t\t} else throw err\n\t\t\t}\n\t\t}\n\t}\n\n\tasync retrieveCar(cid: CID) {\n\t\treturn retrieveCar(cid)\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;AACA,YAAY,WAAW;AAGvB,SAAS,cAAc;AAMvB,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM,OAAO,KAAK;AAK/D,IAAM,sBAAN,MAAM,qBAAgD;AAAA,EAkB5D,YAES,SACD,YACA,QACA,UACN;AAJO;AACD;AACA;AACA;AAAA,EACL;AAAA,EAvBH,aAAa,KAAK;AAAA,IAAE;AAAA;AAAA,EACpB,GAIG;AACF,UAAM,EAAE,OAAO,WAAW,IAAI,OAAO,MAAM,MAAM,6BAA6B,GAAG,KAAK;AAEtF,UAAM,UAAU,MAAY,gBAAU,OAAO;AAC7C,QAAI,gBAAgB,UAAU;AAM9B,WAAO,IAAI;AAAA,MAAoB;AAAA,MAAS;AAAA,MAAY;AAAA,MAAQ;AAAA;AAAA,IAAmB;AAAA,EAChF;AAAA,EASA,MAAM,SAAS,KAAW;AACzB,aAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC7C,UAAI;AACH,YAAI,CAAC,KAAK,UAAU;AACnB,gBAAM,YAAY,KAAK,QAAQ,KAAK,QAAQ,IAAI,CAAC;AACjD,eAAK,WAAW,MAAM,YAAY,KAAK,MAAM;AAAA,QAC9C;AACA,cAAM,cAAc,MAAM,mBAAmB,KAAK,SAAS,KAAK,YAAY,KAAK,QAAQ;AACzF,eAAO,SAAS,KAAW,aAAO,WAAW,CAAC;AAAA,MAC/C,SAAS,KAAK;AACb,YAAK,IAAY,SAAS,SAAS,uBAAuB,GAAG;AAC5D,eAAK,4DAA4D,GAAG;AAAA,QACrE;AAAO,gBAAM;AAAA,MACd;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,YAAY,KAAU;AAC3B,WAAO,YAAY,GAAG;AAAA,EACvB;AACD;","names":[]}
@@ -0,0 +1,11 @@
1
+ import { CarReader } from '@ipld/car';
2
+ import { CidString } from '@wovin/core/applog';
3
+ import { ApplogStreamInMemory } from '@wovin/core/stream';
4
+ import { CID } from 'multiformats/cid';
5
+ export declare function retrievePubStream(pubID: CidString, pinnedCID?: CidString): Promise<{
6
+ cid: CID<unknown, number, number, import("multiformats/cid").Version>;
7
+ dataStream: ApplogStreamInMemory;
8
+ }>;
9
+ export declare function resolveIPNS(name: CidString): Promise<CID>;
10
+ export declare function retrieveCar(cid: CID): Promise<CarReader>;
11
+ //# sourceMappingURL=retrieve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve.d.ts","sourceRoot":"","sources":["../src/retrieve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAU,SAAS,EAAmB,MAAM,oBAAoB,CAAA;AAEvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAEzD,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAItC,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,SAAS;;;GAqB9E;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAO/D;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAa9D"}
@@ -0,0 +1,11 @@
1
+ import {
2
+ resolveIPNS,
3
+ retrieveCar,
4
+ retrievePubStream
5
+ } from "./chunk-BVBXK7QG.js";
6
+ export {
7
+ resolveIPNS,
8
+ retrieveCar,
9
+ retrievePubStream
10
+ };
11
+ //# sourceMappingURL=retrieve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,8 @@
1
+ import { ucan } from '@oddjs/odd';
2
+ import * as ucans from '@ucans/ucans';
3
+ import { CID } from 'multiformats';
4
+ export declare function storeCar(car: Blob, encodedUcan: string): Promise<CID>;
5
+ export declare function createRequestToken(keypair: ucans.DidableKey, serviceDID: string, ucanToken: ucan.Ucan): Promise<ucans.Ucan<string>>;
6
+ export declare function registerDid(apiKey: string, did: string): Promise<void>;
7
+ export declare function getRootUcan(apiKey: string): Promise<ucan.Ucan>;
8
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,IAAI,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAIlC,wBAAsB,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAmB,OAAO,CAAC,GAAG,CAAC,CAgB3F;AA0BD,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,KAAK,CAAC,UAAU,EAEzB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,IAAI,CAAC,IAAI,+BA0BpB;AACD,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,iBAa5D;AACD,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,sBAW/C"}
package/dist/store.js ADDED
@@ -0,0 +1,13 @@
1
+ import {
2
+ createRequestToken,
3
+ getRootUcan,
4
+ registerDid,
5
+ storeCar
6
+ } from "./chunk-IXVGCOBN.js";
7
+ export {
8
+ createRequestToken,
9
+ getRootUcan,
10
+ registerDid,
11
+ storeCar
12
+ };
13
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,3 @@
1
+ import { Crypto } from '@oddjs/odd';
2
+ export declare function getDid(crypto: Crypto.Implementation): Promise<string>;
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAO,MAAM,YAAY,CAAA;AAExC,wBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ3E"}
package/dist/utils.js ADDED
@@ -0,0 +1,14 @@
1
+ // src/utils.ts
2
+ import { did } from "@oddjs/odd";
3
+ async function getDid(crypto) {
4
+ const pubKey = await crypto.keystore.publicExchangeKey();
5
+ return did.publicKeyToDid(
6
+ crypto,
7
+ pubKey,
8
+ "ed25519"
9
+ );
10
+ }
11
+ export {
12
+ getDid
13
+ };
14
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import { Crypto, did } from '@oddjs/odd'\n\nexport async function getDid(crypto: Crypto.Implementation): Promise<string> {\n\tconst pubKey = await crypto.keystore.publicExchangeKey()\n\n\treturn did.publicKeyToDid(\n\t\tcrypto,\n\t\tpubKey,\n\t\t'ed25519',\n\t)\n}\n"],"mappings":";AAAA,SAAiB,WAAW;AAE5B,eAAsB,OAAO,QAAgD;AAC5E,QAAM,SAAS,MAAM,OAAO,SAAS,kBAAkB;AAEvD,SAAO,IAAI;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;","names":[]}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@wovin/connect-nftstorage",
3
+ "version": "0.0.1-RC15",
4
+ "type": "module",
5
+ "scripts": {
6
+ "build": "tsup && tsc --emitDeclarationOnly --declaration",
7
+ "watch": "npm run build --watch",
8
+ "lint": "eslint .",
9
+ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
10
+ "pub": "npm publish --tag latest --access=public"
11
+ },
12
+ "main": "dist/index.cjs",
13
+ "module": "dist/index.js",
14
+ "types": "dist/index.d.ts",
15
+ "exports": {
16
+ ".": "./dist/index.js",
17
+ "./retrieve": "./dist/retrieve.js",
18
+ "./utils": "./dist/utils.js",
19
+ "./store": "./dist/store.js"
20
+ },
21
+ "files": [
22
+ "dist/"
23
+ ],
24
+ "dependencies": {
25
+ "@ipld/car": "^5.2.4",
26
+ "@oddjs/odd": "^0.37.2",
27
+ "@ucans/ucans": "^0.12.0",
28
+ "@wovin/core": "0.0.1-RC15",
29
+ "besonders-logger": "1.0.0-RC11",
30
+ "multiformats": "^12.1.3",
31
+ "ucan-storage": "^1.3.0"
32
+ },
33
+ "devDependencies": {
34
+ "esbuild-plugin-polyfill-node": "^0.3.0",
35
+ "tsup": "^8.0.1",
36
+ "tsupconfig": "workspace:^",
37
+ "typescript": "^5.0.2"
38
+ }
39
+ }