@bitcobblers/wod-wiki-storage 0.44.2160 → 0.45.2166
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/{chunk-MOGQICXM.mjs → chunk-7ICLFFYU.mjs} +2 -2
- package/dist/chunk-7ICLFFYU.mjs.map +1 -0
- package/dist/{chunk-IMNG2HY5.mjs → chunk-J6KVDPTL.mjs} +3 -3
- package/dist/chunk-J6KVDPTL.mjs.map +1 -0
- package/dist/{chunk-JFVXIJJI.mjs → chunk-PJ7GRYOZ.mjs} +8 -8
- package/dist/chunk-PJ7GRYOZ.mjs.map +1 -0
- package/dist/{chunk-IFLOX2TK.mjs → chunk-UN56ET7P.mjs} +3 -3
- package/dist/{chunk-IFLOX2TK.mjs.map → chunk-UN56ET7P.mjs.map} +1 -1
- package/dist/idb/index.cjs +1 -1
- package/dist/idb/index.cjs.map +1 -1
- package/dist/idb/index.d.cts +3 -3
- package/dist/idb/index.d.ts +3 -3
- package/dist/idb/index.mjs +3 -3
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +5 -5
- package/dist/{policy-DRYF6Y8i.d.cts → policy-BBwCBMtp.d.cts} +3 -2
- package/dist/{policy-CPscN81J.d.ts → policy-C86TCPSM.d.ts} +3 -2
- package/dist/sql/index.cjs +60 -44
- package/dist/sql/index.cjs.map +1 -1
- package/dist/sql/index.d.cts +3 -3
- package/dist/sql/index.d.ts +3 -3
- package/dist/sql/index.mjs +64 -48
- package/dist/sql/index.mjs.map +1 -1
- package/dist/{sync-DG4Z-szj.d.cts → sync-BDu_Q__z.d.cts} +1 -1
- package/dist/{sync-Bjj_c1ea.d.ts → sync-BQ0g8ctt.d.ts} +1 -1
- package/dist/{wire-DGYxXt3I.d.ts → wire-BO8FM1LJ.d.cts} +17 -8
- package/dist/{wire-DGYxXt3I.d.cts → wire-BO8FM1LJ.d.ts} +17 -8
- package/package.json +6 -6
- package/dist/chunk-IMNG2HY5.mjs.map +0 -1
- package/dist/chunk-JFVXIJJI.mjs.map +0 -1
- package/dist/chunk-MOGQICXM.mjs.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Membership, Note, Session, BlockRevision } from '@bitcobblers/wod-wiki-core';
|
|
2
2
|
export { AnalyticsDataPoint, Attachment, BlockEffort, BlockEquipment, BlockIndexRow, BlockRevision, EventGrain, EventRecord, Membership, Note, NoteBlock, NoteBlockKind, NoteKind, NoteTag, Page, PageNote, ResultOrigin, Session, Tag, TagType, TagTypeRecord } from '@bitcobblers/wod-wiki-core';
|
|
3
|
-
import { S as StoreName, I as IStorage, e as StoreDef, a as IReadOnlyStore, b as StoreType, c as IReadWriteStore, D as DomainQuery, f as DomainQueryResult, d as IStorageTransaction } from './wire-
|
|
4
|
-
export { C as COLUMN_TYPES, g as DB_VERSION, h as DOMAIN_PROJECTION_VERSION, i as
|
|
5
|
-
export { a as USER_DELETED_SEED_PREFIX, U as UserScopeContext, c as collectUserScopeContext, i as isSeedMetaKey, b as isUserOwnedRow, u as userDeletedSeedKey, d as userDeletedSeedNoteId } from './policy-
|
|
3
|
+
import { S as StoreName, I as IStorage, e as StoreDef, a as IReadOnlyStore, b as StoreType, c as IReadWriteStore, D as DomainQuery, f as DomainQueryResult, d as IStorageTransaction } from './wire-BO8FM1LJ.cjs';
|
|
4
|
+
export { C as COLUMN_TYPES, g as DB_VERSION, h as DOMAIN_PROJECTION_VERSION, i as DomainDetail, j as DomainOrder, k as DomainPredicate, l as IndexDef, K as KeyDTO, R as RangeDTO, m as STORE_DEFS, n as Scalar, o as StorageColumnType, p as StorageSchema, T as TxOp, q as compareKeys, r as encodeKey, s as extractKeyPart, t as isRange, u as keyFromValue, v as keyInRange, w as parseDomainQueryResult, x as rangeFromIDB } from './wire-BO8FM1LJ.cjs';
|
|
5
|
+
export { a as USER_DELETED_SEED_PREFIX, U as UserScopeContext, c as collectUserScopeContext, i as isSeedMetaKey, b as isUserOwnedRow, u as userDeletedSeedKey, d as userDeletedSeedNoteId } from './policy-BBwCBMtp.cjs';
|
|
6
6
|
import '@bitcobblers/wod-wiki-lang';
|
|
7
7
|
|
|
8
8
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Membership, Note, Session, BlockRevision } from '@bitcobblers/wod-wiki-core';
|
|
2
2
|
export { AnalyticsDataPoint, Attachment, BlockEffort, BlockEquipment, BlockIndexRow, BlockRevision, EventGrain, EventRecord, Membership, Note, NoteBlock, NoteBlockKind, NoteKind, NoteTag, Page, PageNote, ResultOrigin, Session, Tag, TagType, TagTypeRecord } from '@bitcobblers/wod-wiki-core';
|
|
3
|
-
import { S as StoreName, I as IStorage, e as StoreDef, a as IReadOnlyStore, b as StoreType, c as IReadWriteStore, D as DomainQuery, f as DomainQueryResult, d as IStorageTransaction } from './wire-
|
|
4
|
-
export { C as COLUMN_TYPES, g as DB_VERSION, h as DOMAIN_PROJECTION_VERSION, i as
|
|
5
|
-
export { a as USER_DELETED_SEED_PREFIX, U as UserScopeContext, c as collectUserScopeContext, i as isSeedMetaKey, b as isUserOwnedRow, u as userDeletedSeedKey, d as userDeletedSeedNoteId } from './policy-
|
|
3
|
+
import { S as StoreName, I as IStorage, e as StoreDef, a as IReadOnlyStore, b as StoreType, c as IReadWriteStore, D as DomainQuery, f as DomainQueryResult, d as IStorageTransaction } from './wire-BO8FM1LJ.js';
|
|
4
|
+
export { C as COLUMN_TYPES, g as DB_VERSION, h as DOMAIN_PROJECTION_VERSION, i as DomainDetail, j as DomainOrder, k as DomainPredicate, l as IndexDef, K as KeyDTO, R as RangeDTO, m as STORE_DEFS, n as Scalar, o as StorageColumnType, p as StorageSchema, T as TxOp, q as compareKeys, r as encodeKey, s as extractKeyPart, t as isRange, u as keyFromValue, v as keyInRange, w as parseDomainQueryResult, x as rangeFromIDB } from './wire-BO8FM1LJ.js';
|
|
5
|
+
export { a as USER_DELETED_SEED_PREFIX, U as UserScopeContext, c as collectUserScopeContext, i as isSeedMetaKey, b as isUserOwnedRow, u as userDeletedSeedKey, d as userDeletedSeedNoteId } from './policy-C86TCPSM.js';
|
|
6
6
|
import '@bitcobblers/wod-wiki-lang';
|
|
7
7
|
|
|
8
8
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { USER_DELETED_SEED_PREFIX, collectUserScopeContext, isSeedMetaKey, isUserOwnedRow, userDeletedSeedKey, userDeletedSeedNoteId } from './chunk-
|
|
2
|
-
import { parseDomainQueryResult, bufferToOps, isDirty, bufferedGet, bufferSlot, overlayRows } from './chunk-
|
|
3
|
-
export { DOMAIN_PROJECTION_VERSION, parseDomainQueryResult } from './chunk-
|
|
4
|
-
import { STORE_DEFS, isRange, rangeFromIDB, keyFromValue, stampUserOwned, rowsEqual, encodeKey } from './chunk-
|
|
5
|
-
export { COLUMN_TYPES, DB_VERSION, DEFAULT_MEMBERSHIP_ID, STORE_DEFS, USER_OWNED_STORES, compareKeys, createDefaultMembership, encodeKey, extractKeyPart, isRange, keyFromValue, keyInRange, rangeFromIDB, rowsEqual, stampUserOwned, validateNoteWrite, validateSessionWrite, validateStorageRow, validateStoredPins } from './chunk-
|
|
1
|
+
export { USER_DELETED_SEED_PREFIX, collectUserScopeContext, isSeedMetaKey, isUserOwnedRow, userDeletedSeedKey, userDeletedSeedNoteId } from './chunk-7ICLFFYU.mjs';
|
|
2
|
+
import { parseDomainQueryResult, bufferToOps, isDirty, bufferedGet, bufferSlot, overlayRows } from './chunk-PJ7GRYOZ.mjs';
|
|
3
|
+
export { DOMAIN_PROJECTION_VERSION, parseDomainQueryResult } from './chunk-PJ7GRYOZ.mjs';
|
|
4
|
+
import { STORE_DEFS, isRange, rangeFromIDB, keyFromValue, stampUserOwned, rowsEqual, encodeKey } from './chunk-J6KVDPTL.mjs';
|
|
5
|
+
export { COLUMN_TYPES, DB_VERSION, DEFAULT_MEMBERSHIP_ID, STORE_DEFS, USER_OWNED_STORES, compareKeys, createDefaultMembership, encodeKey, extractKeyPart, isRange, keyFromValue, keyInRange, rangeFromIDB, rowsEqual, stampUserOwned, validateNoteWrite, validateSessionWrite, validateStorageRow, validateStoredPins } from './chunk-J6KVDPTL.mjs';
|
|
6
6
|
import './chunk-XRQKLSOT.mjs';
|
|
7
7
|
|
|
8
8
|
// src/api.ts
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { S as StoreName } from './wire-
|
|
1
|
+
import { S as StoreName } from './wire-BO8FM1LJ.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Shared user-scope sync policy (
|
|
4
|
+
* Shared user-scope sync policy (the backup/restore contract in
|
|
5
|
+
* docs/architecture/interfaces.md).
|
|
5
6
|
*
|
|
6
7
|
* ONE ownership classification governs outbox journals, bootstrap
|
|
7
8
|
* snapshots, the schema32 outbox cutover and cross-schema conversions. Rows
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { S as StoreName } from './wire-
|
|
1
|
+
import { S as StoreName } from './wire-BO8FM1LJ.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Shared user-scope sync policy (
|
|
4
|
+
* Shared user-scope sync policy (the backup/restore contract in
|
|
5
|
+
* docs/architecture/interfaces.md).
|
|
5
6
|
*
|
|
6
7
|
* ONE ownership classification governs outbox journals, bootstrap
|
|
7
8
|
* snapshots, the schema32 outbox cutover and cross-schema conversions. Rows
|
package/dist/sql/index.cjs
CHANGED
|
@@ -387,7 +387,7 @@ function validateStorageRow(store, value) {
|
|
|
387
387
|
const positive = (field) => typeof row[field] === "number" && Number.isSafeInteger(row[field]) && row[field] > 0;
|
|
388
388
|
const required = (field) => typeof row[field] === "string" && row[field].length > 0;
|
|
389
389
|
if (store === "notes") {
|
|
390
|
-
if (!required("id") || typeof row.title !== "string" || typeof row.rawContent !== "string" || !positive("sourceRevision") || typeof row.createdAt !== "number" || !Number.isFinite(row.createdAt) || "segments" in row || "segmentIds" in row || row.date !== void 0 && (typeof row.date !== "number" || !Number.isFinite(row.date)) || row.seedOrigin !== void 0 && row.seedOrigin !== "seed" && row.seedOrigin !== "user" || row.seedVersion !== void 0 && !(typeof row.seedVersion === "number" && Number.isSafeInteger(row.seedVersion) && row.seedVersion >= 0) || row.tags !== void 0 && (!Array.isArray(row.tags) || !row.tags.every((tag) => typeof tag === "string")) || ["type", "sourceId", "sourcePath", "
|
|
390
|
+
if (!required("id") || typeof row.title !== "string" || typeof row.rawContent !== "string" || !positive("sourceRevision") || typeof row.createdAt !== "number" || !Number.isFinite(row.createdAt) || "segments" in row || "segmentIds" in row || row.date !== void 0 && (typeof row.date !== "number" || !Number.isFinite(row.date)) || row.seedOrigin !== void 0 && row.seedOrigin !== "seed" && row.seedOrigin !== "user" || row.feedOrigin !== void 0 && row.feedOrigin !== "feed" && row.feedOrigin !== "user" || row.feedOrigin === "feed" && (row.seedOrigin === void 0 || typeof row.feedSourceId !== "string" || row.feedSourceId.length === 0) || row.feedOrigin === "user" && row.seedOrigin === "seed" || row.feedSourceId !== void 0 && row.feedOrigin !== "feed" || row.seedVersion !== void 0 && !(typeof row.seedVersion === "number" && Number.isSafeInteger(row.seedVersion) && row.seedVersion >= 0) || row.tags !== void 0 && (!Array.isArray(row.tags) || !row.tags.every((tag) => typeof tag === "string")) || ["type", "sourceId", "sourcePath", "notebookId", "seedChunkId", "feedSourceId"].some((field) => row[field] !== void 0 && typeof row[field] !== "string")) {
|
|
391
391
|
throw new StorageError(400, "invalid whole Note", "invalid_note_blocks");
|
|
392
392
|
}
|
|
393
393
|
try {
|
|
@@ -981,16 +981,21 @@ async function initializeStore(db) {
|
|
|
981
981
|
}
|
|
982
982
|
});
|
|
983
983
|
}
|
|
984
|
-
var DOMAIN_PROJECTION_VERSION =
|
|
984
|
+
var DOMAIN_PROJECTION_VERSION = 4;
|
|
985
985
|
var TABLES = ["domain_note", "query_block"];
|
|
986
986
|
var PROJECTION_GUARD_KEY = "domain_projection";
|
|
987
|
-
function
|
|
987
|
+
function sourceNote(row) {
|
|
988
988
|
const item = {};
|
|
989
|
-
for (const key of ["id", "noteId", "sourceId", "type", "seedOrigin", "seedChunkId", "
|
|
989
|
+
for (const key of ["id", "noteId", "sourceId", "type", "seedOrigin", "seedChunkId", "feedOrigin", "feedSourceId", "sourcePath", "notebookId"]) {
|
|
990
990
|
const value = row[key];
|
|
991
991
|
if (typeof value === "string") item[key] = value;
|
|
992
992
|
else if (value != null) throw new StorageError(400, `${key} must be a string`);
|
|
993
993
|
}
|
|
994
|
+
const tags = row["tags"];
|
|
995
|
+
if (tags !== void 0 && tags !== null) {
|
|
996
|
+
if (!Array.isArray(tags) || !tags.every((t) => typeof t === "string")) throw new StorageError(400, "tags must be a string array");
|
|
997
|
+
item.tags = tags;
|
|
998
|
+
}
|
|
994
999
|
return item;
|
|
995
1000
|
}
|
|
996
1001
|
var num = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
@@ -1001,11 +1006,11 @@ function ensureDdl(db) {
|
|
|
1001
1006
|
const n = db.dialect === "postgres" ? " DOUBLE PRECISION" : "";
|
|
1002
1007
|
const t = db.dialect === "postgres" ? ' TEXT COLLATE "C"' : " TEXT";
|
|
1003
1008
|
const ddl = [
|
|
1004
|
-
`CREATE TABLE IF NOT EXISTS "domain_note" ("note_id"${t} PRIMARY KEY NOT NULL, "note_type"${t}, "
|
|
1009
|
+
`CREATE TABLE IF NOT EXISTS "domain_note" ("note_id"${t} PRIMARY KEY NOT NULL, "note_type"${t}, "source_id"${t}, "source_path"${t}, "title"${t} NOT NULL, "title_search"${t} NOT NULL, "created_at"${n} NOT NULL, "date"${n}, "text_search"${t} NOT NULL, "journal"${n} NOT NULL, "payload"${t} NOT NULL)`,
|
|
1005
1010
|
`CREATE INDEX IF NOT EXISTS "idx_domain_note_date" ON "domain_note" ("date", "note_id")`,
|
|
1006
1011
|
`CREATE INDEX IF NOT EXISTS "idx_domain_note_created" ON "domain_note" ("created_at", "note_id")`,
|
|
1007
1012
|
`CREATE INDEX IF NOT EXISTS "idx_domain_note_source_path" ON "domain_note" ("source_path")`,
|
|
1008
|
-
`CREATE TABLE IF NOT EXISTS "query_block" ("occurrence_id"${t} PRIMARY KEY NOT NULL, "source_note_id"${t}, "parent_note_id"${t}, "content_id"${t}, "section_key"${t}, "ordinal"${n}, "data_type"${t}, "source_id"${t}, "source_path"${t}, "
|
|
1013
|
+
`CREATE TABLE IF NOT EXISTS "query_block" ("occurrence_id"${t} PRIMARY KEY NOT NULL, "source_note_id"${t}, "parent_note_id"${t}, "content_id"${t}, "section_key"${t}, "ordinal"${n} NOT NULL, "data_type"${t}, "source_id"${t}, "source_path"${t}, "effective_date"${n} NOT NULL, "created_at"${n} NOT NULL, "note_title"${t}, "normalized_text"${t} NOT NULL, "journal"${n} NOT NULL, "payload"${t} NOT NULL)`,
|
|
1009
1014
|
`CREATE INDEX IF NOT EXISTS "idx_query_block_type" ON "query_block" ("data_type", "effective_date", "occurrence_id")`,
|
|
1010
1015
|
`CREATE INDEX IF NOT EXISTS "idx_query_block_parent" ON "query_block" ("parent_note_id", "ordinal")`,
|
|
1011
1016
|
`CREATE INDEX IF NOT EXISTS "idx_query_block_content" ON "query_block" ("content_id")`,
|
|
@@ -1016,17 +1021,16 @@ function ensureDdl(db) {
|
|
|
1016
1021
|
for (const sql of ddl) await tx.exec(sql);
|
|
1017
1022
|
});
|
|
1018
1023
|
}
|
|
1019
|
-
var DOMAIN_NOTE_COLS = ["note_id", "note_type", "
|
|
1020
|
-
var QUERY_BLOCK_COLS = ["occurrence_id", "source_note_id", "parent_note_id", "content_id", "section_key", "ordinal", "data_type", "source_id", "source_path", "
|
|
1024
|
+
var DOMAIN_NOTE_COLS = ["note_id", "note_type", "source_id", "source_path", "title", "title_search", "created_at", "date", "text_search", "journal", "payload"];
|
|
1025
|
+
var QUERY_BLOCK_COLS = ["occurrence_id", "source_note_id", "parent_note_id", "content_id", "section_key", "ordinal", "data_type", "source_id", "source_path", "effective_date", "created_at", "note_title", "normalized_text", "journal", "payload"];
|
|
1021
1026
|
var conflictUpdate = (table, cols, keys) => `ON CONFLICT (${keys.map((k) => `"${k}"`).join(", ")}) DO UPDATE SET ` + cols.filter((c) => !keys.includes(c)).map((c) => `"${c}" = excluded."${c}"`).join(",") + ` WHERE ` + cols.filter((col) => !keys.includes(col)).map((col) => `"${table}"."${col}" IS DISTINCT FROM excluded."${col}"`).join(" OR ");
|
|
1022
1027
|
function domainNoteRow(note) {
|
|
1023
1028
|
const id = text(note.id);
|
|
1024
1029
|
if (!id) return void 0;
|
|
1025
|
-
const source =
|
|
1030
|
+
const source = sourceNote(note);
|
|
1026
1031
|
return [
|
|
1027
1032
|
id,
|
|
1028
1033
|
T(note.type),
|
|
1029
|
-
T(wodWikiWql.catalogOfItem(source)),
|
|
1030
1034
|
T(note.sourceId),
|
|
1031
1035
|
T(note.sourcePath),
|
|
1032
1036
|
T(note.title) ?? "",
|
|
@@ -1045,7 +1049,7 @@ async function upsertDomainNotes(conn, notes) {
|
|
|
1045
1049
|
function queryBlockRow(block, parent) {
|
|
1046
1050
|
const id = text(block.id);
|
|
1047
1051
|
if (!id) return void 0;
|
|
1048
|
-
const source =
|
|
1052
|
+
const source = sourceNote(block);
|
|
1049
1053
|
const createdAt = N(block.createdAt);
|
|
1050
1054
|
const effective = parent ? parent.date ?? parent.created_at : createdAt;
|
|
1051
1055
|
return [
|
|
@@ -1058,7 +1062,6 @@ function queryBlockRow(block, parent) {
|
|
|
1058
1062
|
T(block.dataType),
|
|
1059
1063
|
T(block.sourceId),
|
|
1060
1064
|
T(block.sourcePath),
|
|
1061
|
-
T(wodWikiWql.catalogOfItem(source)),
|
|
1062
1065
|
effective,
|
|
1063
1066
|
createdAt,
|
|
1064
1067
|
parent?.note.title ?? T(block.noteTitle),
|
|
@@ -1238,11 +1241,21 @@ async function rebuildProjections(conn) {
|
|
|
1238
1241
|
`CREATE TABLE IF NOT EXISTS "${SCHEMA_TABLE}" ("key" TEXT PRIMARY KEY, "value" TEXT NOT NULL)`
|
|
1239
1242
|
);
|
|
1240
1243
|
for (const t of TABLES) await conn.exec(`DELETE FROM "${t}"`);
|
|
1241
|
-
const notes = await conn.query(`SELECT "data" FROM "notes"`);
|
|
1242
|
-
const noteObjs = notes.map((row) => decodeRowJson(String(row.data)));
|
|
1244
|
+
const notes = await conn.query(`SELECT "k0", "data" FROM "notes"`);
|
|
1245
|
+
const noteObjs = notes.map((row) => wodWikiWql.migrateLegacyRow(decodeRowJson(String(row.data))));
|
|
1246
|
+
for (let i = 0; i < notes.length; i++) {
|
|
1247
|
+
if (wodWikiWql.hasLegacyIdentity(decodeRowJson(String(notes[i].data)))) {
|
|
1248
|
+
await conn.exec(`UPDATE "notes" SET "data" = ? WHERE "k0" = ?`, [encodeRowJson(noteObjs[i]), String(notes[i].k0)]);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1243
1251
|
await upsertDomainNotes(conn, noteObjs);
|
|
1244
|
-
const blocks = await conn.query(`SELECT "data" FROM "block_index"`);
|
|
1245
|
-
const blockObjs = blocks.map((row) => decodeRowJson(String(row.data)));
|
|
1252
|
+
const blocks = await conn.query(`SELECT "k0", "data" FROM "block_index"`);
|
|
1253
|
+
const blockObjs = blocks.map((row) => wodWikiWql.migrateLegacyRow(decodeRowJson(String(row.data))));
|
|
1254
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
1255
|
+
if (wodWikiWql.hasLegacyIdentity(decodeRowJson(String(blocks[i].data)))) {
|
|
1256
|
+
await conn.exec(`UPDATE "block_index" SET "data" = ? WHERE "k0" = ?`, [encodeRowJson(blockObjs[i]), String(blocks[i].k0)]);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1246
1259
|
const index = indexNoteIdentities(noteObjs);
|
|
1247
1260
|
await upsertQueryBlocks(conn, blockObjs.map((b) => [b, resolveParentFrom(index, b)]));
|
|
1248
1261
|
await conn.exec(
|
|
@@ -1344,7 +1357,7 @@ var MAX_CLAUSES = 32;
|
|
|
1344
1357
|
var MAX_VALUES = 64;
|
|
1345
1358
|
var MAX_VALUE_LEN = 256;
|
|
1346
1359
|
var MAX_ORDER = 4;
|
|
1347
|
-
var listFields = ["id", "noteId", "type", "
|
|
1360
|
+
var listFields = ["id", "noteId", "type", "source", "tags", "effort"];
|
|
1348
1361
|
var onlyKeys = (obj, allowed) => Object.keys(obj).every((k) => allowed.includes(k));
|
|
1349
1362
|
function bad(msg) {
|
|
1350
1363
|
return new StorageError(400, msg);
|
|
@@ -1376,6 +1389,15 @@ function parsePredicate(v, plan) {
|
|
|
1376
1389
|
}
|
|
1377
1390
|
return { field, values: strArray(obj.values, `predicate ${field}.values`), ...negate ? { negate } : {} };
|
|
1378
1391
|
}
|
|
1392
|
+
if (field === "typedTag") {
|
|
1393
|
+
if (!onlyKeys(obj, ["field", "tagType", "values", "negate"])) {
|
|
1394
|
+
throw bad("predicate typedTag accepts only field/tagType/values/negate");
|
|
1395
|
+
}
|
|
1396
|
+
if (typeof obj.tagType !== "string" || obj.tagType.length < 1 || obj.tagType.length > MAX_VALUE_LEN) {
|
|
1397
|
+
throw bad(`predicate typedTag.tagType must be 1..=${MAX_VALUE_LEN} chars`);
|
|
1398
|
+
}
|
|
1399
|
+
return { field: "typedTag", tagType: obj.tagType, values: strArray(obj.values, "predicate typedTag.values"), ...negate ? { negate } : {} };
|
|
1400
|
+
}
|
|
1379
1401
|
if (field === "text") {
|
|
1380
1402
|
if (!onlyKeys(obj, ["field", "value"]) || negate) throw bad("predicate text accepts only {field, value}");
|
|
1381
1403
|
if (typeof obj.value !== "string" || obj.value.length < 1 || obj.value.length > MAX_VALUE_LEN) {
|
|
@@ -1408,9 +1430,9 @@ function parsePredicate(v, plan) {
|
|
|
1408
1430
|
}
|
|
1409
1431
|
if (field === "defaultNotes") {
|
|
1410
1432
|
if (plan === "blocks") throw bad("predicate defaultNotes does not apply to the blocks plan");
|
|
1411
|
-
if (!onlyKeys(obj, ["field", "
|
|
1412
|
-
if (typeof obj.
|
|
1413
|
-
return { field: "defaultNotes",
|
|
1433
|
+
if (!onlyKeys(obj, ["field", "nonPages"])) throw bad("predicate defaultNotes accepts only {field, nonPages}");
|
|
1434
|
+
if (typeof obj.nonPages !== "boolean") throw bad("predicate defaultNotes.nonPages must be boolean");
|
|
1435
|
+
return { field: "defaultNotes", nonPages: obj.nonPages };
|
|
1414
1436
|
}
|
|
1415
1437
|
throw bad(`unknown predicate field: ${field}`);
|
|
1416
1438
|
}
|
|
@@ -1435,8 +1457,8 @@ function parseQuery(body) {
|
|
|
1435
1457
|
if (body === null || typeof body !== "object" || Array.isArray(body)) throw bad("body must be a DomainQuery object");
|
|
1436
1458
|
const obj = body;
|
|
1437
1459
|
const plan = obj.plan;
|
|
1438
|
-
if (plan !== "notes" && plan !== "blocks" && plan !== "
|
|
1439
|
-
throw bad("body.plan must be notes | blocks |
|
|
1460
|
+
if (plan !== "notes" && plan !== "blocks" && plan !== "detail") {
|
|
1461
|
+
throw bad("body.plan must be notes | blocks | detail");
|
|
1440
1462
|
}
|
|
1441
1463
|
for (const k of Object.keys(obj)) {
|
|
1442
1464
|
if (!["plan", "selection", "filters", "order", "offset", "limit"].includes(k)) {
|
|
@@ -1493,25 +1515,17 @@ var Sql = class {
|
|
|
1493
1515
|
return `${col} IN (${values.map((v) => this.bind(v)).join(", ")})`;
|
|
1494
1516
|
}
|
|
1495
1517
|
};
|
|
1496
|
-
var SOURCE_ALL_KINDS = ["journal",
|
|
1518
|
+
var SOURCE_ALL_KINDS = ["journal", ...wodWikiWql.WQL_SOURCE_VALUES.filter((k) => k !== "journal")];
|
|
1497
1519
|
function sourceKindSql(ctx, kind, sid, typeExpr, journalCol) {
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
case "pages":
|
|
1506
|
-
return `(${sid} = 'page' OR substr(${sid}, 1, 5) = 'page:' OR substr(${sid}, 1, 7) = 'guides:')`;
|
|
1507
|
-
case "guide":
|
|
1508
|
-
case "guides":
|
|
1509
|
-
return `(substr(${sid}, 1, 7) = 'guides:')`;
|
|
1510
|
-
case "playground":
|
|
1511
|
-
return typeExpr ? `(${sid} = 'playground' OR (${typeExpr} IS NOT NULL AND ${typeExpr} = 'playground'))` : `(${sid} = 'playground')`;
|
|
1512
|
-
default:
|
|
1513
|
-
return `(${sid} = ${ctx.bind(kind)})`;
|
|
1520
|
+
if (kind === "journal") return `(${journalCol} = 1)`;
|
|
1521
|
+
const shape = wodWikiWql.sourceShape(kind) ?? { exact: [kind] };
|
|
1522
|
+
const parts = [];
|
|
1523
|
+
for (const v of shape.exact ?? []) parts.push(`${sid} = ${ctx.bind(v)}`);
|
|
1524
|
+
for (const p of shape.prefixes ?? []) parts.push(`substr(${sid}, 1, ${p.length}) = ${ctx.bind(p)}`);
|
|
1525
|
+
if (shape.legacyType) {
|
|
1526
|
+
parts.push(typeExpr ? `${typeExpr} = ${ctx.bind(shape.legacyType)}` : "FALSE");
|
|
1514
1527
|
}
|
|
1528
|
+
return `(${parts.join(" OR ")})`;
|
|
1515
1529
|
}
|
|
1516
1530
|
function sourcePredicateSql(ctx, values, negate, sid, typeExpr, journalCol) {
|
|
1517
1531
|
const matched = values.map((v) => sourceKindSql(ctx, v, sid, typeExpr, journalCol)).join(" OR ");
|
|
@@ -1524,7 +1538,6 @@ function predicateSql(ctx, p, plan) {
|
|
|
1524
1538
|
const sid = blocks ? 'q."source_id"' : 'n."source_id"';
|
|
1525
1539
|
const typeExpr = blocks ? null : 'n."note_type"';
|
|
1526
1540
|
const typeCol = blocks ? 'q."data_type"' : 'n."note_type"';
|
|
1527
|
-
const catalogCol = blocks ? 'q."catalog"' : 'n."catalog"';
|
|
1528
1541
|
const journalCol = blocks ? 'q."journal"' : 'n."journal"';
|
|
1529
1542
|
const noteId = blocks ? 'q."source_note_id"' : 'n."note_id"';
|
|
1530
1543
|
switch (p.field) {
|
|
@@ -1534,8 +1547,6 @@ function predicateSql(ctx, p, plan) {
|
|
|
1534
1547
|
return wrap(p.negate === true, ctx.inList(noteId, p.values));
|
|
1535
1548
|
case "type":
|
|
1536
1549
|
return wrap(p.negate === true, ctx.inList(typeCol, p.values));
|
|
1537
|
-
case "catalog":
|
|
1538
|
-
return wrap(p.negate === true, ctx.inList(catalogCol, p.values));
|
|
1539
1550
|
case "source":
|
|
1540
1551
|
return sourcePredicateSql(ctx, p.values, p.negate === true, sid, typeExpr, journalCol);
|
|
1541
1552
|
case "tags":
|
|
@@ -1543,6 +1554,11 @@ function predicateSql(ctx, p, plan) {
|
|
|
1543
1554
|
p.negate === true,
|
|
1544
1555
|
`EXISTS (SELECT 1 FROM "note_tags" nt JOIN "tags" t ON t."k0" = nt."i_by_tag_0" WHERE nt."i_by_note_0" = ${noteId} AND t."i_by_label_0" IN (${p.values.map((v) => ctx.bind(v)).join(", ")}))`
|
|
1545
1556
|
);
|
|
1557
|
+
case "typedTag":
|
|
1558
|
+
return wrap(
|
|
1559
|
+
p.negate === true,
|
|
1560
|
+
`EXISTS (SELECT 1 FROM "note_tags" nt JOIN "tags" t ON t."k0" = nt."i_by_tag_0" WHERE nt."i_by_note_0" = ${noteId} AND t."i_by_type_0" = ${ctx.bind(p.tagType)} AND t."i_by_label_0" IN (${p.values.map((v) => ctx.bind(v)).join(", ")}))`
|
|
1561
|
+
);
|
|
1546
1562
|
case "effort":
|
|
1547
1563
|
return wrap(
|
|
1548
1564
|
p.negate === true,
|
|
@@ -1564,7 +1580,7 @@ function predicateSql(ctx, p, plan) {
|
|
|
1564
1580
|
return `(${sid} IS NULL OR ${sid} = '' OR ${all})`;
|
|
1565
1581
|
}
|
|
1566
1582
|
case "defaultNotes":
|
|
1567
|
-
return p.
|
|
1583
|
+
return p.nonPages ? `(n."note_type" IS NULL OR n."note_type" <> 'page')` : `(n."note_type" = 'note' OR (substr(COALESCE(n."source_id", ''), 1, 5) <> 'page:' AND substr(COALESCE(n."source_id", ''), 1, 7) <> 'guides:' AND COALESCE(n."note_type", '') NOT IN ('feed','syntax','behavior','analytics','dashboard','home','page')))`;
|
|
1568
1584
|
}
|
|
1569
1585
|
}
|
|
1570
1586
|
function clausesSql(ctx, clauses, plan) {
|
|
@@ -1615,7 +1631,7 @@ async function execute(conn, q, pg) {
|
|
|
1615
1631
|
const matchedCount = q.filters.length === 0 ? selectedCount : await count(fullWhere, allParams);
|
|
1616
1632
|
const ordering = orderSql(q.order, plan);
|
|
1617
1633
|
const paging = pagingSql(q, pg);
|
|
1618
|
-
if (plan !== "
|
|
1634
|
+
if (plan !== "detail") {
|
|
1619
1635
|
const pageSql2 = `SELECT "payload" FROM ${table}${fullWhere} ORDER BY ${ordering}${paging}`;
|
|
1620
1636
|
const rows2 = (await conn.query(pageSql2, allParams)).map((r) => decodeRowJson(String(r.payload)));
|
|
1621
1637
|
const result = { projectionVersion: DOMAIN_PROJECTION_VERSION, selectedCount, matchedCount, plan, rows: rows2 };
|