@hollware/server 1.0.0-rc.0 → 1.0.0-rc.2

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.
@@ -726,6 +726,40 @@ sqliteTable("audit_log", {
726
726
  check("audit_log_json", sql`(${t.actorMeta} IS NULL OR json_valid(${t.actorMeta})) AND (${t.detail} IS NULL OR json_valid(${t.detail}))`),
727
727
  check("audit_log_sizes", sql`length(${t.action}) <= 64 AND (${t.detail} IS NULL OR length(${t.detail}) <= 2000) AND (${t.actorMeta} IS NULL OR length(${t.actorMeta}) <= 2000)`)
728
728
  ]);
729
+ sqliteTable("assets", {
730
+ id: id("ast"),
731
+ siteId: siteId(),
732
+ sha256: text("sha256").notNull(),
733
+ /** The media type of the file served: the converted one, or the original kept as it came. */
734
+ format: text("format").notNull(),
735
+ /** In pixels; `null` for an SVG, which has no fixed size. */
736
+ width: integer("width"),
737
+ height: integer("height"),
738
+ bytes: integer("bytes").notNull(),
739
+ originalFormat: text("original_format").notNull(),
740
+ originalBytes: integer("original_bytes").notNull(),
741
+ alt: text("alt").notNull(),
742
+ filename: text("filename").notNull(),
743
+ /** The person whose token or session uploaded it. */
744
+ createdBy: text("created_by").notNull(),
745
+ ...timestamps()
746
+ }, (t) => [
747
+ unique("assets_id_site").on(t.id, t.siteId),
748
+ unique("assets_sha256").on(t.siteId, t.sha256),
749
+ index("assets_site_time").on(t.siteId, t.createdAt, t.id),
750
+ foreignKey({
751
+ name: "assets_site",
752
+ columns: [t.siteId],
753
+ foreignColumns: [sites.id]
754
+ }),
755
+ foreignKey({
756
+ name: "assets_creator",
757
+ columns: [t.createdBy],
758
+ foreignColumns: [users.id]
759
+ }),
760
+ check("assets_formats", sql`${t.format} IN ('image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/gif', 'image/svg+xml') AND ${t.originalFormat} IN ('image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/gif', 'image/svg+xml')`),
761
+ check("assets_sizes", sql`${t.bytes} > 0 AND ${t.originalBytes} BETWEEN 1 AND 10485760 AND length(${t.alt}) BETWEEN 1 AND 500 AND length(${t.filename}) BETWEEN 1 AND 200 AND length(${t.sha256}) = 64`)
762
+ ]);
729
763
  //#endregion
730
764
  //#region src/identity/secrets.ts
731
765
  /**
@@ -0,0 +1,42 @@
1
+ -- Generated by drizzle-kit, then edited by hand (ADR-023): the triggers at the end are not in the
2
+ -- schema, since drizzle-kit does not model them; append-only.workerd.test.ts lists them after
3
+ -- every migration.
4
+ --
5
+ -- The images of a site (ADR-038). An asset is never deleted, since a revision may name it, and
6
+ -- nothing of it changes but its alt: its id is the hash of its bytes, and R2 holds those bytes.
7
+ CREATE TABLE `assets` (
8
+ `id` text PRIMARY KEY NOT NULL,
9
+ `site_id` text NOT NULL,
10
+ `sha256` text NOT NULL,
11
+ `format` text NOT NULL,
12
+ `width` integer,
13
+ `height` integer,
14
+ `bytes` integer NOT NULL,
15
+ `original_format` text NOT NULL,
16
+ `original_bytes` integer NOT NULL,
17
+ `alt` text NOT NULL,
18
+ `filename` text NOT NULL,
19
+ `created_by` text NOT NULL,
20
+ `created_at` text NOT NULL,
21
+ `updated_at` text NOT NULL,
22
+ FOREIGN KEY (`site_id`) REFERENCES `sites`(`id`) ON UPDATE no action ON DELETE no action,
23
+ FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action,
24
+ CONSTRAINT "assets_formats" CHECK("assets"."format" IN ('image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/gif', 'image/svg+xml') AND "assets"."original_format" IN ('image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/gif', 'image/svg+xml')),
25
+ CONSTRAINT "assets_sizes" CHECK("assets"."bytes" > 0 AND "assets"."original_bytes" BETWEEN 1 AND 10485760 AND length("assets"."alt") BETWEEN 1 AND 500 AND length("assets"."filename") BETWEEN 1 AND 200 AND length("assets"."sha256") = 64)
26
+ );
27
+ --> statement-breakpoint
28
+ CREATE INDEX `assets_site_time` ON `assets` (`site_id`,`created_at`,`id`);--> statement-breakpoint
29
+ CREATE UNIQUE INDEX `assets_id_site` ON `assets` (`id`,`site_id`);--> statement-breakpoint
30
+ CREATE UNIQUE INDEX `assets_sha256` ON `assets` (`site_id`,`sha256`);
31
+ --> statement-breakpoint
32
+ CREATE TRIGGER `assets_no_delete`
33
+ BEFORE DELETE ON `assets`
34
+ BEGIN
35
+ SELECT RAISE(ABORT, 'append-only: an asset is never deleted, since a revision may name it');
36
+ END;
37
+ --> statement-breakpoint
38
+ CREATE TRIGGER `assets_immutable`
39
+ BEFORE UPDATE OF `id`, `site_id`, `sha256`, `format`, `width`, `height`, `bytes`, `original_format`, `original_bytes`, `filename`, `created_by`, `created_at` ON `assets`
40
+ BEGIN
41
+ SELECT RAISE(ABORT, 'append-only: only the alt of an asset changes');
42
+ END;