Skip to content
This repository was archived by the owner on Jul 16, 2024. It is now read-only.

Commit 2f66210

Browse files
committed
Added option to store digital assets into static folder instead of using Gatsby cache
1 parent 5bd8491 commit 2f66210

File tree

5 files changed

+270
-49
lines changed

5 files changed

+270
-49
lines changed

README.md

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ module.exports = {
3636
query: '',
3737
},
3838
renditions: 'none',
39+
preview: false,
40+
auth: '',
41+
staticAssetDownload: 'false'.
42+
staticAssetRootDir: 'asset'
43+
3944
},
4045
},
4146
],
@@ -73,22 +78,55 @@ This setting controls which renditions of digital assets will be downloaded. Thi
7378

7479
- `custom` (default) means that only custom renditions will be downloaded.
7580
- `none` means that only the original data will be downloaded.
76-
- `all` means that all of the OCE-generated renditions (*thumbnail*, *small*, etc.) will be downloaded as well as any custom renditions.
81+
- `all` means that all of the system generated renditions (*thumbnail*, *small*, etc.) will be downloaded as well as any custom renditions.
82+
83+
> NOTE: For each image downloaded, Gatsby will generate multiple renditions of its own to use for responsive display. This means that if you use the `all` value for renditions, Gatsby will generate resized copies of both the original image and for each of the system renditions (*thumbnail*, *small*, etc.). This can add a lot of processing time and network load to the build process for support that you may not need. It is recommended that you use the `none` or `custom` option unless you wish to explicitly use the system renditions.
84+
85+
**`preview`** [optional]
86+
This setting controls whether the client will be retrieving preview (unpublished) data or not. If true, it must be used with the auth parameter. It defaults to false.
87+
88+
**`auth`** [optional]
89+
This setting is used to set authentication tokens required when downloading from a secure publishing channel (preview=false) or preview items. It may use basic auth or
90+
an OAuth bearer token. It defaults to an empty string.
91+
92+
**`staticAssetDownload`** [optional]
93+
This setting is used to make the plugin download binary assets into the public directory of the site as opposed to storing them in the internal Gatsby cache. This allows items such as image files to be referenced as direct URLs rather than using GraphQL to access them. It is used in combination with the staticAssetRootDir (described below). The default value is false which means all data will be in the cache instead.
94+
95+
**`staticAssetRootDir`** [optional]
96+
This setting is ignored unless staticAssetDownload is set to true. This allows a developer to define a directory in the website that will contain all the downloaded assets. This can help to segregate the items coming from the server from other static data. The default value is "asset", but it can be set to any string that is a valid directory name.
97+
98+
**`How to use static download:`**
99+
Assume there is a digital asset on the server called Logo.jpg that contains an image to be used in a site.
100+
If staticAssetDownload is false then the binary image will be stored in the cache as well as any selected renditions. (See 'renditions' flag above) These binary files can then be queried and traversed via GraphQL
101+
102+
If staticAssetDownload is true and staticAssetRootDir is set to 'server' then the file will be available in the website as: /server/Logo.jpg and could be displayed
103+
in an \<img\> tag as \<img src="/server/Logo.jpg"\/> . If the user has chosen to download all the renditions of the digital assets in their site then the following urls
104+
will be available:
105+
/server/Logo.jpg (the original)
106+
/server/Large/Logo.jpg (the large rendition)
107+
/server/Medium/Logo.jpg (the medium rendition)
108+
/server/Small/Logo.jpg (the small rendition)
109+
/server/Thumbnail/Logo.jpg (the thumbnail rendition)
110+
111+
If there are any custom renditions, then they will also appear as
112+
/server/*custom rendition name*/Logo.jpg
113+
114+
115+
77116

78-
> NOTE: For each image downloaded, Gatsby will generate multiple renditions of its own to use for responsive display. This means that if you use the `all` value for renditions, Gatsby will generate resized copies of both the original image and for each of the OCE renditions (*thumbnail*, *small*, etc.). This can add a lot of processing time and network load to the build process for support that you may not need. It is recommended that you use the `none` or `custom` option unless you wish to explicitly use the OCE renditions.
79117

80118
### Content Model
81119

82-
The data model used for OCE data in Gatsby closely models the JSON data provided by the OCE REST interface. There are a few small exceptions though that are needed to avoid conflicts between Gatsby node reserved fields and OCE data. These include:
120+
The data model used for content data in Gatsby closely models the JSON data provided by the Oracle Content Management REST interface. There are a few small exceptions though that are needed to avoid conflicts between Gatsby node reserved fields and Oracle Content Management data. These include:
83121

