Skip to content

Commit

Permalink
ref(build): Use babel instead of tsc for transpiling.
Browse files Browse the repository at this point in the history
Signed-off-by: Jesse Stuart <hi@jessestuart.com>
  • Loading branch information
jessestuart committed Apr 23, 2019
1 parent ce5a4df commit 0aaf04f
Show file tree
Hide file tree
Showing 12 changed files with 495 additions and 150 deletions.
3 changes: 0 additions & 3 deletions .babelrc

This file was deleted.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
!*.config.js
# vim set ft=gitignore
**/*.d.ts
**/*.map
*.tgz
Expand All @@ -11,3 +11,5 @@
/types/
report*
tags*
# ==========================================
!*.config.js
92 changes: 63 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,37 @@
gatsby-source-s3-image
</h1>

[![CircleCI][circleci-badge]][circleci-link]
[![npm][npm-badge]][npm-link]
[![CircleCI][circleci-badge]][circleci-link] [![npm][npm-badge]][npm-link]
[![Maintainability][codeclimate]][codeclimate 2]
[![codecov][codecov]][codecov 2]

GatsbyJS Source plugin for **converting images from an S3-compliant API[1] into
GatsbyJS nodes** (with full support for hooking into all of the powerful
features the `GatsbyImage` API has to offer).
## What is this?

Additionally, `gatsby-source-s3-image` will **automatically detect and extract
image EXIF metadata from your photos**, and expose this data at the GraphQL
layer as node fields. Currently supported EXIF fields include:
`gatsby-source-s3-image` is a [GatsbyJS][github] _Source_ plugin for
**converting images from any S3-compliant API[1] into GatsbyJS nodes**.

[1] This includes AWS S3, of course, as well as third-party solutions like
Digital Ocean Spaces, or open source / self-hosted products like [MinIO][min].

### But I can just query S3 manually client-side...

Sure, knock yourself out. But there are a few benefits you get out-of-the-box
with this package:

- Native integration with Gatsby's GraphQL data ontology, of course. You just
provide the bucket details (and IAM credentials, if not public, which is
recommended).
- Several other benefits come with this tight integration with Gatsby API's,
such as intelligent caching (nobody wants to wind up with an unexpected S3
bill as your CI server happily churns out builds, amiright?); automatic image
asset optimization thanks to `gatsby-image`, etc.
- And to top things off — `gatsby-source-s3-image` will **automatically detect
and extract image EXIF metadata from your photos**, and expose this data at

### Tell me more about this EXIF stuff.

Currently supported EXIF fields that are automatically extracted when available
include:

- `DateCreatedISO` (`string`)
- `DateTimeOriginal` (`number`)
Expand All @@ -34,7 +53,8 @@ These fields are properties of the "wrapper" node, `S3ImageAsset`. This type
composes the `ImageSharp` node, the `File` node representing the cached image on
disk (fetched via the `RemoteFileNode` API), and lastly the extracted EXIF data.
As a result, you can easily retrieve both a set of images as well as any subset
of their associated metadata in a single request. For example:
of their associated metadata in a single request — or just the metadata by
itself, if that's all you need. For example:

```es6
export const pageQuery = graphql`
Expand All @@ -55,13 +75,13 @@ export const pageQuery = graphql`
height
width
}
thumbnailSizes: fluid(maxWidth: 512) {
thumbnailSizes: fluid(maxWidth: 256) {
aspectRatio
src
srcSet
sizes
}
largeSizes: fluid(maxWidth: 1536) {
largeSizes: fluid(maxWidth: 1024) {
aspectRatio
src
srcSet
Expand All @@ -76,23 +96,21 @@ export const pageQuery = graphql`
`
```

[1] This includes AWS S3, of course, as well as third-party solutions like
Digital Ocean Spaces, or open source / self-hosted products like
[MinIO][min].
## Usage

### Setup

1. Add the dependency to your `package.json`:
Add the dependency to your `package.json`:

```console
$ yarn add gatsby-source-s3-image
$ # Or:
$ npm install --save gatsby-source-s3-image
```

1. Next, register the plugin with the GatsbyJS runtime in the `plugins` exported
from your `gatsby-config.js` file, filling in the values to point to wherever
your bucket is hosted:
Next, register the plugin with the GatsbyJS runtime in the `plugins` field
exported from your `gatsby-config.js` file, filling in the values to point to
wherever your bucket is hosted:

