From 745f58a10d90ab1f8ffe52f37dae031b55cbd25a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 18 Dec 2024 15:20:28 +0100 Subject: [PATCH] build: generate drivers meta (#526) --- .github/workflows/autofix.yml | 1 + .prettierignore | 1 + build.config.ts | 2 +- package.json | 5 +- pnpm-lock.yaml | 7 +- scripts/gen-drivers.ts | 82 +++++++++++++++++++++ src/_drivers.ts | 131 ++++++++++++++++++++++++++++++++++ src/index.ts | 103 ++------------------------ tsconfig.json | 5 +- 9 files changed, 236 insertions(+), 101 deletions(-) create mode 100644 scripts/gen-drivers.ts create mode 100644 src/_drivers.ts diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index fc52df9e..c2bbaedf 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -19,6 +19,7 @@ jobs: node-version: 20 cache: "pnpm" - run: pnpm install + - run: pnpm run gen-drivers - name: Fix lint issues run: pnpm run lint:fix - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c diff --git a/.prettierignore b/.prettierignore index 7bc19813..b3bfee53 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ test/drivers/tmp +src/_drivers.ts dist node_modules .output diff --git a/build.config.ts b/build.config.ts index 46ad68c7..c6a9e7d5 100644 --- a/build.config.ts +++ b/build.config.ts @@ -21,5 +21,5 @@ export default defineBuildConfig({ declaration: false, }, ], - externals: ["mongodb"], + externals: ["mongodb", "unstorage", /unstorage\/drivers\//], }); diff --git a/package.json b/package.json index 6482dc07..bfb393b3 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ ], "scripts": { "bench": "jiti test/server.bench.ts", - "build": "unbuild", + "build": "pnpm gen-drivers && unbuild", + "gen-drivers": "jiti scripts/gen-drivers.ts", "dev": "vitest", "lint": "eslint . && prettier -c .", "lint:fix": "eslint . --fix && prettier -w .", @@ -90,9 +91,11 @@ "jiti": "^2.4.1", "jsdom": "^25.0.1", "mitata": "^1.0.21", + "mlly": "^1.7.3", "mongodb": "^6.12.0", "mongodb-memory-server": "^10.1.2", "prettier": "^3.4.2", + "scule": "^1.3.0", "types-cloudflare-worker": "^1.2.0", "typescript": "^5.7.2", "unbuild": "^3.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19b7dc78..2b89b330 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -144,6 +144,9 @@ importers: mitata: specifier: ^1.0.21 version: 1.0.21 + mlly: + specifier: ^1.7.3 + version: 1.7.3 mongodb: specifier: ^6.12.0 version: 6.12.0 @@ -153,6 +156,9 @@ importers: prettier: specifier: ^3.4.2 version: 3.4.2 + scule: + specifier: ^1.3.0 + version: 1.3.0 types-cloudflare-worker: specifier: ^1.2.0 version: 1.2.0 @@ -2927,7 +2933,6 @@ packages: libsql@0.4.7: resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==} - cpu: [x64, arm64, wasm32] os: [darwin, linux, win32] lilconfig@3.1.3: diff --git a/scripts/gen-drivers.ts b/scripts/gen-drivers.ts new file mode 100644 index 00000000..b5788f18 --- /dev/null +++ b/scripts/gen-drivers.ts @@ -0,0 +1,82 @@ +import { readFile, readdir, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { findTypeExports } from "mlly"; +import { camelCase, upperFirst } from "scule"; + +const driversDir = fileURLToPath(new URL("../src/drivers", import.meta.url)); + +const driversMetaFile = fileURLToPath( + new URL("../src/_drivers.ts", import.meta.url) +); + +const driverEntries: string[] = ( + await readdir(driversDir, { withFileTypes: true }) +) + .filter((entry) => entry.isFile()) + .map((entry) => entry.name); + +const drivers: { + name: string; + safeName: string; + names: string[]; + subpath: string; + optionsTExport?: string; + optionsTName?: string; +}[] = []; + +for (const entry of driverEntries) { + const name = entry.replace(/\.ts$/, ""); + const subpath = `unstorage/drivers/${name}`; + const fullPath = join(driversDir, `${name}.ts`); + + const contents = await readFile(fullPath, "utf8"); + const optionsTExport = findTypeExports(contents).find((type) => + type.name?.endsWith("Options") + )?.name; + + const safeName = camelCase(name) + .replace(/kv/i, "KV") + .replace("localStorage", "localstorage"); + + const names = [...new Set([name, safeName])]; + + const optionsTName = upperFirst(safeName) + "Options"; + + drivers.push({ + name, + safeName, + names, + subpath, + optionsTExport, + optionsTName, + }); +} + +const genCode = /* ts */ `// Auto-generated using scripts/gen-drivers. +// Do not manually edit! + +${drivers + .filter((d) => d.optionsTExport) + .map( + (d) => + /* ts */ `import type { ${d.optionsTExport} as ${d.optionsTName} } from "${d.subpath}";` + ) + .join("\n")} + +export type BuiltinDriverName = ${drivers.flatMap((d) => d.names.map((name) => `"${name}"`)).join(" | ")}; + +export type BuiltinDriverOptions = { + ${drivers + .filter((d) => d.optionsTExport) + .flatMap((d) => d.names.map((name) => `"${name}": ${d.optionsTName};`)) + .join("\n ")} +}; + +export const builtinDrivers = { + ${drivers.flatMap((d) => d.names.map((name) => `"${name}": "${d.subpath}"`)).join(",\n ")}, +} as const; +`; + +await writeFile(driversMetaFile, genCode, "utf8"); +console.log("Generated drivers metadata file to", driversMetaFile); diff --git a/src/_drivers.ts b/src/_drivers.ts new file mode 100644 index 00000000..b6a05496 --- /dev/null +++ b/src/_drivers.ts @@ -0,0 +1,131 @@ +// Auto-generated using scripts/gen-drivers. +// Do not manually edit! + +import type { AzureAppConfigurationOptions as AzureAppConfigurationOptions } from "unstorage/drivers/azure-app-configuration"; +import type { AzureCosmosOptions as AzureCosmosOptions } from "unstorage/drivers/azure-cosmos"; +import type { AzureKeyVaultOptions as AzureKeyVaultOptions } from "unstorage/drivers/azure-key-vault"; +import type { AzureStorageBlobOptions as AzureStorageBlobOptions } from "unstorage/drivers/azure-storage-blob"; +import type { AzureStorageTableOptions as AzureStorageTableOptions } from "unstorage/drivers/azure-storage-table"; +import type { CapacitorPreferencesOptions as CapacitorPreferencesOptions } from "unstorage/drivers/capacitor-preferences"; +import type { KVOptions as CloudflareKVBindingOptions } from "unstorage/drivers/cloudflare-kv-binding"; +import type { KVHTTPOptions as CloudflareKVHttpOptions } from "unstorage/drivers/cloudflare-kv-http"; +import type { CloudflareR2Options as CloudflareR2BindingOptions } from "unstorage/drivers/cloudflare-r2-binding"; +import type { DB0DriverOptions as Db0Options } from "unstorage/drivers/db0"; +import type { DenoKvNodeOptions as DenoKVNodeOptions } from "unstorage/drivers/deno-kv-node"; +import type { DenoKvOptions as DenoKVOptions } from "unstorage/drivers/deno-kv"; +import type { FSStorageOptions as FsLiteOptions } from "unstorage/drivers/fs-lite"; +import type { FSStorageOptions as FsOptions } from "unstorage/drivers/fs"; +import type { GithubOptions as GithubOptions } from "unstorage/drivers/github"; +import type { HTTPOptions as HttpOptions } from "unstorage/drivers/http"; +import type { IDBKeyvalOptions as IndexedbOptions } from "unstorage/drivers/indexedb"; +import type { LocalStorageOptions as LocalstorageOptions } from "unstorage/drivers/localstorage"; +import type { LRUDriverOptions as LruCacheOptions } from "unstorage/drivers/lru-cache"; +import type { MongoDbOptions as MongodbOptions } from "unstorage/drivers/mongodb"; +import type { ExtraOptions as NetlifyBlobsOptions } from "unstorage/drivers/netlify-blobs"; +import type { OverlayStorageOptions as OverlayOptions } from "unstorage/drivers/overlay"; +import type { PlanetscaleDriverOptions as PlanetscaleOptions } from "unstorage/drivers/planetscale"; +import type { RedisOptions as RedisOptions } from "unstorage/drivers/redis"; +import type { SessionStorageOptions as SessionStorageOptions } from "unstorage/drivers/session-storage"; +import type { UpstashOptions as UpstashOptions } from "unstorage/drivers/upstash"; +import type { VercelBlobOptions as VercelBlobOptions } from "unstorage/drivers/vercel-blob"; +import type { VercelKVOptions as VercelKVOptions } from "unstorage/drivers/vercel-kv"; + +export type BuiltinDriverName = "azure-app-configuration" | "azureAppConfiguration" | "azure-cosmos" | "azureCosmos" | "azure-key-vault" | "azureKeyVault" | "azure-storage-blob" | "azureStorageBlob" | "azure-storage-table" | "azureStorageTable" | "capacitor-preferences" | "capacitorPreferences" | "cloudflare-kv-binding" | "cloudflareKVBinding" | "cloudflare-kv-http" | "cloudflareKVHttp" | "cloudflare-r2-binding" | "cloudflareR2Binding" | "db0" | "deno-kv-node" | "denoKVNode" | "deno-kv" | "denoKV" | "fs-lite" | "fsLite" | "fs" | "github" | "http" | "indexedb" | "localstorage" | "lru-cache" | "lruCache" | "memory" | "mongodb" | "netlify-blobs" | "netlifyBlobs" | "null" | "overlay" | "planetscale" | "redis" | "session-storage" | "sessionStorage" | "upstash" | "vercel-blob" | "vercelBlob" | "vercel-kv" | "vercelKV"; + +export type BuiltinDriverOptions = { + "azure-app-configuration": AzureAppConfigurationOptions; + "azureAppConfiguration": AzureAppConfigurationOptions; + "azure-cosmos": AzureCosmosOptions; + "azureCosmos": AzureCosmosOptions; + "azure-key-vault": AzureKeyVaultOptions; + "azureKeyVault": AzureKeyVaultOptions; + "azure-storage-blob": AzureStorageBlobOptions; + "azureStorageBlob": AzureStorageBlobOptions; + "azure-storage-table": AzureStorageTableOptions; + "azureStorageTable": AzureStorageTableOptions; + "capacitor-preferences": CapacitorPreferencesOptions; + "capacitorPreferences": CapacitorPreferencesOptions; + "cloudflare-kv-binding": CloudflareKVBindingOptions; + "cloudflareKVBinding": CloudflareKVBindingOptions; + "cloudflare-kv-http": CloudflareKVHttpOptions; + "cloudflareKVHttp": CloudflareKVHttpOptions; + "cloudflare-r2-binding": CloudflareR2BindingOptions; + "cloudflareR2Binding": CloudflareR2BindingOptions; + "db0": Db0Options; + "deno-kv-node": DenoKVNodeOptions; + "denoKVNode": DenoKVNodeOptions; + "deno-kv": DenoKVOptions; + "denoKV": DenoKVOptions; + "fs-lite": FsLiteOptions; + "fsLite": FsLiteOptions; + "fs": FsOptions; + "github": GithubOptions; + "http": HttpOptions; + "indexedb": IndexedbOptions; + "localstorage": LocalstorageOptions; + "lru-cache": LruCacheOptions; + "lruCache": LruCacheOptions; + "mongodb": MongodbOptions; + "netlify-blobs": NetlifyBlobsOptions; + "netlifyBlobs": NetlifyBlobsOptions; + "overlay": OverlayOptions; + "planetscale": PlanetscaleOptions; + "redis": RedisOptions; + "session-storage": SessionStorageOptions; + "sessionStorage": SessionStorageOptions; + "upstash": UpstashOptions; + "vercel-blob": VercelBlobOptions; + "vercelBlob": VercelBlobOptions; + "vercel-kv": VercelKVOptions; + "vercelKV": VercelKVOptions; +}; + +export const builtinDrivers = { + "azure-app-configuration": "unstorage/drivers/azure-app-configuration", + "azureAppConfiguration": "unstorage/drivers/azure-app-configuration", + "azure-cosmos": "unstorage/drivers/azure-cosmos", + "azureCosmos": "unstorage/drivers/azure-cosmos", + "azure-key-vault": "unstorage/drivers/azure-key-vault", + "azureKeyVault": "unstorage/drivers/azure-key-vault", + "azure-storage-blob": "unstorage/drivers/azure-storage-blob", + "azureStorageBlob": "unstorage/drivers/azure-storage-blob", + "azure-storage-table": "unstorage/drivers/azure-storage-table", + "azureStorageTable": "unstorage/drivers/azure-storage-table", + "capacitor-preferences": "unstorage/drivers/capacitor-preferences", + "capacitorPreferences": "unstorage/drivers/capacitor-preferences", + "cloudflare-kv-binding": "unstorage/drivers/cloudflare-kv-binding", + "cloudflareKVBinding": "unstorage/drivers/cloudflare-kv-binding", + "cloudflare-kv-http": "unstorage/drivers/cloudflare-kv-http", + "cloudflareKVHttp": "unstorage/drivers/cloudflare-kv-http", + "cloudflare-r2-binding": "unstorage/drivers/cloudflare-r2-binding", + "cloudflareR2Binding": "unstorage/drivers/cloudflare-r2-binding", + "db0": "unstorage/drivers/db0", + "deno-kv-node": "unstorage/drivers/deno-kv-node", + "denoKVNode": "unstorage/drivers/deno-kv-node", + "deno-kv": "unstorage/drivers/deno-kv", + "denoKV": "unstorage/drivers/deno-kv", + "fs-lite": "unstorage/drivers/fs-lite", + "fsLite": "unstorage/drivers/fs-lite", + "fs": "unstorage/drivers/fs", + "github": "unstorage/drivers/github", + "http": "unstorage/drivers/http", + "indexedb": "unstorage/drivers/indexedb", + "localstorage": "unstorage/drivers/localstorage", + "lru-cache": "unstorage/drivers/lru-cache", + "lruCache": "unstorage/drivers/lru-cache", + "memory": "unstorage/drivers/memory", + "mongodb": "unstorage/drivers/mongodb", + "netlify-blobs": "unstorage/drivers/netlify-blobs", + "netlifyBlobs": "unstorage/drivers/netlify-blobs", + "null": "unstorage/drivers/null", + "overlay": "unstorage/drivers/overlay", + "planetscale": "unstorage/drivers/planetscale", + "redis": "unstorage/drivers/redis", + "session-storage": "unstorage/drivers/session-storage", + "sessionStorage": "unstorage/drivers/session-storage", + "upstash": "unstorage/drivers/upstash", + "vercel-blob": "unstorage/drivers/vercel-blob", + "vercelBlob": "unstorage/drivers/vercel-blob", + "vercel-kv": "unstorage/drivers/vercel-kv", + "vercelKV": "unstorage/drivers/vercel-kv", +} as const; diff --git a/src/index.ts b/src/index.ts index 9c772957..d8df1533 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,102 +1,11 @@ export * from "./storage"; export * from "./types"; export * from "./utils"; -export { defineDriver } from "./drivers/utils"; - -export const builtinDrivers = { - azureAppConfiguration: "unstorage/drivers/azure-app-configuration", - azureCosmos: "unstorage/drivers/azure-cosmos", - azureKeyVault: "unstorage/drivers/azure-key-vault", - azureStorageBlob: "unstorage/drivers/azure-storage-blob", - azureStorageTable: "unstorage/drivers/azure-storage-table", - cloudflareKVBinding: "unstorage/drivers/cloudflare-kv-binding", - cloudflareKVHTTP: "unstorage/drivers/cloudflare-kv-http", - cloudflareR2Binding: "unstorage/drivers/cloudflare-r2-binding", - db0: "unstorage/drivers/db0", - denoKv: "unstorage/drivers/deno-kv", - denoKvNode: "unstorage/drivers/deno-kv-node", - fs: "unstorage/drivers/fs", - fsLite: "unstorage/drivers/fs-lite", - github: "unstorage/drivers/github", - http: "unstorage/drivers/http", - indexedb: "unstorage/drivers/indexedb", - localStorage: "unstorage/drivers/localstorage", - lruCache: "unstorage/drivers/lru-cache", - memory: "unstorage/drivers/memory", - mongodb: "unstorage/drivers/mongodb", - netlifyBlobs: "unstorage/drivers/netlify-blobs", - null: "unstorage/drivers/null", - overlay: "unstorage/drivers/overlay", - planetscale: "unstorage/drivers/planetscale", - redis: "unstorage/drivers/redis", - sessionStorage: "unstorage/drivers/session-storage", - upstash: "unstorage/drivers/upstash", - vercelKV: "unstorage/drivers/vercel-kv", - - /** @deprecated */ - "cloudflare-kv-binding": "unstorage/drivers/cloudflare-kv-binding", - /** @deprecated */ - "cloudflare-kv-http": "unstorage/drivers/cloudflare-kv-http", -} as const; -type ExtractOpts = T extends (opts: infer Opts) => any ? Opts : never; - -export type BuiltinDriverOptions = { - azureAppConfiguration: ExtractOpts< - (typeof import("./drivers/azure-app-configuration"))["default"] - >; - azureCosmos: ExtractOpts< - (typeof import("./drivers/azure-cosmos"))["default"] - >; - azureKeyVault: ExtractOpts< - (typeof import("./drivers/azure-key-vault"))["default"] - >; - azureStorageBlob: ExtractOpts< - (typeof import("./drivers/azure-storage-blob"))["default"] - >; - azureStorageTable: ExtractOpts< - (typeof import("./drivers/azure-storage-table"))["default"] - >; - cloudflareKVBinding: ExtractOpts< - (typeof import("./drivers/cloudflare-kv-binding"))["default"] - >; - cloudflareKVHTTP: ExtractOpts< - (typeof import("./drivers/cloudflare-kv-http"))["default"] - >; - cloudflareR2Binding: ExtractOpts< - (typeof import("./drivers/cloudflare-r2-binding"))["default"] - >; - db0: ExtractOpts<(typeof import("./drivers/db0"))["default"]>; - fs: ExtractOpts<(typeof import("./drivers/fs"))["default"]>; - fsLite: ExtractOpts<(typeof import("./drivers/fs-lite"))["default"]>; - github: ExtractOpts<(typeof import("./drivers/github"))["default"]>; - http: ExtractOpts<(typeof import("./drivers/http"))["default"]>; - indexedb: ExtractOpts<(typeof import("./drivers/indexedb"))["default"]>; - localStorage: ExtractOpts< - (typeof import("./drivers/localstorage"))["default"] - >; - lruCache: ExtractOpts<(typeof import("./drivers/lru-cache"))["default"]>; - memory: ExtractOpts<(typeof import("./drivers/memory"))["default"]>; - mongodb: ExtractOpts<(typeof import("./drivers/mongodb"))["default"]>; - netlifyBlobs: ExtractOpts< - (typeof import("./drivers/netlify-blobs"))["default"] - >; - overlay: ExtractOpts<(typeof import("./drivers/overlay"))["default"]>; - planetscale: ExtractOpts<(typeof import("./drivers/planetscale"))["default"]>; - redis: ExtractOpts<(typeof import("./drivers/redis"))["default"]>; - sessionStorage: ExtractOpts< - (typeof import("./drivers/session-storage"))["default"] - >; - vercelKV: ExtractOpts<(typeof import("./drivers/vercel-kv"))["default"]>; - - /** @deprecated */ - "cloudflare-kv-binding": ExtractOpts< - (typeof import("./drivers/cloudflare-kv-binding"))["default"] - >; - /** @deprecated */ - "cloudflare-kv-http": ExtractOpts< - (typeof import("./drivers/cloudflare-kv-http"))["default"] - >; -}; +export { defineDriver } from "./drivers/utils"; -export type BuiltinDriverName = keyof typeof builtinDrivers; +export { + builtinDrivers, + type BuiltinDriverName, + type BuiltinDriverOptions, +} from "./_drivers"; diff --git a/tsconfig.json b/tsconfig.json index af35df31..c21a19c9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,9 @@ "noEmit": true, "allowImportingTsExtensions": true, "skipLibCheck": true, - "types": ["node", "deno"] + "types": ["node", "deno"], + "paths": { + "unstorage/drivers/*": ["./src/drivers/*"] + } } }