1885990081
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
CI / helm (push) Waiting to run
CI / push-validation (push) Waiting to run
CI / status-check (push) Blocked by required conditions
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / security (push) Waiting to run
CI / quality (push) Waiting to run
CI / unit_tests (push) Waiting to run
CI / integration_tests (push) Waiting to run
CI / e2e_tests (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / benchmark-publish (push) Waiting to run
102 lines
3.1 KiB
TypeScript
102 lines
3.1 KiB
TypeScript
#!/usr/bin/env -S npx --yes tsx
|
|
// =============================================================================
|
|
// delete.ts — Delete a key's value from the vault
|
|
//
|
|
// Part of: .opencode/skills/templating-vault/scripts/
|
|
//
|
|
// Removes a key's value file. Respects write-once and owner restrictions.
|
|
// Optionally deletes recursively under a prefix.
|
|
//
|
|
// USAGE:
|
|
// delete.ts --key <key> [--owner <id>] [--recursive]
|
|
// [--config <path>] [--store-dir <path>]
|
|
//
|
|
// OUTPUT (stdout): JSON result
|
|
// =============================================================================
|
|
import * as fs from 'node:fs';
|
|
import * as path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import {
|
|
parseCommonFlags, getFlag, hasFlag, output,
|
|
loadConfig, resolveStore, loadKeyMeta, deleteValue,
|
|
hasValue, listAllKeys, keyToPath,
|
|
} from './api.ts';
|
|
|
|
async function main(): Promise<void> {
|
|
const { config: cfgPath, storeDirs, rest } = parseCommonFlags(process.argv);
|
|
const config = loadConfig(cfgPath, storeDirs.length > 0 ? storeDirs : undefined);
|
|
|
|
const key = getFlag(rest, '--key');
|
|
const owner = getFlag(rest, '--owner');
|
|
const recursive = hasFlag(rest, '--recursive');
|
|
|
|
if (!key) {
|
|
output({ deleted: false, error: '--key is required' });
|
|
process.exit(1);
|
|
}
|
|
|
|
// Check access
|
|
const resolved = resolveStore(config, key);
|
|
if (resolved.mapping.access === 'readonly') {
|
|
output({ deleted: false, error: `Store for prefix "${resolved.mapping.prefix}" is readonly` });
|
|
process.exit(1);
|
|
}
|
|
|
|
if (recursive) {
|
|
// Delete all keys under prefix
|
|
const keys = listAllKeys(config, key, true);
|
|
let deletedCount = 0;
|
|
const errors: string[] = [];
|
|
|
|
// Also include the key itself
|
|
if (hasValue(config, key)) {
|
|
const meta = loadKeyMeta(config, key);
|
|
if (meta.write_once) {
|
|
errors.push(`${key}: write-once, cannot delete`);
|
|
} else {
|
|
deleteValue(config, key);
|
|
deletedCount++;
|
|
}
|
|
}
|
|
|
|
for (const k of keys) {
|
|
const meta = loadKeyMeta(config, k);
|
|
if (meta.write_once) {
|
|
errors.push(`${k}: write-once, cannot delete`);
|
|
continue;
|
|
}
|
|
if (deleteValue(config, k)) deletedCount++;
|
|
}
|
|
|
|
output({ deleted: true, count: deletedCount, errors: errors.length > 0 ? errors : undefined });
|
|
} else {
|
|
// Delete single key
|
|
if (!hasValue(config, key)) {
|
|
output({ deleted: false, error: `Key "${key}" has no value` });
|
|
process.exit(1);
|
|
}
|
|
|
|
const meta = loadKeyMeta(config, key);
|
|
|
|
if (meta.write_once) {
|
|
output({ deleted: false, error: `Key "${key}" is write-once, cannot delete` });
|
|
process.exit(1);
|
|
}
|
|
|
|
if (meta.owner && owner && meta.owner !== owner) {
|
|
output({ deleted: false, error: `Key "${key}" is owned by "${meta.owner}", not "${owner}"` });
|
|
process.exit(1);
|
|
}
|
|
|
|
deleteValue(config, key);
|
|
output({ deleted: true, key });
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
main().catch((err: unknown) => {
|
|
output({ deleted: false, error: String(err instanceof Error ? err.message : err) });
|
|
process.exit(1);
|
|
});
|
|
}
|