```es6
const sourceS3 = {
Expand All @@ -112,10 +130,10 @@ const plugins = [
module.exports = { plugins }
```

### Querying
## Querying

1. As mentioned above, `gatsby-source-s3-image` exposes nodes of type
`S3ImageAsset`:
As mentioned above, `gatsby-source-s3-image` exposes nodes of type
`S3ImageAsset`:

```typescript
interface S3ImageAssetNode {
Expand Down Expand Up @@ -146,13 +164,13 @@ interface ExifData {
```

Not only can this be used to populate page data, I've found it useful in
bootstrapping the pages themselves, e.g., to dynamically create dynamic photo
gallery pages at build time depending on the contents of a bucket, something
like:
bootstrapping the pages themselves, e.g., to programmatically create dynamic
Photo Gallery pages at build time depending on the contents of a bucket. For
example:

```es6
// In `gatsby-node.js` -- using a query like this:
const photographyQuery = `{
const photographyQuery = graphql`{
allS3ImageAsset {
edges {
node {
Expand Down Expand Up @@ -191,12 +209,28 @@ const createPages = ({ actions }) => {
}
```

[circleci-badge]: https://circleci.com/gh/jessestuart/gatsby-source-s3-image.svg?style=shield
## _Nota Bene:_ Gatsby Version Compatibility

`gatsby-source-s3-image` was recently [updated][github 2] to support Gatsby V2,
which required some breaking changes. The Gatsby V1-compatible version of the
plugin is still fully functional, and will continue to receive maintenance
updates as necessary. The last release compatible with Gatsby V1 can be found
[here][github 3]

[circleci-badge]:
https://circleci.com/gh/jessestuart/gatsby-source-s3-image.svg?style=shield
[circleci-link]: https://circleci.com/gh/jessestuart/gatsby-source-s3-image
[codeclimate 2]: https://codeclimate.com/github/jessestuart/gatsby-source-s3-image/maintainability
[codeclimate]: https://api.codeclimate.com/v1/badges/4488634e45e84d3cbdbe/maintainability
[codeclimate]:
https://api.codeclimate.com/v1/badges/4488634e45e84d3cbdbe/maintainability
[codeclimate 2]:
https://codeclimate.com/github/jessestuart/gatsby-source-s3-image/maintainability
[codecov]:
https://codecov.io/gh/jessestuart/gatsby-source-s3-image/branch/master/graph/badge.svg
[codecov 2]: https://codecov.io/gh/jessestuart/gatsby-source-s3-image
[codecov]: https://codecov.io/gh/jessestuart/gatsby-source-s3-image/branch/master/graph/badge.svg
[github]: https://github.com/gatsbyjs/gatsby
[github 2]: https://github.com/jessestuart/gatsby-source-s3-image/pull/238
[github 3]:
https://github.com/jessestuart/gatsby-source-s3-image/releases/tag/v0.2.133
[min]: https://min.io
[npm-badge]: https://img.shields.io/npm/v/gatsby-source-s3-image.svg
[npm-link]: https://www.npmjs.com/package/gatsby-source-s3-image
17 changes: 17 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
sourceRoot: 'src/',
ignore: ['./src/__tests__/*'],
presets: [
[
'@babel/preset-env',
{
// For more info on babel + core-js v3,
// @see https://babeljs.io/blog/2019/03/19/7.4.0
useBuiltIns: 'usage',
corejs: 3,
},
],
'@babel/preset-typescript',
'minify',
],
}
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testRegex: '(/__tests__/.*\\.([tj]sx?)|(\\.|/)(test|spec))\\.([tj]sx?)$',
testRegex: '(/__tests__/.*\\.([t]sx?)|(\\.|/)(test|spec))\\.([t]sx?)$',
transform: { '^.+\\.tsx?$': 'ts-jest' },
}
15 changes: 11 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"version": "1.1.1",
"author": "Jesse Stuart <hi@jessestuart.com>",
"dependencies": {
"@babel/runtime": "7.4.3",
"aws-sdk": "2.441.0",
"bluebird": "3.5.4",
"exif-parser": "0.1.12",
Expand All @@ -16,18 +15,24 @@
"@babel/cli": "7.4.3",
"@babel/core": "7.4.3",
"@babel/preset-typescript": "7.3.3",
"@babel/runtime": "7.4.3",
"@semantic-release/git": "7.0.8",
"@types/bluebird": "3.5.26",
"@types/jest": "24.0.11",
"@types/lodash": "4.14.123",
"@types/node": "11.13.7",
"@types/mitm": "1.3.2",
"@types/node": "11.13.6",
"@types/redux-mock-store": "1.0.0",
"@typescript-eslint/eslint-plugin": "1.7.0",
"@typescript-eslint/parser": "1.7.0",
"babel-jest": "24.7.1",
"babel-plugin-add-module-exports": "1.0.2",
"babel-plugin-lodash": "3.3.4",
"babel-preset-gatsby-package": "0.1.4",
"babel-preset-minify": "0.5.0",
"codecov": "3.3.0",
"concurrently": "4.1.0",
"core-js": "3",
"eslint": "5.16.0",
"eslint-config-prettier": "4.1.0",
"eslint-config-standard": "12.0.0",
Expand Down Expand Up @@ -75,11 +80,13 @@
"url": "git+https://github.com/jessestuart/gatsby-source-s3-image"
},
"scripts": {
"build": "tsc",
"build": "babel --extensions '.ts' src/ --out-dir .",
"check-types": "tsc",
"lint": "eslint src/** --ext ts,tsx",
"prepublishOnly": "yarn build",
"semantic-release": "yarn build && semantic-release",
"test": "jest",
"test": "concurrently 'yarn check-types' 'yarn jest'",
"test:watch": "concurrently 'yarn tsc --watch' 'yarn jest --watch'",
"update": "ncu -ua && yarn -s",
"watch": "yarn build -w"
},
Expand Down
74 changes: 39 additions & 35 deletions src/__tests__/source-nodes.spec.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,59 @@
import sourceFilesystem from 'gatsby-source-filesystem'

