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