@sascha384/tic 1.35.0 → 2.0.1
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/.claude-plugin/plugin.json +1 -1
- package/README.md +17 -63
- package/dist/backends/availability.js +4 -2
- package/dist/backends/availability.js.map +1 -1
- package/dist/backends/factory.d.ts +5 -3
- package/dist/backends/factory.js +28 -43
- package/dist/backends/factory.js.map +1 -1
- package/dist/backends/files/hash.d.ts +1 -0
- package/dist/backends/files/hash.js +5 -0
- package/dist/backends/files/hash.js.map +1 -0
- package/dist/backends/files/index.d.ts +48 -0
- package/dist/backends/files/index.js +174 -0
- package/dist/backends/files/index.js.map +1 -0
- package/dist/backends/files/sync.d.ts +13 -0
- package/dist/backends/files/sync.js +69 -0
- package/dist/backends/files/sync.js.map +1 -0
- package/dist/backends/jira/config.d.ts +1 -1
- package/dist/backends/jira/config.js +6 -9
- package/dist/backends/jira/config.js.map +1 -1
- package/dist/backends/types.d.ts +12 -0
- package/dist/backends/types.js +5 -1
- package/dist/backends/types.js.map +1 -1
- package/dist/cli/commands/config.js +27 -14
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/init.js +10 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts +4 -4
- package/dist/cli/commands/mcp.js +16 -25
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/index.js +16 -19
- package/dist/cli/index.js.map +1 -1
- package/dist/commands.js +0 -6
- package/dist/commands.js.map +1 -1
- package/dist/components/Header.js +3 -2
- package/dist/components/Header.js.map +1 -1
- package/dist/components/OverlayPanel.d.ts +2 -1
- package/dist/components/OverlayPanel.js +8 -1
- package/dist/components/OverlayPanel.js.map +1 -1
- package/dist/components/Settings.js +6 -11
- package/dist/components/Settings.js.map +1 -1
- package/dist/components/StatusScreen.js +1 -1
- package/dist/components/StatusScreen.js.map +1 -1
- package/dist/components/WorkItemForm.js +6 -9
- package/dist/components/WorkItemForm.js.map +1 -1
- package/dist/components/WorkItemList.js +102 -51
- package/dist/components/WorkItemList.js.map +1 -1
- package/dist/index.js +20 -8
- package/dist/index.js.map +1 -1
- package/dist/storage/config.d.ts +61 -0
- package/dist/storage/config.js +309 -0
- package/dist/storage/config.js.map +1 -0
- package/dist/storage/db.d.ts +11 -0
- package/dist/storage/db.js +34 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/storage/index.d.ts +73 -0
- package/dist/storage/index.js +966 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/mappers.d.ts +35 -0
- package/dist/storage/mappers.js +70 -0
- package/dist/storage/mappers.js.map +1 -0
- package/dist/storage/schema.d.ts +1844 -0
- package/dist/storage/schema.js +197 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/syncQueue.d.ts +13 -0
- package/dist/storage/syncQueue.js +98 -0
- package/dist/storage/syncQueue.js.map +1 -0
- package/dist/storage/undo.d.ts +22 -0
- package/dist/storage/undo.js +129 -0
- package/dist/storage/undo.js.map +1 -0
- package/dist/stores/backendDataStore.d.ts +4 -1
- package/dist/stores/backendDataStore.js +61 -40
- package/dist/stores/backendDataStore.js.map +1 -1
- package/dist/stores/configStore.d.ts +3 -1
- package/dist/stores/configStore.js +25 -65
- package/dist/stores/configStore.js.map +1 -1
- package/dist/stores/filterStore.d.ts +2 -0
- package/dist/stores/filterStore.js +7 -2
- package/dist/stores/filterStore.js.map +1 -1
- package/dist/stores/uiStore.d.ts +0 -2
- package/dist/stores/uiStore.js.map +1 -1
- package/dist/stores/undoStore.d.ts +4 -0
- package/dist/stores/undoStore.js +32 -0
- package/dist/stores/undoStore.js.map +1 -1
- package/dist/sync/SyncManager.d.ts +3 -4
- package/dist/sync/SyncManager.js +78 -37
- package/dist/sync/SyncManager.js.map +1 -1
- package/dist/sync/types.d.ts +10 -1
- package/drizzle/0000_next_vance_astro.sql +183 -0
- package/drizzle/meta/0000_snapshot.json +1188 -0
- package/drizzle/meta/_journal.json +13 -0
- package/package.json +6 -1
- package/skills/config/SKILL.md +2 -2
- package/dist/backends/local/config.d.ts +0 -38
- package/dist/backends/local/config.js +0 -42
- package/dist/backends/local/config.js.map +0 -1
- package/dist/backends/local/index.d.ts +0 -45
- package/dist/backends/local/index.js +0 -291
- package/dist/backends/local/index.js.map +0 -1
- package/dist/sync/queue.d.ts +0 -12
- package/dist/sync/queue.js +0 -56
- package/dist/sync/queue.js.map +0 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { eq } from 'drizzle-orm';
|
|
4
|
+
import { createDatabase } from './db.js';
|
|
5
|
+
import * as schema from './schema.js';
|
|
6
|
+
export const defaultConfig = {
|
|
7
|
+
backend: 'none',
|
|
8
|
+
types: ['epic', 'issue', 'task'],
|
|
9
|
+
statuses: ['backlog', 'todo', 'in-progress', 'review', 'done'],
|
|
10
|
+
current_iteration: 'default',
|
|
11
|
+
iterations: ['default'],
|
|
12
|
+
next_id: 1,
|
|
13
|
+
branchMode: 'worktree',
|
|
14
|
+
autoUpdate: true,
|
|
15
|
+
branchCommand: `claude "Brainstorm the implementation of issue #$TIC_ITEM_ID: $TIC_ITEM_TITLE. $TIC_ITEM_DESCRIPTION"`,
|
|
16
|
+
copyToClipboard: true,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Read just the backend type from the SQLite database synchronously.
|
|
20
|
+
* Used by CLI's `tryGetCapabilities()` which runs at startup before
|
|
21
|
+
* any async work. Returns 'none' if the DB doesn't exist yet.
|
|
22
|
+
*/
|
|
23
|
+
export function readBackendTypeSync(root) {
|
|
24
|
+
const dbPath = path.join(root, '.tic', 'tic.db');
|
|
25
|
+
if (!fs.existsSync(dbPath))
|
|
26
|
+
return 'none';
|
|
27
|
+
const db = createDatabase(root);
|
|
28
|
+
try {
|
|
29
|
+
const row = db
|
|
30
|
+
.select({ backend: schema.projectConfig.backend })
|
|
31
|
+
.from(schema.projectConfig)
|
|
32
|
+
.where(eq(schema.projectConfig.id, 1))
|
|
33
|
+
.get();
|
|
34
|
+
const backend = row?.backend ?? 'none';
|
|
35
|
+
// 'drizzle' is the seed default — treat it as 'none' for capability lookup
|
|
36
|
+
return backend === 'drizzle' ? 'none' : backend;
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
db.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read the full Config from the SQLite database.
|
|
44
|
+
*/
|
|
45
|
+
export function readConfig(db) {
|
|
46
|
+
// 1. Read projectConfig singleton (id=1)
|
|
47
|
+
const pc = db
|
|
48
|
+
.select()
|
|
49
|
+
.from(schema.projectConfig)
|
|
50
|
+
.where(eq(schema.projectConfig.id, 1))
|
|
51
|
+
.get();
|
|
52
|
+
// 2. Read ordered arrays
|
|
53
|
+
const statusRows = db
|
|
54
|
+
.select()
|
|
55
|
+
.from(schema.statuses)
|
|
56
|
+
.orderBy(schema.statuses.sortOrder)
|
|
57
|
+
.all();
|
|
58
|
+
const typeRows = db
|
|
59
|
+
.select()
|
|
60
|
+
.from(schema.workItemTypes)
|
|
61
|
+
.orderBy(schema.workItemTypes.sortOrder)
|
|
62
|
+
.all();
|
|
63
|
+
const iterationRows = db
|
|
64
|
+
.select()
|
|
65
|
+
.from(schema.iterations)
|
|
66
|
+
.orderBy(schema.iterations.sortOrder)
|
|
67
|
+
.all();
|
|
68
|
+
// 3. Read jiraConfig singleton
|
|
69
|
+
const jc = db
|
|
70
|
+
.select()
|
|
71
|
+
.from(schema.jiraConfig)
|
|
72
|
+
.where(eq(schema.jiraConfig.id, 1))
|
|
73
|
+
.get();
|
|
74
|
+
// 4. Read saved views with filters and sort entries
|
|
75
|
+
const viewRows = db.select().from(schema.savedViews).all();
|
|
76
|
+
const filterRows = db.select().from(schema.savedViewFilters).all();
|
|
77
|
+
const sortRows = db
|
|
78
|
+
.select()
|
|
79
|
+
.from(schema.savedViewSortEntries)
|
|
80
|
+
.orderBy(schema.savedViewSortEntries.sortOrder)
|
|
81
|
+
.all();
|
|
82
|
+
// Build the config object
|
|
83
|
+
const config = {
|
|
84
|
+
backend: pc?.backend ?? 'drizzle',
|
|
85
|
+
statuses: statusRows.map((r) => r.name),
|
|
86
|
+
types: typeRows.map((r) => r.name),
|
|
87
|
+
current_iteration: pc?.currentIteration ?? '',
|
|
88
|
+
iterations: iterationRows.map((r) => r.name),
|
|
89
|
+
next_id: pc?.nextId ?? 1,
|
|
90
|
+
branchMode: pc?.branchMode ?? 'worktree',
|
|
91
|
+
autoUpdate: pc?.autoUpdate ?? true,
|
|
92
|
+
};
|
|
93
|
+
// Optional fields — only include when they have non-default values
|
|
94
|
+
if (pc?.defaultType && pc.defaultType !== '') {
|
|
95
|
+
config.defaultType = pc.defaultType;
|
|
96
|
+
}
|
|
97
|
+
if (pc?.showDetailPanel === true) {
|
|
98
|
+
config.showDetailPanel = true;
|
|
99
|
+
}
|
|
100
|
+
if (pc?.branchCommand && pc.branchCommand !== '') {
|
|
101
|
+
config.branchCommand = pc.branchCommand;
|
|
102
|
+
}
|
|
103
|
+
if (pc?.copyToClipboard !== undefined) {
|
|
104
|
+
config.copyToClipboard = pc.copyToClipboard;
|
|
105
|
+
}
|
|
106
|
+
if (pc?.defaultView && pc.defaultView !== '') {
|
|
107
|
+
config.defaultView = pc.defaultView;
|
|
108
|
+
}
|
|
109
|
+
// Jira — only include if site is non-empty
|
|
110
|
+
if (jc && jc.site !== '') {
|
|
111
|
+
const jira = {
|
|
112
|
+
site: jc.site,
|
|
113
|
+
project: jc.project,
|
|
114
|
+
};
|
|
115
|
+
if (jc.boardId !== '') {
|
|
116
|
+
jira.boardId = Number(jc.boardId);
|
|
117
|
+
}
|
|
118
|
+
config.jira = jira;
|
|
119
|
+
}
|
|
120
|
+
// Views — only include if there are any
|
|
121
|
+
if (viewRows.length > 0) {
|
|
122
|
+
// Group filters by view name and field
|
|
123
|
+
const filtersByView = new Map();
|
|
124
|
+
for (const f of filterRows) {
|
|
125
|
+
let viewFilters = filtersByView.get(f.viewName);
|
|
126
|
+
if (!viewFilters) {
|
|
127
|
+
viewFilters = new Map();
|
|
128
|
+
filtersByView.set(f.viewName, viewFilters);
|
|
129
|
+
}
|
|
130
|
+
let fieldValues = viewFilters.get(f.field);
|
|
131
|
+
if (!fieldValues) {
|
|
132
|
+
fieldValues = [];
|
|
133
|
+
viewFilters.set(f.field, fieldValues);
|
|
134
|
+
}
|
|
135
|
+
fieldValues.push(f.value);
|
|
136
|
+
}
|
|
137
|
+
// Group sort entries by view name
|
|
138
|
+
const sortByView = new Map();
|
|
139
|
+
for (const s of sortRows) {
|
|
140
|
+
let viewSort = sortByView.get(s.viewName);
|
|
141
|
+
if (!viewSort) {
|
|
142
|
+
viewSort = [];
|
|
143
|
+
sortByView.set(s.viewName, viewSort);
|
|
144
|
+
}
|
|
145
|
+
viewSort.push({ column: s.column, direction: s.direction });
|
|
146
|
+
}
|
|
147
|
+
config.views = viewRows.map((v) => {
|
|
148
|
+
const viewFilters = filtersByView.get(v.name);
|
|
149
|
+
const filters = {};
|
|
150
|
+
if (viewFilters) {
|
|
151
|
+
for (const [field, values] of viewFilters) {
|
|
152
|
+
filters[field] = values;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const result = {
|
|
156
|
+
name: v.name,
|
|
157
|
+
filters,
|
|
158
|
+
};
|
|
159
|
+
const viewSort = sortByView.get(v.name);
|
|
160
|
+
if (viewSort && viewSort.length > 0) {
|
|
161
|
+
result.sort = viewSort;
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return config;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Insert (or replace) the full Config into the database tables using
|
|
170
|
+
* the given transaction handle. Shared by `writeConfig` and the legacy
|
|
171
|
+
* migration so the insertion logic is defined in exactly one place.
|
|
172
|
+
*/
|
|
173
|
+
export function insertConfigTx(tx, config) {
|
|
174
|
+
// 1. Upsert projectConfig singleton
|
|
175
|
+
tx.insert(schema.projectConfig)
|
|
176
|
+
.values({
|
|
177
|
+
id: 1,
|
|
178
|
+
backend: config.backend,
|
|
179
|
+
currentIteration: config.current_iteration,
|
|
180
|
+
nextId: config.next_id,
|
|
181
|
+
branchMode: config.branchMode,
|
|
182
|
+
branchCommand: config.branchCommand ?? '',
|
|
183
|
+
copyToClipboard: config.copyToClipboard ?? true,
|
|
184
|
+
autoUpdate: config.autoUpdate,
|
|
185
|
+
defaultType: config.defaultType ?? '',
|
|
186
|
+
showDetailPanel: config.showDetailPanel ?? false,
|
|
187
|
+
defaultView: config.defaultView ?? '',
|
|
188
|
+
})
|
|
189
|
+
.onConflictDoUpdate({
|
|
190
|
+
target: schema.projectConfig.id,
|
|
191
|
+
set: {
|
|
192
|
+
backend: config.backend,
|
|
193
|
+
currentIteration: config.current_iteration,
|
|
194
|
+
nextId: config.next_id,
|
|
195
|
+
branchMode: config.branchMode,
|
|
196
|
+
branchCommand: config.branchCommand ?? '',
|
|
197
|
+
copyToClipboard: config.copyToClipboard ?? true,
|
|
198
|
+
autoUpdate: config.autoUpdate,
|
|
199
|
+
defaultType: config.defaultType ?? '',
|
|
200
|
+
showDetailPanel: config.showDetailPanel ?? false,
|
|
201
|
+
defaultView: config.defaultView ?? '',
|
|
202
|
+
},
|
|
203
|
+
})
|
|
204
|
+
.run();
|
|
205
|
+
// 2. Replace statuses
|
|
206
|
+
tx.delete(schema.statuses).run();
|
|
207
|
+
for (let i = 0; i < config.statuses.length; i++) {
|
|
208
|
+
tx.insert(schema.statuses)
|
|
209
|
+
.values({ name: config.statuses[i], sortOrder: i })
|
|
210
|
+
.run();
|
|
211
|
+
}
|
|
212
|
+
// 3. Replace types
|
|
213
|
+
tx.delete(schema.workItemTypes).run();
|
|
214
|
+
for (let i = 0; i < config.types.length; i++) {
|
|
215
|
+
tx.insert(schema.workItemTypes)
|
|
216
|
+
.values({ name: config.types[i], sortOrder: i })
|
|
217
|
+
.run();
|
|
218
|
+
}
|
|
219
|
+
// 4. Replace iterations
|
|
220
|
+
tx.delete(schema.iterations).run();
|
|
221
|
+
for (let i = 0; i < config.iterations.length; i++) {
|
|
222
|
+
tx.insert(schema.iterations)
|
|
223
|
+
.values({ name: config.iterations[i], sortOrder: i })
|
|
224
|
+
.run();
|
|
225
|
+
}
|
|
226
|
+
// 5. Upsert jiraConfig
|
|
227
|
+
if (config.jira) {
|
|
228
|
+
tx.insert(schema.jiraConfig)
|
|
229
|
+
.values({
|
|
230
|
+
id: 1,
|
|
231
|
+
site: config.jira.site,
|
|
232
|
+
project: config.jira.project,
|
|
233
|
+
boardId: config.jira.boardId !== undefined ? String(config.jira.boardId) : '',
|
|
234
|
+
})
|
|
235
|
+
.onConflictDoUpdate({
|
|
236
|
+
target: schema.jiraConfig.id,
|
|
237
|
+
set: {
|
|
238
|
+
site: config.jira.site,
|
|
239
|
+
project: config.jira.project,
|
|
240
|
+
boardId: config.jira.boardId !== undefined
|
|
241
|
+
? String(config.jira.boardId)
|
|
242
|
+
: '',
|
|
243
|
+
},
|
|
244
|
+
})
|
|
245
|
+
.run();
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// Clear jira config by setting to empty values
|
|
249
|
+
tx.insert(schema.jiraConfig)
|
|
250
|
+
.values({ id: 1, site: '', project: '', boardId: '' })
|
|
251
|
+
.onConflictDoUpdate({
|
|
252
|
+
target: schema.jiraConfig.id,
|
|
253
|
+
set: { site: '', project: '', boardId: '' },
|
|
254
|
+
})
|
|
255
|
+
.run();
|
|
256
|
+
}
|
|
257
|
+
// 6. Replace saved views (cascade deletes filters and sort entries)
|
|
258
|
+
tx.delete(schema.savedViews).run();
|
|
259
|
+
if (config.views && config.views.length > 0) {
|
|
260
|
+
for (const view of config.views) {
|
|
261
|
+
tx.insert(schema.savedViews).values({ name: view.name }).run();
|
|
262
|
+
// Insert filters
|
|
263
|
+
const filters = view.filters;
|
|
264
|
+
if (filters) {
|
|
265
|
+
for (const [field, values] of Object.entries(filters)) {
|
|
266
|
+
if (values && values.length > 0) {
|
|
267
|
+
for (const value of values) {
|
|
268
|
+
tx.insert(schema.savedViewFilters)
|
|
269
|
+
.values({ viewName: view.name, field, value })
|
|
270
|
+
.run();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Insert sort entries
|
|
276
|
+
if (view.sort && view.sort.length > 0) {
|
|
277
|
+
for (let i = 0; i < view.sort.length; i++) {
|
|
278
|
+
const s = view.sort[i];
|
|
279
|
+
tx.insert(schema.savedViewSortEntries)
|
|
280
|
+
.values({
|
|
281
|
+
viewName: view.name,
|
|
282
|
+
column: s.column,
|
|
283
|
+
direction: s.direction,
|
|
284
|
+
sortOrder: i,
|
|
285
|
+
})
|
|
286
|
+
.run();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Write the full Config to the SQLite database, replacing all existing data.
|
|
294
|
+
* Uses a transaction to keep tables consistent.
|
|
295
|
+
*/
|
|
296
|
+
export function writeConfig(db, config) {
|
|
297
|
+
db.transaction((tx) => {
|
|
298
|
+
insertConfigTx(tx, config);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Read the current config, merge partial updates over it, and write back.
|
|
303
|
+
*/
|
|
304
|
+
export function updateConfig(db, partial) {
|
|
305
|
+
const current = readConfig(db);
|
|
306
|
+
const merged = { ...current, ...partial };
|
|
307
|
+
writeConfig(db, merged);
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/storage/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { type BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
3
|
+
import * as schema from './schema.js';
|
|
4
|
+
export type TicDatabase = BetterSQLite3Database<typeof schema> & {
|
|
5
|
+
close(): void;
|
|
6
|
+
/** Access raw better-sqlite3 instance when needed */
|
|
7
|
+
raw: Database.Database;
|
|
8
|
+
};
|
|
9
|
+
/** Transaction handle passed to `db.transaction()` callbacks. */
|
|
10
|
+
export type TicTransaction = Parameters<Parameters<TicDatabase['transaction']>[0]>[0];
|
|
11
|
+
export declare function createDatabase(root: string): TicDatabase;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { drizzle, } from 'drizzle-orm/better-sqlite3';
|
|
3
|
+
import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import * as schema from './schema.js';
|
|
7
|
+
export function createDatabase(root) {
|
|
8
|
+
const isMemory = root === ':memory:';
|
|
9
|
+
let dbPath;
|
|
10
|
+
if (isMemory) {
|
|
11
|
+
dbPath = ':memory:';
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
const ticDir = path.join(root, '.tic');
|
|
15
|
+
fs.mkdirSync(ticDir, { recursive: true });
|
|
16
|
+
dbPath = path.join(ticDir, 'tic.db');
|
|
17
|
+
}
|
|
18
|
+
const sqlite = new Database(dbPath);
|
|
19
|
+
// Enable WAL mode for concurrent access (TUI + MCP + CLI)
|
|
20
|
+
if (!isMemory) {
|
|
21
|
+
sqlite.pragma('journal_mode = WAL');
|
|
22
|
+
}
|
|
23
|
+
// Enable foreign key constraints
|
|
24
|
+
sqlite.pragma('foreign_keys = ON');
|
|
25
|
+
const db = drizzle(sqlite, { schema });
|
|
26
|
+
// Apply migrations
|
|
27
|
+
const migrationsFolder = path.join(import.meta.dirname, '../../drizzle');
|
|
28
|
+
migrate(db, { migrationsFolder });
|
|
29
|
+
const ticDb = db;
|
|
30
|
+
ticDb.close = () => sqlite.close();
|
|
31
|
+
ticDb.raw = sqlite;
|
|
32
|
+
return ticDb;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/storage/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EACL,OAAO,GAER,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,qCAAqC,CAAC;AAC9D,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAatC,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,QAAQ,GAAG,IAAI,KAAK,UAAU,CAAC;IACrC,IAAI,MAAc,CAAC;IAEnB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,UAAU,CAAC;IACtB,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEpC,0DAA0D;IAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACtC,CAAC;IAED,iCAAiC;IACjC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAEnC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAEvC,mBAAmB;IACnB,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACzE,OAAO,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAElC,MAAM,KAAK,GAAG,EAA4B,CAAC;IAC3C,KAAK,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACnC,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC;IAEnB,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { BaseBackend } from '../backends/types.js';
|
|
2
|
+
import type { BackendCapabilities, SoftDeleteBackend } from '../backends/types.js';
|
|
3
|
+
import type { WorkItem, NewWorkItem, NewComment, Comment, Template } from '../types.js';
|
|
4
|
+
import { type TicDatabase } from './db.js';
|
|
5
|
+
export interface StorageOptions {
|
|
6
|
+
tempIds?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class Storage extends BaseBackend implements SoftDeleteBackend {
|
|
9
|
+
private db;
|
|
10
|
+
private root;
|
|
11
|
+
private tempIds;
|
|
12
|
+
private constructor();
|
|
13
|
+
/**
|
|
14
|
+
* Create a Storage instance, initializing the database and seeding defaults.
|
|
15
|
+
*/
|
|
16
|
+
static create(root: string, options?: StorageOptions): Storage;
|
|
17
|
+
/**
|
|
18
|
+
* Create a Storage instance from an existing database instance (for testing).
|
|
19
|
+
*/
|
|
20
|
+
static createFromDb(db: TicDatabase, options?: StorageOptions): Storage;
|
|
21
|
+
getDatabase(): TicDatabase;
|
|
22
|
+
getRoot(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Seed default configuration, statuses, types, and iterations using INSERT OR IGNORE.
|
|
25
|
+
*/
|
|
26
|
+
private seedDefaults;
|
|
27
|
+
/**
|
|
28
|
+
* If a legacy config.yml exists and the DB still has seed defaults,
|
|
29
|
+
* migrate the YAML config into the database and rename the file.
|
|
30
|
+
*/
|
|
31
|
+
private migrateFromYaml;
|
|
32
|
+
/**
|
|
33
|
+
* Close the database connection. Call this when done with the backend.
|
|
34
|
+
*/
|
|
35
|
+
destroy(): void;
|
|
36
|
+
getCapabilities(): BackendCapabilities;
|
|
37
|
+
getStatuses(): Promise<string[]>;
|
|
38
|
+
getIterations(): Promise<string[]>;
|
|
39
|
+
getWorkItemTypes(): Promise<string[]>;
|
|
40
|
+
getAssignees(): Promise<string[]>;
|
|
41
|
+
getLabels(): Promise<string[]>;
|
|
42
|
+
getCurrentIteration(): Promise<string>;
|
|
43
|
+
setCurrentIteration(name: string): Promise<void>;
|
|
44
|
+
listWorkItems(iteration?: string): Promise<WorkItem[]>;
|
|
45
|
+
getWorkItem(id: string): Promise<WorkItem>;
|
|
46
|
+
getChildren(id: string): Promise<WorkItem[]>;
|
|
47
|
+
getDependents(id: string): Promise<WorkItem[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Helper: given a set of work item rows, fetch their labels/deps/comments and assemble.
|
|
50
|
+
*/
|
|
51
|
+
private assembleWorkItems;
|
|
52
|
+
getItemUrl(id: string): string;
|
|
53
|
+
private validateRelationships;
|
|
54
|
+
createWorkItem(data: NewWorkItem): Promise<WorkItem>;
|
|
55
|
+
importWorkItem(item: WorkItem): Promise<WorkItem>;
|
|
56
|
+
updateWorkItem(id: string, data: Partial<WorkItem>): Promise<WorkItem>;
|
|
57
|
+
deleteWorkItem(id: string): Promise<void>;
|
|
58
|
+
softDeleteWorkItem(id: string): Promise<void>;
|
|
59
|
+
addComment(workItemId: string, comment: NewComment): Promise<Comment>;
|
|
60
|
+
restoreWorkItem(id: string): Promise<void>;
|
|
61
|
+
permanentlyDeleteWorkItem(id: string): Promise<void>;
|
|
62
|
+
cleanupTrash(): Promise<void>;
|
|
63
|
+
openItem(id: string): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Slugify a template name (same logic as LocalBackend).
|
|
66
|
+
*/
|
|
67
|
+
private slugifyName;
|
|
68
|
+
listTemplates(): Promise<Template[]>;
|
|
69
|
+
getTemplate(slug: string): Promise<Template>;
|
|
70
|
+
createTemplate(template: Template): Promise<Template>;
|
|
71
|
+
updateTemplate(oldSlug: string, template: Template): Promise<Template>;
|
|
72
|
+
deleteTemplate(slug: string): Promise<void>;
|
|
73
|
+
}
|