Skip to content

Commit

Permalink
refactor: build native ESM (#98)
Browse files Browse the repository at this point in the history
Co-authored-by: Marcin Rataj <lidel@lidel.org>

BREAKING CHANGE: minified version is ESM now
  • Loading branch information
whizzzkid authored and lidel committed Oct 21, 2022
1 parent 4b508ac commit 14e31d1
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 25 deletions.
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: ''
}
}
},
test: {
before: (...args) => {
if (args[0].runner === 'node') {
return {
env: {
NODE_OPTIONS: '--loader=esmock'
}
}
}
}
}
}
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
10 changes: 5 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ jobs:
- uses: actions/checkout@v2
- uses: microsoft/playwright-github-action@v1
- run: npm install
- run: npx aegir test -t browser --bail --cov
- run: npx aegir test -t webworker --bail
- run: npx aegir test -t browser --bail --cov --files test/**/*.browser.spec.{js,cjs,mjs}
- run: npx aegir test -t webworker --bail --files test/**/*.browser.spec.{js,cjs,mjs}
- uses: codecov/codecov-action@v1
test-firefox:
needs: check
Expand All @@ -54,19 +54,19 @@ jobs:
- uses: actions/checkout@v2
- uses: microsoft/playwright-github-action@v1
- run: npm install
- run: npx aegir test -t browser -t webworker --bail -- --browser firefox
- run: npx aegir test -t browser -t webworker --bail --files test/**/*.browser.spec.{js,cjs,mjs} -- --browser firefox
test-webkit:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: microsoft/playwright-github-action@v1
- run: npm install
- run: npx aegir test -t browser -t webworker --bail -- --browser webkit
- run: npx aegir test -t browser -t webworker --bail --files test/**/*.browser.spec.{js,cjs,mjs} -- --browser webkit
test-electron-main:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npx xvfb-maybe aegir test -t electron-main --bail
- run: npx xvfb-maybe aegir test -t electron-main --bail --files test/**/*.browser.spec.{js,cjs,mjs}
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,39 +42,54 @@ npm install --save ipfs-geoip

### CDN

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

```html
<!-- loading the minified version using jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/ipfs-geoip/dist/index.min.js"></script>
<script type="module">
import { lookup } from 'https://cdn.jsdelivr.net/npm/ipfs-geoip@N.N.N/dist/index.min.js';
const gateway = 'https://ipfs.io'
console.log(await lookup(gateway, '66.6.44.4'))
</script>
```

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

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

## Usage

### With public gateways (default)

If `ipfs` is a string or array of strings with public gateway URLs, it will be used for
If `gateways` is a string or array of strings with public gateway URLs, it will be used for
fetching IPFS blocks as [`application/vnd.ipld.raw`](https://www.iana.org/assignments/media-types/application/vnd.ipld.raw)
and parsing them as DAG-CBOR locally:
and parsing them as DAG-CBOR locally via [@ipld/dag-cbor](https://www.npmjs.com/package/@ipld/dag-cbor):

```js
const geoip = require('ipfs-geoip')
const exampleIp = '66.6.44.4'

const ipfsGw = ['https://ipfs.io', 'https://dweb.link']
const gateways = ['https://ipfs.io', 'https://dweb.link']

try {
const result = await geoip.lookup(ipfsGw, exampleIp)
const result = await geoip.lookup(gateways, exampleIp)
console.log('Result: ', result)
} catch (err) {
console.log('Error: ' + err)
}

try {
const result = await geoip.lookupPretty(ipfsGw, '/ip4/' + exampleIp)
const result = await geoip.lookupPretty(gateways, '/ip4/' + exampleIp)
console.log('Pretty result: %s', result.formatted)
} catch (err) {
console.log('Error: ' + err)
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'

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",
"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}",
"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",
"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)
}
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')
}
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'
})
})
})

0 comments on commit 14e31d1

Please sign in to comment.