118 lines
3.5 KiB
JavaScript
118 lines
3.5 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Upsert a platform admin with a tenant company (fixes empty-company 400s).
|
|
* Loads monorepo-root `.env` only for DATABASE_URL.
|
|
* Email/password are CLI flags only — never read from .env.
|
|
*
|
|
* Usage (from repo root):
|
|
* npm run seed:platform-admin -- --email you@example.com --password '…'
|
|
* npm run seed:platform-admin -- --email you@example.com --promote-only
|
|
* npm run seed:platform-admin -- --email you@example.com --password '…' --company 'Acme Ops'
|
|
*/
|
|
import { spawnSync } from "node:child_process";
|
|
import path from "node:path";
|
|
import { detectHostProfile, withGoLowMem } from "./lowmem-env.mjs";
|
|
import { loadRootEnv, repoRoot } from "./root-env.mjs";
|
|
|
|
const env = withGoLowMem(loadRootEnv(process.env), detectHostProfile());
|
|
|
|
function usage(msg) {
|
|
if (msg) console.error(msg);
|
|
console.error(`Usage:
|
|
npm run seed:platform-admin -- --email you@example.com --password 'strong-password'
|
|
npm run seed:platform-admin -- --email you@example.com --promote-only
|
|
npm run seed:platform-admin -- --email you@example.com --password '…' --company 'Acme Ops'
|
|
|
|
Email/password must be passed on the CLI (not stored in .env).
|
|
DATABASE_URL comes from the shell or monorepo-root .env.
|
|
Creates a company + admin membership + Free plan unless --no-company.`);
|
|
process.exit(1);
|
|
}
|
|
|
|
/** Parse `--key value` / `--flag` from argv after npm's `--`. */
|
|
function parseArgs(argv) {
|
|
const out = {
|
|
email: "",
|
|
password: "",
|
|
name: "",
|
|
company: "",
|
|
promoteOnly: false,
|
|
noCompany: false,
|
|
};
|
|
for (let i = 0; i < argv.length; i++) {
|
|
const a = argv[i];
|
|
if (a === "--promote-only") {
|
|
out.promoteOnly = true;
|
|
continue;
|
|
}
|
|
if (a === "--no-company") {
|
|
out.noCompany = true;
|
|
continue;
|
|
}
|
|
if (a === "--email" || a === "-email") {
|
|
out.email = String(argv[++i] || "").trim();
|
|
continue;
|
|
}
|
|
if (a === "--password" || a === "-password") {
|
|
out.password = String(argv[++i] || "");
|
|
continue;
|
|
}
|
|
if (a === "--name" || a === "-name") {
|
|
out.name = String(argv[++i] || "").trim();
|
|
continue;
|
|
}
|
|
if (a === "--company" || a === "-company") {
|
|
// Join remaining tokens until next --flag so unquoted "Admin Company" works.
|
|
const parts = [];
|
|
while (i + 1 < argv.length && !String(argv[i + 1]).startsWith("-")) {
|
|
parts.push(String(argv[++i]));
|
|
}
|
|
out.company = parts.join(" ").trim();
|
|
continue;
|
|
}
|
|
if (a === "--help" || a === "-h") usage();
|
|
usage(`Unknown argument: ${a}`);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
const opts = parseArgs(process.argv.slice(2));
|
|
|
|
if (!env.DATABASE_URL) {
|
|
usage("DATABASE_URL is required (shell or monorepo-root .env)");
|
|
}
|
|
if (!opts.email || !opts.email.includes("@")) {
|
|
usage("--email is required");
|
|
}
|
|
if (!opts.promoteOnly && opts.password.length < 8) {
|
|
usage("--password is required (min 8 characters), or pass --promote-only");
|
|
}
|
|
|
|
const apiDir = path.join(repoRoot, "apps", "api");
|
|
const args = [
|
|
"run",
|
|
"./cmd/seed-platform-admin",
|
|
"-postgres",
|
|
env.DATABASE_URL,
|
|
"-email",
|
|
opts.email,
|
|
"-confirm",
|
|
];
|
|
if (opts.name) args.push("-name", opts.name);
|
|
if (opts.company) args.push("-company", opts.company);
|
|
if (opts.noCompany) args.push("-no-company");
|
|
if (opts.promoteOnly) {
|
|
args.push("-promote-only");
|
|
} else {
|
|
args.push("-password", opts.password);
|
|
}
|
|
|
|
console.log(`==> seed-platform-admin ${opts.email}`);
|
|
const r = spawnSync("go", args, {
|
|
cwd: apiDir,
|
|
env,
|
|
stdio: "inherit",
|
|
shell: false,
|
|
});
|
|
process.exit(r.status ?? 1);
|