Merge pull request #939 from lbryio/master

cuts staging from master
This commit is contained in:
jessopb 2019-02-26 11:58:26 -05:00 committed by GitHub
commit f636023f80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 490 additions and 273 deletions

View file

@ -47,6 +47,7 @@ For a closed, custom-hosted and branded example, check out https://lbry.theantim
- `./lbrynet account_balance` gets your balance (initially 0.0) - `./lbrynet account_balance` gets your balance (initially 0.0)
- `./lbrynet address_list` gets addresses you can use to recieve LBC - `./lbrynet address_list` gets addresses you can use to recieve LBC
- [FFmpeg](https://www.ffmpeg.org/download.html) - [FFmpeg](https://www.ffmpeg.org/download.html)
- [ImageMagick](https://packages.ubuntu.com/xenial/graphics/imagemagick)
- Spee.ch (below) - Spee.ch (below)
- pm2 (optional) process manager such as pm2 to run speech server.js - pm2 (optional) process manager such as pm2 to run speech server.js
- http proxy server e.g. caddy, nginx, or traefik, to forward 80/443 to speech port 3000 - http proxy server e.g. caddy, nginx, or traefik, to forward 80/443 to speech port 3000
@ -260,9 +261,11 @@ Spee.ch has a few types of URL formats that return different assets from the LBR
- retrieve the controlling `LBRY` claim: - retrieve the controlling `LBRY` claim:
- https://spee.ch/`claim` - https://spee.ch/`claim`
- https://spee.ch/`claim`.`ext` (serve) - https://spee.ch/`claim`.`ext` (serve)
- https://spee.ch/`claim`.`ext`&`querystring` (serve transformed)
- retrieve a specific `LBRY` claim: - retrieve a specific `LBRY` claim:
- https://spee.ch/`claim_id`/`claim` - https://spee.ch/`claim_id`/`claim`
- https://spee.ch/`claim_id`/`claim`.`ext` (serve) - https://spee.ch/`claim_id`/`claim`.`ext` (serve)
- https://spee.ch/`claim_id`/`claim`.`ext`&`querystring` (serve transformed)
- retrieve all contents for the controlling `LBRY` channel - retrieve all contents for the controlling `LBRY` channel
- https://spee.ch/`@channel` - https://spee.ch/`@channel`
- a specific `LBRY` channel - a specific `LBRY` channel
@ -270,9 +273,15 @@ Spee.ch has a few types of URL formats that return different assets from the LBR
- retrieve a specific claim within the controlling `LBRY` channel - retrieve a specific claim within the controlling `LBRY` channel
- https://spee.ch/`@channel`/`claim` - https://spee.ch/`@channel`/`claim`
- https://spee.ch/`@channel`/`claim`.`ext` (serve) - https://spee.ch/`@channel`/`claim`.`ext` (serve)
- https://spee.ch/`@channel`/`claim`.`ext`&`querystring` (serve)
- retrieve a specific claim within a specific `LBRY` channel - retrieve a specific claim within a specific `LBRY` channel
- https://spee.ch/`@channel`:`channel_id`/`claim` - https://spee.ch/`@channel`:`channel_id`/`claim`
- https://spee.ch/`@channel`:`channel_id`/`claim`.`ext` (serve) - https://spee.ch/`@channel`:`channel_id`/`claim`.`ext` (serve)
- https://spee.ch/`@channel`:`channel_id`/`claim`.`ext`&`querystring` (serve)
- `querystring` can include the following transformation values separated by `&`
- h=`number` (defines height)
- w=`number` (defines width)
- t=`crop` or `stretch` (defines transformation - missing implies constrained proportions)
### Dependencies ### Dependencies

0
changelog.md Normal file
View file

View file

@ -49,6 +49,10 @@
} }
}, },
"serving": { "serving": {
"dynamicFileSizing": {
"enabled": true,
"maxDimension": 2000
},
"markdownSettings": { "markdownSettings": {
"skipHtmlMain": true, "skipHtmlMain": true,
"escapeHtmlMain": true, "escapeHtmlMain": true,
@ -83,10 +87,7 @@
"code", "code",
"html", "html",
"parsedHtml" "parsedHtml"
], ]
"disallowedTypesMain": [],
"disallowedTypesDescriptions": ["image", "html"],
"disallowedTypesExample": ["image", "html"]
}, },
"customFileExtensions": { "customFileExtensions": {
"application/x-troff-man": "man", "application/x-troff-man": "man",

View file

@ -1,6 +1,7 @@
select { select {
margin: 0; margin: 0;
display: inline-block; display: inline-block;
background: $base-color; background: $background-color;
border: 0; border: 0;
color: $text-color;
} }

View file

@ -7,9 +7,6 @@ const ChannelSelectDropdown = ({ selectedChannel, handleSelection, loggedInChann
id='channel-name-select' id='channel-name-select'
value={selectedChannel} value={selectedChannel}
onChange={handleSelection}> onChange={handleSelection}>
{ loggedInChannelName && (
<option value={loggedInChannelName} >{loggedInChannelName}</option>
)}
<option value={LOGIN}>Existing</option> <option value={LOGIN}>Existing</option>
<option value={CREATE}>New</option> <option value={CREATE}>New</option>
</select> </select>

View file

@ -1,23 +1,28 @@
import React from 'react'; import React from 'react';
import RowLabeled from '@components/RowLabeled'; import RowLabeled from '@components/RowLabeled';
import Label from '@components/Label'; import Label from '@components/Label';
import { LICENSES } from '@clientConstants/publish_license_urls';
const PublishLicenseInput = ({ handleSelect }) => { const PublishLicenseInput = ({ handleSelect, license }) => {
return ( return (
<RowLabeled <RowLabeled
label={ label={
<Label value={'License:'} /> <Label value={'License'} />
} }
content={ content={
<select <select
type='text' type='text'
name='license' name='license'
id='publish-license' id='publish-license'
value={license}
onChange={handleSelect} onChange={handleSelect}
> >
<option value=''>Unspecified</option> <option value=''>Unspecified</option>
<option value='Public Domain'>Public Domain</option> {
<option value='Creative Commons'>Creative Commons</option> LICENSES.map(function(item, i){
return <option key={item + 'license key'} value={item}>{item}</option>;
})
}
</select> </select>
} }
/> />

View file

@ -0,0 +1,32 @@
import React from 'react';
import RowLabeled from '@components/RowLabeled';
import Label from '@components/Label';
import { CC_LICENSES } from '@clientConstants/publish_license_urls';
const PublishLicenseUrlInput = ({ handleSelect, licenseUrl }) => {
return (
<RowLabeled
label={
<Label value={'License Url'} />
}
content={
<select
type='text'
name='licenseUrl'
id='publish-license-url'
value={licenseUrl}
onChange={handleSelect}
>
<option value=''>Unspecified</option>
{
CC_LICENSES.map(function(item, i){
return <option key={item.url} value={item.url}>{item.value}</option>
})
}
</select>
}
/>
);
};
export default PublishLicenseUrlInput;

View file

@ -0,0 +1,33 @@
export const CC_LICENSES = [
{
value: 'CC Attr. 4.0 Int',
url: 'https://creativecommons.org/licenses/by/4.0/legalcode',
},
{
value: 'CC Attr-ShareAlike 4.0 Int',
url: 'https://creativecommons.org/licenses/by-sa/4.0/legalcode',
},
{
value: 'CC Attr-NoDerivatives 4.0 Int',
url: 'https://creativecommons.org/licenses/by-nd/4.0/legalcode',
},
{
value: 'CC Attr-NonComm 4.0 Int',
url: 'https://creativecommons.org/licenses/by-nc/4.0/legalcode',
},
{
value: 'CC Attr-NonComm-ShareAlike 4.0 Int',
url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode',
},
{
value: 'CC Attr-NonComm-NoDerivatives 4.0 Int',
url: 'https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode',
},
];
export const LICENSES = ['Public Domain', 'Other', 'Copyright', 'Creative Commons'];
export const PUBLIC_DOMAIN = 'Public Domain';
export const OTHER = 'other';
export const COPYRIGHT = 'copyright';
export const CREATIVE_COMMONS = 'Creative Commons';

View file

@ -7,7 +7,7 @@ import AssetShareButtons from '@components/AssetShareButtons';
import ClickToCopy from '@components/ClickToCopy'; import ClickToCopy from '@components/ClickToCopy';
import siteConfig from '@config/siteConfig.json'; import siteConfig from '@config/siteConfig.json';
import createCanonicalLink from '@globalutils/createCanonicalLink'; import createCanonicalLink from '@globalutils/createCanonicalLink';
import AssetInfoFooter from '../../components/AssetInfoFooter/index'; import AssetInfoFooter from '@components/AssetInfoFooter/index';
import { createPermanentURI } from '@clientutils/createPermanentURI'; import { createPermanentURI } from '@clientutils/createPermanentURI';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
@ -18,7 +18,20 @@ class AssetInfo extends React.Component {
render () { render () {
const { editable, asset } = this.props; const { editable, asset } = this.props;
const { claimViews, claimData } = asset; const { claimViews, claimData } = asset;
const { channelName, claimId, channelShortId, description, name, fileExt, contentType, host, certificateId } = claimData; const {
channelName,
claimId,
channelShortId,
description,
name,
fileExt,
contentType,
host,
certificateId,
license,
licenseUrl,
transactionTime
} = claimData;
const canonicalUrl = createCanonicalLink({ asset: { ...claimData, shortId: asset.shortId }}); const canonicalUrl = createCanonicalLink({ asset: { ...claimData, shortId: asset.shortId }});
const assetCanonicalUrl = `${host}${canonicalUrl}`; const assetCanonicalUrl = `${host}${canonicalUrl}`;
@ -55,7 +68,7 @@ class AssetInfo extends React.Component {
{editable && ( {editable && (
<RowLabeled <RowLabeled
label={<Label value={'Edit'} />} label={<Label value={'Edit'} />}
content={<Link to={`/edit${canonicalUrl}`}>{name}</Link>} content={<Link className='link--primary' to={`/edit${canonicalUrl}`}>{name}</Link>}
/> />
)} )}
{channelName && ( {channelName && (
@ -71,6 +84,7 @@ class AssetInfo extends React.Component {
} }
/> />
)} )}
<SpaceBetween>
{claimViews ? ( {claimViews ? (
<RowLabeled <RowLabeled
label={ label={
@ -83,7 +97,22 @@ class AssetInfo extends React.Component {
} }
/> />
) : null} ) : null}
{license && (
<RowLabeled
label={
<Label value={'License'} />
}
content={
<div className='text'>
{licenseUrl ? (
<a className={'link--primary'} href={licenseUrl} target={'_blank'}>{license}</a>
) : (
<span>{license}</span> )}
</div>
}
/>
)}
</SpaceBetween>
<RowLabeled <RowLabeled
label={ label={
<Label value={'Share'} /> <Label value={'Share'} />

View file

@ -7,6 +7,7 @@ const mapStateToProps = ({ publish }) => {
showMetadataInputs: publish.showMetadataInputs, showMetadataInputs: publish.showMetadataInputs,
description: publish.metadata.description, description: publish.metadata.description,
license: publish.metadata.license, license: publish.metadata.license,
licenseUrl: publish.metadata.licenseUrl,
nsfw: publish.metadata.nsfw, nsfw: publish.metadata.nsfw,
isUpdate: publish.isUpdate, isUpdate: publish.isUpdate,
}; };
@ -17,10 +18,13 @@ const mapDispatchToProps = dispatch => {
onMetadataChange: (name, value) => { onMetadataChange: (name, value) => {
dispatch(updateMetadata(name, value)); dispatch(updateMetadata(name, value));
}, },
onToggleMetadataInputs: (value) => { onToggleMetadataInputs: value => {
dispatch(toggleMetadataInputs(value)); dispatch(toggleMetadataInputs(value));
}, },
}; };
}; };
export default connect(mapStateToProps, mapDispatchToProps)(View); export default connect(
mapStateToProps,
mapDispatchToProps
)(View);

View file

@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import PublishDescriptionInput from '@components/PublishDescriptionInput'; import PublishDescriptionInput from '@components/PublishDescriptionInput';
import PublishLicenseInput from '@components/PublishLicenseInput'; import PublishLicenseInput from '@components/PublishLicenseInput';
import PublishLicenseUrlInput from '@components/PublishLicenseUrlInput';
import PublishNsfwInput from '@components/PublishNsfwInput'; import PublishNsfwInput from '@components/PublishNsfwInput';
import ButtonSecondary from '@components/ButtonSecondary'; import ButtonSecondary from '@components/ButtonSecondary';
import Row from '@components/Row';
class PublishMetadataInputs extends React.Component { class PublishMetadataInputs extends React.Component {
constructor (props) { constructor (props) {
@ -25,22 +25,32 @@ class PublishMetadataInputs extends React.Component {
const name = event.target.name; const name = event.target.name;
const selectedOption = event.target.selectedOptions[0].value; const selectedOption = event.target.selectedOptions[0].value;
this.props.onMetadataChange(name, selectedOption); this.props.onMetadataChange(name, selectedOption);
if (name === 'license' && selectedOption !== 'Creative Commons'){
this.props.onMetadataChange('licenseUrl', '');
}
} }
render () { render () {
const { showMetadataInputs, description, isUpdate, nsfw } = this.props; const { showMetadataInputs, description, isUpdate, nsfw, license, licenseUrl } = this.props;
return ( return (
<div> <div>
{(showMetadataInputs || isUpdate) && ( {(showMetadataInputs || isUpdate) && (
<React.Fragment> <React.Fragment>
<PublishDescriptionInput <PublishDescriptionInput
description={this.props.description} description={description}
handleInput={this.handleInput} handleInput={this.handleInput}
/> />
<PublishLicenseInput <PublishLicenseInput
handleSelect={this.handleSelect} handleSelect={this.handleSelect}
license={license}
/> />
{ (this.props.license === 'Creative Commons') && (
<PublishLicenseUrlInput
handleSelect={this.handleSelect}
licenseUrl={licenseUrl}
/>
)}
<PublishNsfwInput <PublishNsfwInput
nsfw={this.props.nsfw} nsfw={nsfw}
handleInput={this.handleInput} handleInput={this.handleInput}
/> />
</React.Fragment> </React.Fragment>

View file

@ -9,7 +9,7 @@ class EditPage extends React.Component {
onHandleShowPageUri(match.params); onHandleShowPageUri(match.params);
setUpdateTrue(); setUpdateTrue();
if (asset) { if (asset) {
['title', 'description', 'license', 'nsfw'].forEach(meta => updateMetadata(meta, asset.claimData[meta])); ['title', 'description', 'license', 'licenseUrl', 'nsfw'].forEach(meta => updateMetadata(meta, asset.claimData[meta]));
} }
setHasChanged(false); setHasChanged(false);
} }

View file

@ -39,6 +39,7 @@ const initialState = {
title: '', title: '',
description: '', description: '',
license: '', license: '',
licenseUrl: '',
nsfw: false, nsfw: false,
}, },
isUpdate: false, isUpdate: false,
@ -51,7 +52,8 @@ const initialState = {
export default function(state = initialState, action) { export default function(state = initialState, action) {
switch (action.type) { switch (action.type) {
case actions.FILE_SELECTED: case actions.FILE_SELECTED:
return Object.assign({}, state.isUpdate ? state : initialState, { // note: clears to initial state return Object.assign({}, state.isUpdate ? state : initialState, {
// note: clears to initial state
file: action.data, file: action.data,
hasChanged: true, hasChanged: true,
}); });
@ -112,4 +114,4 @@ export default function (state = initialState, action) {
default: default:
return state; return state;
} }
}; }

View file

@ -1,9 +1,16 @@
export const createPublishMetadata = (claim, { type }, { title, description, license, nsfw }, publishInChannel, selectedChannel) => { export const createPublishMetadata = (
claim,
{ type },
{ title, description, license, licenseUrl, nsfw },
publishInChannel,
selectedChannel
) => {
let metadata = { let metadata = {
name: claim, name: claim,
title, title,
description, description,
license, license,
licenseUrl,
nsfw, nsfw,
type, type,
}; };

View file

@ -26,7 +26,6 @@ PUBLISHING:
"primaryClaimAddress": null, - generally supplied by your lbrynet sdk "primaryClaimAddress": null, - generally supplied by your lbrynet sdk
"uploadDirectory": "/home/lbry/Uploads", - lbrynet sdk will know your uploads are here "uploadDirectory": "/home/lbry/Uploads", - lbrynet sdk will know your uploads are here
"lbrynetHome": "/home/lbry",
"thumbnailChannel": null, - when publishing non-image content, thumbnails will go here. "thumbnailChannel": null, - when publishing non-image content, thumbnails will go here.
"thumbnailChannelId": null, "thumbnailChannelId": null,
"additionalClaimAddresses": [], "additionalClaimAddresses": [],
@ -53,6 +52,10 @@ PUBLISHING:
SERVING: SERVING:
"dynamicFileSizing": {
"enabled": false, - if you choose to allow your instance to serve transform images
"maxDimension": 2000 - the maximum size you allow transform to scale
},
"markdownSettings": { "markdownSettings": {
"skipHtmlMain": true, - false: render html, in a somewhat unpredictable way~ "skipHtmlMain": true, - false: render html, in a somewhat unpredictable way~
"escapeHtmlMain": true, - true: rather than render html, escape it and print it visibly "escapeHtmlMain": true, - true: rather than render html, escape it and print it visibly

141
package-lock.json generated
View file

@ -1522,20 +1522,11 @@
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
"dev": true "dev": true
}, },
"align-text": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
"integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
"requires": {
"kind-of": "^3.0.2",
"longest": "^1.0.1",
"repeat-string": "^1.5.2"
}
},
"amdefine": { "amdefine": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"dev": true
}, },
"ansi-align": { "ansi-align": {
"version": "2.0.0", "version": "2.0.0",
@ -1765,9 +1756,12 @@
"dev": true "dev": true
}, },
"async": { "async": {
"version": "1.5.2", "version": "2.6.2",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
"requires": {
"lodash": "^4.17.11"
}
}, },
"async-each": { "async-each": {
"version": "1.0.1", "version": "1.0.1",
@ -3015,12 +3009,6 @@
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
"dev": true "dev": true
}, },
"camelcase": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
"optional": true
},
"camelcase-keys": { "camelcase-keys": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
@ -3088,16 +3076,6 @@
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
}, },
"center-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
"optional": true,
"requires": {
"align-text": "^0.1.3",
"lazy-cache": "^1.0.3"
}
},
"chai": { "chai": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
@ -3341,25 +3319,6 @@
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
}, },
"cliui": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
"optional": true,
"requires": {
"center-align": "^0.1.1",
"right-align": "^0.1.1",
"wordwrap": "0.0.2"
},
"dependencies": {
"wordwrap": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
"optional": true
}
}
},
"clone-deep": { "clone-deep": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
@ -6544,14 +6503,21 @@
"dev": true "dev": true
}, },
"handlebars": { "handlebars": {
"version": "4.0.11", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz",
"integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==",
"requires": { "requires": {
"async": "^1.4.0", "async": "^2.5.0",
"optimist": "^0.6.1", "optimist": "^0.6.1",
"source-map": "^0.4.4", "source-map": "^0.6.1",
"uglify-js": "^2.6" "uglify-js": "^3.1.4"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
} }
}, },
"har-schema": { "har-schema": {
@ -7807,6 +7773,7 @@
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"dev": true,
"requires": { "requires": {
"is-buffer": "^1.1.5" "is-buffer": "^1.1.5"
} }
@ -7820,12 +7787,6 @@
"package-json": "^4.0.0" "package-json": "^4.0.0"
} }
}, },
"lazy-cache": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
"integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
"optional": true
},
"lcid": { "lcid": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
@ -8205,11 +8166,6 @@
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
}, },
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
},
"loose-envify": { "loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -8596,7 +8552,7 @@
}, },
"minimist": { "minimist": {
"version": "0.0.10", "version": "0.0.10",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
}, },
"mississippi": { "mississippi": {
@ -13870,15 +13826,6 @@
} }
} }
}, },
"right-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
"optional": true,
"requires": {
"align-text": "^0.1.1"
}
},
"rimraf": { "rimraf": {
"version": "2.6.2", "version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
@ -14746,6 +14693,7 @@
"version": "0.4.4", "version": "0.4.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
"dev": true,
"requires": { "requires": {
"amdefine": ">=0.0.4" "amdefine": ">=0.0.4"
} }
@ -15651,30 +15599,23 @@
"dev": true "dev": true
}, },
"uglify-js": { "uglify-js": {
"version": "2.8.29", "version": "3.4.9",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
"integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==",
"optional": true, "optional": true,
"requires": { "requires": {
"source-map": "~0.5.1", "commander": "~2.17.1",
"uglify-to-browserify": "~1.0.0", "source-map": "~0.6.1"
"yargs": "~3.10.0"
}, },
"dependencies": { "dependencies": {
"source-map": { "source-map": {
"version": "0.5.7", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true "optional": true
} }
} }
}, },
"uglify-to-browserify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
"optional": true
},
"uid-safe": { "uid-safe": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@ -16716,12 +16657,6 @@
"string-width": "^2.1.1" "string-width": "^2.1.1"
} }
}, },
"window-size": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
"optional": true
},
"winston": { "winston": {
"version": "2.4.4", "version": "2.4.4",
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz",
@ -16881,18 +16816,6 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
}, },
"yargs": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
"optional": true,
"requires": {
"camelcase": "^1.0.2",
"cliui": "^2.1.0",
"decamelize": "^1.0.0",
"window-size": "0.1.0"
}
},
"yargs-parser": { "yargs-parser": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",

View file

@ -6,7 +6,7 @@ const {
const getterMethods = { const getterMethods = {
generated_extension() { generated_extension() {
logger.info('trying to generate extension', this.content_type); logger.debug('trying to generate extension', this.content_type);
if (customFileExtensions.hasOwnProperty(this.content_type)) { if (customFileExtensions.hasOwnProperty(this.content_type)) {
return customFileExtensions[this.content_type]; return customFileExtensions[this.content_type];
} else { } else {
@ -136,6 +136,14 @@ export default (sequelize, { BOOLEAN, DATE, DECIMAL, ENUM, INTEGER, STRING, TEXT
type: STRING, type: STRING,
set() {}, set() {},
}, },
license: {
type: STRING,
set() {},
},
license_url: {
type: STRING,
set() {},
},
}, },
{ {
freezeTableName: true, freezeTableName: true,

View file

@ -1,8 +1,10 @@
const chainquery = require('chainquery').default; const chainquery = require('chainquery').default;
const logger = require('winston');
const getClaimData = require('server/utils/getClaimData'); const getClaimData = require('server/utils/getClaimData');
const { returnPaginatedChannelClaims } = require('./channelPagination.js'); const { returnPaginatedChannelClaims } = require('./channelPagination.js');
const getChannelClaims = async (channelName, channelLongId, page) => { const getChannelClaims = async (channelName, channelLongId, page) => {
logger.debug(`getChannelClaims: ${channelName}, ${channelLongId}, ${page}`);
let channelShortId = await chainquery.claim.queries.getShortClaimIdFromLongClaimId( let channelShortId = await chainquery.claim.queries.getShortClaimIdFromLongClaimId(
channelLongId, channelLongId,
channelName channelName

View file

@ -1,11 +1,13 @@
const { getClaim } = require('../../../../lbrynet'); const { getClaim } = require('../../../../lbrynet');
const { createFileRecordDataAfterGet } = require('../../../../models/utils/createFileRecordData.js'); const {
createFileRecordDataAfterGet,
} = require('../../../../models/utils/createFileRecordData.js');
const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js');
const getClaimData = require('server/utils/getClaimData'); const getClaimData = require('server/utils/getClaimData');
const chainquery = require('chainquery').default; const chainquery = require('chainquery').default;
const db = require('../../../../models'); const db = require('../../../../models');
const waitOn = require('wait-on');
const logger = require('winston'); const logger = require('winston');
const awaitFileSize = require('server/utils/awaitFileSize');
/* /*
@ -36,11 +38,11 @@ const claimGet = async ({ ip, originalUrl, params }, res) => {
if (!claimData) { if (!claimData) {
throw new Error('claim/get: getClaimData failed to get file blobs'); throw new Error('claim/get: getClaimData failed to get file blobs');
} }
await waitOn({ let fileReady = await awaitFileSize(lbrynetResult.download_path, 2000000, 10000, 250);
resources: [ lbrynetResult.download_path ],
timeout : 10000, // 10 seconds if (fileReady !== 'ready') {
window : 500, throw new Error('claim/get: failed to get file after 10 seconds');
}); }
const fileData = await createFileRecordDataAfterGet(claimData, lbrynetResult); const fileData = await createFileRecordDataAfterGet(claimData, lbrynetResult);
if (!fileData) { if (!fileData) {
throw new Error('claim/get: createFileRecordDataAfterGet failed to create file in time'); throw new Error('claim/get: createFileRecordDataAfterGet failed to create file in time');

View file

@ -1,6 +1,17 @@
const logger = require('winston'); const logger = require('winston');
const { details, publishing } = require('@config/siteConfig'); const { details, publishing } = require('@config/siteConfig');
const createPublishParams = (filePath, name, title, description, license, nsfw, thumbnail, channelName, channelClaimId) => { const createPublishParams = (
filePath,
name,
title,
description,
license,
licenseUrl,
nsfw,
thumbnail,
channelName,
channelClaimId
) => {
// provide defaults for title // provide defaults for title
if (title === null || title.trim() === '') { if (title === null || title.trim() === '') {
title = name; title = name;
@ -13,6 +24,10 @@ const createPublishParams = (filePath, name, title, description, license, nsfw,
if (license === null || license.trim() === '') { if (license === null || license.trim() === '') {
license = ''; // default to empty string license = ''; // default to empty string
} }
// provide default for licenseUrl
if (licenseUrl === null || licenseUrl.trim() === '') {
licenseUrl = ''; // default to empty string
}
// create the basic publish params // create the basic publish params
const publishParams = { const publishParams = {
name, name,
@ -24,6 +39,7 @@ const createPublishParams = (filePath, name, title, description, license, nsfw,
author: details.title, author: details.title,
language: 'en', language: 'en',
license, license,
licenseUrl,
nsfw, nsfw,
}, },
claim_address: publishing.primaryClaimAddress, claim_address: publishing.primaryClaimAddress,

View file

@ -1,7 +1,7 @@
const logger = require('winston'); const logger = require('winston');
const { details, publishing } = require('@config/siteConfig'); const { details, publishing } = require('@config/siteConfig');
const createThumbnailPublishParams = (thumbnailFilePath, claimName, license, nsfw) => { const createThumbnailPublishParams = (thumbnailFilePath, claimName, license, licenseUrl, nsfw) => {
if (!thumbnailFilePath) { if (!thumbnailFilePath) {
return; return;
} }
@ -17,6 +17,7 @@ const createThumbnailPublishParams = (thumbnailFilePath, claimName, license, nsf
author: details.title, author: details.title,
language: 'en', language: 'en',
license, license,
licenseUrl,
nsfw, nsfw,
}, },
claim_address: publishing.primaryClaimAddress, claim_address: publishing.primaryClaimAddress,

View file

@ -1,10 +1,15 @@
const logger = require('winston'); const logger = require('winston');
const { details: { host }, publishing: { disabled, disabledMessage } } = require('@config/siteConfig'); const {
details: { host },
publishing: { disabled, disabledMessage },
} = require('@config/siteConfig');
const { sendGATimingEvent } = require('../../../../utils/googleAnalytics.js'); const { sendGATimingEvent } = require('server/utils/googleAnalytics.js');
const isApprovedChannel = require('@globalutils/isApprovedChannel'); const isApprovedChannel = require('@globalutils/isApprovedChannel');
const { publishing: { publishOnlyApproved, approvedChannels } } = require('@config/siteConfig'); const {
publishing: { publishOnlyApproved, approvedChannels },
} = require('@config/siteConfig');
const { handleErrorResponse } = require('../../../utils/errorHandlers.js'); const { handleErrorResponse } = require('../../../utils/errorHandlers.js');
@ -55,6 +60,7 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res)
fileType, fileType,
gaStartTime, gaStartTime,
license, license,
licenseUrl,
name, name,
nsfw, nsfw,
thumbnail, thumbnail,
@ -69,8 +75,24 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res)
// validate the body and files of the request // validate the body and files of the request
try { try {
// validateApiPublishRequest(body, files); // validateApiPublishRequest(body, files);
({name, nsfw, license, title, description, thumbnail} = parsePublishApiRequestBody(body)); ({
({fileName, filePath, fileExtension, fileType, thumbnailFileName, thumbnailFilePath, thumbnailFileType} = parsePublishApiRequestFiles(files)); name,
nsfw,
license,
licenseUrl,
title,
description,
thumbnail,
} = parsePublishApiRequestBody(body));
({
fileName,
filePath,
fileExtension,
fileType,
thumbnailFileName,
thumbnailFilePath,
thumbnailFileType,
} = parsePublishApiRequestFiles(files));
({ channelName, channelId, channelPassword } = body); ({ channelName, channelId, channelPassword } = body);
} catch (error) { } catch (error) {
return res.status(400).json({ success: false, message: error.message }); return res.status(400).json({ success: false, message: error.message });
@ -88,8 +110,19 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res)
return Promise.all([ return Promise.all([
checkClaimAvailability(name), checkClaimAvailability(name),
createPublishParams(filePath, name, title, description, license, nsfw, thumbnail, channelName, channelClaimId), createPublishParams(
createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw), filePath,
name,
title,
description,
license,
licenseUrl,
nsfw,
thumbnail,
channelName,
channelClaimId
),
createThumbnailPublishParams(thumbnailFilePath, name, license, licenseUrl, nsfw),
]); ]);
}) })
.then(([claimAvailable, publishParams, thumbnailPublishParams]) => { .then(([claimAvailable, publishParams, thumbnailPublishParams]) => {
@ -113,9 +146,15 @@ const claimPublish = ({ body, files, headers, ip, originalUrl, user, tor }, res)
({ claimId } = claimData); ({ claimId } = claimData);
if (channelName) { if (channelName) {
return chainquery.claim.queries.getShortClaimIdFromLongClaimId(claimData.certificateId, channelName); logger.info(`api/claim/publish: claimData.certificateId ${claimData.certificateId}`);
return chainquery.claim.queries.getShortClaimIdFromLongClaimId(
claimData.certificateId,
channelName
);
} else { } else {
return chainquery.claim.queries.getShortClaimIdFromLongClaimId(claimId, name, claimData).catch(() => { return chainquery.claim.queries
.getShortClaimIdFromLongClaimId(claimId, name, claimData)
.catch(() => {
return claimId.slice(0, 1); return claimId.slice(0, 1);
}); });
} }

View file

@ -1,15 +1,26 @@
const parsePublishApiRequestBody = ({name, nsfw, license, title, description, thumbnail}) => { const parsePublishApiRequestBody = ({
name,
nsfw,
license,
licenseUrl,
title,
description,
thumbnail,
}) => {
// validate name // validate name
if (!name) { if (!name) {
throw new Error('no name field found in request'); throw new Error('no name field found in request');
} }
const invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name); const invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name);
if (invalidNameCharacters) { if (invalidNameCharacters) {
throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"'); throw new Error(
'The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"'
);
} }
// optional parameters // optional parameters
nsfw = (nsfw === 'true'); nsfw = nsfw === 'true';
license = license || null; license = license || null;
licenseUrl = licenseUrl || null;
title = title || null; title = title || null;
description = description || null; description = description || null;
thumbnail = thumbnail || null; thumbnail = thumbnail || null;
@ -18,6 +29,7 @@ const parsePublishApiRequestBody = ({name, nsfw, license, title, description, th
name, name,
nsfw, nsfw,
license, license,
licenseUrl,
title, title,
description, description,
thumbnail, thumbnail,

View file

@ -19,10 +19,11 @@ const createCanonicalLink = require('@globalutils/createCanonicalLink');
route to update a claim through the daemon route to update a claim through the daemon
*/ */
const updateMetadata = ({ nsfw, license, title, description }) => { const updateMetadata = ({ nsfw, license, licenseUrl, title, description }) => {
const update = {}; const update = {};
if (nsfw) update['nsfw'] = nsfw; if (nsfw) update['nsfw'] = nsfw;
if (license) update['license'] = license; if (license) update['license'] = license;
if (licenseUrl) update['license_url'] = licenseUrl;
if (title) update['title'] = title; if (title) update['title'] = title;
if (description) update['description'] = description; if (description) update['description'] = description;
return update; return update;
@ -65,6 +66,7 @@ const claimUpdate = ({ body, files, headers, ip, originalUrl, user, tor }, res)
thumbnail, thumbnail,
fileExtension, fileExtension,
license, license,
licenseUrl,
name, name,
nsfw, nsfw,
thumbnailFileName, thumbnailFileName,
@ -127,10 +129,11 @@ const claimUpdate = ({ body, files, headers, ip, originalUrl, user, tor }, res)
description: claimRecord.description, description: claimRecord.description,
nsfw: claimRecord.nsfw, nsfw: claimRecord.nsfw,
license: claimRecord.license, license: claimRecord.license,
licenseUrl: claimRecord.license_url,
language: 'en', language: 'en',
author: details.title, author: details.title,
}, },
updateMetadata({ title, description, nsfw, license }) updateMetadata({ title, description, nsfw, license, licenseUrl })
); );
const publishParams = { const publishParams = {
name, name,

View file

@ -1,5 +1,12 @@
const logger = require('winston'); const logger = require('winston');
const transformImage = require('./transformImage'); const transformImage = require('./transformImage');
const isValidQueryObject = require('server/utils/isValidQueryObj');
const {
serving: { dynamicFileSizing },
} = require('@config/siteConfig');
const { enabled: dynamicEnabled } = dynamicFileSizing;
const serveFile = async ({ filePath, fileType }, res, originalUrl) => { const serveFile = async ({ filePath, fileType }, res, originalUrl) => {
const queryObject = {}; const queryObject = {};
// TODO: replace quick/dirty try catch with better practice // TODO: replace quick/dirty try catch with better practice
@ -21,7 +28,10 @@ const serveFile = async ({ filePath, fileType }, res, originalUrl) => {
let mediaType = fileType ? fileType.substr(0, fileType.indexOf('/')) : ''; let mediaType = fileType ? fileType.substr(0, fileType.indexOf('/')) : '';
const transform = const transform =
mediaType === 'image' && queryObject.hasOwnProperty('h') && queryObject.hasOwnProperty('w'); mediaType === 'image' &&
queryObject.hasOwnProperty('h') &&
queryObject.hasOwnProperty('w') &&
dynamicEnabled;
const sendFileOptions = { const sendFileOptions = {
headers: { headers: {
@ -32,7 +42,16 @@ const serveFile = async ({ filePath, fileType }, res, originalUrl) => {
}, },
}; };
logger.debug(`fileOptions for ${filePath}:`, sendFileOptions); logger.debug(`fileOptions for ${filePath}:`, sendFileOptions);
try {
if (transform) { if (transform) {
if (!isValidQueryObject(queryObject)) {
logger.debug(`Unacceptable querystring`, { queryObject });
res.status(400).json({
success: false,
message: 'Querystring may not have dimensions greater than 2000',
});
res.end();
}
logger.debug(`transforming and sending file`); logger.debug(`transforming and sending file`);
let xformed = await transformImage(filePath, queryObject); let xformed = await transformImage(filePath, queryObject);
@ -41,6 +60,9 @@ const serveFile = async ({ filePath, fileType }, res, originalUrl) => {
} else { } else {
res.status(200).sendFile(filePath, sendFileOptions); res.status(200).sendFile(filePath, sendFileOptions);
} }
} catch (e) {
logger.debug(e);
}
}; };
module.exports = serveFile; module.exports = serveFile;

View file

@ -0,0 +1,27 @@
const fs = require('fs');
const { promisify } = require('util');
const fsstat = promisify(fs.stat);
const awaitFileSize = (path, sizeInBytes, timeout, interval) => {
return new Promise((resolve, reject) => {
let totalTime = 0;
let timer = setInterval(() => {
totalTime = totalTime + interval;
fsstat(path)
.then(stats => {
if (stats.size > sizeInBytes) {
clearInterval(interval);
resolve('ready');
}
if (totalTime > timeout) {
const error = new Error('File did not arrive in time');
error.name = 'FILE_NOT_ARRIVED';
reject(error);
}
})
.catch();
}, interval);
});
};
module.exports = awaitFileSize;

View file

@ -59,5 +59,8 @@ module.exports = async (data, chName = null, chShortId = null) => {
host, host,
pending: Boolean(dataVals.height === 0), pending: Boolean(dataVals.height === 0),
blocked: blocked, blocked: blocked,
license: dataVals.license,
licenseUrl: dataVals.license_url,
transactionTime: dataVals.transaction_time,
}; };
}; };

View file

@ -0,0 +1,24 @@
const {
serving: { dynamicFileSizing },
} = require('@config/siteConfig');
const { maxDimension } = dynamicFileSizing;
const isValidQueryObj = queryObj => {
let {
h: cHeight = null,
w: cWidth = null,
t: transform = null,
x: xOrigin = null,
y: yOrigin = null,
} = queryObj;
return (
((cHeight <= maxDimension && cHeight > 0) || cHeight === null) &&
((cWidth <= maxDimension && cWidth > 0) || cWidth === null) &&
(transform === null || transform === 'crop' || transform === 'stretch') &&
((xOrigin <= maxDimension && xOrigin >= 0) || xOrigin === null) &&
((yOrigin <= maxDimension && yOrigin >= 0) || yOrigin === null)
);
};
module.exports = isValidQueryObj;

View file

@ -39,6 +39,9 @@ module.exports = () => {
moduleAliases['@clientutils'] = resolve(`${DEFAULT_ROOT}/utils`); moduleAliases['@clientutils'] = resolve(`${DEFAULT_ROOT}/utils`);
// moduleAliases['@serverutils'] = resolve('server/utils'); // moduleAliases['@serverutils'] = resolve('server/utils');
// aliases for constants
moduleAliases['@clientConstants'] = resolve(`${DEFAULT_ROOT}/constants`);
// create specific aliases for locally defined components in the following folders // create specific aliases for locally defined components in the following folders
moduleAliases = addAliasesForCustomComponentFolder('containers', moduleAliases); moduleAliases = addAliasesForCustomComponentFolder('containers', moduleAliases);
moduleAliases = addAliasesForCustomComponentFolder('components', moduleAliases); moduleAliases = addAliasesForCustomComponentFolder('components', moduleAliases);
@ -53,7 +56,6 @@ module.exports = () => {
moduleAliases['@sagas'] = resolve(`${DEFAULT_ROOT}/sagas`); moduleAliases['@sagas'] = resolve(`${DEFAULT_ROOT}/sagas`);
moduleAliases['@app'] = resolve(`${DEFAULT_ROOT}/app.js`); moduleAliases['@app'] = resolve(`${DEFAULT_ROOT}/app.js`);
// return finished aliases // return finished aliases
return moduleAliases; return moduleAliases;
}; };