@columenlabs/lumen-person 0.1.149 → 0.1.151
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/README.md +1 -0
- package/dist/move.d.ts +13 -2
- package/dist/move.js +5 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -81,6 +81,7 @@ An app that kept its own Durable Object moves into the person's store a page at
|
|
|
81
81
|
- The old store answers `exportRows(sql, table, after)`: rows after a rowid bookmark, at most 500 rows and about 4 MB a page (at least one row, so a big blob still moves), bytes as `{b64}`.
|
|
82
82
|
- The module's wake writes each page with `importRows(sql, table, page)` inside `ctx.transaction`, keeps the bookmark and asks to wake again. Rows keep their rowids, so a page sent twice changes nothing.
|
|
83
83
|
- When every table is across, `rowStats` on both sides (rows and highest rowid per table) must match before the app reads from the new store. Stop the old store's alarm and writes while it moves; a table whose stats differ goes again.
|
|
84
|
+
- An old store that held many people's rows in one table moves each person's part: `exportRows(sql, table, after, { where: { sql: 'scope = ?', args: [email] } })` and `rowStats(sql, tables, where)` with the same filter.
|
|
84
85
|
|
|
85
86
|
Point-in-time recovery (`ctx.storage.getBookmarkForTime`) restores the whole store, every module at once. Restore one module from its dump instead, and keep PITR for the whole store.
|
|
86
87
|
|
package/dist/move.d.ts
CHANGED
|
@@ -9,6 +9,15 @@ export type RowStats = Record<string, {
|
|
|
9
9
|
n: number;
|
|
10
10
|
max: number;
|
|
11
11
|
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Only some rows of the old store's tables: a condition and its bound values, for an old store that
|
|
14
|
+
* held many people's rows in one table (`{ sql: 'scope = ?', args: [email] }`). The condition is
|
|
15
|
+
* code, never a person's text; the values are bound.
|
|
16
|
+
*/
|
|
17
|
+
export interface RowFilter {
|
|
18
|
+
sql: string;
|
|
19
|
+
args: unknown[];
|
|
20
|
+
}
|
|
12
21
|
/**
|
|
13
22
|
* Rows of `table` after rowid `after`, in rowid order: at most `limit` rows and about `maxBytes`
|
|
14
23
|
* (at least one row a page, so a big blob still moves). Bytes come as `{b64}`, as in a dump.
|
|
@@ -16,6 +25,7 @@ export type RowStats = Record<string, {
|
|
|
16
25
|
export declare function exportRows(sql: SqlLike, table: string, after: number, opts?: {
|
|
17
26
|
limit?: number;
|
|
18
27
|
maxBytes?: number;
|
|
28
|
+
where?: RowFilter;
|
|
19
29
|
}): RowsPage;
|
|
20
30
|
/**
|
|
21
31
|
* Writes a page into `table`, naming only the columns the table has (the rest keep their
|
|
@@ -25,5 +35,6 @@ export declare function exportRows(sql: SqlLike, table: string, after: number, o
|
|
|
25
35
|
export declare function importRows(sql: SqlLike, table: string, page: DumpTable & {
|
|
26
36
|
ids?: number[];
|
|
27
37
|
}): number;
|
|
28
|
-
/** Row counts and highest rowids of `tables` (a missing table counts as empty)
|
|
29
|
-
|
|
38
|
+
/** Row counts and highest rowids of `tables` (a missing table counts as empty), of the rows
|
|
39
|
+
* `where` picks when given. */
|
|
40
|
+
export declare function rowStats(sql: SqlLike, tables: string[], where?: RowFilter): RowStats;
|
package/dist/move.js
CHANGED
|
@@ -22,7 +22,7 @@ export function exportRows(sql, table, after, opts = {}) {
|
|
|
22
22
|
if (!cols.length)
|
|
23
23
|
return { cols, rows: [], ids: [], next: null };
|
|
24
24
|
const found = sql
|
|
25
|
-
.exec(`SELECT rowid AS _rowid_, * FROM ${quote(table)} WHERE rowid > ? ORDER BY rowid LIMIT ?`, after, limit)
|
|
25
|
+
.exec(`SELECT rowid AS _rowid_, * FROM ${quote(table)} WHERE rowid > ?${opts.where ? ` AND (${opts.where.sql})` : ''} ORDER BY rowid LIMIT ?`, after, ...(opts.where?.args ?? []), limit)
|
|
26
26
|
.toArray();
|
|
27
27
|
const rows = [];
|
|
28
28
|
const ids = [];
|
|
@@ -59,13 +59,14 @@ export function importRows(sql, table, page) {
|
|
|
59
59
|
page.rows.forEach((row, k) => sql.exec(insert, ...(ids ? [ids[k]] : []), ...pick.map(([, i]) => fromJson(row[i]))));
|
|
60
60
|
return page.rows.length;
|
|
61
61
|
}
|
|
62
|
-
/** Row counts and highest rowids of `tables` (a missing table counts as empty)
|
|
63
|
-
|
|
62
|
+
/** Row counts and highest rowids of `tables` (a missing table counts as empty), of the rows
|
|
63
|
+
* `where` picks when given. */
|
|
64
|
+
export function rowStats(sql, tables, where) {
|
|
64
65
|
const out = {};
|
|
65
66
|
for (const t of tables) {
|
|
66
67
|
try {
|
|
67
68
|
const r = sql
|
|
68
|
-
.exec(`SELECT COUNT(*) AS n, MAX(rowid) AS max FROM ${quote(t)}`)
|
|
69
|
+
.exec(`SELECT COUNT(*) AS n, MAX(rowid) AS max FROM ${quote(t)}${where ? ` WHERE ${where.sql}` : ''}`, ...(where?.args ?? []))
|
|
69
70
|
.toArray()[0];
|
|
70
71
|
out[t] = { n: Number(r?.n ?? 0), max: Number(r?.max ?? 0) };
|
|
71
72
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-person",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.151",
|
|
4
4
|
"description": "Lumen's one store per person: a Durable Object whose SQLite holds every app's tables for that person, with migrations that fail per app, one alarm shared by every app, and backup, restore and delete per app or whole.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|