refactor: remove legacy config and state aliases (PR5)
This commit is contained in:
@@ -17,7 +17,7 @@ describe('migrate room registrations step', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('migrates pending legacy rows and legacy json into canonical room tables idempotently', async () => {
|
||||
it('migrates pending legacy rows into canonical room tables idempotently', async () => {
|
||||
const tempRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'ejclaw-migrate-rooms-'),
|
||||
);
|
||||
@@ -103,31 +103,10 @@ describe('migrate room registrations step', () => {
|
||||
);
|
||||
legacyDb.close();
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(dataDir, 'registered_groups.json'),
|
||||
JSON.stringify({
|
||||
'dc:json-room': {
|
||||
name: 'JSON Room',
|
||||
folder: 'json-room',
|
||||
trigger: '@Andy',
|
||||
added_at: '2024-02-01T00:00:00.000Z',
|
||||
agentType: 'claude-code',
|
||||
requiresTrigger: true,
|
||||
isMain: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const emitStatusMock = vi.fn();
|
||||
vi.doMock('./status.js', () => ({
|
||||
emitStatus: emitStatusMock,
|
||||
}));
|
||||
vi.doMock('../src/logger.js', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const { run } = await import('./migrate-room-registrations.js');
|
||||
|
||||
@@ -143,12 +122,6 @@ describe('migrate room registrations step', () => {
|
||||
)
|
||||
.all(),
|
||||
).toEqual([
|
||||
{
|
||||
chat_jid: 'dc:json-room',
|
||||
room_mode: 'single',
|
||||
mode_source: 'inferred',
|
||||
owner_agent_type: 'claude-code',
|
||||
},
|
||||
{
|
||||
chat_jid: 'dc:legacy-room',
|
||||
room_mode: 'tribunal',
|
||||
@@ -165,11 +138,6 @@ describe('migrate room registrations step', () => {
|
||||
)
|
||||
.all(),
|
||||
).toEqual([
|
||||
{
|
||||
chat_jid: 'dc:json-room',
|
||||
role: 'owner',
|
||||
agent_type: 'claude-code',
|
||||
},
|
||||
{
|
||||
chat_jid: 'dc:legacy-room',
|
||||
role: 'owner',
|
||||
@@ -201,22 +169,13 @@ describe('migrate room registrations step', () => {
|
||||
]);
|
||||
migratedDb.close();
|
||||
|
||||
expect(fs.existsSync(path.join(dataDir, 'registered_groups.json'))).toBe(
|
||||
false,
|
||||
);
|
||||
expect(
|
||||
fs.existsSync(path.join(dataDir, 'registered_groups.json.migrated')),
|
||||
).toBe(true);
|
||||
expect(emitStatusMock).toHaveBeenLastCalledWith(
|
||||
'MIGRATE_ROOM_REGISTRATIONS',
|
||||
expect.objectContaining({
|
||||
MIGRATED_ROOMS: 2,
|
||||
MIGRATED_ROLE_OVERRIDES: 3,
|
||||
MIGRATED_ROOMS: 1,
|
||||
MIGRATED_ROLE_OVERRIDES: 2,
|
||||
SKIPPED_ROOMS: 0,
|
||||
MIGRATED_JSON_ROOMS: 1,
|
||||
SKIPPED_JSON_ROOMS: 0,
|
||||
BACKED_UP_LEGACY_ROWS: 2,
|
||||
RENAMED_LEGACY_JSON: true,
|
||||
STATUS: 'success',
|
||||
}),
|
||||
);
|
||||
@@ -229,10 +188,7 @@ describe('migrate room registrations step', () => {
|
||||
MIGRATED_ROOMS: 0,
|
||||
MIGRATED_ROLE_OVERRIDES: 0,
|
||||
SKIPPED_ROOMS: 0,
|
||||
MIGRATED_JSON_ROOMS: 0,
|
||||
SKIPPED_JSON_ROOMS: 0,
|
||||
BACKED_UP_LEGACY_ROWS: 0,
|
||||
RENAMED_LEGACY_JSON: false,
|
||||
STATUS: 'success',
|
||||
}),
|
||||
);
|
||||
@@ -370,12 +326,6 @@ describe('migrate room registrations step', () => {
|
||||
vi.doMock('./status.js', () => ({
|
||||
emitStatus: emitStatusMock,
|
||||
}));
|
||||
vi.doMock('../src/logger.js', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const { run } = await import('./migrate-room-registrations.js');
|
||||
|
||||
@@ -417,9 +367,9 @@ describe('migrate room registrations step', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('fails and leaves registered_groups.json in place when it contains invalid entries', async () => {
|
||||
it('fails when unexpected data state files are still present', async () => {
|
||||
const tempRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'ejclaw-migrate-rooms-invalid-json-'),
|
||||
path.join(os.tmpdir(), 'ejclaw-migrate-rooms-legacy-files-'),
|
||||
);
|
||||
tempRoots.push(tempRoot);
|
||||
const storeDir = path.join(tempRoot, 'store');
|
||||
@@ -429,298 +379,12 @@ describe('migrate room registrations step', () => {
|
||||
vi.stubEnv('EJCLAW_STORE_DIR', storeDir);
|
||||
vi.stubEnv('EJCLAW_DATA_DIR', dataDir);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(dataDir, 'registered_groups.json'),
|
||||
JSON.stringify({
|
||||
'dc:bad-room': {
|
||||
name: 'Bad Room',
|
||||
folder: '../bad',
|
||||
trigger: '@Andy',
|
||||
added_at: '2024-02-01T00:00:00.000Z',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
vi.doMock('./status.js', () => ({
|
||||
emitStatus: vi.fn(),
|
||||
}));
|
||||
vi.doMock('../src/logger.js', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
}));
|
||||
fs.writeFileSync(path.join(dataDir, 'registered_groups.json'), '{}');
|
||||
|
||||
const { run } = await import('./migrate-room-registrations.js');
|
||||
|
||||
await expect(run([])).rejects.toThrow(
|
||||
/Invalid legacy registered_groups\.json folder/,
|
||||
/Unexpected data state files detected before room migration/,
|
||||
);
|
||||
expect(fs.existsSync(path.join(dataDir, 'registered_groups.json'))).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
fs.existsSync(path.join(dataDir, 'registered_groups.json.migrated')),
|
||||
).toBe(false);
|
||||
|
||||
const migratedDb = new Database(path.join(storeDir, 'messages.db'));
|
||||
expect(
|
||||
migratedDb
|
||||
.prepare(
|
||||
`SELECT name
|
||||
FROM sqlite_master
|
||||
WHERE type = 'table'
|
||||
AND name IN ('room_settings', 'registered_groups_legacy_backup')`,
|
||||
)
|
||||
.all(),
|
||||
).toEqual([{ name: 'room_settings' }]);
|
||||
expect(
|
||||
migratedDb.prepare('SELECT COUNT(*) AS count FROM room_settings').get(),
|
||||
).toEqual({ count: 0 });
|
||||
migratedDb.close();
|
||||
});
|
||||
|
||||
it('treats identical registered_groups.json entries as idempotent when room_settings already exists', async () => {
|
||||
const tempRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'ejclaw-migrate-rooms-json-idempotent-'),
|
||||
);
|
||||
tempRoots.push(tempRoot);
|
||||
const storeDir = path.join(tempRoot, 'store');
|
||||
const dataDir = path.join(tempRoot, 'data');
|
||||
fs.mkdirSync(storeDir, { recursive: true });
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
vi.stubEnv('EJCLAW_STORE_DIR', storeDir);
|
||||
vi.stubEnv('EJCLAW_DATA_DIR', dataDir);
|
||||
|
||||
const dbPath = path.join(storeDir, 'messages.db');
|
||||
const db = new Database(dbPath);
|
||||
db.exec(`
|
||||
CREATE TABLE room_settings (
|
||||
chat_jid TEXT PRIMARY KEY,
|
||||
room_mode TEXT NOT NULL,
|
||||
mode_source TEXT NOT NULL DEFAULT 'explicit',
|
||||
name TEXT,
|
||||
folder TEXT,
|
||||
trigger_pattern TEXT,
|
||||
requires_trigger INTEGER DEFAULT 1,
|
||||
is_main INTEGER DEFAULT 0,
|
||||
owner_agent_type TEXT,
|
||||
work_dir TEXT,
|
||||
created_at TEXT,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE room_role_overrides (
|
||||
chat_jid TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
agent_type TEXT NOT NULL,
|
||||
agent_config_json TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
PRIMARY KEY (chat_jid, role)
|
||||
);
|
||||
`);
|
||||
db.prepare(
|
||||
`INSERT INTO room_settings (
|
||||
chat_jid,
|
||||
room_mode,
|
||||
mode_source,
|
||||
name,
|
||||
folder,
|
||||
trigger_pattern,
|
||||
requires_trigger,
|
||||
is_main,
|
||||
owner_agent_type,
|
||||
work_dir,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
).run(
|
||||
'dc:json-room',
|
||||
'single',
|
||||
'inferred',
|
||||
'JSON Room',
|
||||
'json-room',
|
||||
'@Andy',
|
||||
1,
|
||||
0,
|
||||
'claude-code',
|
||||
null,
|
||||
'2024-02-01T00:00:00.000Z',
|
||||
'2024-02-01T00:00:00.000Z',
|
||||
);
|
||||
db.close();
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(dataDir, 'registered_groups.json'),
|
||||
JSON.stringify({
|
||||
'dc:json-room': {
|
||||
name: 'JSON Room',
|
||||
folder: 'json-room',
|
||||
trigger: '@Andy',
|
||||
added_at: '2024-02-01T00:00:00.000Z',
|
||||
agentType: 'claude-code',
|
||||
requiresTrigger: true,
|
||||
isMain: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const emitStatusMock = vi.fn();
|
||||
vi.doMock('./status.js', () => ({
|
||||
emitStatus: emitStatusMock,
|
||||
}));
|
||||
vi.doMock('../src/logger.js', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const { run } = await import('./migrate-room-registrations.js');
|
||||
|
||||
await run([]);
|
||||
|
||||
const migratedDb = new Database(dbPath, { readonly: true });
|
||||
expect(
|
||||
migratedDb
|
||||
.prepare(
|
||||
`SELECT chat_jid, role, agent_type
|
||||
FROM room_role_overrides
|
||||
ORDER BY chat_jid, role`,
|
||||
)
|
||||
.all(),
|
||||
).toEqual([
|
||||
{
|
||||
chat_jid: 'dc:json-room',
|
||||
role: 'owner',
|
||||
agent_type: 'claude-code',
|
||||
},
|
||||
]);
|
||||
migratedDb.close();
|
||||
|
||||
expect(fs.existsSync(path.join(dataDir, 'registered_groups.json'))).toBe(
|
||||
false,
|
||||
);
|
||||
expect(
|
||||
fs.existsSync(path.join(dataDir, 'registered_groups.json.migrated')),
|
||||
).toBe(true);
|
||||
expect(emitStatusMock).toHaveBeenLastCalledWith(
|
||||
'MIGRATE_ROOM_REGISTRATIONS',
|
||||
expect.objectContaining({
|
||||
MIGRATED_ROOMS: 0,
|
||||
MIGRATED_JSON_ROOMS: 0,
|
||||
MIGRATED_ROLE_OVERRIDES: 1,
|
||||
RENAMED_LEGACY_JSON: true,
|
||||
STATUS: 'success',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('fails and preserves registered_groups.json when table and json owner overrides conflict', async () => {
|
||||
const tempRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), 'ejclaw-migrate-rooms-json-conflict-'),
|
||||
);
|
||||
tempRoots.push(tempRoot);
|
||||
const storeDir = path.join(tempRoot, 'store');
|
||||
const dataDir = path.join(tempRoot, 'data');
|
||||
fs.mkdirSync(storeDir, { recursive: true });
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
vi.stubEnv('EJCLAW_STORE_DIR', storeDir);
|
||||
vi.stubEnv('EJCLAW_DATA_DIR', dataDir);
|
||||
|
||||
const dbPath = path.join(storeDir, 'messages.db');
|
||||
const db = new Database(dbPath);
|
||||
db.exec(`
|
||||
CREATE TABLE registered_groups (
|
||||
jid TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
folder TEXT NOT NULL,
|
||||
trigger_pattern TEXT NOT NULL,
|
||||
added_at TEXT NOT NULL,
|
||||
agent_config TEXT,
|
||||
requires_trigger INTEGER DEFAULT 1,
|
||||
is_main INTEGER DEFAULT 0,
|
||||
agent_type TEXT NOT NULL DEFAULT 'claude-code',
|
||||
work_dir TEXT,
|
||||
PRIMARY KEY (jid, agent_type),
|
||||
UNIQUE (folder, agent_type)
|
||||
)
|
||||
`);
|
||||
db.prepare(
|
||||
`INSERT INTO registered_groups (
|
||||
jid,
|
||||
name,
|
||||
folder,
|
||||
trigger_pattern,
|
||||
added_at,
|
||||
agent_config,
|
||||
requires_trigger,
|
||||
is_main,
|
||||
agent_type,
|
||||
work_dir
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
).run(
|
||||
'dc:shared-room',
|
||||
'Shared Room',
|
||||
'shared-room',
|
||||
'@Andy',
|
||||
'2024-03-01T00:00:00.000Z',
|
||||
'{"source":"table"}',
|
||||
1,
|
||||
0,
|
||||
'claude-code',
|
||||
null,
|
||||
);
|
||||
db.close();
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(dataDir, 'registered_groups.json'),
|
||||
JSON.stringify({
|
||||
'dc:shared-room': {
|
||||
name: 'Shared Room',
|
||||
folder: 'shared-room',
|
||||
trigger: '@Andy',
|
||||
added_at: '2024-03-01T00:00:00.000Z',
|
||||
agentType: 'claude-code',
|
||||
agentConfig: { source: 'json' },
|
||||
requiresTrigger: true,
|
||||
isMain: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
vi.doMock('./status.js', () => ({
|
||||
emitStatus: vi.fn(),
|
||||
}));
|
||||
vi.doMock('../src/logger.js', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const { run } = await import('./migrate-room-registrations.js');
|
||||
|
||||
await expect(run([])).rejects.toThrow(
|
||||
/owner override conflicts with existing owner override/,
|
||||
);
|
||||
|
||||
const migratedDb = new Database(dbPath, { readonly: true });
|
||||
expect(
|
||||
migratedDb.prepare('SELECT COUNT(*) AS count FROM room_settings').get(),
|
||||
).toEqual({ count: 0 });
|
||||
expect(
|
||||
migratedDb
|
||||
.prepare('SELECT COUNT(*) AS count FROM room_role_overrides')
|
||||
.get(),
|
||||
).toEqual({ count: 0 });
|
||||
migratedDb.close();
|
||||
|
||||
expect(fs.existsSync(path.join(dataDir, 'registered_groups.json'))).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
fs.existsSync(path.join(dataDir, 'registered_groups.json.migrated')),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user