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 = { /** * 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) {}