84122
- All assets are typed as `oceAsset` so that they can be distinguished from other assets in GraphQL queries.
85-
- Some OCE asset fields are renamed to avoid conflicts with reserved Gatsby node field names. `id` becomes `oceId`, `fields` becomes `oceFields`, and `type` becomes `oceType`.
86-
- In traditional OCE usage, a digital asset provides a URL that can be used to retrieve the binary form(s) of the asset from the server. As Gatsby builds static sites, these binary values must be stored locally and are placed in file nodes in the GraphQL store. To allow these binary forms to be retrieved easily in a site, a link is established between the file nodes and the digital asset nodes. What this means is that it is possible to traverse an `oceAsset` and find the internal Gatsby representations of its binary data without having to load the file nodes as well. All of an `oceAsset`'s file data can be found under the field `childrenFile`.
123+
- Some Oracle Content Management asset fields are renamed to avoid conflicts with reserved Gatsby node field names. `id` becomes `oceId`, `fields` becomes `oceFields`, and `type` becomes `oceType`.
124+
- In traditional Oracle Content Management usage, a digital asset provides a URL that can be used to retrieve the binary form(s) of the asset from the server. As Gatsby builds static sites, these binary values must be stored locally and are placed in file nodes in the GraphQL store. To allow these binary forms to be retrieved easily in a site, a link is established between the file nodes and the digital asset nodes. What this means is that it is possible to traverse an `oceAsset` and find the internal Gatsby representations of its binary data without having to load the file nodes as well. All of an `oceAsset`'s file data can be found under the field `childrenFile`.
87125

88126
## Examples
89127

90128
You can query `OceAsset` nodes in the following manner:
91-
(This returns the names and types of all assets. Note that the `type` field is internal to Gatsby, so we use the `oceType` field to get the OCE name for each definition )
129+
(This returns the names and types of all assets. Note that the `type` field is internal to Gatsby, so we use the `oceType` field to get the Oracle Content Management name for each definition )
92130

