mirror of
https://github.com/Nezumi-2711/next-gdrive-index.git
synced 2026-09-22 13:38:38 +00:00
322 lines
10 KiB
TypeScript
322 lines
10 KiB
TypeScript
import { z } from "zod";
|
|
|
|
const configurationTemplate = `import { type z } from "zod";
|
|
import { BASE_URL } from "~/constant";
|
|
|
|
import { type Schema_Config } from "~/types/schema";
|
|
|
|
const config: z.input<typeof Schema_Config> = {
|
|
/**
|
|
* If possible, please don't change this value
|
|
* Even if you're creating a PR, just let me change it myself
|
|
*/
|
|
version: "{{ version }}",
|
|
/**
|
|
* Base path of the app, used for generating links
|
|
*
|
|
* If you're using another port for development, you can set it here
|
|
*
|
|
* @default process.env.NEXT_PUBLIC_DOMAIN
|
|
* @fallback process.env.NEXT_PUBLIC_VERCEL_URL
|
|
*/
|
|
basePath: new URL(BASE_URL).toString(),
|
|
|
|
/**
|
|
* Show deploy guide dropdown on navbar
|
|
* that contains the deploy guide and configurator
|
|
*
|
|
* Set this to false on final deployment, except you want to show it
|
|
*
|
|
* @default false
|
|
*/
|
|
showGuideButton: {{ showGuideButton }},
|
|
|
|
/**
|
|
* How long the cache will be stored in the browser
|
|
* Used for all pages and api routes
|
|
*
|
|
* @default "public, max-age=60, s-maxage=60, stale-while-revalidate"
|
|
*/
|
|
cacheControl: "{{ cacheControl }}",
|
|
|
|
apiConfig: {
|
|
/**
|
|
* Starting point of the drive.
|
|
* Will be used for '/' route.
|
|
*
|
|
* Since service account can't access 'root' folder
|
|
* You need to create a new folder and share it with the service account
|
|
* Then, copy the folder id and paste it here
|
|
*/
|
|
rootFolder:
|
|
"{{ api.rootFolder }}",
|
|
|
|
/**
|
|
* If your rootfolder inside a shared drive, you NEED to set this to true
|
|
* If not, you can set this to false
|
|
*
|
|
* You also need to set the shared drive ID to make it work
|
|
* Make sure you have add your service account to the shared drive since the service account can't access the shared drive by default
|
|
*
|
|
* Where to get the shared drive id?
|
|
* Go to your Shared Drive > Click on the shared drive > copy the ID from the url
|
|
* ex: https://drive.google.com/drive/u/0/folders/:shared_drive_id
|
|
*
|
|
* Then you need to encrypt it using \`/api/internal/encrypt?q=:shared_drive_id\` route
|
|
*/
|
|
isTeamDrive: {{ api.isTeamDrive }},
|
|
sharedDrive: "{{ api.sharedDrive }}",
|
|
|
|
defaultQuery: ["trashed = false", "(not mimeType contains 'google-apps' or mimeType contains 'folder')"],
|
|
defaultField:
|
|
"id, name, mimeType, thumbnailLink, fileExtension, modifiedTime, size, imageMediaMetadata, videoMediaMetadata, webContentLink, trashed",
|
|
defaultOrder: "folder, name asc, modifiedTime desc",
|
|
itemsPerPage: {{ api.itemsPerPage }},
|
|
searchResult: {{ api.searchResult }},
|
|
|
|
/**
|
|
* Special file name that will be used for certain purposes
|
|
* These files will be ignored when searching for files
|
|
* and will be hidden from the files list by default
|
|
*/
|
|
specialFile: {
|
|
password: "{{ api.specialFile.password }}",
|
|
readme: "{{ api.specialFile.readme }}",
|
|
/**
|
|
* Banner will be used for opengraph image for folder
|
|
* By default, all folder will use default og image
|
|
*/
|
|
banner: "{{ api.specialFile.banner }}",
|
|
},
|
|
/**
|
|
* Reason why banner has multiple extensions:
|
|
* - If I use contains query, it will also match the file or folder that contains the word.
|
|
* (e.g: File / folder with the name of "Test Password" will be matched)
|
|
* - If I use = query, it will only match the exact name, hence the multiple extensions
|
|
*
|
|
* You can add more extensions if you want
|
|
*/
|
|
hiddenFiles: {{ api.hiddenFiles }},
|
|
|
|
/**
|
|
* By default, the app will use the thumbnail URL from Google Drive
|
|
*
|
|
* Sometimes, the thumbnail can't be accessed because of CORS policy
|
|
* If you're having this issue, you can set this to true
|
|
*
|
|
* This will make the api fetch the thumbnail and serve it from the server
|
|
* instead of using the Google Drive thumbnail
|
|
*
|
|
* This will increase the server load, so use it wisely
|
|
*
|
|
* Default: true
|
|
*/
|
|
proxyThumbnail: {{ api.proxyThumbnail }},
|
|
|
|
/**
|
|
* Only show preview for files that are smaller than this size
|
|
* If the file is larger than this size, it will show "can't preview" message instead
|
|
*
|
|
* Why?
|
|
* Since the stream endpoint are counted as a bandwidth usage
|
|
* I want to limit the preview to only small files
|
|
* It also to prevent abuse from the user
|
|
*
|
|
* You can also set this to 0 to disable the limit
|
|
*
|
|
* Default: 100MB
|
|
*/
|
|
streamMaxSize: {{ api.streamMaxSize }},
|
|
|
|
/**
|
|
* Maximum file size that can be downloaded via api routes
|
|
* If it's larger than this, it will be redirected to the file url
|
|
*
|
|
* If you're using Vercel, they have a limit of ~4 - ~4.5MB response size
|
|
* ref: https://vercel.com/docs/functions/runtimes#request-body-size
|
|
* If you're using another platform, you can match the limit with your platform
|
|
* Or you can set this to 0 to disable the limit
|
|
*
|
|
* Default: 4MB
|
|
*/
|
|
maxFileSize: {{ api.maxFileSize }},
|
|
|
|
/**
|
|
* Allow user to download protected file without password.
|
|
* If this set to false, download link will have temporary token attached to it
|
|
* If this set to true, user can download the file without password as long as they have the link
|
|
*
|
|
* Default: false
|
|
*/
|
|
allowDownloadProtectedFile: {{ api.allowDownloadProtectedFile }},
|
|
|
|
/**
|
|
* Duration in hours.
|
|
* In version 2, this will be used for download link expiration.
|
|
* If you need it under 1 hour, you can use math expression. (e.g: (5 / 60) * 1 = 5 minutes)
|
|
*
|
|
* This only affect when the user download the file
|
|
* For example if you set it for example 30 minutes (0.5)
|
|
* After 30 minutes, and the user still downloading the file, the download will NOT be interrupted
|
|
* But if the user refresh the page / trying to download again, the download link will be expired
|
|
*
|
|
* Default: 1 hour
|
|
*/
|
|
temporaryTokenDuration: {{ api.temporaryTokenDuration }},
|
|
},
|
|
|
|
siteConfig: {
|
|
/**
|
|
* Site Name will be used for default metadata title
|
|
* Site Name Template will be used if the page has a title
|
|
* %s will be replaced with the page title
|
|
* %t will be replaced with the site name
|
|
*
|
|
* You can set it to undefined if you don't want to use it
|
|
*/
|
|
siteName: "{{ site.siteName }}",
|
|
siteNameTemplate: "{{ site.siteNameTemplate }}",
|
|
siteDescription: "{{ site.siteDescription }}",
|
|
siteIcon: "/logo.svg",
|
|
siteAuthor: "{{ site.siteAuthor }}",
|
|
favIcon: "/favicon.png",
|
|
/**
|
|
* Next.js Metadata robots object
|
|
*
|
|
* ref: https://nextjs.org/docs/app/api-reference/functions/generate-metadata#robots
|
|
*/
|
|
robots: "{{ site.robots }}",
|
|
twitterHandle: "{{ site.twitterHandle }}",
|
|
|
|
/**
|
|
* Show file extension on the file name
|
|
* Example:
|
|
* true | false
|
|
* file.txt | file
|
|
* 100KB | txt / 100KB
|
|
*
|
|
* Default: false
|
|
*/
|
|
showFileExtension: {{ site.showFileExtension }},
|
|
|
|
/**
|
|
* Site wide password protection
|
|
* If this is set, all files and folders will be protected by this password
|
|
*
|
|
* The site password are set from Environment Variable (NEXT_GDRIVE_INDEX_PASSWORD)
|
|
* It's because I don't want to store sensitive data in the code
|
|
*/
|
|
privateIndex: {{ site.privateIndex }},
|
|
|
|
/**
|
|
* Maximum breadcrumb length
|
|
* If the breadcrumb is longer than this, it will be shortened
|
|
*/
|
|
breadcrumbMax: {{ site.breadcrumbMax }},
|
|
|
|
/**
|
|
* Toast notification configuration
|
|
*
|
|
* position: Self-explanatory
|
|
* duration: duration before the toast disappear in milliseconds
|
|
*/
|
|
toaster: {
|
|
position: "{{ site.toaster.position }}",
|
|
duration: {{ site.toaster.duration }},
|
|
},
|
|
|
|
/**
|
|
* Configuration for file preview
|
|
*/
|
|
previewSettings: {
|
|
manga: {
|
|
/**
|
|
* Load first X MB of the file for preview
|
|
* or load first X items for preview
|
|
*
|
|
* @default
|
|
* maxSize: 15MB
|
|
* maxItem: 10 items
|
|
*/
|
|
maxSize: 15 * 1024 * 1024,
|
|
maxItem: 10,
|
|
},
|
|
},
|
|
|
|
/**
|
|
* Example item:
|
|
* {
|
|
* icon: string, // icon name from lucide icons (https://lucide.dev/icons/)
|
|
* name: string,
|
|
* href: string,
|
|
* external?: boolean
|
|
* }
|
|
*/
|
|
navbarItems: {{ site.navbarItems }},
|
|
|
|
/**
|
|
* Add support / donation links on the navbar
|
|
* Example item:
|
|
* {
|
|
* name: string,
|
|
* currency: string,
|
|
* href: string,
|
|
* }
|
|
*/
|
|
supports: {{ site.supports }},
|
|
|
|
/**
|
|
* Footer content
|
|
* You can also set it to empty array if you don't want to use it
|
|
*
|
|
* Basic markdown is supported (bold, italic, and link)
|
|
* External link will be opened in new tab
|
|
*
|
|
* Template:
|
|
* - {{ year }} will be replaced with the current year
|
|
* - {{ repository }} will be replaced with the original repository link
|
|
* - {{ poweredBy }} will be replaced with "Powered by next-gdrive-index", linked to the repository
|
|
* - {{ author }} will be replaced with author from siteAuthor config above (If it's not set, it will be set to mbaharip)
|
|
* - {{ version }} will be replaced with the current version
|
|
* - {{ siteName }} will be replaced with the siteName config above
|
|
* - {{ handle }} will be replaced with the twitter handle from twitterHandle config above
|
|
* - {{ creator }} will be replaced with mbaharip if you want to credit me
|
|
*/
|
|
footer: {{ site.footer }},
|
|
/**
|
|
* Add page load time on the footer
|
|
* If you don't want to use it, you can set it to false
|
|
*/
|
|
experimental_pageLoadTime: false,
|
|
},
|
|
};
|
|
|
|
export default config;
|
|
`;
|
|
const environmentTemplate = `# Base64 Encoded Service Account JSON
|
|
GD_SERVICE_B64={{ serviceAccount }}
|
|
# Secret Key for Encryption
|
|
ENCRYPTION_KEY={{ key }}
|
|
# Index password, used when private mode is enabled
|
|
SITE_PASSWORD={{ password }}
|
|
|
|
# [Optional] Only domain, without protocol (ex: mbaharip.com)
|
|
# Needed if you're not using Vercel
|
|
NEXT_PUBLIC_DOMAIN={{ domain }}`;
|
|
|
|
const version1Schema = z.object({});
|
|
const version2Schema = z.object({});
|
|
const newVersion2Schema = z.object({});
|
|
const environmentSchema = z.object({
|
|
GD_SERVICE_B64: z.string(),
|
|
ENCRYPTION_KEY: z.string(),
|
|
SITE_PASSWORD: z.string().optional(),
|
|
NEXT_PUBLIC_DOMAIN: z.string().optional(),
|
|
});
|
|
|
|
export function parseVersion1Config(configuration: string) {}
|
|
|
|
export function parseVersion2Config(configuration: string) {}
|
|
|
|
export function parseEnvironmentConfig(configuration: string) {}
|