🌳
pt0/deployF/servicesF/ipfsF/ipfsActionsF.mts
1import * as _ from 'lodash-es'
8const isIpAddress = (s: string) => /^\d{1,3}(\.\d{1,3}){3}$/.test(s)
10const buildAnnounceAddrs = ({externalIp, nodePort}: {externalIp: string, nodePort: number}) => {
11 const proto = isIpAddress(externalIp) ? 'ip4' : 'dns4'
12 return [
13 `/${proto}/${externalIp}/tcp/${nodePort}`,
14 `/${proto}/${externalIp}/udp/${nodePort}/quic`,
15 `/${proto}/${externalIp}/udp/${nodePort}/quic-v1`,
16 ]
19const kuboApiCall = async (apiUrl: string, apiPath: string) => {
20 const url = apiUrl + apiPath
21 const resp = await fetch(url, {method: 'POST'})
22 return resp.json()
25export const ensureAnnounceAddrs = async ({apiUrl, peerConfig}: {apiUrl: string, peerConfig: {externalIp: string, nodePort?: number}}) => {
26 const {externalIp, nodePort = 30202} = peerConfig
27 const targetAddrs = buildAnnounceAddrs({externalIp, nodePort})
29 const currentCfg = await kuboApiCall(apiUrl, '/api/v0/config?arg=Addresses.Announce')
30 const currentAddrs = currentCfg.Value || []
32 if (_.isEqual(_.sortBy(currentAddrs), _.sortBy(targetAddrs))) {
33 console.log('Announce addresses already configured')
34 return
35 }
37 console.log('Setting announce addresses:', targetAddrs)
38 await kuboApiCall(apiUrl, `/api/v0/config?arg=Addresses.Announce&arg=${encodeURIComponent(JSON.stringify(targetAddrs))}&json=true`)
39 console.log('Announce addresses updated')
42export const ensurePeeringConfig = async ({apiUrl}: {apiUrl: string}) => {
43 const targetPeers = await getOtherPeersForApiUrl(apiUrl)
44 if (targetPeers.length === 0) { console.log('No peers to configure'); return }
46 for (const peer of targetPeers) {
47 const multiaddr = `${peer.Addrs[0]}/p2p/${peer.ID}`
48 const connectResp = await kuboApiCall(apiUrl, `/api/v0/swarm/connect?arg=${encodeURIComponent(multiaddr)}`)
49 if (connectResp.Strings?.[0]?.includes('success')) {
50 await kuboApiCall(apiUrl, `/api/v0/swarm/peering/add?arg=${encodeURIComponent(multiaddr)}`)
51 console.log('Peering added:', peer.ID.slice(-8))
52 } else {
53 betLog(chalkYellow('âš  peerConnectFail'), {peer: peer.ID.slice(-8), multiaddr, connectResp})
54 }
55 }
58export const handleIpfsAction = async ({action, apiUrl, gatewayUrl, peerConfig, inputPath}: {action: string, apiUrl: string, gatewayUrl: string, peerConfig?: {externalIp?: string, nodePort?: number, peerAddrs?: string[]}, inputPath?: string}) => {
59 const {externalIp, nodePort = 30202, peerAddrs = []} = peerConfig || {}
61 const kuboApi = async (apiPath: string, optsH?: Record<string, unknown>) => {
62 const url = apiUrl + apiPath
63 optsH = {method: 'POST', ...optsH}
64 const resp = await fetch(url, optsH)
65 const respJson = await resp.json()
66 betLog('kuboApi', {url, optsH, respJson})
67 return respJson
68 }
70 const actions = {
71 testapiconn: () => testApiConn({apiUrl, gatewayUrl}),
72 getnode: () => getNodeInfo(apiUrl),
73 setcfg: async () => {
74 await kuboApi(`/api/v0/config?arg=Swarm.Transports.Network.QUIC&arg=true&bool=true`)
75 },
76 getcfg: async () => {
77 await kuboApi(`/api/v0/config/show`)
78 },
79 setannounce: async () => {
80 const announceAddrs = buildAnnounceAddrs({externalIp: externalIp!, nodePort})
81 const resp = await kuboApi(`/api/v0/config?arg=Addresses.Announce&arg=${encodeURIComponent(JSON.stringify(announceAddrs))}&json=true`)
82 betLog('setAnnounce', {announceAddrs, resp})
83 },
84 connpeers: async () => {
85 await Promise.all(peerAddrs.flatMap(addr => [
86 kuboApi(`/api/v0/swarm/connect?arg=${encodeURIComponent(addr)}`),
87 ]))
88 },
89 setpeers: async () => {
90 const peerId = peerAddrs[0]?.split('/p2p/')[1]
91 const cleanAddrs = _.map(peerAddrs, addr => addr.split('/p2p/')[0])
92 const peers = [{ID: peerId, Addrs: cleanAddrs}]
93 const encodedValue = encodeURIComponent(JSON.stringify(peers))
95 await kuboApi(`/api/v0/config?arg=Peering.Peers&arg=${encodedValue}&json=true`)
96 },
97 restart: () => kuboApi('/api/v0/shutdown'),
98 getpeers: async () => {
99 await kuboApi(`/api/v0/swarm/peers`)
100 },
101 setpin: () => setPinFromIpns(apiUrl),
102 upload: () => ipfsUpload({apiUrl, gatewayUrl, inputPath: inputPath!})
103 }
105 const actionFn = actions[action as keyof typeof actions]
106 if (actionFn) {
107 await actionFn()
108 return true
109 }
110 return false