mirror of
https://github.com/tedkulp/vidgrab
synced 2026-04-18 21:34:02 -04:00
Back to nextjs
This commit is contained in:
@@ -5,17 +5,19 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { EventEmitterModule } from '@nestjs/event-emitter';
|
||||
import { BullModule } from '@nestjs/bull';
|
||||
|
||||
import configuration from '../config/configuration';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { WebModule } from '../web/web.module';
|
||||
import { YtdlModule } from '../ytdl/ytdl.module';
|
||||
import { JobGateway } from './job.gateway';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
ignoreEnvFile: true,
|
||||
isGlobal: true,
|
||||
// load: [configuration],
|
||||
load: [configuration],
|
||||
}),
|
||||
EventEmitterModule.forRoot({
|
||||
wildcard: true,
|
||||
@@ -38,6 +40,6 @@ import { YtdlModule } from '../ytdl/ytdl.module';
|
||||
WebModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
providers: [AppService, JobGateway],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import {
|
||||
OnGatewayConnection,
|
||||
OnGatewayDisconnect,
|
||||
WebSocketGateway,
|
||||
WebSocketServer,
|
||||
} from '@nestjs/websockets';
|
||||
import { pick } from 'lodash';
|
||||
import { Server, Socket } from 'socket.io';
|
||||
|
||||
import { JobEvent } from '@vidgrab2/api-interfaces';
|
||||
|
||||
@WebSocketGateway()
|
||||
export class JobGateway implements OnGatewayConnection, OnGatewayDisconnect {
|
||||
private readonly logger = new Logger(JobGateway.name);
|
||||
|
||||
@WebSocketServer()
|
||||
private server: Server | undefined;
|
||||
private clients: Socket[] = [];
|
||||
|
||||
handleConnection(client: Socket) {
|
||||
this.clients.push(client);
|
||||
this.logger.verbose('handleConnection', client);
|
||||
}
|
||||
|
||||
handleDisconnect(client: Socket) {
|
||||
for (let i = 0; i < this.clients.length; i++) {
|
||||
if (this.clients[i] === client) {
|
||||
this.clients.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose('handleDisconnect', client);
|
||||
}
|
||||
|
||||
private broadcast(event: string, message: any) {
|
||||
const broadCastMessage = JSON.stringify(message);
|
||||
for (const c of this.clients) {
|
||||
c.send(event, broadCastMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@OnEvent('job.added')
|
||||
async sendAddedJob(payload: JobEvent) {
|
||||
if (this.server && payload.job) {
|
||||
const state = await payload.job.getState();
|
||||
const progress = payload.job.progress();
|
||||
|
||||
payload.job = {
|
||||
...pick(payload.job, ['id', 'name', 'data']),
|
||||
progress: progress ? `${progress}%` : 'n/a',
|
||||
state: state,
|
||||
};
|
||||
this.server.emit('job.added', payload);
|
||||
}
|
||||
}
|
||||
|
||||
@OnEvent('job.updated')
|
||||
async sendJobUpdate(payload: JobEvent) {
|
||||
if (this.server && payload.job) {
|
||||
const state = await payload.job.getState();
|
||||
const progress = payload.job.progress();
|
||||
|
||||
payload.job = {
|
||||
...pick(payload.job, ['id', 'name', 'data']),
|
||||
progress: progress ? `${progress}%` : 'n/a',
|
||||
state: state,
|
||||
};
|
||||
this.server.emit('job.updated', payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export default () => ({
|
||||
redisHost: process.env.REDIS_HOST || 'localhost',
|
||||
redisPort: process.env.REDIS_PORT
|
||||
? parseInt(process.env.REDIS_PORT, 10)
|
||||
: 6379,
|
||||
fileDir: process.env.FILE_DIR || '/tmp',
|
||||
});
|
||||
@@ -1,13 +1,15 @@
|
||||
import { InjectQueue } from '@nestjs/bull';
|
||||
import {
|
||||
Body,
|
||||
CacheInterceptor,
|
||||
CacheTTL,
|
||||
Controller,
|
||||
Get,
|
||||
HttpCode,
|
||||
Logger,
|
||||
Post,
|
||||
Render,
|
||||
Req,
|
||||
UseInterceptors,
|
||||
UsePipes,
|
||||
ValidationPipe,
|
||||
} from '@nestjs/common';
|
||||
@@ -28,8 +30,9 @@ export class WebController {
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@Render('Index')
|
||||
@Get('/info')
|
||||
// @Render('Index')
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async root(@Req() request: any) {
|
||||
const fullUrl =
|
||||
request.protocol + '://' + request.get('host') + request.originalUrl;
|
||||
@@ -75,6 +78,8 @@ export class WebController {
|
||||
}
|
||||
|
||||
@Get('/extractors')
|
||||
@UseInterceptors(CacheInterceptor)
|
||||
@CacheTTL(600)
|
||||
async listExtractors() {
|
||||
const extractors = await this.ytdlService.listExtractors();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BullModule } from '@nestjs/bull';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CacheModule, Module } from '@nestjs/common';
|
||||
import { YtdlModule } from '../ytdl/ytdl.module';
|
||||
|
||||
import { WebController } from './web.controller';
|
||||
@@ -9,6 +9,7 @@ import { WebController } from './web.controller';
|
||||
BullModule.registerQueue({
|
||||
name: 'vidgrab',
|
||||
}),
|
||||
CacheModule.register(),
|
||||
YtdlModule,
|
||||
],
|
||||
controllers: [WebController],
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ConfigService } from '@nestjs/config';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { Job } from 'bull';
|
||||
import { throttle } from 'lodash';
|
||||
import split from 'split2';
|
||||
import * as split from 'split2';
|
||||
import { QueueDto } from '@vidgrab2/api-interfaces';
|
||||
import { raw } from 'youtube-dl-exec';
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["src/plugins/index.js"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"no-undef": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"fileServerFolder": ".",
|
||||
"fixturesFolder": "./src/fixtures",
|
||||
"integrationFolder": "./src/integration",
|
||||
"modifyObstructiveCode": false,
|
||||
"pluginsFile": "./src/plugins/index",
|
||||
"supportFile": "./src/support/index.ts",
|
||||
"video": true,
|
||||
"videosFolder": "../../dist/cypress/apps/client-e2e/videos",
|
||||
"screenshotsFolder": "../../dist/cypress/apps/client-e2e/screenshots",
|
||||
"chromeWebSecurity": false
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { getGreeting } from '../support/app.po';
|
||||
|
||||
describe('client', () => {
|
||||
beforeEach(() => cy.visit('/'));
|
||||
|
||||
it('should display welcome message', () => {
|
||||
// Custom command example, see `../support/commands.ts` file
|
||||
cy.login('my-email@something.com', 'myPassword');
|
||||
|
||||
// Function helper example, see `../support/app.po.ts` file
|
||||
getGreeting().contains('Welcome to client!');
|
||||
});
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
|
||||
// Preprocess Typescript file using Nx helper
|
||||
on('file:preprocessor', preprocessTypescript(config));
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export const getGreeting = () => cy.get('h1');
|
||||
@@ -1,33 +0,0 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
declare namespace Cypress {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Chainable<Subject> {
|
||||
login(email: string, password: string): void;
|
||||
}
|
||||
}
|
||||
//
|
||||
// -- This is a parent command --
|
||||
Cypress.Commands.add('login', (email, password) => {
|
||||
console.log('Custom command example: Login', email, password);
|
||||
});
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
@@ -1,17 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"sourceMap": false,
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"allowJs": true,
|
||||
"types": ["cypress", "node"],
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.js"],
|
||||
"angularCompilerOptions": {
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.e2e.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ["@nrwl/next/babel"],
|
||||
"plugins": []
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
||||
+17
-27
@@ -1,36 +1,26 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"extends": [
|
||||
"plugin:@nrwl/nx/react-typescript",
|
||||
"../../.eslintrc.json",
|
||||
"next",
|
||||
"next/core-web-vitals"
|
||||
],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"extends": [
|
||||
"plugin:@nrwl/nx/angular",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
],
|
||||
"rules": {
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "attribute",
|
||||
"prefix": "vidgrab2",
|
||||
"style": "camelCase"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "vidgrab2",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
]
|
||||
}
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.html"],
|
||||
"extends": ["plugin:@nrwl/nx/angular-template"],
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
],
|
||||
"env": {
|
||||
"jest": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
|
||||
import './jobs.module.css';
|
||||
|
||||
interface Props {
|
||||
jobs?: any[];
|
||||
}
|
||||
|
||||
const Container: React.FC<Props> = ({ jobs }) => {
|
||||
return (
|
||||
<table className="table is-striped is-hoverable is-fullwidth is-narrow">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Status</th>
|
||||
<th>
|
||||
<abbr title="Service">Svc</abbr>
|
||||
</th>
|
||||
<th>Title</th>
|
||||
<th>
|
||||
<abbr title="Percent Downloaded">%</abbr>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{jobs &&
|
||||
jobs.map((j) => (
|
||||
<tr key={j.id}>
|
||||
<td>{j.id}</td>
|
||||
<td>{j.state}</td>
|
||||
<td>{j.data.extractor}</td>
|
||||
<td>
|
||||
<a
|
||||
href={j.data.url}
|
||||
title={j.data.title}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{j.data.title}
|
||||
</a>
|
||||
</td>
|
||||
<td>{j.progress}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
||||
|
||||
export default Container;
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
declare module '*.svg' {
|
||||
const content: any;
|
||||
export const ReactComponent: any;
|
||||
export default content;
|
||||
}
|
||||
@@ -1,20 +1,10 @@
|
||||
module.exports = {
|
||||
displayName: 'client',
|
||||
preset: '../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||
},
|
||||
},
|
||||
coverageDirectory: '../../coverage/apps/client',
|
||||
transform: {
|
||||
'^.+\\.(ts|js|html)$': 'jest-preset-angular',
|
||||
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',
|
||||
'^.+\\.[tj]sx?$': 'babel-jest',
|
||||
},
|
||||
snapshotSerializers: [
|
||||
'jest-preset-angular/build/serializers/no-ng-attributes',
|
||||
'jest-preset-angular/build/serializers/ng-snapshot',
|
||||
'jest-preset-angular/build/serializers/html-comment',
|
||||
],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/apps/client',
|
||||
};
|
||||
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
@@ -0,0 +1,15 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const withNx = require('@nrwl/next/plugins/with-nx');
|
||||
|
||||
/**
|
||||
* @type {import('@nrwl/next/plugins/with-nx').WithNxOptions}
|
||||
**/
|
||||
const nextConfig = {
|
||||
nx: {
|
||||
// Set this to false if you do not want to use SVGR
|
||||
// See: https://github.com/gregberge/svgr
|
||||
svgr: true,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = withNx(nextConfig);
|
||||
@@ -0,0 +1,6 @@
|
||||
import '../styles/styles.css';
|
||||
|
||||
// This default export is required in a new `pages/_app.js` file.
|
||||
export default function MyApp({ Component, pageProps }) {
|
||||
return <Component {...pageProps} />;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import Document, { Head, Html, Main, NextScript } from 'next/document';
|
||||
|
||||
class MyDocument extends Document {
|
||||
static async getInitialProps(ctx) {
|
||||
const initialProps = await Document.getInitialProps(ctx);
|
||||
return { ...initialProps };
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html>
|
||||
<Head>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
|
||||
/>
|
||||
</Head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<section className="section has-background-light">
|
||||
<div className="container">
|
||||
<nav className="level">
|
||||
<h1 className="title is-1 level-item has-text-centered">
|
||||
Vidgrab
|
||||
</h1>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Main />
|
||||
</div>
|
||||
|
||||
<footer id="footer" className="footer">
|
||||
<div className="content has-text-centered">
|
||||
<p>
|
||||
Code and “Design” by <a href="#">Ted Kulp</a>. Based
|
||||
on youtube-dl.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument;
|
||||
@@ -0,0 +1,41 @@
|
||||
import { NextPage, NextPageContext } from 'next';
|
||||
|
||||
// The component's props type
|
||||
type PageProps = {
|
||||
extractors?: string[];
|
||||
};
|
||||
|
||||
// extending the default next context type
|
||||
type PageContext = NextPageContext & {
|
||||
query: PageProps;
|
||||
};
|
||||
|
||||
// react component
|
||||
const Page: NextPage<PageProps> = ({ extractors }) => {
|
||||
return (
|
||||
<>
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<div className="content">
|
||||
<p>
|
||||
Here is the list of currently supported services. This is
|
||||
generated dynamically because youtube-dl adds new services all the
|
||||
time.
|
||||
</p>
|
||||
<ul>{extractors && extractors.map((e) => <li key={e}>{e}</li>)}</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export async function getServerSideProps({ query }: PageContext) {
|
||||
const res = await fetch('http://localhost:3333/api/extractors');
|
||||
|
||||
return {
|
||||
props: await res?.json(),
|
||||
};
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,94 @@
|
||||
import { NextPage, NextPageContext, GetServerSideProps } from 'next';
|
||||
import React, { useState } from 'react';
|
||||
import getRawBody from 'raw-body';
|
||||
import { YtResponse } from 'youtube-dl-exec';
|
||||
|
||||
// The component's props type
|
||||
type PageProps = {
|
||||
title: string;
|
||||
extractor: string;
|
||||
description: string;
|
||||
videoUrl: string;
|
||||
thumbnails: string;
|
||||
upload_date: string;
|
||||
duration: number;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
formats: any[];
|
||||
};
|
||||
|
||||
// extending the default next context type
|
||||
type PageContext = NextPageContext & {
|
||||
query: PageProps;
|
||||
};
|
||||
|
||||
// react component
|
||||
const Page: NextPage<PageProps> = (props) => {
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
|
||||
const onSubmit = (e: React.SyntheticEvent) => {
|
||||
setSubmitted(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<form method="POST" action="/" onSubmit={onSubmit}>
|
||||
<div className="field is-grouped">
|
||||
<div className="control is-expanded">
|
||||
<div className="select is-fullwidth">
|
||||
<select name="format">
|
||||
{props.formats &&
|
||||
props.formats.map((f) => (
|
||||
<option key={f.format_id} value={f.format_id}>
|
||||
{f.format} ({f.ext})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="control">
|
||||
<button
|
||||
className={`button is-primary ${submitted?'is-loading':''}`}
|
||||
id="form-submit"
|
||||
type="submit"
|
||||
>
|
||||
Queue Download
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="url" value={props.videoUrl} />
|
||||
<input type="hidden" name="title" value={props.title} />
|
||||
<input type="hidden" name="extractor" value={props.extractor} />
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const getServerSideProps: GetServerSideProps<YtResponse> = async ({ req }) => {
|
||||
let data: YtResponse;
|
||||
|
||||
if (req.method == "POST") {
|
||||
const body = await getRawBody(req);
|
||||
|
||||
const res = await fetch('http://localhost:3333/api/getinfo', {
|
||||
method: 'post',
|
||||
body: body.toString('utf-8'),
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
});
|
||||
data = await res.json();
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
...data,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,138 @@
|
||||
import { NextPage, NextPageContext, GetServerSideProps } from 'next';
|
||||
import Link from 'next/link';
|
||||
import getRawBody from 'raw-body';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Client from 'socket.io-client';
|
||||
|
||||
import Jobs from '../components/jobs/jobs';
|
||||
|
||||
// The component's props type
|
||||
type PageProps = {
|
||||
bookmarklet?: string;
|
||||
jobs?: any[];
|
||||
};
|
||||
|
||||
// extending the default next context type
|
||||
type PageContext = NextPageContext & {
|
||||
query: PageProps;
|
||||
};
|
||||
|
||||
// react component
|
||||
const Page: NextPage<PageProps> = ({ bookmarklet, jobs }) => {
|
||||
const [_socket, setSocket] = useState<any>();
|
||||
const [currentJobs, setCurrentJobs] = useState<any>(jobs);
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
|
||||
const onSubmit = (e: React.SyntheticEvent) => {
|
||||
setSubmitted(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const newSocket = Client();
|
||||
setSocket(newSocket);
|
||||
|
||||
newSocket.on('job.added', (payload: any) => {
|
||||
setCurrentJobs((current: any[]) => {
|
||||
return [payload.job, ...current.slice(0, -1)];
|
||||
});
|
||||
});
|
||||
|
||||
newSocket.on('job.updated', (payload: any) => {
|
||||
setCurrentJobs((current: { id: any }[]) => {
|
||||
const foundIndex = current.findIndex(
|
||||
(cj: { id: any }) => cj.id == payload.job.id
|
||||
);
|
||||
|
||||
if (foundIndex > -1) {
|
||||
current[foundIndex] = payload.job;
|
||||
}
|
||||
|
||||
return [...current];
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
newSocket.disconnect();
|
||||
setSocket(undefined);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<form method="POST" action="/getinfo" onSubmit={onSubmit}>
|
||||
<div className="field is-grouped">
|
||||
<div className="control is-expanded">
|
||||
<input
|
||||
className="input is-medium"
|
||||
name="url"
|
||||
placeholder="URL to Download"
|
||||
/>
|
||||
<p className="help">
|
||||
<Link href="/extractors">
|
||||
* List of currently available services
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
<div className="control">
|
||||
<button
|
||||
className={`button is-primary is-medium ${submitted?'is-loading':''}`}
|
||||
id="form-submit"
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="container content has-text-centered">
|
||||
<p>Drag this to your bookmark bar!</p>
|
||||
<a
|
||||
className="bookmarklet"
|
||||
ref={(node) =>
|
||||
node && bookmarklet && node.setAttribute('href', bookmarklet)
|
||||
}
|
||||
>
|
||||
Vidgrab It!
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<h2 className="subtitle is-4 has-text-centered">Recent Downloads</h2>
|
||||
|
||||
<Jobs jobs={currentJobs} />
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async ({ req }) => {
|
||||
let data;
|
||||
|
||||
if (req.method == "POST") {
|
||||
const body = await getRawBody(req);
|
||||
|
||||
const res = await fetch('http://localhost:3333/api/queue', {
|
||||
method: 'post',
|
||||
body: body.toString('utf-8'),
|
||||
headers: {
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
});
|
||||
data = await res.json();
|
||||
}
|
||||
|
||||
const res = await fetch('http://localhost:3333/api/info');
|
||||
|
||||
return {
|
||||
props: await res.json(),
|
||||
};
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -2,5 +2,10 @@
|
||||
"/api": {
|
||||
"target": "http://localhost:3333",
|
||||
"secure": false
|
||||
},
|
||||
"/socket.io": {
|
||||
"target": "http://localhost:3333",
|
||||
"secure": false,
|
||||
"ws": true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="262px" height="163px" viewBox="0 0 262 163" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="Styles-&-Quick-Wins" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Nx---Quick-Wins" transform="translate(-476.000000, -1284.000000)" fill-rule="nonzero">
|
||||
<g id="Logos" transform="translate(-11.000000, 782.000000)">
|
||||
<g id="Nx_Flat_White" transform="translate(487.000000, 502.000000)">
|
||||
<polygon id="Path" fill="#FFFFFF" points="130.68 104.59 97.49 52.71 97.44 96.3 40.24 0 0 0 0 162.57 39.79 162.57 39.92 66.39 96.53 158.26"/>
|
||||
<polygon id="Path" fill="#FFFFFF" points="97.5 41.79 137.24 41.79 137.33 41.33 137.33 0 97.54 0 97.49 41.33"/>
|
||||
<path d="M198.66,86.86 C189.139872,86.6795216 180.538723,92.516445 177.19,101.43 C182.764789,93.0931021 193.379673,89.7432211 202.73,93.37 C207.05,95.13 212.73,97.97 217.23,96.45 C212.950306,90.4438814 206.034895,86.8725952 198.66,86.86 L198.66,86.86 Z" id="Path" fill="#96D8E9"/>
|
||||
<path d="M243.75,106.42 C243.75,101.55 241.1,100.42 235.6,98.42 C231.52,97 226.89,95.4 223.52,91 C222.86,90.13 222.25,89.15 221.6,88.11 C220.14382,85.4164099 218.169266,83.037429 215.79,81.11 C212.58,78.75 208.37,77.6 202.91,77.6 C191.954261,77.6076705 182.084192,84.2206169 177.91,94.35 C183.186964,87.0278244 191.956716,83.0605026 200.940147,83.9314609 C209.923578,84.8024193 217.767888,90.3805017 221.54,98.58 C223.424615,101.689762 227.141337,103.174819 230.65,102.22 C236.02,101.07 235.65,106.15 243.76,107.87 L243.75,106.42 Z" id="Path" fill="#48C4E5"/>
|
||||
<path d="M261.46,105.38 L261.46,105.27 C261.34,73.03 235.17,45.45 202.91,45.45 C183.207085,45.4363165 164.821777,55.3450614 154,71.81 L153.79,71.45 L137.23,45.45 L97.5,45.4499858 L135.25,104.57 L98.41,162.57 L137,162.57 L153.79,136.78 L170.88,162.57 L209.48,162.57 L174.48,107.49 C173.899005,106.416838 173.583536,105.220114 173.56,104 C173.557346,96.2203871 176.64661,88.7586448 182.147627,83.2576275 C187.648645,77.7566101 195.110387,74.6673462 202.89,74.67 C219.11,74.67 221.82,84.37 225.32,88.93 C232.23,97.93 246.03,93.99 246.03,105.73 L246.03,105.73 C246.071086,108.480945 247.576662,111.001004 249.979593,112.340896 C252.382524,113.680787 255.317747,113.636949 257.679593,112.225896 C260.041438,110.814842 261.471086,108.250945 261.43,105.5 L261.43,105.5 L261.43,105.38 L261.46,105.38 Z" id="Path" fill="#FFFFFF"/>
|
||||
<path d="M261.5,113.68 C261.892278,116.421801 261.504116,119.218653 260.38,121.75 C258.18,126.84 254.51,125.14 254.51,125.14 C254.51,125.14 251.35,123.6 253.27,120.65 C255.4,117.36 259.61,117.74 261.5,113.68 Z" id="Path" fill="#FFFFFF"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg
|
||||
className="material-icons"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 347 B |
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
import Index from '../pages/index';
|
||||
|
||||
describe('Index', () => {
|
||||
it('should render successfully', () => {
|
||||
const { baseElement } = render(<Index />);
|
||||
expect(baseElement).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
<!-- <div style="text-align: center">
|
||||
<h1>Welcome to client!</h1>
|
||||
<img
|
||||
width="450"
|
||||
src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png"
|
||||
alt="Nx - Smart, Extensible Build Framework"
|
||||
/>
|
||||
</div>
|
||||
<div>Message: {{ hello$ | async | json }}</div> -->
|
||||
<router-outlet></router-outlet>
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Remove template code below
|
||||
*/
|
||||
:host {
|
||||
display: block;
|
||||
font-family: sans-serif;
|
||||
min-width: 300px;
|
||||
max-width: 600px;
|
||||
margin: 50px auto;
|
||||
}
|
||||
|
||||
.gutter-left {
|
||||
margin-left: 9px;
|
||||
}
|
||||
|
||||
.col-span-2 {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #143055;
|
||||
color: white;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 0 36px;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-left: 18px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
margin: 40px 0 10px 0;
|
||||
}
|
||||
|
||||
.resources {
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-gap: 9px;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.resource {
|
||||
color: #0094ba;
|
||||
height: 36px;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||
border-radius: 4px;
|
||||
padding: 3px 9px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.resource:hover {
|
||||
background-color: rgba(68, 138, 255, 0.04);
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 9px;
|
||||
border-radius: 4px;
|
||||
background-color: black;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
details {
|
||||
border-radius: 4px;
|
||||
color: #333;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border: 1px solid rgba(0, 0, 0, 0.12);
|
||||
padding: 3px 9px;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.github-star-container {
|
||||
margin-top: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.github-star-container a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.github-star-badge {
|
||||
color: #24292e;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
padding: 3px 10px;
|
||||
border: 1px solid rgba(27, 31, 35, 0.2);
|
||||
border-radius: 3px;
|
||||
background-image: linear-gradient(-180deg, #fafbfc, #eff3f6 90%);
|
||||
margin-left: 4px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.github-star-badge:hover {
|
||||
background-image: linear-gradient(-180deg, #f0f3f6, #e6ebf1 90%);
|
||||
border-color: rgba(27, 31, 35, 0.35);
|
||||
background-position: -0.5em;
|
||||
}
|
||||
.github-star-badge .material-icons {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AppComponent],
|
||||
imports: [HttpClientModule],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Message } from '@vidgrab2/api-interfaces';
|
||||
|
||||
@Component({
|
||||
selector: 'vidgrab2-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
})
|
||||
export class AppComponent {
|
||||
hello$ = this.http.get<Message>('/api/hello');
|
||||
constructor(private http: HttpClient) {}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { ExtractorsComponent } from './extractors/extractors.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: AppComponent },
|
||||
{ path: 'extractors', component: ExtractorsComponent },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, ExtractorsComponent],
|
||||
imports: [BrowserModule, HttpClientModule, RouterModule.forRoot(routes)],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
@@ -1,13 +0,0 @@
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="content">
|
||||
<p>
|
||||
Here is the list of currently supported services. This is generated
|
||||
dynamically because youtube-dl adds new services all the time.
|
||||
</p>
|
||||
<ul>
|
||||
<li *ngFor="let e of extractors$ | async">{{ e }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,20 +0,0 @@
|
||||
/* eslint-disable @angular-eslint/no-empty-lifecycle-method */
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'vidgrab2-extractors',
|
||||
templateUrl: './extractors.component.html',
|
||||
styleUrls: ['./extractors.component.scss']
|
||||
})
|
||||
export class ExtractorsComponent implements OnInit {
|
||||
|
||||
extractors$ = this.http.get<{extractors: string[]}>('/api/extractors').pipe(map(e => e.extractors));
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
// Does a thing
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment = {
|
||||
production: false,
|
||||
};
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Client</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<section class="section has-background-light">
|
||||
<div class="container">
|
||||
<nav class="level">
|
||||
<h1 class="title is-1 level-item has-text-centered">Vidgrab</h1>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<vidgrab2-root></vidgrab2-root>
|
||||
</div>
|
||||
|
||||
<footer id="footer" class="footer">
|
||||
<div class="content has-text-centered">
|
||||
<p>
|
||||
Code and "Design" by <a href="#">Ted Kulp</a>. Based on youtube-dl.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,13 +0,0 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic()
|
||||
.bootstrapModule(AppModule)
|
||||
.catch((err) => console.error(err));
|
||||
@@ -1,64 +0,0 @@
|
||||
/**
|
||||
* This file includes polyfills needed by Angular and is loaded before the app.
|
||||
* You can add your own extra polyfills to this file.
|
||||
*
|
||||
* This file is divided into 2 sections:
|
||||
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||
* file.
|
||||
*
|
||||
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||
*
|
||||
* Learn more in https://angular.io/guide/browser-support
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* BROWSER POLYFILLS
|
||||
*/
|
||||
|
||||
/**
|
||||
* IE11 requires the following for NgClass support on SVG elements
|
||||
*/
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/**
|
||||
* Web Animations `@angular/platform-browser/animations`
|
||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||||
*/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
/**
|
||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||
* because those flags need to be set before `zone.js` being loaded, and webpack
|
||||
* will put import in the top of bundle, so user need to create a separate file
|
||||
* in this directory (for example: zone-flags.ts), and put the following flags
|
||||
* into that file, and then add the following code before importing zone.js.
|
||||
* import './zone-flags';
|
||||
*
|
||||
* The flags allowed in zone-flags.ts are listed here.
|
||||
*
|
||||
* The following flags will work for all browsers.
|
||||
*
|
||||
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
|
||||
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||
*
|
||||
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||
*
|
||||
* (window as any).__Zone_enable_cross_context_check = true;
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by default for Angular itself.
|
||||
*/
|
||||
import 'zone.js'; // Included with Angular CLI.
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
@@ -1 +0,0 @@
|
||||
import 'jest-preset-angular/setup-jest';
|
||||
@@ -1,4 +1,3 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
body {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": []
|
||||
},
|
||||
"files": ["src/main.ts", "src/polyfills.ts"],
|
||||
"include": ["src/**/*.d.ts"]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
}
|
||||
}
|
||||
+11
-21
@@ -1,27 +1,17 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.editor.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"jsx": "preserve",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"types": ["node", "jest"],
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true
|
||||
}
|
||||
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
@@ -3,8 +3,14 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
"types": ["jest", "node"],
|
||||
"jsx": "react"
|
||||
},
|
||||
"files": ["src/test-setup.ts"],
|
||||
"include": ["**/*.spec.ts", "**/*.d.ts"]
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user