diff options
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 4 | ||||
-rw-r--r-- | src/server/apis/google/GoogleApiServerUtils.ts | 13 | ||||
-rw-r--r-- | src/server/apis/google/GooglePhotosUtils.ts | 12 | ||||
-rw-r--r-- | src/server/authentication/config/passport.ts | 18 | ||||
-rw-r--r-- | src/server/credentials/auth.json | 12 | ||||
-rw-r--r-- | src/server/credentials/google_docs_credentials.json | 12 | ||||
-rw-r--r-- | src/server/credentials/google_docs_token.json | 2 | ||||
-rw-r--r-- | src/server/credentials/google_photos_credentials.ts | 35 | ||||
-rw-r--r-- | src/server/index.ts | 27 | ||||
-rw-r--r-- | src/typings/index.d.ts | 632 |
11 files changed, 447 insertions, 323 deletions
diff --git a/package.json b/package.json index f98224469..f0f2b467e 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "@types/node": "^10.12.30", "@types/nodemailer": "^4.6.6", "@types/passport": "^1.0.0", + "@types/passport-google-oauth20": "^2.0.2", "@types/passport-local": "^1.0.33", "@types/pdfjs-dist": "^2.0.0", "@types/prosemirror-commands": "^1.0.1", @@ -141,6 +142,7 @@ "golden-layout": "^1.5.9", "google-auth-library": "^4.2.4", "googleapis": "^40.0.0", + "googlephotos": "^0.2.1", "howler": "^2.1.2", "html-to-image": "^0.1.0", "i": "^0.3.6", @@ -166,6 +168,7 @@ "npm": "^6.10.3", "p-limit": "^2.2.0", "passport": "^0.4.0", + "passport-google-oauth20": "^2.0.0", "passport-local": "^1.0.0", "pdfjs-dist": "^2.0.943", "probe-image-size": "^4.0.0", diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ab87f0c7b..df0718072 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -15,7 +15,7 @@ import { listSpec } from '../../new_fields/Schema'; import { BoolCast, Cast, FieldValue, StrCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString } from '../../Utils'; +import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString, PostToServer } from '../../Utils'; import { DocServer } from '../DocServer'; import { Docs } from '../documents/Documents'; import { ClientUtils } from '../util/ClientUtils'; @@ -128,6 +128,8 @@ export class MainView extends React.Component { window.removeEventListener("keydown", KeyManager.Instance.handle); window.addEventListener("keydown", KeyManager.Instance.handle); + PostToServer('/googleDocs/Photos/Test', {}); + reaction(() => { let workspaces = CurrentUserUtils.UserDocument.workspaces; let recent = CurrentUserUtils.UserDocument.recentlyClosed; diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts index 8785cd974..2fb44d9a2 100644 --- a/src/server/apis/google/GoogleApiServerUtils.ts +++ b/src/server/apis/google/GoogleApiServerUtils.ts @@ -5,6 +5,7 @@ import { OAuth2Client } from "google-auth-library"; import { Opt } from "../../../new_fields/Doc"; import { GlobalOptions } from "googleapis-common"; import { GaxiosResponse } from "gaxios"; +import Photos = require("googlephotos"); /** * Server side authentication for Google Api queries. @@ -20,16 +21,18 @@ export namespace GoogleApiServerUtils { 'presentations.readonly', 'drive', 'drive.file', + 'photoslibrary', + 'photoslibrary.sharing' ]; export const parseBuffer = (data: Buffer) => JSON.parse(data.toString()); export enum Service { Documents = "Documents", - Slides = "Slides" + Slides = "Slides", + Photos = "Photos" } - export interface CredentialPaths { credentials: string; token: string; @@ -50,7 +53,7 @@ export namespace GoogleApiServerUtils { reject(err); return console.log('Error loading client secret file:', err); } - return authorize(parseBuffer(credentials), paths.token).then(auth => { + return authorize(parseBuffer(credentials), paths.token).then(async auth => { let routed: Opt<Endpoint>; let parameters: EndpointParameters = { auth, version: "v1" }; switch (sector) { @@ -60,6 +63,10 @@ export namespace GoogleApiServerUtils { case Service.Slides: routed = google.slides(parameters).presentations; break; + case Service.Photos: + const photos = new Photos(auth); + let response = await photos.albums.list(); + console.log("WE GOT SOMETHING!", response); } resolve(routed); }); diff --git a/src/server/apis/google/GooglePhotosUtils.ts b/src/server/apis/google/GooglePhotosUtils.ts new file mode 100644 index 000000000..c33ad2dd9 --- /dev/null +++ b/src/server/apis/google/GooglePhotosUtils.ts @@ -0,0 +1,12 @@ +import request = require('request-promise'); +const key = require("../../credentials/auth.json"); + +export const PhotosLibraryQuery = async (authToken: any, parameters: any) => { + let options = { + headers: { 'Content-Type': 'application/json' }, + json: parameters, + auth: { 'bearer': authToken }, + }; + const result = await request.post(config.apiEndpoint + '/v1/mediaItems:search', options); + return result; +};
\ No newline at end of file diff --git a/src/server/authentication/config/passport.ts b/src/server/authentication/config/passport.ts index d42741410..97ded8785 100644 --- a/src/server/authentication/config/passport.ts +++ b/src/server/authentication/config/passport.ts @@ -1,12 +1,14 @@ import * as passport from 'passport'; import * as passportLocal from 'passport-local'; -import * as mongodb from 'mongodb'; -import * as _ from "lodash"; +import _ from "lodash"; import { default as User } from '../models/user_model'; import { Request, Response, NextFunction } from "express"; import { RouteStore } from '../../RouteStore'; +import * as GoogleOAuth from "passport-google-oauth20"; +const config = require("../../credentials/google_photos_credentials"); const LocalStrategy = passportLocal.Strategy; +const GoogleOAuthStrategy = GoogleOAuth.Strategy; passport.serializeUser<any, any>((user, done) => { done(undefined, user.id); @@ -32,6 +34,18 @@ passport.use(new LocalStrategy({ usernameField: 'email', passReqToCallback: true }); })); + +passport.use(new GoogleOAuthStrategy( + { + clientID: config.oAuthClientID, + clientSecret: config.oAuthclientSecret, + callbackURL: config.oAuthCallbackUrl, + // Set the correct profile URL that does not require any additional APIs + userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo' + }, + (token, refreshToken, profile, done) => done(undefined, { profile, token }) +)); + export let isAuthenticated = (req: Request, res: Response, next: NextFunction) => { if (req.isAuthenticated()) { return next(); diff --git a/src/server/credentials/auth.json b/src/server/credentials/auth.json new file mode 100644 index 000000000..557eca4b6 --- /dev/null +++ b/src/server/credentials/auth.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": "brown-dash", + "private_key_id": "ddf0473a9ac56956b5818e04a7ee406a64d5b0a6", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCueRfxic2oL9nr\nnWSLgl7XR/BKikm4p2sib6szaoTO+q6itcJgt2TDleK/7Y4KW/KhvCfhWVet0Hz0\nIDyg4N/gc2yxuDA6/m8DPWU9kDj8VFR7LVFawOKgo1WbgLcC0Qu8qHzAffrlg8si\nhj3vGuoS/YDn/mz0krwFmCfIx+S0lJ9a7FUjJL5C+CIwAEEYiU7xnTW7pVVNXAm/\n/YKD17ToAjREOtlfVVYO7tZ7V5BiW0I0jJvxw+t1pgrZZe7WPBSBJg9KKGIl+mRi\ndtUMR9Hyt3nMKNZIrSm0OkAz82HxfcapRdSB3wkVjoyW63YaTVHKoBOqRElfMtoM\nqu8wbhhNAgMBAAECggEAA41wJ8kg8J8peQMZ/b7gZvzuPy+h0M/J3j2MrG3rY9qA\nrUv1oqoBSXvhuNDhtEN12oYIqtg6m+L+Sas8CMuOC2rWPafM2u/80IGoGtDhtCjp\nv8inBX8ew4YSiL7IxdbTU2/70Es7DVV5u0t6ndsmr88ibYwwPupGR/fhPCpDyssg\n7lFAEpOwnbKG9a7E7axHpXBRSIE54sh+ESyf6MHH/oyKOLhZ0v4PjRDKaKuMDRst\nMOClgNjD/4bzKpfWljuPYemXz1oIBQitBW5aXnCdsmdrmOLDQpz3qOgIo+RRiyki\nvVU5N54L65sj4WisLt1TT45wbhrkQUz+8GmhV5rHwQKBgQDow32/gSb/M0BKFk5y\n+pSeoLkYp/dwfBFWYT6CNBaKePARFVCdr3db8yOEQD4hrmTOU0EP9c4FSLcaa0Xy\n7n2crhhfZWFpIpRMyXhpeKpqdjQFimfBOK6cIdjnWrtJ6Ik3m4E9p7kKThIsInTc\n/TETwAyzFN+J2ADRdrUdCukOwQKBgQC/4+1Rk8a++Jr9Sznx+JH4vj/J2cGsu7uQ\n0nikcOAFO5HzG7+mt9Wv9/MiPtEYwmc7YziDXldKLpshT2m6wrS1uzzOXAnvXFAh\npiCXQsmVA3gmrVd53k+eZfqrZ1n/rL1kCewRS5LX8xIhM28VIkGqkVy4ZEifMotG\nZKSbH0b4jQKBgQCsJ6rh8Uw+hFGQel8be2pgyM8eBV1lvN213ca11oC1ei1U9Ubi\n2dyWDYa/UiSiFLJKSBlfDJaMIfQLfjwGKY6OS9WK+RjLAeBdysVcfPrOMw7W6j9D\nEgFTSVV8CAdt6qdSkZlNWLfrf0LBkdqNeFbMHMdHzLBo63HverUJ/f/SAQKBgHIk\n2t5T0T14FHnnbaiJ/ArC4J7pcVOWuJQFHs5ydk+mh8LdFrvNTsdF7tLIGwlnWpDx\nDITYcYQnBRBjdLkraONRZXI7PY2sk93wPCK+D7scPTSEmCxeGW5XqyyaZea4klAX\nttzy336lkHs/ZSxlHDqiDU2CGdDY+A//fgroKAdhAoGAA5FXfMzTQLGqxg4J2B1z\nFEXNbrqZZFGgKiveUhhZLm4zPiHXtZXvDtSLwGgcO8oGfTfYueTcHb/Eiar7mKv+\n+SqpAqkINJTthIFVIiD39S9jPFUXzBkf5ZJKPLKQArhzEGxen+SD6ZUO058fA94L\n9FblRGlMtr2o5z0NC7H5zaU=\n-----END PRIVATE KEY-----\n", + "client_email": "google-photos-api@brown-dash.iam.gserviceaccount.com", + "client_id": "112995422877175743408", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-photos-api%40brown-dash.iam.gserviceaccount.com" +}
\ No newline at end of file diff --git a/src/server/credentials/google_docs_credentials.json b/src/server/credentials/google_docs_credentials.json index 8d097d363..955c5a3c1 100644 --- a/src/server/credentials/google_docs_credentials.json +++ b/src/server/credentials/google_docs_credentials.json @@ -1 +1,11 @@ -{"installed":{"client_id":"343179513178-ud6tvmh275r2fq93u9eesrnc66t6akh9.apps.googleusercontent.com","project_id":"quickstart-1565056383187","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"w8KIFSc0MQpmUYHed4qEzn8b","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}
\ No newline at end of file +{ + "installed": { + "client_id": "343179513178-ud6tvmh275r2fq93u9eesrnc66t6akh9.apps.googleusercontent.com", + "project_id": "quickstart-1565056383187", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_secret": "w8KIFSc0MQpmUYHed4qEzn8b", + "redirect_uris": ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"] + } +}
\ No newline at end of file diff --git a/src/server/credentials/google_docs_token.json b/src/server/credentials/google_docs_token.json index 07c02d56c..cea452f08 100644 --- a/src/server/credentials/google_docs_token.json +++ b/src/server/credentials/google_docs_token.json @@ -1 +1 @@ -{"access_token":"ya29.GltjB4-x03xFpd2NY2555cxg1xlT_ajqRi78M9osOfdOF2jTIjlPkn_UZL8cUwVP0DPC8rH3vhhg8RpspFe8Vewx92shAO3RPos_uMH0CUqEiCiZlaaB5I3Jq3Mv","refresh_token":"1/teUKUqGKMLjVqs-eed0L8omI02pzSxMUYaxGc2QxBw0","scope":"https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents.readonly","token_type":"Bearer","expiry_date":1565654175862}
\ No newline at end of file +{"access_token":"ya29.Glt2B3lsrpWxZ9DMg1RcTksAFzfR8dVWhf7d7tAvbJ4UbcSVO0Q3aYNGtaMKPtmxR24rH88iQSiKCL8S328TQFEN6LtZgvizymednK5EW0jNCvG6ecdZQ-vwcypR","refresh_token":"1/6X3oGYz4A0p8UW2IgsZ-GqTgQUY43S6Ahsaf_GQhSs8","scope":"https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/photoslibrary.sharing https://www.googleapis.com/auth/photoslibrary","token_type":"Bearer","expiry_date":1567360444627}
\ No newline at end of file diff --git a/src/server/credentials/google_photos_credentials.ts b/src/server/credentials/google_photos_credentials.ts new file mode 100644 index 000000000..11c1c766c --- /dev/null +++ b/src/server/credentials/google_photos_credentials.ts @@ -0,0 +1,35 @@ +const config: any = {}; + +// The OAuth client ID from the Google Developers console. +config.oAuthClientID = '1005546247619-l40012sl4idpq17b5emielcs1delffog.apps.googleusercontent.com'; + +// The OAuth client secret from the Google Developers console. +config.oAuthclientSecret = 'xEUJ0OBvhlCKA6SLt8TvWBs3'; + +// The callback to use for OAuth requests. This is the URL where the app is +// running. For testing and running it locally, use 127.0.0.1. +config.oAuthCallbackUrl = 'http://localhost:1050/auth/google/callback'; + +// The port where the app should listen for requests. +config.port = 1050; + +// The scopes to request. The app requires the photoslibrary.readonly and +// plus.me scopes. +config.scopes = [ + 'https://www.googleapis.com/auth/photoslibrary.readonly', + 'profile', +]; + +// The number of photos to load for search requests. +config.photosToLoad = 150; + +// The page size to use for search requests. 100 is reccommended. +config.searchPageSize = 100; + +// The page size to use for the listing albums request. 50 is reccommended. +config.albumPageSize = 50; + +// The API end point to use. Do not change. +config.apiEndpoint = 'https://photoslibrary.googleapis.com'; + +module.exports = config;
\ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index 34a0a19f1..6105dedcc 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -29,6 +29,7 @@ import { RouteStore } from './RouteStore'; import v4 = require('uuid/v4'); const app = express(); const config = require('../../webpack.config'); +const OAuthConfig = require('../server/credentials/google_photos_credentials'); import { createCanvas, loadImage, Canvas } from "canvas"; const compiler = webpack(config); const port = 1050; // default port to listen @@ -46,6 +47,7 @@ import { GaxiosResponse } from 'gaxios'; import { Opt } from '../new_fields/Doc'; import { docs_v1 } from 'googleapis'; import { Endpoint } from 'googleapis-common'; +import { PhotosLibraryQuery } from './apis/google/GooglePhotosUtils'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); const probe = require("probe-image-size"); @@ -196,6 +198,31 @@ const solrURL = "http://localhost:8983/solr/#/dash"; // GETTERS +// app.get('/auth/google', passport.authenticate('google', { +// scope: OAuthConfig.scopes, +// failureFlash: true, // Display errors to the user. +// session: true, +// })); + +// app.get("/failed", (req, res) => res.send("DIDN'T WORK!")); + +// app.get( +// '/auth/google/callback', +// passport.authenticate( +// 'google', { failureRedirect: '/failed', failureFlash: true, session: true }), +// (req, res) => { +// // User has logged in. +// console.log('OAUTH: user has logged in 1.'); +// PhotosLibraryQuery(req.user.token, {}); +// console.log('OAUTH: user has logged in 2.'); +// res.redirect('/'); +// }); + +// app.get('/GooglePhotos', (req, res) => { +// console.log("WORKING ON GOOGLE PHOTOS"); +// PhotosLibraryQuery(req.user.token, {}); +// }); + app.get("/search", async (req, res) => { const solrQuery: any = {}; ["q", "fq", "start", "rows", "hl", "hl.fl"].forEach(key => solrQuery[key] = req.query[key]); diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index 7939ae8be..36d828fdb 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -1,322 +1,324 @@ /// <reference types="node" /> -declare module '@react-pdf/renderer' { - import * as React from 'react'; - - namespace ReactPDF { - interface Style { - [property: string]: any; - } - interface Styles { - [key: string]: Style; - } - type Orientation = 'portrait' | 'landscape'; - - interface DocumentProps { - title?: string; - author?: string; - subject?: string; - keywords?: string; - creator?: string; - producer?: string; - onRender?: () => any; - } - - /** - * This component represent the PDF document itself. It must be the root - * of your tree element structure, and under no circumstances should it be - * used as children of another react-pdf component. In addition, it should - * only have childs of type <Page />. - */ - class Document extends React.Component<DocumentProps> { } - - interface NodeProps { - style?: Style | Style[]; - /** - * Render component in all wrapped pages. - * @see https://react-pdf.org/advanced#fixed-components - */ - fixed?: boolean; - /** - * Force the wrapping algorithm to start a new page when rendering the - * element. - * @see https://react-pdf.org/advanced#page-breaks - */ - break?: boolean; - } - - interface PageProps extends NodeProps { - /** - * Enable page wrapping for this page. - * @see https://react-pdf.org/components#page-wrapping - */ - wrap?: boolean; - debug?: boolean; - size?: string | [number, number] | { width: number; height: number }; - orientation?: Orientation; - ruler?: boolean; - rulerSteps?: number; - verticalRuler?: boolean; - verticalRulerSteps?: number; - horizontalRuler?: boolean; - horizontalRulerSteps?: number; - ref?: Page; - } - - /** - * Represents single page inside the PDF document, or a subset of them if - * using the wrapping feature. A <Document /> can contain as many pages as - * you want, but ensure not rendering a page inside any component besides - * Document. - */ - class Page extends React.Component<PageProps> { } - - interface ViewProps extends NodeProps { - /** - * Enable/disable page wrapping for element. - * @see https://react-pdf.org/components#page-wrapping - */ - wrap?: boolean; - debug?: boolean; - render?: (props: { pageNumber: number }) => React.ReactNode; - children?: React.ReactNode; - } - - /** - * The most fundamental component for building a UI and is designed to be - * nested inside other views and can have 0 to many children. - */ - class View extends React.Component<ViewProps> { } - - interface ImageProps extends NodeProps { - debug?: boolean; - src: string | { data: Buffer; format: 'png' | 'jpg' }; - cache?: boolean; - } - - /** - * A React component for displaying network or local (Node only) JPG or - * PNG images, as well as base64 encoded image strings. - */ - class Image extends React.Component<ImageProps> { } - - interface TextProps extends NodeProps { - /** - * Enable/disable page wrapping for element. - * @see https://react-pdf.org/components#page-wrapping - */ - wrap?: boolean; - debug?: boolean; - render?: ( - props: { pageNumber: number; totalPages: number }, - ) => React.ReactNode; - children?: React.ReactNode; - /** - * How much hyphenated breaks should be avoided. - */ - hyphenationCallback?: number; - } - - /** - * A React component for displaying text. Text supports nesting of other - * Text or Link components to create inline styling. - */ - class Text extends React.Component<TextProps> { } - - interface LinkProps extends NodeProps { - /** - * Enable/disable page wrapping for element. - * @see https://react-pdf.org/components#page-wrapping - */ - wrap?: boolean; - debug?: boolean; - src: string; - children?: React.ReactNode; - } +declare module 'googlephotos'; - /** - * A React component for displaying an hyperlink. Link’s can be nested - * inside a Text component, or being inside any other valid primitive. - */ - class Link extends React.Component<LinkProps> { } - - interface NoteProps extends NodeProps { - children: string; - } - - class Note extends React.Component<NoteProps> { } - - interface BlobProviderParams { - blob: Blob | null; - url: string | null; - loading: boolean; - error: Error | null; - } - interface BlobProviderProps { - document: React.ReactElement<DocumentProps>; - children: (params: BlobProviderParams) => React.ReactNode; - } - - /** - * Easy and declarative way of getting document's blob data without - * showing it on screen. - * @see https://react-pdf.org/advanced#on-the-fly-rendering - * @platform web - */ - class BlobProvider extends React.Component<BlobProviderProps> { } - - interface PDFViewerProps { - width?: number; - height?: number; - style?: Style | Style[]; - className?: string; - children?: React.ReactElement<DocumentProps>; - } - - /** - * Iframe PDF viewer for client-side generated documents. - * @platform web - */ - class PDFViewer extends React.Component<PDFViewerProps> { } - - interface PDFDownloadLinkProps { - document: React.ReactElement<DocumentProps>; - fileName?: string; - style?: Style | Style[]; - className?: string; - children?: - | React.ReactNode - | ((params: BlobProviderParams) => React.ReactNode); +declare module '@react-pdf/renderer' { + import * as React from 'react'; + + namespace ReactPDF { + interface Style { + [property: string]: any; + } + interface Styles { + [key: string]: Style; + } + type Orientation = 'portrait' | 'landscape'; + + interface DocumentProps { + title?: string; + author?: string; + subject?: string; + keywords?: string; + creator?: string; + producer?: string; + onRender?: () => any; + } + + /** + * This component represent the PDF document itself. It must be the root + * of your tree element structure, and under no circumstances should it be + * used as children of another react-pdf component. In addition, it should + * only have childs of type <Page />. + */ + class Document extends React.Component<DocumentProps> { } + + interface NodeProps { + style?: Style | Style[]; + /** + * Render component in all wrapped pages. + * @see https://react-pdf.org/advanced#fixed-components + */ + fixed?: boolean; + /** + * Force the wrapping algorithm to start a new page when rendering the + * element. + * @see https://react-pdf.org/advanced#page-breaks + */ + break?: boolean; + } + + interface PageProps extends NodeProps { + /** + * Enable page wrapping for this page. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + size?: string | [number, number] | { width: number; height: number }; + orientation?: Orientation; + ruler?: boolean; + rulerSteps?: number; + verticalRuler?: boolean; + verticalRulerSteps?: number; + horizontalRuler?: boolean; + horizontalRulerSteps?: number; + ref?: Page; + } + + /** + * Represents single page inside the PDF document, or a subset of them if + * using the wrapping feature. A <Document /> can contain as many pages as + * you want, but ensure not rendering a page inside any component besides + * Document. + */ + class Page extends React.Component<PageProps> { } + + interface ViewProps extends NodeProps { + /** + * Enable/disable page wrapping for element. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + render?: (props: { pageNumber: number }) => React.ReactNode; + children?: React.ReactNode; + } + + /** + * The most fundamental component for building a UI and is designed to be + * nested inside other views and can have 0 to many children. + */ + class View extends React.Component<ViewProps> { } + + interface ImageProps extends NodeProps { + debug?: boolean; + src: string | { data: Buffer; format: 'png' | 'jpg' }; + cache?: boolean; + } + + /** + * A React component for displaying network or local (Node only) JPG or + * PNG images, as well as base64 encoded image strings. + */ + class Image extends React.Component<ImageProps> { } + + interface TextProps extends NodeProps { + /** + * Enable/disable page wrapping for element. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + render?: ( + props: { pageNumber: number; totalPages: number }, + ) => React.ReactNode; + children?: React.ReactNode; + /** + * How much hyphenated breaks should be avoided. + */ + hyphenationCallback?: number; + } + + /** + * A React component for displaying text. Text supports nesting of other + * Text or Link components to create inline styling. + */ + class Text extends React.Component<TextProps> { } + + interface LinkProps extends NodeProps { + /** + * Enable/disable page wrapping for element. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + src: string; + children?: React.ReactNode; + } + + /** + * A React component for displaying an hyperlink. Link’s can be nested + * inside a Text component, or being inside any other valid primitive. + */ + class Link extends React.Component<LinkProps> { } + + interface NoteProps extends NodeProps { + children: string; + } + + class Note extends React.Component<NoteProps> { } + + interface BlobProviderParams { + blob: Blob | null; + url: string | null; + loading: boolean; + error: Error | null; + } + interface BlobProviderProps { + document: React.ReactElement<DocumentProps>; + children: (params: BlobProviderParams) => React.ReactNode; + } + + /** + * Easy and declarative way of getting document's blob data without + * showing it on screen. + * @see https://react-pdf.org/advanced#on-the-fly-rendering + * @platform web + */ + class BlobProvider extends React.Component<BlobProviderProps> { } + + interface PDFViewerProps { + width?: number; + height?: number; + style?: Style | Style[]; + className?: string; + children?: React.ReactElement<DocumentProps>; + } + + /** + * Iframe PDF viewer for client-side generated documents. + * @platform web + */ + class PDFViewer extends React.Component<PDFViewerProps> { } + + interface PDFDownloadLinkProps { + document: React.ReactElement<DocumentProps>; + fileName?: string; + style?: Style | Style[]; + className?: string; + children?: + | React.ReactNode + | ((params: BlobProviderParams) => React.ReactNode); + } + + /** + * Anchor tag to enable generate and download PDF documents on the fly. + * @see https://react-pdf.org/advanced#on-the-fly-rendering + * @platform web + */ + class PDFDownloadLink extends React.Component<PDFDownloadLinkProps> { } + + interface EmojiSource { + url: string; + format: string; + } + interface RegisteredFont { + src: string; + loaded: boolean; + loading: boolean; + data: any; + [key: string]: any; + } + type HyphenationCallback = ( + words: string[], + glyphString: { [key: string]: any }, + ) => string[]; + + const Font: { + register: ( + src: string, + options: { family: string;[key: string]: any }, + ) => void; + getEmojiSource: () => EmojiSource; + getRegisteredFonts: () => string[]; + registerEmojiSource: (emojiSource: EmojiSource) => void; + registerHyphenationCallback: ( + hyphenationCallback: HyphenationCallback, + ) => void; + getHyphenationCallback: () => HyphenationCallback; + getFont: (fontFamily: string) => RegisteredFont | undefined; + load: ( + fontFamily: string, + document: React.ReactElement<DocumentProps>, + ) => Promise<void>; + clear: () => void; + reset: () => void; + }; + + const StyleSheet: { + hairlineWidth: number; + create: <TStyles>(styles: TStyles) => TStyles; + resolve: ( + style: Style, + container: { + width: number; + height: number; + orientation: Orientation; + }, + ) => Style; + flatten: (...styles: Style[]) => Style; + absoluteFillObject: { + position: 'absolute'; + left: 0; + right: 0; + top: 0; + bottom: 0; + }; + }; + + const version: any; + + const PDFRenderer: any; + + const createInstance: ( + element: { + type: string; + props: { [key: string]: any }; + }, + root?: any, + ) => any; + + const pdf: ( + document: React.ReactElement<DocumentProps>, + ) => { + isDirty: () => boolean; + updateContainer: (document: React.ReactElement<any>) => void; + toBuffer: () => NodeJS.ReadableStream; + toBlob: () => Blob; + toString: () => string; + }; + + const renderToStream: ( + document: React.ReactElement<DocumentProps>, + ) => NodeJS.ReadableStream; + + const renderToFile: ( + document: React.ReactElement<DocumentProps>, + filePath: string, + callback?: (output: NodeJS.ReadableStream, filePath: string) => any, + ) => Promise<NodeJS.ReadableStream>; + + const render: typeof renderToFile; } - /** - * Anchor tag to enable generate and download PDF documents on the fly. - * @see https://react-pdf.org/advanced#on-the-fly-rendering - * @platform web - */ - class PDFDownloadLink extends React.Component<PDFDownloadLinkProps> { } - - interface EmojiSource { - url: string; - format: string; - } - interface RegisteredFont { - src: string; - loaded: boolean; - loading: boolean; - data: any; - [key: string]: any; - } - type HyphenationCallback = ( - words: string[], - glyphString: { [key: string]: any }, - ) => string[]; - - const Font: { - register: ( - src: string, - options: { family: string;[key: string]: any }, - ) => void; - getEmojiSource: () => EmojiSource; - getRegisteredFonts: () => string[]; - registerEmojiSource: (emojiSource: EmojiSource) => void; - registerHyphenationCallback: ( - hyphenationCallback: HyphenationCallback, - ) => void; - getHyphenationCallback: () => HyphenationCallback; - getFont: (fontFamily: string) => RegisteredFont | undefined; - load: ( - fontFamily: string, - document: React.ReactElement<DocumentProps>, - ) => Promise<void>; - clear: () => void; - reset: () => void; + const Document: typeof ReactPDF.Document; + const Page: typeof ReactPDF.Page; + const View: typeof ReactPDF.View; + const Image: typeof ReactPDF.Image; + const Text: typeof ReactPDF.Text; + const Link: typeof ReactPDF.Link; + const Note: typeof ReactPDF.Note; + const Font: typeof ReactPDF.Font; + const StyleSheet: typeof ReactPDF.StyleSheet; + const createInstance: typeof ReactPDF.createInstance; + const PDFRenderer: typeof ReactPDF.PDFRenderer; + const version: typeof ReactPDF.version; + const pdf: typeof ReactPDF.pdf; + + export default ReactPDF; + export { + Document, + Page, + View, + Image, + Text, + Link, + Note, + Font, + StyleSheet, + createInstance, + PDFRenderer, + version, + pdf, }; - - const StyleSheet: { - hairlineWidth: number; - create: <TStyles>(styles: TStyles) => TStyles; - resolve: ( - style: Style, - container: { - width: number; - height: number; - orientation: Orientation; - }, - ) => Style; - flatten: (...styles: Style[]) => Style; - absoluteFillObject: { - position: 'absolute'; - left: 0; - right: 0; - top: 0; - bottom: 0; - }; - }; - - const version: any; - - const PDFRenderer: any; - - const createInstance: ( - element: { - type: string; - props: { [key: string]: any }; - }, - root?: any, - ) => any; - - const pdf: ( - document: React.ReactElement<DocumentProps>, - ) => { - isDirty: () => boolean; - updateContainer: (document: React.ReactElement<any>) => void; - toBuffer: () => NodeJS.ReadableStream; - toBlob: () => Blob; - toString: () => string; - }; - - const renderToStream: ( - document: React.ReactElement<DocumentProps>, - ) => NodeJS.ReadableStream; - - const renderToFile: ( - document: React.ReactElement<DocumentProps>, - filePath: string, - callback?: (output: NodeJS.ReadableStream, filePath: string) => any, - ) => Promise<NodeJS.ReadableStream>; - - const render: typeof renderToFile; - } - - const Document: typeof ReactPDF.Document; - const Page: typeof ReactPDF.Page; - const View: typeof ReactPDF.View; - const Image: typeof ReactPDF.Image; - const Text: typeof ReactPDF.Text; - const Link: typeof ReactPDF.Link; - const Note: typeof ReactPDF.Note; - const Font: typeof ReactPDF.Font; - const StyleSheet: typeof ReactPDF.StyleSheet; - const createInstance: typeof ReactPDF.createInstance; - const PDFRenderer: typeof ReactPDF.PDFRenderer; - const version: typeof ReactPDF.version; - const pdf: typeof ReactPDF.pdf; - - export default ReactPDF; - export { - Document, - Page, - View, - Image, - Text, - Link, - Note, - Font, - StyleSheet, - createInstance, - PDFRenderer, - version, - pdf, - }; }
\ No newline at end of file |