hzl-core 1.16.1 → 1.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/migrations/v2-upgrade.test.d.ts +2 -0
- package/dist/__tests__/migrations/v2-upgrade.test.d.ts.map +1 -0
- package/dist/__tests__/migrations/v2-upgrade.test.js +165 -0
- package/dist/__tests__/migrations/v2-upgrade.test.js.map +1 -0
- package/dist/db/datastore.d.ts.map +1 -1
- package/dist/db/datastore.js +5 -0
- package/dist/db/datastore.js.map +1 -1
- package/dist/db/migrations/index.d.ts +21 -0
- package/dist/db/migrations/index.d.ts.map +1 -0
- package/dist/db/migrations/index.js +50 -0
- package/dist/db/migrations/index.js.map +1 -0
- package/dist/db/migrations/v2.d.ts +15 -1
- package/dist/db/migrations/v2.d.ts.map +1 -1
- package/dist/db/migrations/v2.js +18 -7
- package/dist/db/migrations/v2.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2-upgrade.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/migrations/v2-upgrade.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test that v2 migration correctly handles upgrading from old database schema
|
|
3
|
+
* that doesn't have the terminal_at column.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
6
|
+
import Database from 'libsql';
|
|
7
|
+
import { runCacheMigrations } from '../../db/migrations/index.js';
|
|
8
|
+
import { CACHE_SCHEMA_V1 } from '../../db/schema.js';
|
|
9
|
+
describe('v2 migration (terminal_at column)', () => {
|
|
10
|
+
let db;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
db = new Database(':memory:');
|
|
13
|
+
});
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
db.close();
|
|
16
|
+
});
|
|
17
|
+
function getColumns(table) {
|
|
18
|
+
const rows = db.prepare(`SELECT name FROM pragma_table_info('${table}')`).all();
|
|
19
|
+
return rows.map(r => r.name);
|
|
20
|
+
}
|
|
21
|
+
it('adds terminal_at column to existing table without it', () => {
|
|
22
|
+
// Create OLD schema (without terminal_at column) - simulates pre-v2 database
|
|
23
|
+
db.exec(`
|
|
24
|
+
CREATE TABLE hzl_local_meta (
|
|
25
|
+
key TEXT PRIMARY KEY,
|
|
26
|
+
value TEXT NOT NULL
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE tasks_current (
|
|
30
|
+
task_id TEXT PRIMARY KEY,
|
|
31
|
+
title TEXT NOT NULL,
|
|
32
|
+
project TEXT NOT NULL,
|
|
33
|
+
status TEXT NOT NULL,
|
|
34
|
+
parent_id TEXT,
|
|
35
|
+
description TEXT,
|
|
36
|
+
links TEXT NOT NULL DEFAULT '[]',
|
|
37
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
38
|
+
priority INTEGER NOT NULL DEFAULT 0,
|
|
39
|
+
due_at TEXT,
|
|
40
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
41
|
+
claimed_at TEXT,
|
|
42
|
+
assignee TEXT,
|
|
43
|
+
progress INTEGER,
|
|
44
|
+
lease_until TEXT,
|
|
45
|
+
created_at TEXT NOT NULL,
|
|
46
|
+
updated_at TEXT NOT NULL,
|
|
47
|
+
last_event_id INTEGER NOT NULL
|
|
48
|
+
);
|
|
49
|
+
`);
|
|
50
|
+
const columnsBefore = getColumns('tasks_current');
|
|
51
|
+
expect(columnsBefore).not.toContain('terminal_at');
|
|
52
|
+
// Run migration
|
|
53
|
+
runCacheMigrations(db);
|
|
54
|
+
const columnsAfter = getColumns('tasks_current');
|
|
55
|
+
expect(columnsAfter).toContain('terminal_at');
|
|
56
|
+
});
|
|
57
|
+
it('skips migration if table does not exist (fresh database)', () => {
|
|
58
|
+
// Empty database - no tables
|
|
59
|
+
db.exec(`
|
|
60
|
+
CREATE TABLE hzl_local_meta (
|
|
61
|
+
key TEXT PRIMARY KEY,
|
|
62
|
+
value TEXT NOT NULL
|
|
63
|
+
);
|
|
64
|
+
`);
|
|
65
|
+
// Should not throw
|
|
66
|
+
expect(() => runCacheMigrations(db)).not.toThrow();
|
|
67
|
+
// Table should not exist yet
|
|
68
|
+
const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='tasks_current'").get();
|
|
69
|
+
expect(row).toBeUndefined();
|
|
70
|
+
});
|
|
71
|
+
it('skips migration if column already exists', () => {
|
|
72
|
+
// Create table WITH terminal_at column (current schema)
|
|
73
|
+
db.exec(CACHE_SCHEMA_V1);
|
|
74
|
+
const columnsBefore = getColumns('tasks_current');
|
|
75
|
+
expect(columnsBefore).toContain('terminal_at');
|
|
76
|
+
// Should not throw (idempotent)
|
|
77
|
+
expect(() => runCacheMigrations(db)).not.toThrow();
|
|
78
|
+
const columnsAfter = getColumns('tasks_current');
|
|
79
|
+
expect(columnsAfter).toContain('terminal_at');
|
|
80
|
+
});
|
|
81
|
+
it('creates index on terminal_at after adding column', () => {
|
|
82
|
+
// Create OLD schema (without terminal_at column)
|
|
83
|
+
db.exec(`
|
|
84
|
+
CREATE TABLE hzl_local_meta (
|
|
85
|
+
key TEXT PRIMARY KEY,
|
|
86
|
+
value TEXT NOT NULL
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE TABLE tasks_current (
|
|
90
|
+
task_id TEXT PRIMARY KEY,
|
|
91
|
+
title TEXT NOT NULL,
|
|
92
|
+
project TEXT NOT NULL,
|
|
93
|
+
status TEXT NOT NULL,
|
|
94
|
+
created_at TEXT NOT NULL,
|
|
95
|
+
updated_at TEXT NOT NULL,
|
|
96
|
+
last_event_id INTEGER NOT NULL
|
|
97
|
+
);
|
|
98
|
+
`);
|
|
99
|
+
runCacheMigrations(db);
|
|
100
|
+
// Check index exists
|
|
101
|
+
const indexes = db.prepare("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='tasks_current'").all();
|
|
102
|
+
const indexNames = indexes.map(i => i.name);
|
|
103
|
+
expect(indexNames).toContain('idx_tasks_current_terminal_at');
|
|
104
|
+
});
|
|
105
|
+
it('full upgrade path: old database then CACHE_SCHEMA_V1', () => {
|
|
106
|
+
// Simulate the actual upgrade path:
|
|
107
|
+
// 1. Old database exists with tasks_current (no terminal_at)
|
|
108
|
+
// 2. runCacheMigrations runs and adds terminal_at
|
|
109
|
+
// 3. CACHE_SCHEMA_V1 runs (should be no-op for table, but creates indexes)
|
|
110
|
+
db.exec(`
|
|
111
|
+
CREATE TABLE hzl_local_meta (
|
|
112
|
+
key TEXT PRIMARY KEY,
|
|
113
|
+
value TEXT NOT NULL
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
CREATE TABLE projection_state (
|
|
117
|
+
name TEXT PRIMARY KEY,
|
|
118
|
+
last_event_id INTEGER NOT NULL DEFAULT 0,
|
|
119
|
+
updated_at TEXT NOT NULL
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
CREATE TABLE projection_cursor (
|
|
123
|
+
key TEXT PRIMARY KEY,
|
|
124
|
+
value TEXT NOT NULL
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
CREATE TABLE tasks_current (
|
|
128
|
+
task_id TEXT PRIMARY KEY,
|
|
129
|
+
title TEXT NOT NULL,
|
|
130
|
+
project TEXT NOT NULL,
|
|
131
|
+
status TEXT NOT NULL,
|
|
132
|
+
parent_id TEXT,
|
|
133
|
+
description TEXT,
|
|
134
|
+
links TEXT NOT NULL DEFAULT '[]',
|
|
135
|
+
tags TEXT NOT NULL DEFAULT '[]',
|
|
136
|
+
priority INTEGER NOT NULL DEFAULT 0,
|
|
137
|
+
due_at TEXT,
|
|
138
|
+
metadata TEXT NOT NULL DEFAULT '{}',
|
|
139
|
+
claimed_at TEXT,
|
|
140
|
+
assignee TEXT,
|
|
141
|
+
progress INTEGER,
|
|
142
|
+
lease_until TEXT,
|
|
143
|
+
created_at TEXT NOT NULL,
|
|
144
|
+
updated_at TEXT NOT NULL,
|
|
145
|
+
last_event_id INTEGER NOT NULL
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
CREATE TABLE task_dependencies (
|
|
149
|
+
task_id TEXT NOT NULL,
|
|
150
|
+
depends_on_id TEXT NOT NULL,
|
|
151
|
+
PRIMARY KEY (task_id, depends_on_id)
|
|
152
|
+
);
|
|
153
|
+
`);
|
|
154
|
+
// Step 1: Run migrations (adds terminal_at)
|
|
155
|
+
runCacheMigrations(db);
|
|
156
|
+
// Step 2: Run CACHE_SCHEMA_V1 (should not fail)
|
|
157
|
+
expect(() => db.exec(CACHE_SCHEMA_V1)).not.toThrow();
|
|
158
|
+
// Verify terminal_at exists and has index
|
|
159
|
+
const columns = getColumns('tasks_current');
|
|
160
|
+
expect(columns).toContain('terminal_at');
|
|
161
|
+
const indexes = db.prepare("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='tasks_current'").all();
|
|
162
|
+
expect(indexes.map(i => i.name)).toContain('idx_tasks_current_terminal_at');
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=v2-upgrade.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v2-upgrade.test.js","sourceRoot":"","sources":["../../../src/__tests__/migrations/v2-upgrade.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datastore.d.ts","sourceRoot":"","sources":["../../src/db/datastore.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,QAAQ,CAAC;AAG9B,OAAO,KAAK,EAAE,QAAQ,EAAc,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"datastore.d.ts","sourceRoot":"","sources":["../../src/db/datastore.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,QAAQ,CAAC;AAG9B,OAAO,KAAK,EAAE,QAAQ,EAAc,SAAS,EAAE,MAAM,YAAY,CAAC;AAMlE,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,gBAAgB,GAAG,cAAc,GAAG,aAAa,CAAC;AAE9F,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC;IAC5B,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC;IAC3B,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3B,KAAK,IAAI,IAAI,CAAC;CACjB;AAiBD,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CA6K3D"}
|
package/dist/db/datastore.js
CHANGED
|
@@ -4,6 +4,7 @@ import path from 'path';
|
|
|
4
4
|
import { EVENTS_SCHEMA_V2, CACHE_SCHEMA_V1, PRAGMAS } from './schema.js';
|
|
5
5
|
import { generateId } from '../utils/id.js';
|
|
6
6
|
import { setInstanceId, getInstanceId, setDeviceId, getDeviceId, setLastSyncAttemptAt, setLastSyncAt, setLastSyncError, clearLastSyncError, clearDirtySince } from './meta.js';
|
|
7
|
+
import { runCacheMigrations } from './migrations/index.js';
|
|
7
8
|
function ensureDirectory(filePath) {
|
|
8
9
|
const dir = path.dirname(filePath);
|
|
9
10
|
if (!fs.existsSync(dir)) {
|
|
@@ -56,6 +57,10 @@ export function createDatastore(config) {
|
|
|
56
57
|
}
|
|
57
58
|
// Initialize schemas
|
|
58
59
|
eventsDb.exec(EVENTS_SCHEMA_V2);
|
|
60
|
+
// Run cache database migrations BEFORE schema exec to add any missing columns.
|
|
61
|
+
// This ensures columns exist before CACHE_SCHEMA_V1 tries to create indexes on them.
|
|
62
|
+
runCacheMigrations(cacheDb);
|
|
63
|
+
// Now create/verify all tables and indexes (safe because columns exist)
|
|
59
64
|
cacheDb.exec(CACHE_SCHEMA_V1);
|
|
60
65
|
// Ensure instance ID exists (generate if new database)
|
|
61
66
|
let instanceId = getInstanceId(eventsDb);
|
package/dist/db/datastore.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datastore.js","sourceRoot":"","sources":["../../src/db/datastore.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"datastore.js","sourceRoot":"","sources":["../../src/db/datastore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache database migrations.
|
|
3
|
+
*
|
|
4
|
+
* These migrations handle schema changes to the cache database (tasks_current, etc.)
|
|
5
|
+
* which stores projections derived from events.
|
|
6
|
+
*/
|
|
7
|
+
import type Database from 'libsql';
|
|
8
|
+
/**
|
|
9
|
+
* Run cache database migrations.
|
|
10
|
+
*
|
|
11
|
+
* This function handles schema changes that need programmatic checks
|
|
12
|
+
* (e.g., checking if a column exists before adding it). It runs BEFORE
|
|
13
|
+
* the main schema creation to ensure columns exist before indexes are created.
|
|
14
|
+
*
|
|
15
|
+
* Scenarios handled:
|
|
16
|
+
* 1. Fresh database: Table doesn't exist → skip (CACHE_SCHEMA_V1 will create it)
|
|
17
|
+
* 2. Old database: Table exists without column → add column
|
|
18
|
+
* 3. Current database: Table exists with column → skip (already migrated)
|
|
19
|
+
*/
|
|
20
|
+
export declare function runCacheMigrations(db: Database.Database): void;
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,QAAQ,CAAC;AAyBnC;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAY9D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache database migrations.
|
|
3
|
+
*
|
|
4
|
+
* These migrations handle schema changes to the cache database (tasks_current, etc.)
|
|
5
|
+
* which stores projections derived from events.
|
|
6
|
+
*/
|
|
7
|
+
import { ADD_TERMINAL_AT_COLUMN, CREATE_TERMINAL_AT_INDEX } from './v2.js';
|
|
8
|
+
/**
|
|
9
|
+
* Check if a table exists in the database.
|
|
10
|
+
*/
|
|
11
|
+
function tableExists(db, table) {
|
|
12
|
+
const row = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name=?`).get(table);
|
|
13
|
+
return row !== undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if a column exists in a table.
|
|
17
|
+
* Returns false if the table doesn't exist.
|
|
18
|
+
*/
|
|
19
|
+
function columnExists(db, table, column) {
|
|
20
|
+
if (!tableExists(db, table)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const rows = db.prepare(`SELECT name FROM pragma_table_info('${table}')`).all();
|
|
24
|
+
return rows.some(row => row.name === column);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Run cache database migrations.
|
|
28
|
+
*
|
|
29
|
+
* This function handles schema changes that need programmatic checks
|
|
30
|
+
* (e.g., checking if a column exists before adding it). It runs BEFORE
|
|
31
|
+
* the main schema creation to ensure columns exist before indexes are created.
|
|
32
|
+
*
|
|
33
|
+
* Scenarios handled:
|
|
34
|
+
* 1. Fresh database: Table doesn't exist → skip (CACHE_SCHEMA_V1 will create it)
|
|
35
|
+
* 2. Old database: Table exists without column → add column
|
|
36
|
+
* 3. Current database: Table exists with column → skip (already migrated)
|
|
37
|
+
*/
|
|
38
|
+
export function runCacheMigrations(db) {
|
|
39
|
+
// Migration V2: Add terminal_at column if table exists but column doesn't
|
|
40
|
+
// Skip if table doesn't exist - CACHE_SCHEMA_V1 will create it with the column
|
|
41
|
+
if (tableExists(db, 'tasks_current') && !columnExists(db, 'tasks_current', 'terminal_at')) {
|
|
42
|
+
db.exec(ADD_TERMINAL_AT_COLUMN);
|
|
43
|
+
}
|
|
44
|
+
// Index creation is handled by CACHE_SCHEMA_V1 (uses IF NOT EXISTS)
|
|
45
|
+
// Only create here if table already exists with the column
|
|
46
|
+
if (columnExists(db, 'tasks_current', 'terminal_at')) {
|
|
47
|
+
db.exec(CREATE_TERMINAL_AT_INDEX);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAE3E;;GAEG;AACH,SAAS,WAAW,CAAC,EAAqB,EAAE,KAAa;IACvD,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,8DAA8D,CAC/D,CAAC,GAAG,CAAC,KAAK,CAAiC,CAAC;IAC7C,OAAO,GAAG,KAAK,SAAS,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,EAAqB,EAAE,KAAa,EAAE,MAAc;IACxE,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,uCAAuC,KAAK,IAAI,CAAC,CAAC,GAAG,EAAwB,CAAC;IACtG,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAqB;IACtD,0EAA0E;IAC1E,+EAA+E;IAC/E,IAAI,WAAW,CAAC,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE,CAAC;QAC1F,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAClC,CAAC;IAED,oEAAoE;IACpE,2DAA2D;IAC3D,IAAI,YAAY,CAAC,EAAE,EAAE,eAAe,EAAE,aAAa,CAAC,EAAE,CAAC;QACrD,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
|
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Migration V2: Add terminal_at column for tracking when tasks enter terminal states.
|
|
3
|
+
*
|
|
4
|
+
* The column is used for age-based pruning eligibility (done/archived tasks
|
|
5
|
+
* older than a threshold can be pruned).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* SQL to add the terminal_at column.
|
|
9
|
+
* IMPORTANT: Only run this if the column doesn't exist (check via pragma_table_info).
|
|
10
|
+
*/
|
|
11
|
+
export declare const ADD_TERMINAL_AT_COLUMN = "\nALTER TABLE tasks_current ADD COLUMN terminal_at TEXT\n";
|
|
12
|
+
/**
|
|
13
|
+
* SQL to create the index on terminal_at. Safe to run multiple times (uses IF NOT EXISTS).
|
|
14
|
+
*/
|
|
15
|
+
export declare const CREATE_TERMINAL_AT_INDEX = "\nCREATE INDEX IF NOT EXISTS idx_tasks_current_terminal_at ON tasks_current(terminal_at)\n";
|
|
2
16
|
//# sourceMappingURL=v2.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/v2.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"v2.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/v2.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,8DAElC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,+FAEpC,CAAC"}
|
package/dist/db/migrations/v2.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Migration V2: Add terminal_at column for tracking when tasks enter terminal states.
|
|
3
|
+
*
|
|
4
|
+
* The column is used for age-based pruning eligibility (done/archived tasks
|
|
5
|
+
* older than a threshold can be pruned).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* SQL to add the terminal_at column.
|
|
9
|
+
* IMPORTANT: Only run this if the column doesn't exist (check via pragma_table_info).
|
|
10
|
+
*/
|
|
11
|
+
export const ADD_TERMINAL_AT_COLUMN = `
|
|
12
|
+
ALTER TABLE tasks_current ADD COLUMN terminal_at TEXT
|
|
13
|
+
`;
|
|
14
|
+
/**
|
|
15
|
+
* SQL to create the index on terminal_at. Safe to run multiple times (uses IF NOT EXISTS).
|
|
16
|
+
*/
|
|
17
|
+
export const CREATE_TERMINAL_AT_INDEX = `
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_current_terminal_at ON tasks_current(terminal_at)
|
|
8
19
|
`;
|
|
9
20
|
//# sourceMappingURL=v2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../../../src/db/migrations/v2.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"v2.js","sourceRoot":"","sources":["../../../src/db/migrations/v2.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;;CAErC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;;CAEvC,CAAC"}
|