kanbo-cli 0.1.0
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/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/better-sqlite3-fU3G4xnX.cjs +2254 -0
- package/dist/better-sqlite3-fU3G4xnX.cjs.map +1 -0
- package/dist/cli.cjs +42949 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/dist-Cd6wg8pp.cjs +942 -0
- package/dist/dist-Cd6wg8pp.cjs.map +1 -0
- package/dist/drizzle-postgres/0000_board.sql +135 -0
- package/dist/drizzle-postgres/0001_history_order.sql +2 -0
- package/dist/drizzle-postgres/0002_issue_pull_requests.sql +16 -0
- package/dist/drizzle-postgres/0003_milestone_start_date.sql +1 -0
- package/dist/drizzle-postgres/0004_status_entry_rules.sql +1 -0
- package/dist/drizzle-postgres/0005_run_external_session_ref.sql +1 -0
- package/dist/drizzle-postgres/README.md +61 -0
- package/dist/drizzle-postgres/meta/0000_snapshot.json +1078 -0
- package/dist/drizzle-postgres/meta/0001_snapshot.json +1090 -0
- package/dist/drizzle-postgres/meta/0002_snapshot.json +1239 -0
- package/dist/drizzle-postgres/meta/0003_snapshot.json +1245 -0
- package/dist/drizzle-postgres/meta/0004_snapshot.json +1251 -0
- package/dist/drizzle-postgres/meta/0005_snapshot.json +1257 -0
- package/dist/drizzle-postgres/meta/_journal.json +48 -0
- package/dist/drizzle-sqlite/0000_board.sql +133 -0
- package/dist/drizzle-sqlite/0001_issue_pull_requests.sql +15 -0
- package/dist/drizzle-sqlite/0002_milestone_start_date.sql +1 -0
- package/dist/drizzle-sqlite/0003_status_entry_rules.sql +1 -0
- package/dist/drizzle-sqlite/0004_run_external_session_ref.sql +1 -0
- package/dist/drizzle-sqlite/README.md +67 -0
- package/dist/drizzle-sqlite/meta/0000_snapshot.json +946 -0
- package/dist/drizzle-sqlite/meta/0001_snapshot.json +1054 -0
- package/dist/drizzle-sqlite/meta/0002_snapshot.json +1061 -0
- package/dist/drizzle-sqlite/meta/0003_snapshot.json +1068 -0
- package/dist/drizzle-sqlite/meta/0004_snapshot.json +1075 -0
- package/dist/drizzle-sqlite/meta/_journal.json +41 -0
- package/dist/lib/board-store-B16YarvX.d.mts +281 -0
- package/dist/lib/board-store-BHHo_ZlR.d.cts +281 -0
- package/dist/lib/index.cjs +340 -0
- package/dist/lib/index.cjs.map +1 -0
- package/dist/lib/index.d.cts +1608 -0
- package/dist/lib/index.d.mts +1608 -0
- package/dist/lib/index.mjs +284 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/manifest-C0EcwwgO.mjs +7866 -0
- package/dist/lib/manifest-C0EcwwgO.mjs.map +1 -0
- package/dist/lib/manifest-CpZOcB_6.cjs +8272 -0
- package/dist/lib/manifest-CpZOcB_6.cjs.map +1 -0
- package/dist/lib/mcp/index.cjs +184 -0
- package/dist/lib/mcp/index.cjs.map +1 -0
- package/dist/lib/mcp/index.d.cts +346 -0
- package/dist/lib/mcp/index.d.mts +346 -0
- package/dist/lib/mcp/index.mjs +173 -0
- package/dist/lib/mcp/index.mjs.map +1 -0
- package/dist/lib/migrate-BhYi9cXw.mjs +656 -0
- package/dist/lib/migrate-BhYi9cXw.mjs.map +1 -0
- package/dist/lib/migrate-DnMjTCvu.cjs +709 -0
- package/dist/lib/migrate-DnMjTCvu.cjs.map +1 -0
- package/dist/lib/migrations-path-CZxVOgeD.cjs +109 -0
- package/dist/lib/migrations-path-CZxVOgeD.cjs.map +1 -0
- package/dist/lib/migrations-path-Ciwan537.mjs +80 -0
- package/dist/lib/migrations-path-Ciwan537.mjs.map +1 -0
- package/dist/lib/postgres/index.cjs +56 -0
- package/dist/lib/postgres/index.cjs.map +1 -0
- package/dist/lib/postgres/index.d.cts +3403 -0
- package/dist/lib/postgres/index.d.mts +3403 -0
- package/dist/lib/postgres/index.mjs +35 -0
- package/dist/lib/postgres/index.mjs.map +1 -0
- package/dist/lib/roles.sql-B9rt-x4o.cjs +1033 -0
- package/dist/lib/roles.sql-B9rt-x4o.cjs.map +1 -0
- package/dist/lib/roles.sql-CvyCGt38.mjs +920 -0
- package/dist/lib/roles.sql-CvyCGt38.mjs.map +1 -0
- package/dist/lib/schema-epoch-ZyumVL_A.d.cts +16 -0
- package/dist/lib/schema-epoch-ZyumVL_A.d.mts +16 -0
- package/dist/lib/schema-fsHqNAip.d.cts +3612 -0
- package/dist/lib/schema-fsHqNAip.d.mts +3612 -0
- package/dist/lib/sqlite/index.cjs +23 -0
- package/dist/lib/sqlite/index.d.cts +175 -0
- package/dist/lib/sqlite/index.d.mts +175 -0
- package/dist/lib/sqlite/index.mjs +4 -0
- package/dist/lib/sqlite/schema.cjs +266 -0
- package/dist/lib/sqlite/schema.cjs.map +1 -0
- package/dist/lib/sqlite/schema.d.cts +2 -0
- package/dist/lib/sqlite/schema.d.mts +2 -0
- package/dist/lib/sqlite/schema.mjs +256 -0
- package/dist/lib/sqlite/schema.mjs.map +1 -0
- package/dist/lib/tool-names-9cmCn0gP.d.cts +112 -0
- package/dist/lib/tool-names-Dxg1UTUl.d.mts +112 -0
- package/dist/page/board.css +477 -0
- package/dist/page/board.js +2 -0
- package/drizzle-postgres/0000_board.sql +135 -0
- package/drizzle-postgres/0001_history_order.sql +2 -0
- package/drizzle-postgres/0002_issue_pull_requests.sql +16 -0
- package/drizzle-postgres/0003_milestone_start_date.sql +1 -0
- package/drizzle-postgres/0004_status_entry_rules.sql +1 -0
- package/drizzle-postgres/0005_run_external_session_ref.sql +1 -0
- package/drizzle-postgres/README.md +61 -0
- package/drizzle-postgres/meta/0000_snapshot.json +1078 -0
- package/drizzle-postgres/meta/0001_snapshot.json +1090 -0
- package/drizzle-postgres/meta/0002_snapshot.json +1239 -0
- package/drizzle-postgres/meta/0003_snapshot.json +1245 -0
- package/drizzle-postgres/meta/0004_snapshot.json +1251 -0
- package/drizzle-postgres/meta/0005_snapshot.json +1257 -0
- package/drizzle-postgres/meta/_journal.json +48 -0
- package/drizzle-sqlite/0000_board.sql +133 -0
- package/drizzle-sqlite/0001_issue_pull_requests.sql +15 -0
- package/drizzle-sqlite/0002_milestone_start_date.sql +1 -0
- package/drizzle-sqlite/0003_status_entry_rules.sql +1 -0
- package/drizzle-sqlite/0004_run_external_session_ref.sql +1 -0
- package/drizzle-sqlite/README.md +67 -0
- package/drizzle-sqlite/meta/0000_snapshot.json +946 -0
- package/drizzle-sqlite/meta/0001_snapshot.json +1054 -0
- package/drizzle-sqlite/meta/0002_snapshot.json +1061 -0
- package/drizzle-sqlite/meta/0003_snapshot.json +1068 -0
- package/drizzle-sqlite/meta/0004_snapshot.json +1075 -0
- package/drizzle-sqlite/meta/_journal.json +41 -0
- package/package.json +147 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_migrations_path = require("../migrations-path-CZxVOgeD.cjs");
|
|
3
|
+
const require_sqlite_schema = require("./schema.cjs");
|
|
4
|
+
const require_migrate = require("../migrate-DnMjTCvu.cjs");
|
|
5
|
+
exports.BOARD_SCHEMA_EPOCH = require_migrations_path.BOARD_SCHEMA_EPOCH;
|
|
6
|
+
exports.assertBoardSchema = require_migrate.assertBoardSchema;
|
|
7
|
+
exports.boardSqliteSchema = require_sqlite_schema.boardSqliteSchema;
|
|
8
|
+
exports.createSqliteBoardStore = require_migrate.createSqliteBoardStore;
|
|
9
|
+
exports.getBoardSqliteMigrationsPath = require_migrate.getBoardSqliteMigrationsPath;
|
|
10
|
+
exports.issueComments = require_sqlite_schema.issueComments;
|
|
11
|
+
exports.issueFieldChanges = require_sqlite_schema.issueFieldChanges;
|
|
12
|
+
exports.issueMilestones = require_sqlite_schema.issueMilestones;
|
|
13
|
+
exports.issueRelations = require_sqlite_schema.issueRelations;
|
|
14
|
+
exports.issueRuns = require_sqlite_schema.issueRuns;
|
|
15
|
+
exports.issueStatuses = require_sqlite_schema.issueStatuses;
|
|
16
|
+
exports.issues = require_sqlite_schema.issues;
|
|
17
|
+
exports.kanbanMeta = require_sqlite_schema.kanbanMeta;
|
|
18
|
+
exports.markBoardFileOwnedByKanbo = require_migrate.markBoardFileOwnedByKanbo;
|
|
19
|
+
exports.migrateBoardFile = require_migrate.migrateBoardFile;
|
|
20
|
+
exports.openBoardDatabase = require_migrate.openBoardDatabase;
|
|
21
|
+
exports.readBoardFileContents = require_migrate.readBoardFileContents;
|
|
22
|
+
exports.readBoardFileOwner = require_migrate.readBoardFileOwner;
|
|
23
|
+
exports.runSqliteTransaction = require_migrate.runSqliteTransaction;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { _ as issueStatuses, c as IssueStatus, d as issueComments, f as issueFieldChanges, g as issueRuns, h as issueRelations, i as IssueMilestone, l as KanbanMeta, n as IssueComment, o as IssueRelation, p as issueMilestones, r as IssueFieldChange, s as IssueRun, t as Issue, u as boardSqliteSchema, v as issues, y as kanbanMeta } from "../schema-fsHqNAip.cjs";
|
|
2
|
+
import { a as BoardStore } from "../board-store-BHHo_ZlR.cjs";
|
|
3
|
+
import { t as BOARD_SCHEMA_EPOCH } from "../schema-epoch-ZyumVL_A.cjs";
|
|
4
|
+
import { BetterSQLite3Database } from "drizzle-orm/better-sqlite3";
|
|
5
|
+
import { Database } from "better-sqlite3";
|
|
6
|
+
//#region src/sqlite/transaction.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* The database handle itself — what the host hands the board — and not an open
|
|
9
|
+
* transaction on it: the helper reaches for the driver connection, which a
|
|
10
|
+
* drizzle `SQLiteTransaction` does not carry.
|
|
11
|
+
*
|
|
12
|
+
* The schema parameter is `Record<string, unknown>` rather than any particular
|
|
13
|
+
* schema, which is what lets one type stand for all three of the files a board
|
|
14
|
+
* can live in (ruling 5-3): a handle drizzle was given a host app's whole schema
|
|
15
|
+
* satisfies it, and so does one given only the board's own nine tables. The
|
|
16
|
+
* board never reaches for `database.query`, so the relational builder those
|
|
17
|
+
* generics shape is not something this package gives up by asking for less —
|
|
18
|
+
* `src/sqlite/database-type.test.ts` is the probe that says both handles still
|
|
19
|
+
* arrive here.
|
|
20
|
+
*/
|
|
21
|
+
type SqliteDatabase = BetterSQLite3Database<Record<string, unknown>>;
|
|
22
|
+
/**
|
|
23
|
+
* How the outer `begin` takes its write lock. `deferred` — the SQLite default —
|
|
24
|
+
* waits for the first write; `immediate` takes the lock up front, so two
|
|
25
|
+
* processes racing for the same file fail fast instead of half-way through.
|
|
26
|
+
* A nested scope is a savepoint and takes no lock of its own, so the mode only
|
|
27
|
+
* reaches the outer statement.
|
|
28
|
+
*/
|
|
29
|
+
type SqliteTransactionMode = 'deferred' | 'immediate';
|
|
30
|
+
/**
|
|
31
|
+
* Run `fn` inside one SQLite transaction that is allowed to await.
|
|
32
|
+
*
|
|
33
|
+
* `database.transaction(...)` cannot serve here: it commits the moment its
|
|
34
|
+
* callback returns, and an async callback returns a pending promise, so the
|
|
35
|
+
* transaction would close before the work inside it ran. The statements are
|
|
36
|
+
* issued by hand instead, and the driver's own `inTransaction` flag picks which
|
|
37
|
+
* — the same branch better-sqlite3 takes. With nothing open: `begin`, then
|
|
38
|
+
* `commit`, or `rollback` when `fn` throws. With a transaction already open —
|
|
39
|
+
* another call to this helper, or one a module opened through
|
|
40
|
+
* `database.transaction` — a `savepoint` … `release` pair, undone by
|
|
41
|
+
* `rollback to` followed by its own `release`. A second `begin` would throw,
|
|
42
|
+
* which is why the flag decides and not a private counter. When SQLite has
|
|
43
|
+
* already aborted the transaction itself the undo is skipped: it would throw
|
|
44
|
+
* over the caller's error.
|
|
45
|
+
*
|
|
46
|
+
* **The callback must be the only database-touching async chain in flight —
|
|
47
|
+
* no `Promise.all` sibling, no lock hand-off, no fire-and-forget promise
|
|
48
|
+
* started before it — and inside it, only await operations that resolve
|
|
49
|
+
* without I/O: store methods, synchronous database writes.** Even a resolved
|
|
50
|
+
* promise yields to the microtask queue first, so a sibling chain already
|
|
51
|
+
* queued in the same macrotask still runs inside this open transaction; a
|
|
52
|
+
* chain started in a separate macrotask is unaffected. Awaiting anything that
|
|
53
|
+
* truly suspends — a timer, the filesystem, the network — hands the
|
|
54
|
+
* connection to whatever runs next, and its writes land in this transaction
|
|
55
|
+
* too.
|
|
56
|
+
*/
|
|
57
|
+
declare function runSqliteTransaction<T>(database: SqliteDatabase, fn: () => Promise<T>, options?: {
|
|
58
|
+
mode?: SqliteTransactionMode;
|
|
59
|
+
}): Promise<T>;
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/sqlite/board-store.sqlite.d.ts
|
|
62
|
+
/**
|
|
63
|
+
* `BoardStore` backed by SQLite: every method resolves immediately, because the
|
|
64
|
+
* core underneath it is synchronous.
|
|
65
|
+
*
|
|
66
|
+
* `database` is a function rather than a handle so the store follows whatever
|
|
67
|
+
* the host currently has open — a server passes its single connection
|
|
68
|
+
* accessor, a standalone reader passes its own.
|
|
69
|
+
*/
|
|
70
|
+
declare function createSqliteBoardStore(options: {
|
|
71
|
+
database: () => SqliteDatabase;
|
|
72
|
+
}): BoardStore;
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/sqlite/migrate.d.ts
|
|
75
|
+
/**
|
|
76
|
+
* The board's SQLite migrations for the file that is running right now — the
|
|
77
|
+
* ones that build a board *file of this package's own*. The two layouts this
|
|
78
|
+
* has to survive are `src/migrations-path.ts`'s subject.
|
|
79
|
+
*/
|
|
80
|
+
declare function getBoardSqliteMigrationsPath(): string;
|
|
81
|
+
/**
|
|
82
|
+
* Create or update a board file this package owns.
|
|
83
|
+
*
|
|
84
|
+
* A host app's own database is not this: there the board is nine tables among
|
|
85
|
+
* the app's own, and the app's migration runner migrates the whole file — which
|
|
86
|
+
* may take two passes, because a migration that rebuilds a table has to drop
|
|
87
|
+
* it with foreign keys off. Nothing here rebuilds anything — `drizzle-sqlite/` starts at the
|
|
88
|
+
* board as it is now and will only ever be appended to — so drizzle's own
|
|
89
|
+
* migrator is the whole of what this needs, and a file that has been migrated
|
|
90
|
+
* before is a no-op by `__drizzle_migrations`.
|
|
91
|
+
*
|
|
92
|
+
* What the file holds afterwards is the board and nothing else: no
|
|
93
|
+
* `workspaces`, no `agents`, no `provider_targets`. Every reference out of the
|
|
94
|
+
* board is a plain text column for exactly that reason (ruling 5-1).
|
|
95
|
+
*/
|
|
96
|
+
declare function migrateBoardFile(database: SqliteDatabase): void;
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/sqlite/open-database.d.ts
|
|
99
|
+
/** One open board file: the drizzle handle, the driver beneath it, and the way to let go. */
|
|
100
|
+
interface BoardDatabase {
|
|
101
|
+
database: SqliteDatabase;
|
|
102
|
+
connection: Database;
|
|
103
|
+
close: () => void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Open a board file with the runtime pragmas a long-running server sets on its
|
|
107
|
+
* own database, so a board read from a terminal behaves the same as one read
|
|
108
|
+
* from inside an app. Migrations are not applied here: the file's owner applies
|
|
109
|
+
* them (`kanbo init --file`, `kanbo migrate`, or the app the database belongs to).
|
|
110
|
+
*
|
|
111
|
+
* Asynchronous because the driver beneath it is loaded on demand — see
|
|
112
|
+
* `loadSqliteDriver`. The native module is asked for first, so an install
|
|
113
|
+
* without it hears the sentence above rather than a module-resolution stack
|
|
114
|
+
* from inside drizzle.
|
|
115
|
+
*/
|
|
116
|
+
declare function openBoardDatabase(path: string): Promise<BoardDatabase>;
|
|
117
|
+
/**
|
|
118
|
+
* Refuse a board file this build cannot speak for, before any statement runs
|
|
119
|
+
* against it: one with no board in it (`missingTables`), one whose board a
|
|
120
|
+
* later migration has since added a table to (`missingAddedTables`) or a
|
|
121
|
+
* column to (`missingColumns`), and one stamped with another epoch. An app
|
|
122
|
+
* that migrates its own database on start need not call this; it is the guard a
|
|
123
|
+
* standalone reader puts in front of a file it did not create.
|
|
124
|
+
*/
|
|
125
|
+
declare function assertBoardSchema(database: SqliteDatabase): void;
|
|
126
|
+
/**
|
|
127
|
+
* Who created this board file's tables from nothing: this package
|
|
128
|
+
* (`kanbo init --file`), or a host app whose own database the board lives in.
|
|
129
|
+
*/
|
|
130
|
+
type BoardFileOwner = 'kanbo' | 'host';
|
|
131
|
+
/**
|
|
132
|
+
* Which of the two ever wrote this file's board, going by the `kanban_meta`
|
|
133
|
+
* marker `kanbo init --file` leaves behind (ruling 5-4).
|
|
134
|
+
*
|
|
135
|
+
* Absent reads as a host database — every file this package has never
|
|
136
|
+
* touched, and a file this build cannot make sense of at all: `assertBoardSchema` is what says a board is missing or too old,
|
|
137
|
+
* not this, so a table or a row that is not there yet is read as "not this
|
|
138
|
+
* package's file" rather than an error of its own.
|
|
139
|
+
*/
|
|
140
|
+
declare function readBoardFileOwner(database: SqliteDatabase): BoardFileOwner;
|
|
141
|
+
/**
|
|
142
|
+
* Leave the marker that tells every later reader this file is this package's
|
|
143
|
+
* own, not a host app's. `kanbo init --file` calls this once, right after
|
|
144
|
+
* migrating; `insert or ignore` is what makes calling it again on the same
|
|
145
|
+
* file a no-op rather than a conflict.
|
|
146
|
+
*/
|
|
147
|
+
declare function markBoardFileOwnedByKanbo(database: SqliteDatabase): void;
|
|
148
|
+
/** What a file already holds, before a board is opened on it or written into it. */
|
|
149
|
+
interface BoardFileContents {
|
|
150
|
+
/** No tables at all — a path nothing has been created in yet, or a zero-byte file. */
|
|
151
|
+
empty: boolean;
|
|
152
|
+
/** Whose board the tables are, by the `file_owner` marker (ruling 5-4). Says nothing about an empty file. */
|
|
153
|
+
owner: BoardFileOwner;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Look at a file on a connection of its own and hand it back closed, so a
|
|
157
|
+
* caller can decide what to do with it before opening it for real.
|
|
158
|
+
*
|
|
159
|
+
* Two callers, two different decisions off the same two facts: the command line
|
|
160
|
+
* asks whose file it is to know whether a host app's `workspaces` row may be
|
|
161
|
+
* looked up in it, and a host app asks before it writes a board into it, because
|
|
162
|
+
* a file with tables that are not this package's is somebody else's database
|
|
163
|
+
* and migrating it would contaminate it (ruling 5-8).
|
|
164
|
+
*
|
|
165
|
+
* A path that is not a SQLite database at all — a README, a half-downloaded
|
|
166
|
+
* file, a directory — throws, and that is deliberately not the same answer as
|
|
167
|
+
* "a database with somebody else's tables in it": one is a mistake about which
|
|
168
|
+
* path to use and the other is a mistake about which file is a board. No pragma
|
|
169
|
+
* is set and nothing is written, so a file that turns out not to be ours is
|
|
170
|
+
* left exactly as it was found, journal mode included.
|
|
171
|
+
*/
|
|
172
|
+
declare function readBoardFileContents(path: string): BoardFileContents;
|
|
173
|
+
//#endregion
|
|
174
|
+
export { BOARD_SCHEMA_EPOCH, type BoardDatabase, type BoardFileContents, type BoardFileOwner, type Issue, type IssueComment, type IssueFieldChange, type IssueMilestone, type IssueRelation, type IssueRun, type IssueStatus, type KanbanMeta, type SqliteDatabase, type SqliteTransactionMode, assertBoardSchema, boardSqliteSchema, createSqliteBoardStore, getBoardSqliteMigrationsPath, issueComments, issueFieldChanges, issueMilestones, issueRelations, issueRuns, issueStatuses, issues, kanbanMeta, markBoardFileOwnedByKanbo, migrateBoardFile, openBoardDatabase, readBoardFileContents, readBoardFileOwner, runSqliteTransaction };
|
|
175
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { _ as issueStatuses, c as IssueStatus, d as issueComments, f as issueFieldChanges, g as issueRuns, h as issueRelations, i as IssueMilestone, l as KanbanMeta, n as IssueComment, o as IssueRelation, p as issueMilestones, r as IssueFieldChange, s as IssueRun, t as Issue, u as boardSqliteSchema, v as issues, y as kanbanMeta } from "../schema-fsHqNAip.mjs";
|
|
2
|
+
import { a as BoardStore } from "../board-store-B16YarvX.mjs";
|
|
3
|
+
import { t as BOARD_SCHEMA_EPOCH } from "../schema-epoch-ZyumVL_A.mjs";
|
|
4
|
+
import { BetterSQLite3Database } from "drizzle-orm/better-sqlite3";
|
|
5
|
+
import { Database } from "better-sqlite3";
|
|
6
|
+
//#region src/sqlite/transaction.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* The database handle itself — what the host hands the board — and not an open
|
|
9
|
+
* transaction on it: the helper reaches for the driver connection, which a
|
|
10
|
+
* drizzle `SQLiteTransaction` does not carry.
|
|
11
|
+
*
|
|
12
|
+
* The schema parameter is `Record<string, unknown>` rather than any particular
|
|
13
|
+
* schema, which is what lets one type stand for all three of the files a board
|
|
14
|
+
* can live in (ruling 5-3): a handle drizzle was given a host app's whole schema
|
|
15
|
+
* satisfies it, and so does one given only the board's own nine tables. The
|
|
16
|
+
* board never reaches for `database.query`, so the relational builder those
|
|
17
|
+
* generics shape is not something this package gives up by asking for less —
|
|
18
|
+
* `src/sqlite/database-type.test.ts` is the probe that says both handles still
|
|
19
|
+
* arrive here.
|
|
20
|
+
*/
|
|
21
|
+
type SqliteDatabase = BetterSQLite3Database<Record<string, unknown>>;
|
|
22
|
+
/**
|
|
23
|
+
* How the outer `begin` takes its write lock. `deferred` — the SQLite default —
|
|
24
|
+
* waits for the first write; `immediate` takes the lock up front, so two
|
|
25
|
+
* processes racing for the same file fail fast instead of half-way through.
|
|
26
|
+
* A nested scope is a savepoint and takes no lock of its own, so the mode only
|
|
27
|
+
* reaches the outer statement.
|
|
28
|
+
*/
|
|
29
|
+
type SqliteTransactionMode = 'deferred' | 'immediate';
|
|
30
|
+
/**
|
|
31
|
+
* Run `fn` inside one SQLite transaction that is allowed to await.
|
|
32
|
+
*
|
|
33
|
+
* `database.transaction(...)` cannot serve here: it commits the moment its
|
|
34
|
+
* callback returns, and an async callback returns a pending promise, so the
|
|
35
|
+
* transaction would close before the work inside it ran. The statements are
|
|
36
|
+
* issued by hand instead, and the driver's own `inTransaction` flag picks which
|
|
37
|
+
* — the same branch better-sqlite3 takes. With nothing open: `begin`, then
|
|
38
|
+
* `commit`, or `rollback` when `fn` throws. With a transaction already open —
|
|
39
|
+
* another call to this helper, or one a module opened through
|
|
40
|
+
* `database.transaction` — a `savepoint` … `release` pair, undone by
|
|
41
|
+
* `rollback to` followed by its own `release`. A second `begin` would throw,
|
|
42
|
+
* which is why the flag decides and not a private counter. When SQLite has
|
|
43
|
+
* already aborted the transaction itself the undo is skipped: it would throw
|
|
44
|
+
* over the caller's error.
|
|
45
|
+
*
|
|
46
|
+
* **The callback must be the only database-touching async chain in flight —
|
|
47
|
+
* no `Promise.all` sibling, no lock hand-off, no fire-and-forget promise
|
|
48
|
+
* started before it — and inside it, only await operations that resolve
|
|
49
|
+
* without I/O: store methods, synchronous database writes.** Even a resolved
|
|
50
|
+
* promise yields to the microtask queue first, so a sibling chain already
|
|
51
|
+
* queued in the same macrotask still runs inside this open transaction; a
|
|
52
|
+
* chain started in a separate macrotask is unaffected. Awaiting anything that
|
|
53
|
+
* truly suspends — a timer, the filesystem, the network — hands the
|
|
54
|
+
* connection to whatever runs next, and its writes land in this transaction
|
|
55
|
+
* too.
|
|
56
|
+
*/
|
|
57
|
+
declare function runSqliteTransaction<T>(database: SqliteDatabase, fn: () => Promise<T>, options?: {
|
|
58
|
+
mode?: SqliteTransactionMode;
|
|
59
|
+
}): Promise<T>;
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/sqlite/board-store.sqlite.d.ts
|
|
62
|
+
/**
|
|
63
|
+
* `BoardStore` backed by SQLite: every method resolves immediately, because the
|
|
64
|
+
* core underneath it is synchronous.
|
|
65
|
+
*
|
|
66
|
+
* `database` is a function rather than a handle so the store follows whatever
|
|
67
|
+
* the host currently has open — a server passes its single connection
|
|
68
|
+
* accessor, a standalone reader passes its own.
|
|
69
|
+
*/
|
|
70
|
+
declare function createSqliteBoardStore(options: {
|
|
71
|
+
database: () => SqliteDatabase;
|
|
72
|
+
}): BoardStore;
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/sqlite/migrate.d.ts
|
|
75
|
+
/**
|
|
76
|
+
* The board's SQLite migrations for the file that is running right now — the
|
|
77
|
+
* ones that build a board *file of this package's own*. The two layouts this
|
|
78
|
+
* has to survive are `src/migrations-path.ts`'s subject.
|
|
79
|
+
*/
|
|
80
|
+
declare function getBoardSqliteMigrationsPath(): string;
|
|
81
|
+
/**
|
|
82
|
+
* Create or update a board file this package owns.
|
|
83
|
+
*
|
|
84
|
+
* A host app's own database is not this: there the board is nine tables among
|
|
85
|
+
* the app's own, and the app's migration runner migrates the whole file — which
|
|
86
|
+
* may take two passes, because a migration that rebuilds a table has to drop
|
|
87
|
+
* it with foreign keys off. Nothing here rebuilds anything — `drizzle-sqlite/` starts at the
|
|
88
|
+
* board as it is now and will only ever be appended to — so drizzle's own
|
|
89
|
+
* migrator is the whole of what this needs, and a file that has been migrated
|
|
90
|
+
* before is a no-op by `__drizzle_migrations`.
|
|
91
|
+
*
|
|
92
|
+
* What the file holds afterwards is the board and nothing else: no
|
|
93
|
+
* `workspaces`, no `agents`, no `provider_targets`. Every reference out of the
|
|
94
|
+
* board is a plain text column for exactly that reason (ruling 5-1).
|
|
95
|
+
*/
|
|
96
|
+
declare function migrateBoardFile(database: SqliteDatabase): void;
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/sqlite/open-database.d.ts
|
|
99
|
+
/** One open board file: the drizzle handle, the driver beneath it, and the way to let go. */
|
|
100
|
+
interface BoardDatabase {
|
|
101
|
+
database: SqliteDatabase;
|
|
102
|
+
connection: Database;
|
|
103
|
+
close: () => void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Open a board file with the runtime pragmas a long-running server sets on its
|
|
107
|
+
* own database, so a board read from a terminal behaves the same as one read
|
|
108
|
+
* from inside an app. Migrations are not applied here: the file's owner applies
|
|
109
|
+
* them (`kanbo init --file`, `kanbo migrate`, or the app the database belongs to).
|
|
110
|
+
*
|
|
111
|
+
* Asynchronous because the driver beneath it is loaded on demand — see
|
|
112
|
+
* `loadSqliteDriver`. The native module is asked for first, so an install
|
|
113
|
+
* without it hears the sentence above rather than a module-resolution stack
|
|
114
|
+
* from inside drizzle.
|
|
115
|
+
*/
|
|
116
|
+
declare function openBoardDatabase(path: string): Promise<BoardDatabase>;
|
|
117
|
+
/**
|
|
118
|
+
* Refuse a board file this build cannot speak for, before any statement runs
|
|
119
|
+
* against it: one with no board in it (`missingTables`), one whose board a
|
|
120
|
+
* later migration has since added a table to (`missingAddedTables`) or a
|
|
121
|
+
* column to (`missingColumns`), and one stamped with another epoch. An app
|
|
122
|
+
* that migrates its own database on start need not call this; it is the guard a
|
|
123
|
+
* standalone reader puts in front of a file it did not create.
|
|
124
|
+
*/
|
|
125
|
+
declare function assertBoardSchema(database: SqliteDatabase): void;
|
|
126
|
+
/**
|
|
127
|
+
* Who created this board file's tables from nothing: this package
|
|
128
|
+
* (`kanbo init --file`), or a host app whose own database the board lives in.
|
|
129
|
+
*/
|
|
130
|
+
type BoardFileOwner = 'kanbo' | 'host';
|
|
131
|
+
/**
|
|
132
|
+
* Which of the two ever wrote this file's board, going by the `kanban_meta`
|
|
133
|
+
* marker `kanbo init --file` leaves behind (ruling 5-4).
|
|
134
|
+
*
|
|
135
|
+
* Absent reads as a host database — every file this package has never
|
|
136
|
+
* touched, and a file this build cannot make sense of at all: `assertBoardSchema` is what says a board is missing or too old,
|
|
137
|
+
* not this, so a table or a row that is not there yet is read as "not this
|
|
138
|
+
* package's file" rather than an error of its own.
|
|
139
|
+
*/
|
|
140
|
+
declare function readBoardFileOwner(database: SqliteDatabase): BoardFileOwner;
|
|
141
|
+
/**
|
|
142
|
+
* Leave the marker that tells every later reader this file is this package's
|
|
143
|
+
* own, not a host app's. `kanbo init --file` calls this once, right after
|
|
144
|
+
* migrating; `insert or ignore` is what makes calling it again on the same
|
|
145
|
+
* file a no-op rather than a conflict.
|
|
146
|
+
*/
|
|
147
|
+
declare function markBoardFileOwnedByKanbo(database: SqliteDatabase): void;
|
|
148
|
+
/** What a file already holds, before a board is opened on it or written into it. */
|
|
149
|
+
interface BoardFileContents {
|
|
150
|
+
/** No tables at all — a path nothing has been created in yet, or a zero-byte file. */
|
|
151
|
+
empty: boolean;
|
|
152
|
+
/** Whose board the tables are, by the `file_owner` marker (ruling 5-4). Says nothing about an empty file. */
|
|
153
|
+
owner: BoardFileOwner;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Look at a file on a connection of its own and hand it back closed, so a
|
|
157
|
+
* caller can decide what to do with it before opening it for real.
|
|
158
|
+
*
|
|
159
|
+
* Two callers, two different decisions off the same two facts: the command line
|
|
160
|
+
* asks whose file it is to know whether a host app's `workspaces` row may be
|
|
161
|
+
* looked up in it, and a host app asks before it writes a board into it, because
|
|
162
|
+
* a file with tables that are not this package's is somebody else's database
|
|
163
|
+
* and migrating it would contaminate it (ruling 5-8).
|
|
164
|
+
*
|
|
165
|
+
* A path that is not a SQLite database at all — a README, a half-downloaded
|
|
166
|
+
* file, a directory — throws, and that is deliberately not the same answer as
|
|
167
|
+
* "a database with somebody else's tables in it": one is a mistake about which
|
|
168
|
+
* path to use and the other is a mistake about which file is a board. No pragma
|
|
169
|
+
* is set and nothing is written, so a file that turns out not to be ours is
|
|
170
|
+
* left exactly as it was found, journal mode included.
|
|
171
|
+
*/
|
|
172
|
+
declare function readBoardFileContents(path: string): BoardFileContents;
|
|
173
|
+
//#endregion
|
|
174
|
+
export { BOARD_SCHEMA_EPOCH, type BoardDatabase, type BoardFileContents, type BoardFileOwner, type Issue, type IssueComment, type IssueFieldChange, type IssueMilestone, type IssueRelation, type IssueRun, type IssueStatus, type KanbanMeta, type SqliteDatabase, type SqliteTransactionMode, assertBoardSchema, boardSqliteSchema, createSqliteBoardStore, getBoardSqliteMigrationsPath, issueComments, issueFieldChanges, issueMilestones, issueRelations, issueRuns, issueStatuses, issues, kanbanMeta, markBoardFileOwnedByKanbo, migrateBoardFile, openBoardDatabase, readBoardFileContents, readBoardFileOwner, runSqliteTransaction };
|
|
175
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { r as BOARD_SCHEMA_EPOCH } from "../migrations-path-Ciwan537.mjs";
|
|
2
|
+
import { boardSqliteSchema, issueComments, issueFieldChanges, issueMilestones, issueRelations, issueRuns, issueStatuses, issues, kanbanMeta } from "./schema.mjs";
|
|
3
|
+
import { a as openBoardDatabase, c as createSqliteBoardStore, i as markBoardFileOwnedByKanbo, l as runSqliteTransaction, n as migrateBoardFile, o as readBoardFileContents, r as assertBoardSchema, s as readBoardFileOwner, t as getBoardSqliteMigrationsPath } from "../migrate-BhYi9cXw.mjs";
|
|
4
|
+
export { BOARD_SCHEMA_EPOCH, assertBoardSchema, boardSqliteSchema, createSqliteBoardStore, getBoardSqliteMigrationsPath, issueComments, issueFieldChanges, issueMilestones, issueRelations, issueRuns, issueStatuses, issues, kanbanMeta, markBoardFileOwnedByKanbo, migrateBoardFile, openBoardDatabase, readBoardFileContents, readBoardFileOwner, runSqliteTransaction };
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let drizzle_orm = require("drizzle-orm");
|
|
3
|
+
let drizzle_orm_sqlite_core = require("drizzle-orm/sqlite-core");
|
|
4
|
+
//#region src/sqlite/schema.ts
|
|
5
|
+
/**
|
|
6
|
+
* The board, as a SQLite file holds it.
|
|
7
|
+
*
|
|
8
|
+
* These nine tables are the board itself, and this package owns them: the same
|
|
9
|
+
* logical schema as `src/postgres/schema.ts`, written for the dialect a file
|
|
10
|
+
* speaks. They live in three different places at runtime — a host app's own
|
|
11
|
+
* database, a board file of a project's own, and neither of those when the
|
|
12
|
+
* board is a Postgres database — and none of those homes owns the shape. A host
|
|
13
|
+
* app re-exports these very objects from its own schema, so its tables and
|
|
14
|
+
* these are the same tables rather than two declarations that have to be kept
|
|
15
|
+
* in step.
|
|
16
|
+
*
|
|
17
|
+
* **Every reference out of the board is a plain text column** (ruling 5-1).
|
|
18
|
+
* `workspace_id`, `delegate_agent_id`, `delegate_provider_target_id` and
|
|
19
|
+
* `source_chat_session_id` name rows in a host app's tables, and a board file of
|
|
20
|
+
* a project's own has no such tables to point at — so they are soft references
|
|
21
|
+
* into whichever app is looking, exactly as they are on Postgres. What an
|
|
22
|
+
* `ON DELETE` would do is done in the open by the app that deletes the row: it
|
|
23
|
+
* empties a removed workspace's board, and clears the delegation off the cards
|
|
24
|
+
* that named a removed agent or provider target. The foreign keys that stay are the
|
|
25
|
+
* ones that point *inside* the board, and they still cascade.
|
|
26
|
+
*/
|
|
27
|
+
const textPk = () => (0, drizzle_orm_sqlite_core.text)("id").primaryKey();
|
|
28
|
+
const timestamps = () => ({
|
|
29
|
+
createdAt: (0, drizzle_orm_sqlite_core.int)("created_at").notNull().default(drizzle_orm.sql`(unixepoch())`),
|
|
30
|
+
updatedAt: (0, drizzle_orm_sqlite_core.int)("updated_at").notNull().default(drizzle_orm.sql`(unixepoch())`)
|
|
31
|
+
});
|
|
32
|
+
const createdAt = () => ({ createdAt: (0, drizzle_orm_sqlite_core.int)("created_at").notNull().default(drizzle_orm.sql`(unixepoch())`) });
|
|
33
|
+
const issueStatuses = (0, drizzle_orm_sqlite_core.sqliteTable)("issue_statuses", {
|
|
34
|
+
id: textPk(),
|
|
35
|
+
workspaceId: (0, drizzle_orm_sqlite_core.text)("workspace_id").notNull(),
|
|
36
|
+
name: (0, drizzle_orm_sqlite_core.text)("name").notNull(),
|
|
37
|
+
description: (0, drizzle_orm_sqlite_core.text)("description"),
|
|
38
|
+
color: (0, drizzle_orm_sqlite_core.text)("color"),
|
|
39
|
+
category: (0, drizzle_orm_sqlite_core.text)("category", { enum: [
|
|
40
|
+
"triage",
|
|
41
|
+
"backlog",
|
|
42
|
+
"unstarted",
|
|
43
|
+
"started",
|
|
44
|
+
"completed",
|
|
45
|
+
"canceled"
|
|
46
|
+
] }).notNull().default("unstarted"),
|
|
47
|
+
order: (0, drizzle_orm_sqlite_core.int)("order").notNull().default(0),
|
|
48
|
+
/**
|
|
49
|
+
* What a card must satisfy before an agent may put it in this column — a JSON
|
|
50
|
+
* array of `ENTRY_RULES` (ruling 6-1); `null` asks for nothing. Read it
|
|
51
|
+
* through `readEntryRules`, never by hand.
|
|
52
|
+
*/
|
|
53
|
+
entryRules: (0, drizzle_orm_sqlite_core.text)("entry_rules"),
|
|
54
|
+
...createdAt()
|
|
55
|
+
}, (table) => ({
|
|
56
|
+
byWorkspace: (0, drizzle_orm_sqlite_core.index)("issue_statuses_workspace_id_idx").on(table.workspaceId),
|
|
57
|
+
byWorkspaceName: (0, drizzle_orm_sqlite_core.uniqueIndex)("issue_statuses_workspace_name_unique").on(table.workspaceId, table.name)
|
|
58
|
+
}));
|
|
59
|
+
const issueMilestones = (0, drizzle_orm_sqlite_core.sqliteTable)("issue_milestones", {
|
|
60
|
+
id: textPk(),
|
|
61
|
+
workspaceId: (0, drizzle_orm_sqlite_core.text)("workspace_id").notNull(),
|
|
62
|
+
title: (0, drizzle_orm_sqlite_core.text)("title").notNull(),
|
|
63
|
+
description: (0, drizzle_orm_sqlite_core.text)("description"),
|
|
64
|
+
/** When the milestone, read as a sprint, begins (unix seconds); null for a plain milestone. */
|
|
65
|
+
startDate: (0, drizzle_orm_sqlite_core.int)("start_date"),
|
|
66
|
+
dueDate: (0, drizzle_orm_sqlite_core.int)("due_date"),
|
|
67
|
+
status: (0, drizzle_orm_sqlite_core.text)("status", { enum: ["open", "closed"] }).notNull().default("open"),
|
|
68
|
+
...timestamps()
|
|
69
|
+
}, (table) => ({ byWorkspace: (0, drizzle_orm_sqlite_core.index)("issue_milestones_workspace_id_idx").on(table.workspaceId) }));
|
|
70
|
+
const issues = (0, drizzle_orm_sqlite_core.sqliteTable)("issues", {
|
|
71
|
+
id: textPk(),
|
|
72
|
+
workspaceId: (0, drizzle_orm_sqlite_core.text)("workspace_id").notNull(),
|
|
73
|
+
number: (0, drizzle_orm_sqlite_core.int)("number").notNull(),
|
|
74
|
+
statusId: (0, drizzle_orm_sqlite_core.text)("status_id").references(() => issueStatuses.id, { onDelete: "set null" }),
|
|
75
|
+
milestoneId: (0, drizzle_orm_sqlite_core.text)("milestone_id").references(() => issueMilestones.id, { onDelete: "set null" }),
|
|
76
|
+
parentIssueId: (0, drizzle_orm_sqlite_core.text)("parent_issue_id").references(() => issues.id, { onDelete: "set null" }),
|
|
77
|
+
title: (0, drizzle_orm_sqlite_core.text)("title").notNull(),
|
|
78
|
+
description: (0, drizzle_orm_sqlite_core.text)("description"),
|
|
79
|
+
priority: (0, drizzle_orm_sqlite_core.text)("priority", { enum: [
|
|
80
|
+
"none",
|
|
81
|
+
"low",
|
|
82
|
+
"medium",
|
|
83
|
+
"high",
|
|
84
|
+
"urgent"
|
|
85
|
+
] }).notNull().default("none"),
|
|
86
|
+
labels: (0, drizzle_orm_sqlite_core.text)("labels").notNull().default("[]"),
|
|
87
|
+
assigneeKind: (0, drizzle_orm_sqlite_core.text)("assignee_kind"),
|
|
88
|
+
assigneeId: (0, drizzle_orm_sqlite_core.text)("assignee_id"),
|
|
89
|
+
dueDate: (0, drizzle_orm_sqlite_core.int)("due_date"),
|
|
90
|
+
createdByKind: (0, drizzle_orm_sqlite_core.text)("created_by_kind", { enum: [
|
|
91
|
+
"user",
|
|
92
|
+
"agent",
|
|
93
|
+
"system",
|
|
94
|
+
"provider-target"
|
|
95
|
+
] }).notNull().default("user"),
|
|
96
|
+
createdById: (0, drizzle_orm_sqlite_core.text)("created_by_id").notNull().default("__self__"),
|
|
97
|
+
sourceChatSessionId: (0, drizzle_orm_sqlite_core.text)("source_chat_session_id"),
|
|
98
|
+
delegateAgentId: (0, drizzle_orm_sqlite_core.text)("delegate_agent_id"),
|
|
99
|
+
delegateProviderTargetId: (0, drizzle_orm_sqlite_core.text)("delegate_provider_target_id"),
|
|
100
|
+
contextRefs: (0, drizzle_orm_sqlite_core.text)("context_refs").notNull().default("[]"),
|
|
101
|
+
statusLine: (0, drizzle_orm_sqlite_core.text)("status_line"),
|
|
102
|
+
waitingFor: (0, drizzle_orm_sqlite_core.text)("waiting_for", { enum: ["human"] }),
|
|
103
|
+
executionMode: (0, drizzle_orm_sqlite_core.text)("execution_mode", { enum: ["worktree", "main"] }).notNull().default("worktree"),
|
|
104
|
+
order: (0, drizzle_orm_sqlite_core.int)("order").notNull().default(0),
|
|
105
|
+
...timestamps()
|
|
106
|
+
}, (table) => ({
|
|
107
|
+
byWorkspace: (0, drizzle_orm_sqlite_core.index)("issues_workspace_id_idx").on(table.workspaceId),
|
|
108
|
+
byWorkspaceNumber: (0, drizzle_orm_sqlite_core.uniqueIndex)("issues_workspace_number_unique").on(table.workspaceId, table.number),
|
|
109
|
+
byStatus: (0, drizzle_orm_sqlite_core.index)("issues_status_id_idx").on(table.statusId),
|
|
110
|
+
byMilestone: (0, drizzle_orm_sqlite_core.index)("issues_milestone_id_idx").on(table.milestoneId),
|
|
111
|
+
byParent: (0, drizzle_orm_sqlite_core.index)("issues_parent_issue_id_idx").on(table.parentIssueId),
|
|
112
|
+
byDelegateAgent: (0, drizzle_orm_sqlite_core.index)("issues_delegate_agent_id_idx").on(table.delegateAgentId),
|
|
113
|
+
byDelegateProviderTarget: (0, drizzle_orm_sqlite_core.index)("issues_delegate_provider_target_id_idx").on(table.delegateProviderTargetId)
|
|
114
|
+
}));
|
|
115
|
+
const issueComments = (0, drizzle_orm_sqlite_core.sqliteTable)("issue_comments", {
|
|
116
|
+
id: textPk(),
|
|
117
|
+
issueId: (0, drizzle_orm_sqlite_core.text)("issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
|
|
118
|
+
content: (0, drizzle_orm_sqlite_core.text)("content").notNull(),
|
|
119
|
+
authorKind: (0, drizzle_orm_sqlite_core.text)("author_kind", { enum: [
|
|
120
|
+
"user",
|
|
121
|
+
"agent",
|
|
122
|
+
"provider-target",
|
|
123
|
+
"system",
|
|
124
|
+
"system.delegated",
|
|
125
|
+
"system.undelegated",
|
|
126
|
+
"system.run",
|
|
127
|
+
"system.approved",
|
|
128
|
+
"system.returned",
|
|
129
|
+
"system.pr"
|
|
130
|
+
] }).notNull().default("user"),
|
|
131
|
+
authorId: (0, drizzle_orm_sqlite_core.text)("author_id"),
|
|
132
|
+
sourceChatSessionId: (0, drizzle_orm_sqlite_core.text)("source_chat_session_id"),
|
|
133
|
+
agentActivityId: (0, drizzle_orm_sqlite_core.text)("agent_activity_id"),
|
|
134
|
+
dedupeKey: (0, drizzle_orm_sqlite_core.text)("dedupe_key"),
|
|
135
|
+
...createdAt()
|
|
136
|
+
}, (table) => ({
|
|
137
|
+
byIssue: (0, drizzle_orm_sqlite_core.index)("issue_comments_issue_id_idx").on(table.issueId),
|
|
138
|
+
byIssueDedupeKey: (0, drizzle_orm_sqlite_core.uniqueIndex)("issue_comments_issue_dedupe_idx").on(table.issueId, table.dedupeKey)
|
|
139
|
+
}));
|
|
140
|
+
const issueRuns = (0, drizzle_orm_sqlite_core.sqliteTable)("issue_runs", {
|
|
141
|
+
id: textPk(),
|
|
142
|
+
issueId: (0, drizzle_orm_sqlite_core.text)("issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
|
|
143
|
+
launchedByKind: (0, drizzle_orm_sqlite_core.text)("launched_by_kind", { enum: [
|
|
144
|
+
"user",
|
|
145
|
+
"agent",
|
|
146
|
+
"external"
|
|
147
|
+
] }).notNull().default("user"),
|
|
148
|
+
launchedById: (0, drizzle_orm_sqlite_core.text)("launched_by_id"),
|
|
149
|
+
agentId: (0, drizzle_orm_sqlite_core.text)("agent_id"),
|
|
150
|
+
agentName: (0, drizzle_orm_sqlite_core.text)("agent_name").notNull(),
|
|
151
|
+
host: (0, drizzle_orm_sqlite_core.text)("host"),
|
|
152
|
+
executionMode: (0, drizzle_orm_sqlite_core.text)("execution_mode", { enum: ["worktree", "main"] }).notNull().default("worktree"),
|
|
153
|
+
branch: (0, drizzle_orm_sqlite_core.text)("branch"),
|
|
154
|
+
worktreePath: (0, drizzle_orm_sqlite_core.text)("worktree_path"),
|
|
155
|
+
state: (0, drizzle_orm_sqlite_core.text)("state", { enum: [
|
|
156
|
+
"running",
|
|
157
|
+
"finished",
|
|
158
|
+
"failed",
|
|
159
|
+
"stopped"
|
|
160
|
+
] }).notNull().default("running"),
|
|
161
|
+
chatSessionId: (0, drizzle_orm_sqlite_core.text)("chat_session_id"),
|
|
162
|
+
/** Where an external agent's own log of this run lives — `claude:<id>` or `codex:<id>` (ruling 7-1), `null` when it never said. */
|
|
163
|
+
externalSessionRef: (0, drizzle_orm_sqlite_core.text)("external_session_ref"),
|
|
164
|
+
startedAt: (0, drizzle_orm_sqlite_core.int)("started_at").notNull().default(drizzle_orm.sql`(unixepoch())`),
|
|
165
|
+
endedAt: (0, drizzle_orm_sqlite_core.int)("ended_at")
|
|
166
|
+
}, (table) => ({
|
|
167
|
+
byIssue: (0, drizzle_orm_sqlite_core.index)("issue_runs_issue_id_idx").on(table.issueId),
|
|
168
|
+
byIssueState: (0, drizzle_orm_sqlite_core.index)("issue_runs_issue_state_idx").on(table.issueId, table.state),
|
|
169
|
+
byChatSession: (0, drizzle_orm_sqlite_core.index)("issue_runs_chat_session_idx").on(table.chatSessionId)
|
|
170
|
+
}));
|
|
171
|
+
const issueRelations = (0, drizzle_orm_sqlite_core.sqliteTable)("issue_relations", {
|
|
172
|
+
id: textPk(),
|
|
173
|
+
sourceIssueId: (0, drizzle_orm_sqlite_core.text)("source_issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
|
|
174
|
+
targetIssueId: (0, drizzle_orm_sqlite_core.text)("target_issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
|
|
175
|
+
type: (0, drizzle_orm_sqlite_core.text)("type", { enum: [
|
|
176
|
+
"blocks",
|
|
177
|
+
"duplicates",
|
|
178
|
+
"relates_to"
|
|
179
|
+
] }).notNull(),
|
|
180
|
+
...createdAt()
|
|
181
|
+
}, (table) => ({
|
|
182
|
+
bySource: (0, drizzle_orm_sqlite_core.index)("issue_relations_source_issue_id_idx").on(table.sourceIssueId),
|
|
183
|
+
byTarget: (0, drizzle_orm_sqlite_core.index)("issue_relations_target_issue_id_idx").on(table.targetIssueId),
|
|
184
|
+
byPairType: (0, drizzle_orm_sqlite_core.uniqueIndex)("issue_relations_pair_type_unique").on(table.sourceIssueId, table.targetIssueId, table.type)
|
|
185
|
+
}));
|
|
186
|
+
const issueFieldChanges = (0, drizzle_orm_sqlite_core.sqliteTable)("issue_field_changes", {
|
|
187
|
+
id: textPk(),
|
|
188
|
+
issueId: (0, drizzle_orm_sqlite_core.text)("issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
|
|
189
|
+
field: (0, drizzle_orm_sqlite_core.text)("field").notNull(),
|
|
190
|
+
fromValue: (0, drizzle_orm_sqlite_core.text)("from_value"),
|
|
191
|
+
toValue: (0, drizzle_orm_sqlite_core.text)("to_value"),
|
|
192
|
+
actorKind: (0, drizzle_orm_sqlite_core.text)("actor_kind", { enum: [
|
|
193
|
+
"user",
|
|
194
|
+
"agent",
|
|
195
|
+
"provider-target",
|
|
196
|
+
"system"
|
|
197
|
+
] }).notNull().default("user"),
|
|
198
|
+
actorId: (0, drizzle_orm_sqlite_core.text)("actor_id"),
|
|
199
|
+
sourceChatSessionId: (0, drizzle_orm_sqlite_core.text)("source_chat_session_id"),
|
|
200
|
+
...createdAt()
|
|
201
|
+
}, (table) => ({ byIssue: (0, drizzle_orm_sqlite_core.index)("issue_field_changes_issue_id_idx").on(table.issueId) }));
|
|
202
|
+
/**
|
|
203
|
+
* A pull request someone said belongs to a card.
|
|
204
|
+
*
|
|
205
|
+
* The link is the board's; what the pull request *is* — open, merged, green —
|
|
206
|
+
* is GitHub's, and the board keeps none of it. Whoever watches GitHub reads the
|
|
207
|
+
* links here and writes what it saw as comments on the card, so this row is a
|
|
208
|
+
* name (`owner/repo#number`, and the URL it came from) and who gave it. One
|
|
209
|
+
* card names one pull request once; the same pull request may belong to several
|
|
210
|
+
* cards, which is why `(owner, repo, number)` is indexed on its own.
|
|
211
|
+
*/
|
|
212
|
+
const issuePullRequests = (0, drizzle_orm_sqlite_core.sqliteTable)("issue_pull_requests", {
|
|
213
|
+
id: textPk(),
|
|
214
|
+
issueId: (0, drizzle_orm_sqlite_core.text)("issue_id").notNull().references(() => issues.id, { onDelete: "cascade" }),
|
|
215
|
+
owner: (0, drizzle_orm_sqlite_core.text)("owner").notNull(),
|
|
216
|
+
repo: (0, drizzle_orm_sqlite_core.text)("repo").notNull(),
|
|
217
|
+
number: (0, drizzle_orm_sqlite_core.int)("number").notNull(),
|
|
218
|
+
url: (0, drizzle_orm_sqlite_core.text)("url").notNull(),
|
|
219
|
+
createdByKind: (0, drizzle_orm_sqlite_core.text)("created_by_kind", { enum: [
|
|
220
|
+
"user",
|
|
221
|
+
"agent",
|
|
222
|
+
"provider-target",
|
|
223
|
+
"system"
|
|
224
|
+
] }).notNull(),
|
|
225
|
+
createdById: (0, drizzle_orm_sqlite_core.text)("created_by_id"),
|
|
226
|
+
...createdAt()
|
|
227
|
+
}, (table) => ({
|
|
228
|
+
byIssuePullRequest: (0, drizzle_orm_sqlite_core.uniqueIndex)("issue_pull_requests_issue_pr_unique").on(table.issueId, table.owner, table.repo, table.number),
|
|
229
|
+
byPullRequest: (0, drizzle_orm_sqlite_core.index)("issue_pull_requests_pr_idx").on(table.owner, table.repo, table.number)
|
|
230
|
+
}));
|
|
231
|
+
/**
|
|
232
|
+
* Monotonic counters the board keeps for its readers: `board` is bumped by the
|
|
233
|
+
* board operations layer once per write transaction that changed something, so a
|
|
234
|
+
* poller can tell a changed board from an unchanged one, and `schema_epoch`
|
|
235
|
+
* records the board schema generation the file was written with.
|
|
236
|
+
*/
|
|
237
|
+
const kanbanMeta = (0, drizzle_orm_sqlite_core.sqliteTable)("kanban_meta", {
|
|
238
|
+
key: (0, drizzle_orm_sqlite_core.text)("key").primaryKey(),
|
|
239
|
+
revision: (0, drizzle_orm_sqlite_core.int)("revision").notNull().default(0),
|
|
240
|
+
updatedAt: (0, drizzle_orm_sqlite_core.int)("updated_at").notNull().default(drizzle_orm.sql`(unixepoch())`)
|
|
241
|
+
});
|
|
242
|
+
/** Every table of the board, in the order a reader of the schema wants them. */
|
|
243
|
+
const boardSqliteSchema = {
|
|
244
|
+
issueStatuses,
|
|
245
|
+
issueMilestones,
|
|
246
|
+
issues,
|
|
247
|
+
issueComments,
|
|
248
|
+
issueRuns,
|
|
249
|
+
issueRelations,
|
|
250
|
+
issueFieldChanges,
|
|
251
|
+
issuePullRequests,
|
|
252
|
+
kanbanMeta
|
|
253
|
+
};
|
|
254
|
+
//#endregion
|
|
255
|
+
exports.boardSqliteSchema = boardSqliteSchema;
|
|
256
|
+
exports.issueComments = issueComments;
|
|
257
|
+
exports.issueFieldChanges = issueFieldChanges;
|
|
258
|
+
exports.issueMilestones = issueMilestones;
|
|
259
|
+
exports.issuePullRequests = issuePullRequests;
|
|
260
|
+
exports.issueRelations = issueRelations;
|
|
261
|
+
exports.issueRuns = issueRuns;
|
|
262
|
+
exports.issueStatuses = issueStatuses;
|
|
263
|
+
exports.issues = issues;
|
|
264
|
+
exports.kanbanMeta = kanbanMeta;
|
|
265
|
+
|
|
266
|
+
//# sourceMappingURL=schema.cjs.map
|