add files
This commit is contained in:
commit
3bb0ca8293
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
**/*/.next
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"client-dev": "yarn workspace siaviewnode-client dev -p 3000",
|
||||||
|
"server-dev": "yarn workspace siaviewnode-server dev",
|
||||||
|
"dev": "concurrently \"yarn client-dev\" \"yarn server-dev\""
|
||||||
|
},
|
||||||
|
"workspaces": {
|
||||||
|
"packages": [
|
||||||
|
"packages/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"lerna": "3.16.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"concurrently": "5.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/types/global" />
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "siaviewnode-client",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"main": "index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/core": "10.0.21",
|
||||||
|
"@material-ui/core": "4.5.1",
|
||||||
|
"@mdx-js/react": "1.5.1",
|
||||||
|
"axios": "0.19.0",
|
||||||
|
"file-saver": "2.0.2",
|
||||||
|
"isomorphic-unfetch": "3.0.0",
|
||||||
|
"next": "9.1.1",
|
||||||
|
"ramda": "0.26.1",
|
||||||
|
"react": "16.10.2",
|
||||||
|
"react-dom": "16.10.2",
|
||||||
|
"react-dropzone": "10.2.1",
|
||||||
|
"streamsaver": "2.0.3",
|
||||||
|
"theme-ui": "0.2.44",
|
||||||
|
"typescript": "3.6.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "12.11.1",
|
||||||
|
"@types/ramda": "0.26.36",
|
||||||
|
"@types/theme-ui": "0.2.3"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react'
|
||||||
|
import App from 'next/app'
|
||||||
|
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||||
|
import { ThemeProvider } from 'theme-ui'
|
||||||
|
import { theme } from '../theme/theme'
|
||||||
|
|
||||||
|
class MyApp extends App {
|
||||||
|
// Only uncomment this method if you have blocking data requirements for
|
||||||
|
// every single page in your application. This disables the ability to
|
||||||
|
// perform automatic static optimization, causing every page in your app to
|
||||||
|
// be server-side rendered.
|
||||||
|
//
|
||||||
|
// static async getInitialProps(appContext) {
|
||||||
|
// // calls page's `getInitialProps` and fills `appProps.pageProps`
|
||||||
|
// const appProps = await App.getInitialProps(appContext);
|
||||||
|
//
|
||||||
|
// return { ...appProps }
|
||||||
|
// }
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { Component, pageProps } = this.props
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
<CssBaseline />
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</ThemeProvider>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyApp
|
|
@ -0,0 +1,68 @@
|
||||||
|
/** @jsx jsx */
|
||||||
|
import { jsx, Box, Flex } from "theme-ui"
|
||||||
|
import {
|
||||||
|
Container,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
Typography,
|
||||||
|
CardActions,
|
||||||
|
Button,
|
||||||
|
makeStyles
|
||||||
|
} from "@material-ui/core"
|
||||||
|
import Dropzone from "../src/components/Dropzone"
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
card: {
|
||||||
|
minWidth: 275
|
||||||
|
},
|
||||||
|
bullet: {
|
||||||
|
display: "inline-block",
|
||||||
|
margin: "0 2px",
|
||||||
|
transform: "scale(0.8)"
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 14
|
||||||
|
},
|
||||||
|
pos: {
|
||||||
|
marginBottom: 12
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const Index = () => {
|
||||||
|
const classes = useStyles({})
|
||||||
|
const bull = <span className={classes.bullet}>•</span>
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box color="white">
|
||||||
|
<Container>
|
||||||
|
<Flex sx={{ alignItems: "center", height: 120 }}>
|
||||||
|
<Box>
|
||||||
|
<Typography sx={{ fontWeight: 600 }}>Sia View Node</Typography>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ ml: "auto" }}>
|
||||||
|
<Button href="https://sia.tech/" target="_blank">
|
||||||
|
About Sia
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
</Container>
|
||||||
|
</Box>
|
||||||
|
<Container>
|
||||||
|
<Card sx={{ width: "100%" }}>
|
||||||
|
<CardContent>
|
||||||
|
<Typography
|
||||||
|
className={classes.title}
|
||||||
|
color="textSecondary"
|
||||||
|
gutterBottom
|
||||||
|
>
|
||||||
|
Drop Your File Here:
|
||||||
|
</Typography>
|
||||||
|
<Dropzone />
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Container>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Index
|
|
@ -0,0 +1,65 @@
|
||||||
|
/** @jsx jsx */
|
||||||
|
import * as R from "ramda"
|
||||||
|
import { useCallback } from "react"
|
||||||
|
import { useDropzone } from "react-dropzone"
|
||||||
|
import { Box, Flex, jsx } from "theme-ui"
|
||||||
|
|
||||||
|
import { saveAs } from "file-saver"
|
||||||
|
|
||||||
|
const API_ENDPOINT = "http://localhost:4000"
|
||||||
|
|
||||||
|
function MyDropzone() {
|
||||||
|
const onDrop = useCallback(acceptedFiles => {
|
||||||
|
const file = R.head(acceptedFiles)
|
||||||
|
const fd = new FormData()
|
||||||
|
fd.append("file", file)
|
||||||
|
if (window) {
|
||||||
|
const streamSaver = require("streamsaver")
|
||||||
|
const url = API_ENDPOINT + "/siafile"
|
||||||
|
fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
body: fd
|
||||||
|
}).then(res => {
|
||||||
|
const readableStream = res.body
|
||||||
|
const fileStream = streamSaver.createWriteStream("file.webm")
|
||||||
|
|
||||||
|
// more optimized
|
||||||
|
if (window.WritableStream && readableStream.pipeTo) {
|
||||||
|
return readableStream
|
||||||
|
.pipeTo(fileStream)
|
||||||
|
.then(() => console.log("done writing"))
|
||||||
|
}
|
||||||
|
;(window as any).writer = fileStream.getWriter()
|
||||||
|
const reader = res.body.getReader()
|
||||||
|
const pump = () =>
|
||||||
|
reader
|
||||||
|
.read()
|
||||||
|
.then(res =>
|
||||||
|
res.done
|
||||||
|
? (window as any).writer.close()
|
||||||
|
: (window as any).writer.write(res.value).then(pump)
|
||||||
|
)
|
||||||
|
pump()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Flex
|
||||||
|
{...getRootProps()}
|
||||||
|
sx={{ height: 400, justifyContent: "center", alignItems: "center" }}
|
||||||
|
>
|
||||||
|
<input {...getInputProps()} />
|
||||||
|
{isDragActive ? (
|
||||||
|
<p>Drop the files here ...</p>
|
||||||
|
) : (
|
||||||
|
<p>Drag 'n' drop some files here, or click to select files</p>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MyDropzone
|
|
@ -0,0 +1,13 @@
|
||||||
|
// example theme.js
|
||||||
|
export const theme = {
|
||||||
|
fonts: {
|
||||||
|
body: 'system-ui, sans-serif',
|
||||||
|
heading: '"Avenir Next", sans-serif',
|
||||||
|
monospace: 'Menlo, monospace'
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
text: '#000',
|
||||||
|
background: '#fff',
|
||||||
|
primary: '#33e'
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": false,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx"
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules
|
||||||
|
build
|
||||||
|
npm-debug.log
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Custom Webpack Configuration With Typescript Example
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
Download the example (or clone the whole project)[https://github.com/palmerhq/backpack.git]:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl https://codeload.github.com/palmerhq/backpack/tar.gz/master | tar -xz --strip=2 backpack-master/examples/with-typescript
|
||||||
|
cd with-typescript
|
||||||
|
```
|
||||||
|
|
||||||
|
Install it and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Idea behind the example
|
||||||
|
|
||||||
|
This demonstrates how to customize the underlying Webpack 2 configuration in a Backpack project using a `backpack.config.js` file.
|
||||||
|
The app itself is exactly the same project as the Webpack configuration example. However, the express application is written in TypeScript.
|
|
@ -0,0 +1,20 @@
|
||||||
|
module.exports = {
|
||||||
|
webpack: (config, options, webpack) => {
|
||||||
|
config.entry.main = [
|
||||||
|
'./src/main.ts'
|
||||||
|
]
|
||||||
|
|
||||||
|
config.resolve = {
|
||||||
|
extensions: [".ts", ".js", ".json"]
|
||||||
|
};
|
||||||
|
|
||||||
|
config.module.rules.push(
|
||||||
|
{
|
||||||
|
test: /\.ts$/,
|
||||||
|
loader: 'awesome-typescript-loader'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "siaviewnode-server",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node ./build/main.js",
|
||||||
|
"dev": "PORT=4000 backpack dev",
|
||||||
|
"build": "backpack build"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "^4.0.34",
|
||||||
|
"awesome-typescript-loader": "^5.2.1",
|
||||||
|
"axios": "0.19.0",
|
||||||
|
"backpack-core": "^0.8.4",
|
||||||
|
"cors": "2.8.5",
|
||||||
|
"express": "^4.14.0",
|
||||||
|
"express-fileupload": "1.1.6",
|
||||||
|
"ramda": "0.26.1",
|
||||||
|
"typescript": "^3.5.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/ramda": "0.26.36"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
import * as express from "express"
|
||||||
|
import * as fileUpload from "express-fileupload"
|
||||||
|
import * as R from "ramda"
|
||||||
|
import * as cors from "cors"
|
||||||
|
import axios from "axios"
|
||||||
|
|
||||||
|
const SIAD_ENDPOINT = "http://localhost:9980"
|
||||||
|
|
||||||
|
// simple siad connection with static strings
|
||||||
|
const siad = axios.create({
|
||||||
|
baseURL: SIAD_ENDPOINT,
|
||||||
|
headers: {
|
||||||
|
"User-Agent": "Sia-Agent",
|
||||||
|
"Access-Control-Allow-Origin": "*"
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
|
username: "",
|
||||||
|
password: "d05bb024715aea0bb734ce057acbae27"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
declare var __DEV__: boolean
|
||||||
|
|
||||||
|
export class Server {
|
||||||
|
public app: express.Express
|
||||||
|
public port: number
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.app = express()
|
||||||
|
this.port = this.getPort()
|
||||||
|
this.setRoutes()
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private start = (): void => {
|
||||||
|
this.app.listen(this.port, this.onListen)
|
||||||
|
}
|
||||||
|
|
||||||
|
private onListen = (err: any): void => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__DEV__) {
|
||||||
|
console.log("> in development")
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`> listening on port ${this.port}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPort = (): number => parseInt(process.env.PORT, 10) || 3000
|
||||||
|
|
||||||
|
private setRoutes = (): void => {
|
||||||
|
this.app.use(cors())
|
||||||
|
this.app.use(
|
||||||
|
fileUpload({
|
||||||
|
limits: { fileSize: 10 * 1024 * 1024 }
|
||||||
|
})
|
||||||
|
)
|
||||||
|
this.app.post("/siafile", this.getSiaFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getSiaFile(
|
||||||
|
req: express.Request & any,
|
||||||
|
res: express.Response
|
||||||
|
): Promise<express.Response> {
|
||||||
|
const selectFile = R.path(["files", "file"])
|
||||||
|
try {
|
||||||
|
const file: any = selectFile(req)
|
||||||
|
console.log("file is", req.files)
|
||||||
|
|
||||||
|
const { data: stream } = await siad.post("/renter/stream", file.data, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data"
|
||||||
|
},
|
||||||
|
responseType: "stream"
|
||||||
|
})
|
||||||
|
|
||||||
|
res.attachment(file.name)
|
||||||
|
res.set("Content-Type", "application/octet-stream")
|
||||||
|
|
||||||
|
stream.on("data", chunk => {
|
||||||
|
console.log("chunk...")
|
||||||
|
res.write(chunk)
|
||||||
|
})
|
||||||
|
stream.on("end", () => {
|
||||||
|
console.log("end...")
|
||||||
|
res.end()
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.log("e is", e)
|
||||||
|
return res.json({ error: e.message })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new Server().app
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["es5", "es2015.promise", "dom"],
|
||||||
|
"strict": false,
|
||||||
|
"skipLibCheck": true
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue