convex
Version:
Client for the Convex Cloud
87 lines (84 loc) • 3.13 kB
text/typescript
import { Command, Option } from "commander";
import chalk from "chalk";
import { readProjectConfig } from "./lib/config";
import {
ensureHasConvexDependency,
formatSize,
fatalServerErr,
} from "./lib/utils";
import axios, { AxiosResponse } from "axios";
import { version } from "../index.js";
import { getUrlAndAdminKey } from "./lib/api";
import { oneoffContext } from "./lib/context";
export const convexImport = new Command("import")
.description("Import a file into a Convex table (EXPERIMENTAL)")
.addOption(
new Option(
"--format <format>",
"Input file format. CSV files must have a header, and each rows' entries are interpreted either as a (floating point) number or a string. JSON files must have a JSON object per line."
)
.choices(["csv", "json"])
.default("csv")
)
.option(
"--prod",
"Import data into this project's production deployment. Defaults to your dev deployment without this flag."
)
.addOption(new Option("--url <url>").hideHelp())
.addOption(new Option("--admin-key <adminKey>").hideHelp())
.argument("<tableName>", "Destination table name (must be empty)")
.argument("<path>", "Path to the input file")
.action(async (tableName: string, path: string, options: any) => {
const ctx = oneoffContext;
const format = options.format;
if (format !== "csv" && format !== "json") {
throw new Error(`Invalid format; ${format}`);
}
const { projectConfig } = await readProjectConfig(ctx);
const deploymentType = options.prod ? "prod" : "dev";
let deploymentUrl, adminKey;
if (!options.url || !options.adminKey) {
let url;
({ url, adminKey } = await getUrlAndAdminKey(
ctx,
projectConfig.project,
projectConfig.team,
deploymentType
));
deploymentUrl = url;
}
adminKey = options.adminKey ?? adminKey;
deploymentUrl = options.url ?? deploymentUrl;
await ensureHasConvexDependency(ctx, "import");
if (!ctx.fs.exists(path)) {
console.error(chalk.gray(`Error: Path ${path} does not exist.`));
return await ctx.fatalError(1, "fs");
}
const data = ctx.fs.readUtf8File(path);
console.log(
chalk.yellow(
`The \`npx convex import\` command is experimental and hasn't been fully polished yet.\nPlease report any issues on the Convex Community Discord (https://convex.dev/community).\n`
)
);
console.log(
chalk.gray(`Importing ${path} (${formatSize(data.length)})...`)
);
const urlName = encodeURIComponent(tableName);
const urlFormat = encodeURIComponent(format);
const client = axios.create();
let resp: AxiosResponse;
try {
const url = `${deploymentUrl}/api/${version}/import?table_name=${urlName}&format=${urlFormat}`;
resp = await client.post(url, data, {
headers: {
Authorization: `Convex ${adminKey}`,
"Content-Type": "text/plain",
},
});
} catch (e) {
return await fatalServerErr(ctx, e);
}
console.log(
chalk.green(`Wrote ${resp.data.numWritten} rows to ${tableName}.`)
);
});