scripts/ was holding two unrelated kinds of thing: install-this-machine, and run-this-occasionally. The eight installers now live in scripts/setup/; what stays at the top level is the build steps (gen-index, prebuild, build/) and the two maintenance scripts (reindex-music, rebuild-soulseek-tree). The move is not just a rename. Three of these derive the repo root from their own location: setup.sh:51 PROJECT_DIR="$(dirname "$SCRIPT_DIR")" setup_mac_light.sh:51 same cleanup-desktop.sh:134 ENV_FILE="$(dirname "$0")/../.env" Left alone, all three would now resolve to scripts/ — and nothing downstream complains. PROJECT_DIR is where .env is written, where `bun install`, `gen:index` and `db:push` run, and what pm2 is pointed at, so a fresh install would have quietly provisioned scripts/ and reported success. cleanup-desktop.sh fails the other way: it would find no .env, print "No .env — skipping", and leave the real VNC_PASSWORD in the real file. All three are now `../..` with a comment saying why the level matters. provision-user-dirs.ts imports data-path.ts relatively; that one tsgo caught. Also disambiguated `setup.sh` where it had become two files. app-store/templates/<name>/setup.sh is a per-sidecar installer with its own contract, and preflight.ts + docs/sidecar-app-store.md discussed both in the same paragraph. The host one is now spelled with its full path at those sites. Verified: bash -n on all six shell scripts, tsgo clean, os-user tests pass, both derivations resolve to the repo root, starship.toml still resolves from os-user-shell.ts, and provision-user-dirs.ts runs under DRY_RUN. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
58 lines
2.4 KiB
TypeScript
58 lines
2.4 KiB
TypeScript
// Create the per-user root under DATA_PATH for the given accounts.
|
|
//
|
|
// bun scripts/setup/provision-user-dirs.ts a@b.com c@d.com
|
|
// DRY_RUN=1 bun scripts/setup/provision-user-dirs.ts a@b.com
|
|
//
|
|
// Takes emails as arguments rather than reading the user table: the directory layout does not depend
|
|
// on the database, and keeping the DB out means this runs with nothing else up. At invite time the
|
|
// caller already knows the email.
|
|
//
|
|
// This is the directory skeleton ONLY. It is deliberately not a revival of the old provision.ts, which
|
|
// also seeded shell rc files and wrote a generated CLAUDE.md + settings.json describing the user's
|
|
// Docker container. That architecture is gone. What survives from it is the useful part: a user has a
|
|
// root, and a home inside it.
|
|
//
|
|
// Idempotent — an existing directory is left exactly as it is, so re-running is safe.
|
|
|
|
import { mkdirSync, existsSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
// The list and DATA_PATH itself come from the platform rather than being restated here. The owner's
|
|
// create-account handler provisions the same skeleton, and a script that drifted from it would produce
|
|
// accounts that differ by how they were made. Importing data-path.ts pulls in no database and no server.
|
|
import { DATA_PATH, USER_DIRS } from '../../src/servers/data-path';
|
|
|
|
const DRY_RUN = process.env.DRY_RUN === '1';
|
|
const emails = process.argv.slice(2).filter(Boolean);
|
|
|
|
if (!emails.length) {
|
|
console.error('Usage: bun scripts/setup/provision-user-dirs.ts <email> [email...]');
|
|
process.exit(2);
|
|
}
|
|
|
|
// A stray argument would create a junk directory next to real user roots, and it would look like a
|
|
// user. Cheap to refuse.
|
|
const invalid = emails.filter((e) => !/^[^\s@/]+@[^\s@/]+\.[^\s@/]+$/.test(e));
|
|
if (invalid.length) {
|
|
console.error(`Not valid email addresses: ${invalid.join(', ')}`);
|
|
process.exit(2);
|
|
}
|
|
|
|
console.log(`DATA_PATH = ${DATA_PATH}`);
|
|
console.log(`${DRY_RUN ? 'Would provision' : 'Provisioning'} ${emails.length} user root(s)\n`);
|
|
|
|
for (const email of emails) {
|
|
const root = join(DATA_PATH, email);
|
|
console.log(`${email}${existsSync(root) ? '' : ' [new root]'}`);
|
|
|
|
for (const dir of USER_DIRS) {
|
|
const path = join(root, dir);
|
|
if (existsSync(path)) {
|
|
console.log(` · ${dir} (exists)`);
|
|
continue;
|
|
}
|
|
if (!DRY_RUN) mkdirSync(path, { recursive: true });
|
|
console.log(` ${DRY_RUN ? '+' : '✓'} ${dir}`);
|
|
}
|
|
console.log('');
|
|
}
|