import Mitm from 'mitm'
import configureMockStore from 'redux-mock-store'

import { sourceNodes } from '../source-nodes'
import fixtures from './fixtures.json'

const mockStore = configureMockStore()
import sourceFilesystem from 'gatsby-source-filesystem';
import _ from 'lodash';
import Mitm from 'mitm';
import configureMockStore from 'redux-mock-store';
import { sourceNodes } from '../source-nodes';
import fixtures from './fixtures.json';

// Mock out Gatby's source-filesystem API.
sourceFilesystem.createRemoteFileNode = jest.fn()

// Mock out `aws-sdk` module to prevent unnecessary calls to S3 during testing.
jest.mock('aws-sdk', () => ({
S3: class {
public listObjectsV2() {
return {
promise: () => fixtures,
}
}
public listObjectsV2 = (..._: any[]) => ({ promise: () => fixtures })
},
}))

describe('source S3ImageAsset nodes', () => {
let args
describe('Source S3ImageAsset nodes.', () => {
let nodes = {}

beforeEach(() => {
args = {
actions: {
createNode: jest.fn(node => (nodes[node.id] = node)),
},
cache: {
get: jest.fn(),
set: jest.fn(),
},
createContentDigest: jest.fn(),
createNodeId: jest.fn(),
store: mockStore,
}
Mitm().on('request', () => {
throw new Error('Network requests forbidden in offline mode.')
let mockStore = {}

const sourceNodeArgs = {
actions: {
createNode: jest.fn(node => (nodes[node.id] = node)),
},
cache: {
get: jest.fn(),
set: jest.fn(),
},
createContentDigest: jest.fn(),
createNodeId: jest.fn(),
store: mockStore,
}

beforeAll(() => {
mockStore = configureMockStore()

Mitm().on('request', req => {
const host = _.get(req, 'headers.host')
const url = _.get(req, 'url')
throw new Error(
`Network requests forbidden in offline mode. Tried to call URL "${host}${url}"`
)
})
})

test('sourceNodes', async () => {
test('Verify sourceNodes creates the correct # of nodes, given our fixtures.', async () => {
// NB: pulls from fixtures defined above, not S3 API.
const entityNodes = await sourceNodes(args, { bucketName: 'fake-bucket' })
const entityNodes = await sourceNodes(sourceNodeArgs, {
bucketName: 'fake-bucket',
})
// `createRemoteFileNode` called once for each of the five images in fixtures.
expect(sourceFilesystem.createRemoteFileNode).toHaveBeenCalledTimes(5)
// 5 images + 2 directories = 7 nodes
expect(entityNodes).toHaveLength(7)
})

// TODO
test('Verify getNodeEntityFields utils func.', () => {})
})
Loading

0 comments on commit 0aaf04f

Please sign in to comment.