93131
```graphql
94132
{
@@ -124,10 +162,7 @@ Load the information needed to display the image `Banner1.jpg` as a fluid (respo
124162
rendition
125163
}
126164
childImageSharp {
127-
fluid(quality: 100) {
128-
129-
...GatsbyImageSharpFluid_withWebp
130-
}
165+
gatsbyImageData(quality: 100, layout: FULL_WIDTH)
131166
}
132167
}
133168
}

gatsby-node.js

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,16 @@ const fetch = require('./src/fetch');
2828
* query: '',
2929
* },
3030
* renditions: 'all',
31+
* staticAssetDownload: false
32+
* staticAssetRootDir: 'asset'
3133
* },
3234
* },
3335
* ]
3436
*</code></pre></div>
3537
* <b>contentServer</b> should be set to the base url for your server. For example: https://oceserver.domain.com<br>
3638
* <b>channelToken</b> should be set to the publishing channel id on the given server<br>
37-
* <b>proxyUrl</b> this is only needed if there is a proxy between the local computer and
38-
* the OCE server. It should be of the form: "http://proxyserver.company.com:port"
39+
* <b>proxyUrl</b> (optional) this is only needed if there is a proxy between the local computer and
40+
* the OCE server. It should be of the form: "http://proxyserver.company.com:port"<br>
3941
* <b>limit</b> (optional) How many assets should be queried from the server in one call.
4042
* This can generally be left alone <br>
4143
* <b>query</b> (optional) It is used to limit what class of assets should be downloaded
@@ -57,6 +59,15 @@ const fetch = require('./src/fetch');
5759
* If your project uses 100 image assets,the plugin will then download 500+ files from the server
5860
* (1 original + 4 generated renditions, plus all custom renditions)
5961
* This is a waste of bandwidth unless you plan to use the oce renditions directly in your site.
62+
* <br>
63+
* <b>staticAssetDownload</b> (optional) should be set to true if you want to download assets as
64+
* files to be included via urls in your site. If it is set to the default value of false the
65+
* binary files will be placed in the Gatsby cache and will be accessible via GraphQL<br>
66+
* <b>staticAssetRootDir</b> this setting is only used if staticAssetDownload is true. It is used
67+
* to set a a prefix that will be prepended to all of the urls for downloaded files. For example:
68+
* If it is set to "content" then the url of a downloaded image called Logo.jpg
69+
* will be /content/Logo.jpg.
70+
*
6071
*
6172
*/
6273
exports.sourceNodes = async (
@@ -72,11 +83,25 @@ exports.sourceNodes = async (
7283
delete configOptions.plugins;
7384

7485
// plugin code goes here...
75-
console.log('Using OCE plugin with the options: ', configOptions);
7686

7787
const {
78-
contentServer, channelToken, proxyUrl = '', items: { limit } = 100, items: { query } = '', renditions = 'custom', debug = false,
88+
contentServer, channelToken, proxyUrl = '', items: { limit } = 100, items: { query } = '', auth = '', preview = false, renditions = 'custom',
89+
staticAssetDownload = false, staticAssetRootDir = 'assets', debug = false,
7990
} = configOptions;
91+
92+
console.log('Using OCE plugin with the options: ', {
93+
contentServer,
94+
channelToken,
95+
proxyUrl,
96+
limit,
97+
query,
98+
auth: `${auth.length} characters`,
99+
preview,
100+
renditions,
101+
staticAssetDownload,
102+
staticAssetRootDir,
103+
debug,
104+
});
80105
try {
81106
if (proxyUrl !== '') {
82107
try {
@@ -87,7 +112,8 @@ exports.sourceNodes = async (
87112
console.log(`ERROR ${e}`);
88113
}
89114
}
90-
let entities = await fetch.all(contentServer, channelToken, limit, query, debug);
115+
let entities = await fetch.all(contentServer, channelToken, limit, query,
116+
auth, preview, debug);
91117
// tidy up the data for further processing
92118
entities = entities.filter((e) => e != null && (typeof e === 'object'));
93119
entities = process.cleanUp(entities);
@@ -100,16 +126,30 @@ exports.sourceNodes = async (
100126
// Generate unique Gatsby ids for indexing
101127
entities = process.createGatsbyIds(createNodeId, entities, channelToken);
102128

129+
if (staticAssetDownload === true || staticAssetDownload === 'true') {
130+
console.log('Starting static download');
131+
await process.prepareForStaticDownload({ staticAssetRootDir });
132+
await process.downloadMediaFilesToStaticDir({
133+
entities,
134+
staticAssetRootDir,
135+
renditions,
136+
auth,
137+
});
138+
console.log('Ending static download');
139+
} else {
103140
// Get a copy of all digital asset files (.jpg, .png, etc...) and make Gatsby nodes for them
104-
entities = await process.downloadMediaFiles({
105-
entities,
106-
store,
107-
cache,
108-
createNode,
109-
createNodeId,
110-
touchNode,
111-
renditions,
112-
});
141+
entities = await process.downloadMediaFiles({
142+
entities,
143+
store,
144+
cache,
145+
createNode,
146+
createNodeId,
147+
touchNode,
148+
renditions,
149+
auth,
150+
});
151+
}
152+
113153
console.log('Completed download of assets');
114154
// Create nodes for all the downloaded assets
115155
await process.createNodesFromEntities({ entities, createNode, createContentDigest });

package.json

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@oracle/gatsby-source-oce",
33
"description": "Gatsby source plugin for using Oracle Content Management as a data source",
44
"author": "Oracle America, Inc.",
5-
"version": "1.0.1",
5+
"version": "1.1.0",
66
"homepage": "https://github.com/oracle/gatsby-source-oce",
77
"repository": {
88
"type": "git",
@@ -35,5 +35,14 @@
3535
"eslint": "~7.11.0",
3636
"eslint-config-airbnb-base": "~14.2.1",
3737
"eslint-plugin-import": "~2.22.1"
38-
}
38+
},
39+
"files": [
40+
"CONTRIBUTING.md",
41+
"LICENSE.txt",
42+
"README.md",
43+
"SECURITY.md",
44+
"THIRD_PARTY*",
45+
"*.js",
46+
"src"
47+
]
3948
}

src/fetch.js

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
/* eslint-disable no-console */
77
/* eslint-disable no-await-in-loop */
88
const fetch = require('node-fetch');
9+
const { Headers } = require('node-fetch');
910
const fs = require('fs').promises;
1011

1112
/**
@@ -23,7 +24,7 @@ const fs = require('fs').promises;
2324
* data retrieved from the OCE server.
2425
*/
2526

26-
exports.all = async (contentServer, channelToken, limit, query, debug) => {
27+
exports.all = async (contentServer, channelToken, limit, query, auth, preview, debug) => {
2728
try {
2829
await fs.rmdir('.data', { recursive: true });
2930
} catch (err) {
@@ -32,33 +33,62 @@ exports.all = async (contentServer, channelToken, limit, query, debug) => {
3233
if (debug) {
3334
await fs.mkdir('.data');
3435
}
35-
const fetchLimit = ((limit != null && limit > 0) ? limit : 10);
3636

37-
const fetchQuery = query ? `&q=${query}` : '';
38-
const allItemsUrl = `${contentServer}/content/published/api/v1.1/items?limit=${fetchLimit}&offset=0&totalResults=true&offset=0&channelToken=${channelToken}${fetchQuery}`;
37+
// const pretty = (o) => JSON.stringify(o, null, 2);
3938

4039
const fetchItem = async (id) => {
41-
const response = await fetch(
42-
`${contentServer}/content/published/api/v1.1/items/${id}?channelToken=${channelToken}&expand=all`,
43-
);
44-
const item = await response.json();
45-
46-
// Remove hyphens which can cause issues
47-
item.type = item.type.replace('-', '');
48-
if (debug) {
49-
await fs.writeFile(
50-
`.data/${id}.json`,
51-
JSON.stringify(item, null, 2),
52-
'utf-8',
53-
);
40+
let item = null;
41+
const itemUrl = preview === 'true' ? `${contentServer}/content/management/api/v1.1/items/${id}` : `${contentServer}/content/published/api/v1.1/items/${id}?channelToken=${channelToken}&expand=all`;
42+
43+
try {
44+
const headers = new Headers({
45+
Authorization: `${auth}`,
46+
Accept: '*/*',
47+
});
48+
49+
const response = await fetch(itemUrl, { headers });
50+
item = await response.json();
51+
52+
// Remove hyphens which can cause issues
53+
item.type = item.type.replace('-', '');
54+
if (debug) {
55+
await fs.writeFile(
56+
`.data/${id}.json`,
57+
JSON.stringify(item, null, 2),
58+
'utf-8',
59+
);
60+
}
61+
} catch (e) {
62+
console.log(`ERROR Download of item ${id} with URL ${itemUrl} ${e} `);
63+
throw (e);
5464
}
5565
return item;
5666
};
5767

5868
const fetchAll = async () => {
69+
const fetchLimit = ((limit != null && limit > 0) ? limit : 10);
70+
71+
const fetchQuery = query ? `&q=${query}` : '';
72+
const allPublishedItemsUrl = `${contentServer}/content/published/api/v1.1/items?limit=${fetchLimit}&offset=0&totalResults=true&offset=0&channelToken=${channelToken}${fetchQuery}`;
73+
const allManagementItemsUrl = `${contentServer}/content/management/api/v1.1/items?limit=${fetchLimit}&offset=0&totalResults=true&offset=0&channelToken=${channelToken}${fetchQuery}`;
74+
75+
const allItemsUrl = preview === 'true' ? allManagementItemsUrl : allPublishedItemsUrl;
76+
5977
// Fetch a response from the apiUrl
6078

61-
let response = await fetch(allItemsUrl);
79+
let response = null;
80+
let headers = '';
81+
try {
82+
if (auth !== '') {
83+
headers = new Headers({
84+
Authorization: `${auth}`,
85+
Accept: '*/*',
86+
});
87+
}
88+
response = await fetch(allItemsUrl, { headers });
89+
} catch (e) {
90+
console.log(`ERROR Failed downloading item list using ${allItemsUrl}`);
91+
}
6292
// Parse the response as JSON
6393
try {
6494
const data = await response.json();
@@ -70,8 +100,7 @@ exports.all = async (contentServer, channelToken, limit, query, debug) => {
70100

71101
for (let offset = fetchLimit; offset < totalResults; offset += fetchLimit) {
72102
const partialQuery = allItemsUrl.replace('&offset=0', `&offset=${offset}`);
73-
// console.log(`partialQuery: ${partialQuery}`);
74-
response = await fetch(partialQuery);
103+
response = await fetch(partialQuery, { headers });
75104
const partialData = await response.json();
76105
data.items = data.items.concat(partialData.items);
77106
}
@@ -93,6 +122,7 @@ exports.all = async (contentServer, channelToken, limit, query, debug) => {
93122
throw err;
94123
}
95124
};
125+
96126
const entities = await fetchAll();
97127
return entities;
98128
};

0 commit comments

Comments
 (0)