@takosjp/yurucommu-core 3.4.5 → 4.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takosjp/yurucommu-core",
3
- "version": "3.4.5",
3
+ "version": "4.0.0",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takosjp/yurucommu-api",
3
- "version": "3.4.5",
3
+ "version": "4.0.0",
4
4
  "description": "Typed client SDK and public API contract for yurucommu-server clients.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -24,7 +24,7 @@ import {
24
24
  storyVotes,
25
25
  } from "../../db/index.ts";
26
26
  import type { Database } from "../../db/index.ts";
27
- import type { IObjectStorage } from "../runtime/types.ts";
27
+ import type { ObjectStore } from "../runtime/types.ts";
28
28
  import { chunkForInClause, D1_IN_CHUNK } from "./chunk.ts";
29
29
  import { normalizeDomain } from "./blocklist.ts";
30
30
  import { isSameActivityPubActor } from "./activitypub-actor-identity.ts";
@@ -112,7 +112,7 @@ function activityPubUrlHostMatchesDomain(
112
112
  async function purgeObjects(
113
113
  db: Database,
114
114
  apIds: string[],
115
- media?: IObjectStorage,
115
+ media?: ObjectStore,
116
116
  ): Promise<void> {
117
117
  if (apIds.length === 0) return;
118
118
  const parentRows = await db
@@ -544,7 +544,7 @@ async function purgeActorInteractionEdges(
544
544
  async function purgeMatchingObjects(
545
545
  db: Database,
546
546
  where: SQL,
547
- media?: IObjectStorage,
547
+ media?: ObjectStore,
548
548
  onPageDeleted?: (count: number) => void,
549
549
  ): Promise<void> {
550
550
  let cursor: string | undefined;
@@ -604,7 +604,7 @@ async function purgeMatchingActivities(
604
604
  async function purgeActorObjects(
605
605
  db: Database,
606
606
  blockedApId: string,
607
- media?: IObjectStorage,
607
+ media?: ObjectStore,
608
608
  onPageDeleted?: (count: number) => void,
609
609
  ): Promise<void> {
610
610
  let cursor: string | undefined;
@@ -666,7 +666,7 @@ async function purgeActorActivities(
666
666
  export async function purgeActorContent(
667
667
  db: Database,
668
668
  blockedApId: string,
669
- media?: IObjectStorage,
669
+ media?: ObjectStore,
670
670
  ): Promise<BlocklistContentPurgeResult> {
671
671
  let deletedObjects = 0;
672
672
  let deletedActivities = 0;
@@ -704,7 +704,7 @@ export async function purgeActorContent(
704
704
  export async function purgeDomainContent(
705
705
  db: Database,
706
706
  domainOrUrl: string,
707
- media?: IObjectStorage,
707
+ media?: ObjectStore,
708
708
  ): Promise<BlocklistContentPurgeResult> {
709
709
  const domain = normalizeDomain(domainOrUrl);
710
710
  if (!domain) {
@@ -38,11 +38,16 @@ export {
38
38
  } from "./runtime/managed-relational.ts";
39
39
  export type {
40
40
  IKeyValueStore,
41
- IObjectStorage,
42
- ListObjectsResult,
43
- ObjectMetadata,
44
- StorageObject,
41
+ ObjectStore,
42
+ ObjectStoreBody,
43
+ ObjectStoreObject,
44
+ ObjectStorePutOptions,
45
45
  } from "./runtime/types.ts";
46
+ export {
47
+ createS3FetchObjectStore,
48
+ S3FetchObjectStoreError,
49
+ type S3ObjectFetcher,
50
+ } from "./runtime/s3-fetch.ts";
46
51
  export type {
47
52
  IQueueBatch,
48
53
  IQueueMessage,
@@ -47,7 +47,7 @@ import {
47
47
  } from "../../db/index.ts";
48
48
  import type { Database } from "../../db/index.ts";
49
49
  import type { Env } from "../types.ts";
50
- import type { IObjectStorage } from "../runtime/types.ts";
50
+ import type { ObjectStore } from "../runtime/types.ts";
51
51
  import { activityApId, generateId } from "../federation-helpers.ts";
52
52
  import { chunkForInClause } from "../lib/chunk.ts";
53
53
  import { snapshotAndEnqueueFollowerDeliveries } from "../lib/delivery/queue-batching.ts";
@@ -80,7 +80,7 @@ interface BatchableDb {
80
80
  */
81
81
  export async function purgeActorMediaUploads(
82
82
  db: Database,
83
- media: IObjectStorage | undefined,
83
+ media: ObjectStore | undefined,
84
84
  apId: string,
85
85
  ): Promise<void> {
86
86
  const uploads = await db
@@ -230,7 +230,7 @@ appsApiRoutes.post(
230
230
  }
231
231
  const r2Key = `${appPrefix}${normalizedPath}`;
232
232
  await media.put(r2Key, contentBytes, {
233
- httpMetadata: { contentType },
233
+ contentType,
234
234
  });
235
235
 
236
236
  results.push({ path: normalizedPath, status: "uploaded" });
@@ -276,14 +276,13 @@ appsServeRoutes.get("/:clientId/:appName/*", async (c) => {
276
276
 
277
277
  const object = await media.get(r2Key);
278
278
  if (object) {
279
- const contentType =
280
- object.httpMetadata?.contentType ?? inferContentType(filePath);
279
+ const contentType = object.contentType ?? inferContentType(filePath);
281
280
  const headers = createHostedHeaders(
282
281
  contentType,
283
282
  filePath.includes("/assets/")
284
283
  ? "public, max-age=31536000, immutable"
285
284
  : "public, max-age=3600",
286
- object.httpEtag,
285
+ object.etag,
287
286
  );
288
287
  return new Response(object.body, { headers });
289
288
  }
@@ -296,7 +295,7 @@ appsServeRoutes.get("/:clientId/:appName/*", async (c) => {
296
295
  const headers = createHostedHeaders(
297
296
  "text/html; charset=utf-8",
298
297
  "no-cache",
299
- indexObject.httpEtag,
298
+ indexObject.etag,
300
299
  );
301
300
  return new Response(indexObject.body, { headers });
302
301
  }
@@ -235,7 +235,7 @@ media.post("/upload", async (c) => {
235
235
  // memory budget.
236
236
  if (isVideo) {
237
237
  await media.put(r2Key, file, {
238
- httpMetadata: { contentType },
238
+ contentType,
239
239
  });
240
240
  } else {
241
241
  const original = new Uint8Array(await file.arrayBuffer());
@@ -247,7 +247,7 @@ media.post("/upload", async (c) => {
247
247
  cleaned.byteOffset + cleaned.byteLength,
248
248
  ) as ArrayBuffer;
249
249
  await media.put(r2Key, cleanedBuffer, {
250
- httpMetadata: { contentType },
250
+ contentType,
251
251
  });
252
252
  }
253
253
 
@@ -579,13 +579,12 @@ async function serveMediaByR2Key(c: MediaContext, r2Key: string) {
579
579
  const object = await media.get(r2Key);
580
580
  if (!object) return c.notFound();
581
581
 
582
- const contentType =
583
- object.httpMetadata?.contentType || "application/octet-stream";
582
+ const contentType = object.contentType || "application/octet-stream";
584
583
  const cacheScope = authResult.isPublic ? "public" : "private";
585
584
  const maxAge = contentType.startsWith("video/")
586
585
  ? CACHE_MAX_AGE_VIDEO
587
586
  : CACHE_MAX_AGE_IMAGE;
588
- const etag = object.httpEtag;
587
+ const etag = object.etag;
589
588
 
590
589
  if (!object.body) {
591
590
  return c.body(null, 200, {
@@ -21,7 +21,7 @@
21
21
 
22
22
  import { and, asc, eq, gt, inArray, isNull, or, sql } from "drizzle-orm";
23
23
  import type { D1Statement, Database } from "../../../db/index.ts";
24
- import type { IObjectStorage } from "../../runtime/types.ts";
24
+ import type { ObjectStore } from "../../runtime/types.ts";
25
25
  import {
26
26
  activities,
27
27
  actors,
@@ -80,7 +80,7 @@ async function deleteAttachedMediaUploadsForObject(
80
80
  db: Database,
81
81
  obj: CascadeObject,
82
82
  removedObjectApIds: ReadonlySet<string>,
83
- media?: IObjectStorage,
83
+ media?: ObjectStore,
84
84
  ): Promise<{
85
85
  mediaKeys: string[];
86
86
  mediaUploadIds: string[];
@@ -191,7 +191,7 @@ async function deleteAttachedMediaUploadsForObject(
191
191
  * system's already-accepted media failure mode.
192
192
  */
193
193
  export async function purgeMediaBlobs(
194
- media: IObjectStorage | undefined,
194
+ media: ObjectStore | undefined,
195
195
  keys: string[],
196
196
  ): Promise<void> {
197
197
  if (!media || keys.length === 0) return;
@@ -220,7 +220,7 @@ export async function reapReplacedMediaUrl(
220
220
  db: Database,
221
221
  oldUrl: string | null | undefined,
222
222
  uploaderApId: string,
223
- media?: IObjectStorage,
223
+ media?: ObjectStore,
224
224
  ): Promise<void> {
225
225
  try {
226
226
  if (!oldUrl || !oldUrl.startsWith("/media/")) return;
@@ -303,7 +303,7 @@ export async function reapReplacedMediaUrl(
303
303
  export async function deleteObjectCascade(
304
304
  db: Database,
305
305
  objectApId: string,
306
- media?: IObjectStorage,
306
+ media?: ObjectStore,
307
307
  ): Promise<string[]> {
308
308
  return await deleteObjectsCascade(db, [objectApId], media);
309
309
  }
@@ -316,7 +316,7 @@ export async function deleteObjectCascade(
316
316
  export async function prepareObjectDeleteCascade(
317
317
  db: Database,
318
318
  objectApId: string,
319
- media?: IObjectStorage,
319
+ media?: ObjectStore,
320
320
  ): Promise<{
321
321
  mediaKeys: string[];
322
322
  statements: readonly [D1Statement, ...D1Statement[]];
@@ -392,7 +392,7 @@ export async function prepareObjectDeleteCascade(
392
392
  export async function deleteObjectsCascade(
393
393
  db: Database,
394
394
  objectApIds: string[],
395
- media?: IObjectStorage,
395
+ media?: ObjectStore,
396
396
  ): Promise<string[]> {
397
397
  const uniqueApIds = [...new Set(objectApIds)];
398
398
  if (uniqueApIds.length === 0) return [];
@@ -8,7 +8,7 @@ import {
8
8
  objects,
9
9
  storyVotes,
10
10
  } from "../../../db/index.ts";
11
- import type { IObjectStorage } from "../../runtime/types.ts";
11
+ import type { ObjectStore } from "../../runtime/types.ts";
12
12
  import {
13
13
  formatUsername,
14
14
  objectApId,
@@ -314,7 +314,7 @@ export function buildAuthor(
314
314
 
315
315
  export async function cleanupExpiredStories(
316
316
  db: Database,
317
- media?: IObjectStorage,
317
+ media?: ObjectStore,
318
318
  ): Promise<number> {
319
319
  const now = new Date().toISOString();
320
320
 
@@ -18,7 +18,7 @@ import {
18
18
  purgeMediaBlobs,
19
19
  } from "../posts/delete-cascade.ts";
20
20
  import type { Env, Variables } from "../../types.ts";
21
- import type { IObjectStorage } from "../../runtime/types.ts";
21
+ import type { ObjectStore } from "../../runtime/types.ts";
22
22
  import {
23
23
  activityApId,
24
24
  actorApId,
@@ -61,10 +61,7 @@ const stories = new Hono<{ Bindings: Env; Variables: Variables }>();
61
61
  // at most one fallback pass runs at a time per isolate.
62
62
  let expiredStoryCleanupInFlight = false;
63
63
 
64
- function maybeCleanupExpiredStories(
65
- db: Database,
66
- media?: IObjectStorage,
67
- ): void {
64
+ function maybeCleanupExpiredStories(db: Database, media?: ObjectStore): void {
68
65
  if (expiredStoryCleanupInFlight) return;
69
66
  if (Math.random() >= 0.01) return; // ~1% of feed requests per isolate
70
67