@hollware/server 0.4.0 → 0.5.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/dist/{ceremonies-V_1BbmZQ.mjs → ceremonies-BM9G03lZ.mjs} +1 -1
- package/dist/index.d.mts +140 -2
- package/dist/index.mjs +867 -81
- package/dist/{store-CsuER6J7.mjs → store-DiS8UFI2.mjs} +42 -1
- package/migrations/0008_search.sql +47 -0
- package/migrations/0009_embeddings.sql +19 -0
- package/migrations/meta/0008_snapshot.json +2110 -0
- package/migrations/meta/0009_snapshot.json +2257 -0
- package/migrations/meta/_journal.json +14 -0
- package/package.json +2 -2
|
@@ -558,6 +558,47 @@ const reviews = sqliteTable("reviews", {
|
|
|
558
558
|
check("reviews_decided", sql`(${t.status} IN ('pending', 'cancelled')) OR (${t.decidedBy} IS NOT NULL AND ${t.decidedAt} IS NOT NULL)`),
|
|
559
559
|
check("reviews_json", sql`json_valid(${t.acknowledged}) AND json_type(${t.acknowledged}) = 'array' AND (${t.requestedMeta} IS NULL OR json_valid(${t.requestedMeta}))`)
|
|
560
560
|
]);
|
|
561
|
+
/**
|
|
562
|
+
* The vectors of an entry, as derived data (v0.5): the published revision they were made from,
|
|
563
|
+
* with which model and which version of the chunker, and how many pieces there are. The vectors
|
|
564
|
+
* live in Vectorize under `<entry id>:<piece>`; this row says which exist and whether they are
|
|
565
|
+
* current. One row per entry: a new publication replaces it.
|
|
566
|
+
*/
|
|
567
|
+
const entryEmbeddings = sqliteTable("entry_embeddings", {
|
|
568
|
+
id: id("emb"),
|
|
569
|
+
siteId: siteId(),
|
|
570
|
+
entryId: text("entry_id").notNull(),
|
|
571
|
+
revisionId: text("revision_id").notNull(),
|
|
572
|
+
model: text("model").notNull(),
|
|
573
|
+
chunkerVersion: text("chunker_version").notNull(),
|
|
574
|
+
/** How many pieces, so how many vectors: `<entry id>:0` to `<entry id>:<pieces - 1>`. */
|
|
575
|
+
pieces: integer("pieces").notNull(),
|
|
576
|
+
/**
|
|
577
|
+
* The entries closest to this one by their summaries, in its collection and locale, closest
|
|
578
|
+
* first, as JSON: `[{ "id": "ent_…", "score": 0.91 }]`. Found when its vectors were made.
|
|
579
|
+
*/
|
|
580
|
+
related: text("related").notNull().default("[]"),
|
|
581
|
+
...timestamps()
|
|
582
|
+
}, (t) => [
|
|
583
|
+
unique("entry_embeddings_id_site").on(t.id, t.siteId),
|
|
584
|
+
unique("entry_embeddings_entry").on(t.siteId, t.entryId),
|
|
585
|
+
foreignKey({
|
|
586
|
+
name: "entry_embeddings_site",
|
|
587
|
+
columns: [t.siteId],
|
|
588
|
+
foreignColumns: [sites.id]
|
|
589
|
+
}),
|
|
590
|
+
foreignKey({
|
|
591
|
+
name: "entry_embeddings_entry_fk",
|
|
592
|
+
columns: [t.entryId, t.siteId],
|
|
593
|
+
foreignColumns: [entries.id, entries.siteId]
|
|
594
|
+
}).onDelete("cascade"),
|
|
595
|
+
foreignKey({
|
|
596
|
+
name: "entry_embeddings_revision_fk",
|
|
597
|
+
columns: [t.revisionId, t.siteId],
|
|
598
|
+
foreignColumns: [revisions.id, revisions.siteId]
|
|
599
|
+
}),
|
|
600
|
+
check("entry_embeddings_pieces", sql`${t.pieces} >= 1`)
|
|
601
|
+
]);
|
|
561
602
|
//#endregion
|
|
562
603
|
//#region src/identity/secrets.ts
|
|
563
604
|
/**
|
|
@@ -757,4 +798,4 @@ async function invitationById(db, id) {
|
|
|
757
798
|
};
|
|
758
799
|
}
|
|
759
800
|
//#endregion
|
|
760
|
-
export {
|
|
801
|
+
export { ROLE_SCOPES as A, reviews as C, sites as D, schedules as E, isRole as M, tokens as O, publications as S, revisions as T, entries as _, findInvitation as a, members as b, invitationById as c, redeemInvitation as d, saveChallenge as f, deliveries as g, userHandle as h, createUser as i, effectiveScopes as j, users as k, membershipsOf as l, touchPasskey as m, createInvitation as n, findPasskey as o, takeChallenge as p, createSession as r, findSession as s, addPasskey as t, passkeysOf as u, entryEmbeddings as v, revisionTags as w, outbox as x, invitations as y };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- Written by hand (ADR-023), as drizzle-kit has no virtual tables. Full-text search (v0.5): an
|
|
2
|
+
-- FTS5 index of the published revision of each entry, its title, its tags and its text. The text
|
|
3
|
+
-- is taken from the stored Comark document, the strings at the text positions of its nodes, so
|
|
4
|
+
-- the Markdown's own marks are never indexed. `unicode61 remove_diacritics 2` matches
|
|
5
|
+
-- "migracion" with "migración".
|
|
6
|
+
--
|
|
7
|
+
-- The triggers keep it in the step that changes what is published, whichever write does it:
|
|
8
|
+
-- publish, a group, a schedule that comes due, unpublish. Only published content is in it.
|
|
9
|
+
CREATE VIRTUAL TABLE `entries_fts` USING fts5(
|
|
10
|
+
`title`,
|
|
11
|
+
`tags`,
|
|
12
|
+
`body`,
|
|
13
|
+
`entry_id` UNINDEXED,
|
|
14
|
+
`site_id` UNINDEXED,
|
|
15
|
+
`collection` UNINDEXED,
|
|
16
|
+
`locale` UNINDEXED,
|
|
17
|
+
tokenize = 'unicode61 remove_diacritics 2'
|
|
18
|
+
);
|
|
19
|
+
--> statement-breakpoint
|
|
20
|
+
CREATE TRIGGER `entries_fts_publication` AFTER UPDATE OF `published_rev` ON `entries`
|
|
21
|
+
BEGIN
|
|
22
|
+
DELETE FROM `entries_fts` WHERE `entry_id` = OLD.`id`;
|
|
23
|
+
INSERT INTO `entries_fts` (`title`, `tags`, `body`, `entry_id`, `site_id`, `collection`, `locale`)
|
|
24
|
+
SELECT
|
|
25
|
+
coalesce(json_extract(r.`frontmatter`, '$.title'), ''),
|
|
26
|
+
coalesce((SELECT group_concat(t.`tag`, ' ') FROM `revision_tags` t WHERE t.`revision_id` = r.`id`), ''),
|
|
27
|
+
coalesce((SELECT group_concat(n.`value`, ' ') FROM json_tree(r.`document`, '$.nodes') n
|
|
28
|
+
WHERE n.`type` = 'text' AND typeof(n.`key`) = 'integer' AND n.`key` >= 2), ''),
|
|
29
|
+
NEW.`id`, NEW.`site_id`, NEW.`collection`, NEW.`locale`
|
|
30
|
+
FROM `revisions` r
|
|
31
|
+
WHERE NEW.`published_rev` IS NOT NULL AND r.`id` = NEW.`published_rev`;
|
|
32
|
+
END;
|
|
33
|
+
--> statement-breakpoint
|
|
34
|
+
CREATE TRIGGER `entries_fts_removal` AFTER DELETE ON `entries`
|
|
35
|
+
BEGIN
|
|
36
|
+
DELETE FROM `entries_fts` WHERE `entry_id` = OLD.`id`;
|
|
37
|
+
END;
|
|
38
|
+
--> statement-breakpoint
|
|
39
|
+
-- What is published already.
|
|
40
|
+
INSERT INTO `entries_fts` (`title`, `tags`, `body`, `entry_id`, `site_id`, `collection`, `locale`)
|
|
41
|
+
SELECT
|
|
42
|
+
coalesce(json_extract(r.`frontmatter`, '$.title'), ''),
|
|
43
|
+
coalesce((SELECT group_concat(t.`tag`, ' ') FROM `revision_tags` t WHERE t.`revision_id` = r.`id`), ''),
|
|
44
|
+
coalesce((SELECT group_concat(n.`value`, ' ') FROM json_tree(r.`document`, '$.nodes') n
|
|
45
|
+
WHERE n.`type` = 'text' AND typeof(n.`key`) = 'integer' AND n.`key` >= 2), ''),
|
|
46
|
+
e.`id`, e.`site_id`, e.`collection`, e.`locale`
|
|
47
|
+
FROM `entries` e JOIN `revisions` r ON r.`id` = e.`published_rev`;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
CREATE TABLE `entry_embeddings` (
|
|
2
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
3
|
+
`site_id` text NOT NULL,
|
|
4
|
+
`entry_id` text NOT NULL,
|
|
5
|
+
`revision_id` text NOT NULL,
|
|
6
|
+
`model` text NOT NULL,
|
|
7
|
+
`chunker_version` text NOT NULL,
|
|
8
|
+
`pieces` integer NOT NULL,
|
|
9
|
+
`related` text DEFAULT '[]' NOT NULL,
|
|
10
|
+
`created_at` text NOT NULL,
|
|
11
|
+
`updated_at` text NOT NULL,
|
|
12
|
+
FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE no action,
|
|
13
|
+
FOREIGN KEY (`entry_id`,`site_id`) REFERENCES `entries`(`id`,`site_id`) ON UPDATE no action ON DELETE cascade,
|
|
14
|
+
FOREIGN KEY (`revision_id`,`site_id`) REFERENCES `revisions`(`id`,`site_id`) ON UPDATE no action ON DELETE no action,
|
|
15
|
+
CONSTRAINT "entry_embeddings_pieces" CHECK("entry_embeddings"."pieces" >= 1)
|
|
16
|
+
);
|
|
17
|
+
--> statement-breakpoint
|
|
18
|
+
CREATE UNIQUE INDEX `entry_embeddings_id_site` ON `entry_embeddings` (`id`,`site_id`);--> statement-breakpoint
|
|
19
|
+
CREATE UNIQUE INDEX `entry_embeddings_entry` ON `entry_embeddings` (`site_id`,`entry_id`);
|