Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: build native ESM #98

Merged
merged 14 commits into from
Oct 21, 2022
25 changes: 25 additions & 0 deletions .aegir.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export default {
tsRepo: false,
build: {
config: {
format: 'esm',
banner: {
js: ''
},
footer: {
js: ''
}
}
Comment on lines +3 to +12
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed because: ipfs/aegir#1096

},
test: {
before: (...args) => {
if (args[0].runner === 'node') {
return {
env: {
NODE_OPTIONS: '--loader=esmock'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}
}
}
}
}
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
root=true

[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for sanity

33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,44 @@ npm install --save ipfs-geoip

Instead of a local installation (and browserification) you may request a [remote copy from jsDelivr](https://www.jsdelivr.com/package/npm/ipfs-geoip):

**<v9**
```html
<!-- loading the minified version using jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/ipfs-geoip/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/ipfs-geoip@8.0.0/dist/index.min.js"></script>
```

When using prebuilt bundle from CDN, `ipfs-geoip` will be exposed under `window.IpfsGeoip`

**>=v9**

```html
<!-- ipfs-http-client at the time of writing does not distribute esm -->
<script src="https://cdn.jsdelivr.net/npm/ipfs-http-client@58.0.1/dist/index.min.js"></script>
<!-- the script type is module -->
<script type="module">
import { lookup } from 'https://cdn.jsdelivr.net/npm/ipfs-geoip@9.0.0/dist/index.min.js';
const client = window.IpfsHttpClient.create({
host: 'ipfs.io',
port: 443,
protocol: 'https'
});
console.log(await lookup(client, '66.6.44.4'))
</script>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once this releases as v9.0.0 module, we can use this, validated locally.

```

The response in the console looks like:
```js
{
"country_name": "USA",
"country_code": "US",
"region_code": "VA",
"city": "Ashburn",
"postal_code": "20149",
"latitude": 39.0469,
"longitude": -77.4903,
"planet": "Earth"
}
```

## Usage

Expand Down
1 change: 0 additions & 1 deletion example/lookup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as geoip from '../src/index.js'
import { create } from 'ipfs-http-client'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer used.


const ipfsGw = process?.env?.IPFS_GATEWAY || 'https://ipfs.io'

Expand Down
37 changes: 37 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 4 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dist"
],
"type": "module",
"main": "src/index.js",
"main": "dist/index.min.js",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now packages can map to the esm directly.

"repository": {
"type": "git",
"url": "https://github.com/ipfs-shipyard/ipfs-geoip"
Expand All @@ -26,9 +26,9 @@
"lint": "aegir lint",
"release": "aegir release",
"build": "aegir build",
"test": "aegir test",
"test": "npm run test:node && npm run test:browser",
"test:node": "aegir test --target node",
"test:browser": "aegir test --target browser",
"test:browser": "aegir test --target browser --files test/**/*.browser.spec.{js,cjs,mjs}",
Comment on lines +29 to +31
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to happen because of: ipfs/aegir#1097 Also, the test files had to be renamed because of this.

"generate": "node bin/generate.js"
},
"dependencies": {
Expand All @@ -47,6 +47,7 @@
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"csv-parse": "^5.3.0",
"esmock": "^2.0.6",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is needed to rewire dependencies to validate behavior.

"gauge": "^4.0.4",
"ipfs-http-client": "^58.0.1",
"multihashes": "^4.0.3",
Expand All @@ -64,9 +65,6 @@
"node": ">=16.0.0",
"npm": ">=8.0.0"
},
"aegir": {
"tsRepo": false
},
"pre-commit": [
"lint"
],
Expand Down
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MAX_LOOKUP_RETRIES = 3
27 changes: 24 additions & 3 deletions src/lookup.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { default as memoize } from 'p-memoize'
import ip from 'ip'
import * as dagCbor from '@ipld/dag-cbor'
import { decode as dagCborDecode } from '@ipld/dag-cbor'
import { CID } from 'multiformats/cid'
import fetch from 'cross-fetch'
import { formatData } from './format.js'
import { MAX_LOOKUP_RETRIES } from './constants.js'

export const GEOIP_ROOT = CID.parse('bafyreihnpl7ami7esahkfdnemm6idx4r2n6u3apmtcrxlqwuapgjsciihy') // b-tree version of GeoLite2-City-CSV_20221018

Expand Down Expand Up @@ -45,6 +46,27 @@ async function getRawBlock (ipfs, cid) {
}
}

/**
* Gets Obj and Block after retrying multiple times.
*
* @param {object|string} ipfs
* @param {CID} cid
* @param {number} numTry - this will be 1 for the first try and recurse till MAX_LOOKUP_RETRIES is reached.
* @returns {Promise<{obj, block}>}
*/
async function getObjAndBlockWithRetries (ipfs, cid, numTry = 1) {
try {
const block = await getRawBlock(ipfs, cid)
const obj = await dagCborDecode(block)
return { obj, block }
} catch (e) {
if (numTry < MAX_LOOKUP_RETRIES) {
return await getObjAndBlockWithRetries(ipfs, cid, numTry + 1)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we fail, we retry till the const value is reached.

}
throw e
}
}

/**
* @param {object|string} ipfs
* @param {CID} cid
Expand All @@ -54,8 +76,7 @@ async function getRawBlock (ipfs, cid) {
async function _lookup (ipfs, cid, lookfor) {
let obj, block
try {
block = await getRawBlock(ipfs, cid)
obj = await dagCbor.decode(block)
({ obj, block } = await getObjAndBlockWithRetries(ipfs, cid))
} catch (e) {
if (process?.env?.DEBUG || process?.env?.TEST) {
if (!block) {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
37 changes: 37 additions & 0 deletions test/lookupMultiple.node.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { decode as dagCborDecode } from '@ipld/dag-cbor'
import esmock from 'esmock'
import { expect } from 'chai'

describe('[Runner Node]: lookup via HTTP Gateway supporting application/vnd.ipld.raw responses', function () {
const ipfsGW = process?.env?.IPFS_GATEWAY || 'https://ipfs.io'

it('looks up multiple times before failing', async () => {
let decodeCallCount = 0
const rewiredGeoIp = await esmock('../src/index.js', {}, {
'@ipld/dag-cbor': {
decode: (...args) => {
decodeCallCount += 1
if (decodeCallCount === 1) {
throw new Error('Decode Failed')
Comment on lines +14 to +15
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fail the decoding on the first try.

}
return dagCborDecode(...args)
}
}
})

const result = await rewiredGeoIp.lookup(ipfsGW, '66.6.44.4')
expect(decodeCallCount).to.be.greaterThan(1)
expect(
result
).to.be.eql({
country_name: 'USA',
country_code: 'US',
region_code: 'VA',
city: 'Ashburn',
postal_code: '20149',
latitude: 39.0469,
longitude: -77.4903,
planet: 'Earth'
})
})
})