@adonisjs/drive
Version:
A thin wrapper on top of Flydrive to work seamlessly with AdonisJS
266 lines (258 loc) • 8.15 kB
JavaScript
import {
debug_default,
errors_exports
} from "./chunk-GRHMQSPS.js";
import "./chunk-MLKGABMK.js";
// index.ts
export * from "flydrive";
// configure.ts
import string from "@adonisjs/core/helpers/string";
// stubs/main.ts
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
var stubsRoot = dirname(fileURLToPath(import.meta.url));
// configure.ts
var STORAGE_SERVICES = {
fs: {
name: "Local filesystem",
env: [],
dependencies: []
},
s3: {
name: "AWS S3",
env: [
{ name: "AWS_ACCESS_KEY_ID", value: "", schema: "Env.schema.string()" },
{ name: "AWS_SECRET_ACCESS_KEY", value: "", schema: "Env.schema.string()" },
{ name: "AWS_REGION", value: "", schema: "Env.schema.string()" },
{ name: "S3_BUCKET", value: "", schema: "Env.schema.string()" }
],
dependencies: ["@aws-sdk/client-s3", "@aws-sdk/s3-request-presigner"]
},
spaces: {
name: "Digital Ocean Spaces",
env: [
{ name: "SPACES_KEY", value: "", schema: "Env.schema.string()" },
{ name: "SPACES_SECRET", value: "", schema: "Env.schema.string()" },
{ name: "SPACES_REGION", value: "", schema: "Env.schema.string()" },
{ name: "SPACES_BUCKET", value: "", schema: "Env.schema.string()" },
{
name: "SPACES_ENDPOINT",
value: `https://\${SPACES_REGION}.digitaloceanspaces.com`,
schema: "Env.schema.string()"
}
],
dependencies: ["@aws-sdk/client-s3", "@aws-sdk/s3-request-presigner"]
},
r2: {
name: "Cloudflare R2",
env: [
{ name: "R2_KEY", value: "", schema: "Env.schema.string()" },
{ name: "R2_SECRET", value: "", schema: "Env.schema.string()" },
{ name: "R2_BUCKET", value: "", schema: "Env.schema.string()" },
{ name: "R2_ENDPOINT", value: "", schema: "Env.schema.string()" }
],
dependencies: ["@aws-sdk/client-s3", "@aws-sdk/s3-request-presigner"]
},
gcs: {
name: "Google Cloud Storage",
env: [
{ name: "GCS_KEY", value: "file://./gcs_key.json", schema: "Env.schema.string()" },
{ name: "GCS_BUCKET", value: "", schema: "Env.schema.string()" }
],
dependencies: ["@google-cloud/storage"]
}
};
var SERVICES_NAMES = Object.keys(STORAGE_SERVICES);
async function configure(command) {
let selectedServices = command.parsedFlags.services;
let shouldInstallPackages = command.parsedFlags.install;
if (!selectedServices) {
selectedServices = await command.prompt.multiple(
"Select the storage services you want to use",
SERVICES_NAMES.map((service) => {
return {
name: service,
message: STORAGE_SERVICES[service].name
};
}),
{
validate(values) {
return !values || !values.length ? "Please select one or more services" : true;
}
}
);
}
const services2 = typeof selectedServices === "string" ? [selectedServices] : selectedServices;
const unknownServices = services2.find((service) => !SERVICES_NAMES.includes(service));
if (unknownServices) {
command.exitCode = 1;
command.logger.logError(
`Invalid service "${unknownServices}". Supported services are: ${string.sentence(
SERVICES_NAMES
)}`
);
return;
}
const pkgsToInstall = services2.flatMap((service) => STORAGE_SERVICES[service].dependencies).map((pkg) => {
return { name: pkg, isDevDependency: false };
});
if (!shouldInstallPackages && pkgsToInstall.length) {
shouldInstallPackages = await command.prompt.confirm(
'Do you want to install additional packages required by "@adonisjs/drive"?'
);
}
const codemods = await command.createCodemods();
await codemods.makeUsingStub(stubsRoot, "config/drive.stub", {
services: services2
});
await codemods.updateRcFile((rcFile) => {
rcFile.addProvider("@adonisjs/drive/drive_provider");
});
await codemods.defineEnvVariables(
services2.reduce(
(result, service) => {
STORAGE_SERVICES[service].env.forEach((envVariable) => {
result[envVariable.name] = envVariable.value;
});
return result;
},
{
DRIVE_DISK: services2[0]
}
)
);
await codemods.defineEnvValidations({
leadingComment: "Variables for configuring the drive package",
variables: services2.reduce(
(result, service) => {
STORAGE_SERVICES[service].env.forEach((envVariable) => {
result[envVariable.name] = envVariable.schema;
});
return result;
},
{
DRIVE_DISK: `Env.schema.enum(['${services2.join("', '")}'] as const)`
}
)
});
if (!pkgsToInstall.length) {
return;
}
if (shouldInstallPackages) {
await codemods.installPackages(pkgsToInstall);
} else {
await codemods.listPackagesToInstall(pkgsToInstall);
}
}
// src/define_config.ts
import { configProvider } from "@adonisjs/core";
import { RuntimeException } from "@adonisjs/core/exceptions";
// src/url_builder.ts
function createURLBuilder(router, config, routeName) {
const prefixUrl = config.appUrl || "";
return {
async generateURL(key) {
return router.builder().params({ "*": key.split("/") }).prefixUrl(prefixUrl).make(routeName);
},
async generateSignedURL(key, _, options) {
const { expiresIn, ...headers } = options;
return router.builder().qs(headers).params({ "*": key.split("/") }).prefixUrl(prefixUrl).makeSigned(routeName, {
expiresIn
});
}
};
}
// src/define_config.ts
function defineConfig(config) {
return configProvider.create(async (app) => {
const { services: services2, fakes, default: defaultDisk } = config;
const servicesNames = Object.keys(services2);
const disks = {};
const locallyServed = [];
for (let serviceName of servicesNames) {
const disk = services2[serviceName];
if (typeof disk === "function") {
disks[serviceName] = disk;
} else {
disks[serviceName] = await disk.resolver(serviceName, app, locallyServed);
}
}
return {
config: {
default: defaultDisk,
fakes: {
location: app.tmpPath("drive-fakes"),
urlBuilder: {
async generateURL(key, _) {
return `/drive/fakes/${key}`;
},
async generateSignedURL(key, _, __) {
return `/drive/fakes/signed/${key}`;
}
},
...fakes
},
services: disks
},
locallyServed
};
});
}
var services = {
fs(config) {
return {
type: "provider",
async resolver(name, app, locallyServed) {
debug_default("configuring fs service");
if (config.serveFiles && !config.routeBasePath) {
throw new RuntimeException(
`Invalid drive config. Missing "routeBasePath" option in "services.${name}" object`
);
}
const routeName = `drive.${name}.serve`;
const fsConfig = {
visibility: config.visibility,
location: config.location
};
if (config.serveFiles) {
const router = await app.container.make("router");
fsConfig.urlBuilder = createURLBuilder(router, config, routeName);
locallyServed.push({
service: name,
routeName,
routePattern: `${config.routeBasePath.replace(/\/$/, "")}/*`
});
}
const { FSDriver } = await import("flydrive/drivers/fs");
return () => new FSDriver(fsConfig);
}
};
},
s3(config) {
return {
type: "provider",
async resolver() {
debug_default("configuring s3 service");
const { S3Driver } = await import("flydrive/drivers/s3");
return () => new S3Driver(config);
}
};
},
gcs(config) {
return {
type: "provider",
async resolver() {
debug_default("configuring gcs service");
const { GCSDriver } = await import("flydrive/drivers/gcs");
return () => new GCSDriver(config);
}
};
}
};
export {
configure,
defineConfig,
errors_exports as errors,
services,
stubsRoot
};