mirror of
https://gitlab.com/soapbox-pub/ditto.git
synced 2025-12-06 11:29:46 +00:00
Make @ditto/utils a separate package
This commit is contained in:
parent
b73e475326
commit
3ec9ea9c91
107 changed files with 170 additions and 149 deletions
|
|
@ -7,7 +7,8 @@
|
||||||
"./packages/ditto",
|
"./packages/ditto",
|
||||||
"./packages/metrics",
|
"./packages/metrics",
|
||||||
"./packages/ratelimiter",
|
"./packages/ratelimiter",
|
||||||
"./packages/translators"
|
"./packages/translators",
|
||||||
|
"./packages/utils"
|
||||||
],
|
],
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"start": "deno run -A --env-file --deny-read=.env packages/ditto/server.ts",
|
"start": "deno run -A --env-file --deny-read=.env packages/ditto/server.ts",
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,15 @@ import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { type EventsDB } from '@/storages/EventsDB.ts';
|
import { type EventsDB } from '@/storages/EventsDB.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { eventAge, Time } from '@/utils.ts';
|
import { eventAge, Time } from '@/utils.ts';
|
||||||
import { getAmount } from '@/utils/bolt11.ts';
|
import { getAmount } from '../utils/bolt11.ts';
|
||||||
import { resolveFavicon } from '@/utils/favicon.ts';
|
import { resolveFavicon } from '../utils/favicon.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../utils/log.ts';
|
||||||
import { resolveNip05 } from '@/utils/nip05.ts';
|
import { resolveNip05 } from '../utils/nip05.ts';
|
||||||
import { parseNoteContent, stripimeta } from '@/utils/note.ts';
|
import { parseNoteContent, stripimeta } from '../utils/note.ts';
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
import { purifyEvent } from '../utils/purify.ts';
|
||||||
import { updateStats } from '@/utils/stats.ts';
|
import { updateStats } from '../utils/stats.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../utils/tags.ts';
|
||||||
import { unfurlCardCached } from '@/utils/unfurl.ts';
|
import { unfurlCardCached } from '../utils/unfurl.ts';
|
||||||
import { renderWebPushNotification } from '@/views/mastodon/push.ts';
|
import { renderWebPushNotification } from '@/views/mastodon/push.ts';
|
||||||
import { PolicyWorker } from '@/workers/policy.ts';
|
import { PolicyWorker } from '@/workers/policy.ts';
|
||||||
import { verifyEventWorker } from '@/workers/verify.ts';
|
import { verifyEventWorker } from '@/workers/verify.ts';
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { ApplicationServer, PushMessageOptions, PushSubscriber, PushSubscription
|
||||||
import { type NStore } from '@nostrify/nostrify';
|
import { type NStore } from '@nostrify/nostrify';
|
||||||
import { logi } from '@soapbox/logi';
|
import { logi } from '@soapbox/logi';
|
||||||
|
|
||||||
import { getInstanceMetadata } from '@/utils/instance.ts';
|
import { getInstanceMetadata } from '../utils/instance.ts';
|
||||||
|
|
||||||
interface DittoPushOpts {
|
interface DittoPushOpts {
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ import { AdminStore } from '@/storages/AdminStore.ts';
|
||||||
import { EventsDB } from '@/storages/EventsDB.ts';
|
import { EventsDB } from '@/storages/EventsDB.ts';
|
||||||
import { InternalRelay } from '@/storages/InternalRelay.ts';
|
import { InternalRelay } from '@/storages/InternalRelay.ts';
|
||||||
import { NPool, NRelay1 } from '@nostrify/nostrify';
|
import { NPool, NRelay1 } from '@nostrify/nostrify';
|
||||||
import { getRelays } from '@/utils/outbox.ts';
|
import { getRelays } from '../utils/outbox.ts';
|
||||||
import { seedZapSplits } from '@/utils/zap-split.ts';
|
import { seedZapSplits } from '../utils/zap-split.ts';
|
||||||
|
|
||||||
export class DittoStorages {
|
export class DittoStorages {
|
||||||
private _db: Promise<EventsDB> | undefined;
|
private _db: Promise<EventsDB> | undefined;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { LRUCache } from 'lru-cache';
|
import { LRUCache } from 'lru-cache';
|
||||||
|
|
||||||
import { Time } from '@/utils/time.ts';
|
import { Time } from '../utils/time.ts';
|
||||||
|
|
||||||
export interface DittoUpload {
|
export interface DittoUpload {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ import { DittoStorages } from '@/DittoStorages.ts';
|
||||||
import { startFirehose } from '@/firehose.ts';
|
import { startFirehose } from '@/firehose.ts';
|
||||||
import { startNotify } from '@/notify.ts';
|
import { startNotify } from '@/notify.ts';
|
||||||
import { EventsDB } from '@/storages/EventsDB.ts';
|
import { EventsDB } from '@/storages/EventsDB.ts';
|
||||||
import { Time } from '@/utils/time.ts';
|
import { Time } from '../utils/time.ts';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
accountController,
|
accountController,
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,17 @@ import { z } from 'zod';
|
||||||
import { type AppController } from '@/app.ts';
|
import { type AppController } from '@/app.ts';
|
||||||
import { getAuthor, getFollowedPubkeys } from '@/queries.ts';
|
import { getAuthor, getFollowedPubkeys } from '@/queries.ts';
|
||||||
import { booleanParamSchema, fileSchema } from '@/schema.ts';
|
import { booleanParamSchema, fileSchema } from '@/schema.ts';
|
||||||
import { uploadFile } from '@/utils/upload.ts';
|
import { uploadFile } from '../../../utils/upload.ts';
|
||||||
import { nostrNow } from '@/utils.ts';
|
import { nostrNow } from '@/utils.ts';
|
||||||
import { assertAuthenticated, createEvent, paginated, parseBody, updateEvent, updateListEvent } from '@/utils/api.ts';
|
import {
|
||||||
import { extractIdentifier, lookupAccount, lookupPubkey } from '@/utils/lookup.ts';
|
assertAuthenticated,
|
||||||
|
createEvent,
|
||||||
|
paginated,
|
||||||
|
parseBody,
|
||||||
|
updateEvent,
|
||||||
|
updateListEvent,
|
||||||
|
} from '../../../utils/api.ts';
|
||||||
|
import { extractIdentifier, lookupAccount, lookupPubkey } from '../../../utils/lookup.ts';
|
||||||
import { renderAccounts, renderEventAccounts, renderStatuses } from '@/views.ts';
|
import { renderAccounts, renderEventAccounts, renderStatuses } from '@/views.ts';
|
||||||
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
||||||
import { renderRelationship } from '@/views/mastodon/relationships.ts';
|
import { renderRelationship } from '@/views/mastodon/relationships.ts';
|
||||||
|
|
@ -16,8 +23,8 @@ import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
import { metadataSchema } from '@/schemas/nostr.ts';
|
import { metadataSchema } from '@/schemas/nostr.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { bech32ToPubkey } from '@/utils.ts';
|
import { bech32ToPubkey } from '@/utils.ts';
|
||||||
import { addTag, deleteTag, findReplyTag, getTagSet } from '@/utils/tags.ts';
|
import { addTag, deleteTag, findReplyTag, getTagSet } from '../../../utils/tags.ts';
|
||||||
import { getPubkeysBySearch } from '@/utils/search.ts';
|
import { getPubkeysBySearch } from '../../../utils/search.ts';
|
||||||
|
|
||||||
const createAccountSchema = z.object({
|
const createAccountSchema = z.object({
|
||||||
username: z.string().min(1).max(30).regex(/^[a-z0-9_]+$/i),
|
username: z.string().min(1).max(30).regex(/^[a-z0-9_]+$/i),
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ import { z } from 'zod';
|
||||||
import { type AppController } from '@/app.ts';
|
import { type AppController } from '@/app.ts';
|
||||||
import { booleanParamSchema } from '@/schema.ts';
|
import { booleanParamSchema } from '@/schema.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { createAdminEvent, paginated, parseBody, updateEventInfo, updateUser } from '@/utils/api.ts';
|
import { createAdminEvent, paginated, parseBody, updateEventInfo, updateUser } from '../../../utils/api.ts';
|
||||||
import { renderNameRequest } from '@/views/ditto.ts';
|
import { renderNameRequest } from '@/views/ditto.ts';
|
||||||
import { AdminAccountView } from '@/views/mastodon/AdminAccountView.ts';
|
import { AdminAccountView } from '@/views/mastodon/AdminAccountView.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../../utils/log.ts';
|
||||||
|
|
||||||
const adminAccountQuerySchema = z.object({
|
const adminAccountQuerySchema = z.object({
|
||||||
local: booleanParamSchema.optional(),
|
local: booleanParamSchema.optional(),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import type { AppController } from '@/app.ts';
|
import type { AppController } from '@/app.ts';
|
||||||
import { parseBody } from '@/utils/api.ts';
|
import { parseBody } from '../../../utils/api.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apps are unnecessary cruft in Mastodon API, but necessary to make clients work.
|
* Apps are unnecessary cruft in Mastodon API, but necessary to make clients work.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { type AppController } from '@/app.ts';
|
import { type AppController } from '@/app.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../../utils/tags.ts';
|
||||||
import { renderStatuses } from '@/views.ts';
|
import { renderStatuses } from '@/views.ts';
|
||||||
|
|
||||||
/** https://docs.joinmastodon.org/methods/bookmarks/#get */
|
/** https://docs.joinmastodon.org/methods/bookmarks/#get */
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import TTLCache from '@isaacs/ttlcache';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { updateUser } from '@/utils/api.ts';
|
import { updateUser } from '../../../utils/api.ts';
|
||||||
|
|
||||||
interface Point {
|
interface Point {
|
||||||
x: number;
|
x: number;
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ import { bytesToString, stringToBytes } from '@scure/base';
|
||||||
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { createEvent, parseBody } from '@/utils/api.ts';
|
import { createEvent, parseBody } from '../../../utils/api.ts';
|
||||||
import { requireNip44Signer } from '@/middleware/requireSigner.ts';
|
import { requireNip44Signer } from '@/middleware/requireSigner.ts';
|
||||||
import { walletSchema } from '@/schema.ts';
|
import { walletSchema } from '@/schema.ts';
|
||||||
import { swapNutzapsMiddleware } from '@/middleware/swapNutzapsMiddleware.ts';
|
import { swapNutzapsMiddleware } from '@/middleware/swapNutzapsMiddleware.ts';
|
||||||
import { isNostrId } from '@/utils.ts';
|
import { isNostrId } from '@/utils.ts';
|
||||||
import { logi } from '@soapbox/logi';
|
import { logi } from '@soapbox/logi';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../../utils/log.ts';
|
||||||
|
|
||||||
type Wallet = z.infer<typeof walletSchema>;
|
type Wallet = z.infer<typeof walletSchema>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,18 @@ import { z } from 'zod';
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { getAuthor } from '@/queries.ts';
|
import { getAuthor } from '@/queries.ts';
|
||||||
import { addTag } from '@/utils/tags.ts';
|
import { addTag } from '../../../utils/tags.ts';
|
||||||
import { createEvent, paginated, parseBody, updateAdminEvent } from '@/utils/api.ts';
|
import { createEvent, paginated, parseBody, updateAdminEvent } from '../../../utils/api.ts';
|
||||||
import { getInstanceMetadata } from '@/utils/instance.ts';
|
import { getInstanceMetadata } from '../../../utils/instance.ts';
|
||||||
import { deleteTag } from '@/utils/tags.ts';
|
import { deleteTag } from '../../../utils/tags.ts';
|
||||||
import { DittoZapSplits, getZapSplits } from '@/utils/zap-split.ts';
|
import { DittoZapSplits, getZapSplits } from '../../../utils/zap-split.ts';
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { screenshotsSchema } from '@/schemas/nostr.ts';
|
import { screenshotsSchema } from '@/schemas/nostr.ts';
|
||||||
import { booleanParamSchema, percentageSchema, wsUrlSchema } from '@/schema.ts';
|
import { booleanParamSchema, percentageSchema, wsUrlSchema } from '@/schema.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { renderNameRequest } from '@/views/ditto.ts';
|
import { renderNameRequest } from '@/views/ditto.ts';
|
||||||
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
||||||
import { updateListAdminEvent } from '@/utils/api.ts';
|
import { updateListAdminEvent } from '../../../utils/api.ts';
|
||||||
|
|
||||||
const markerSchema = z.enum(['read', 'write']);
|
const markerSchema = z.enum(['read', 'write']);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import denoJson from 'deno.json' with { type: 'json' };
|
import denoJson from 'deno.json' with { type: 'json' };
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { getInstanceMetadata } from '@/utils/instance.ts';
|
import { getInstanceMetadata } from '../../../utils/instance.ts';
|
||||||
|
|
||||||
const version = `3.0.0 (compatible; Ditto ${denoJson.version})`;
|
const version = `3.0.0 (compatible; Ditto ${denoJson.version})`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { parseBody } from '@/utils/api.ts';
|
import { parseBody } from '../../../utils/api.ts';
|
||||||
|
|
||||||
const kv = await Deno.openKv();
|
const kv = await Deno.openKv();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import { z } from 'zod';
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { dittoUploads } from '@/DittoUploads.ts';
|
import { dittoUploads } from '@/DittoUploads.ts';
|
||||||
import { fileSchema } from '@/schema.ts';
|
import { fileSchema } from '@/schema.ts';
|
||||||
import { parseBody } from '@/utils/api.ts';
|
import { parseBody } from '../../../utils/api.ts';
|
||||||
import { renderAttachment } from '@/views/mastodon/attachments.ts';
|
import { renderAttachment } from '@/views/mastodon/attachments.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../../utils/log.ts';
|
||||||
import { uploadFile } from '@/utils/upload.ts';
|
import { uploadFile } from '../../../utils/upload.ts';
|
||||||
|
|
||||||
const mediaBodySchema = z.object({
|
const mediaBodySchema = z.object({
|
||||||
file: fileSchema,
|
file: fileSchema,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { type AppController } from '@/app.ts';
|
import { type AppController } from '@/app.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../../utils/tags.ts';
|
||||||
import { renderAccounts } from '@/views.ts';
|
import { renderAccounts } from '@/views.ts';
|
||||||
|
|
||||||
/** https://docs.joinmastodon.org/methods/mutes/#get */
|
/** https://docs.joinmastodon.org/methods/mutes/#get */
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { z } from 'zod';
|
||||||
import { AppContext, AppController } from '@/app.ts';
|
import { AppContext, AppController } from '@/app.ts';
|
||||||
import { DittoPagination } from '@/interfaces/DittoPagination.ts';
|
import { DittoPagination } from '@/interfaces/DittoPagination.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { paginated } from '@/utils/api.ts';
|
import { paginated } from '../../../utils/api.ts';
|
||||||
import { renderNotification } from '@/views/mastodon/notifications.ts';
|
import { renderNotification } from '@/views/mastodon/notifications.ts';
|
||||||
|
|
||||||
/** Set of known notification types across backends. */
|
/** Set of known notification types across backends. */
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import { z } from 'zod';
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { nostrNow } from '@/utils.ts';
|
import { nostrNow } from '@/utils.ts';
|
||||||
import { parseBody } from '@/utils/api.ts';
|
import { parseBody } from '../../../utils/api.ts';
|
||||||
import { aesEncrypt } from '@/utils/aes.ts';
|
import { aesEncrypt } from '../../../utils/aes.ts';
|
||||||
import { generateToken, getTokenHash } from '@/utils/auth.ts';
|
import { generateToken, getTokenHash } from '../../../utils/auth.ts';
|
||||||
import { Kysely } from 'kysely';
|
import { Kysely } from 'kysely';
|
||||||
|
|
||||||
const passwordGrantSchema = z.object({
|
const passwordGrantSchema = z.object({
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ import { z } from 'zod';
|
||||||
import { type AppController } from '@/app.ts';
|
import { type AppController } from '@/app.ts';
|
||||||
import { configSchema, elixirTupleSchema } from '@/schemas/pleroma-api.ts';
|
import { configSchema, elixirTupleSchema } from '@/schemas/pleroma-api.ts';
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { createAdminEvent, updateAdminEvent, updateUser } from '@/utils/api.ts';
|
import { createAdminEvent, updateAdminEvent, updateUser } from '../../../utils/api.ts';
|
||||||
import { lookupPubkey } from '@/utils/lookup.ts';
|
import { lookupPubkey } from '../../../utils/lookup.ts';
|
||||||
import { getPleromaConfigs } from '@/utils/pleroma.ts';
|
import { getPleromaConfigs } from '../../../utils/pleroma.ts';
|
||||||
|
|
||||||
const frontendConfigController: AppController = async (c) => {
|
const frontendConfigController: AppController = async (c) => {
|
||||||
const configDB = await getPleromaConfigs(c.var);
|
const configDB = await getPleromaConfigs(c.var);
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { nip19 } from 'nostr-tools';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { parseBody } from '@/utils/api.ts';
|
import { parseBody } from '../../../utils/api.ts';
|
||||||
import { getTokenHash } from '@/utils/auth.ts';
|
import { getTokenHash } from '../../../utils/auth.ts';
|
||||||
|
|
||||||
/** https://docs.joinmastodon.org/entities/WebPushSubscription/ */
|
/** https://docs.joinmastodon.org/entities/WebPushSubscription/ */
|
||||||
interface MastodonPushSubscription {
|
interface MastodonPushSubscription {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { createEvent } from '@/utils/api.ts';
|
import { createEvent } from '../../../utils/api.ts';
|
||||||
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { NostrFilter, NSchema as n } from '@nostrify/nostrify';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { type AppController } from '@/app.ts';
|
import { type AppController } from '@/app.ts';
|
||||||
import { createEvent, paginated, parseBody, updateEventInfo } from '@/utils/api.ts';
|
import { createEvent, paginated, parseBody, updateEventInfo } from '../../../utils/api.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { renderAdminReport } from '@/views/mastodon/reports.ts';
|
import { renderAdminReport } from '@/views/mastodon/reports.ts';
|
||||||
import { renderReport } from '@/views/mastodon/reports.ts';
|
import { renderReport } from '@/views/mastodon/reports.ts';
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@ import { z } from 'zod';
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { booleanParamSchema } from '@/schema.ts';
|
import { booleanParamSchema } from '@/schema.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { extractIdentifier, lookupPubkey } from '@/utils/lookup.ts';
|
import { extractIdentifier, lookupPubkey } from '../../../utils/lookup.ts';
|
||||||
import { resolveNip05 } from '@/utils/nip05.ts';
|
import { resolveNip05 } from '../../../utils/nip05.ts';
|
||||||
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
import { getFollowedPubkeys } from '@/queries.ts';
|
import { getFollowedPubkeys } from '@/queries.ts';
|
||||||
import { getPubkeysBySearch } from '@/utils/search.ts';
|
import { getPubkeysBySearch } from '../../../utils/search.ts';
|
||||||
import { paginated, paginatedList } from '@/utils/api.ts';
|
import { paginated, paginatedList } from '../../../utils/api.ts';
|
||||||
|
|
||||||
const searchQuerySchema = z.object({
|
const searchQuerySchema = z.object({
|
||||||
q: z.string().transform(decodeURIComponent),
|
q: z.string().transform(decodeURIComponent),
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,22 @@ import { type AppController } from '@/app.ts';
|
||||||
import { DittoUpload, dittoUploads } from '@/DittoUploads.ts';
|
import { DittoUpload, dittoUploads } from '@/DittoUploads.ts';
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts';
|
import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts';
|
||||||
import { addTag, deleteTag } from '@/utils/tags.ts';
|
import { addTag, deleteTag } from '../../../utils/tags.ts';
|
||||||
import { asyncReplaceAll } from '@/utils/text.ts';
|
import { asyncReplaceAll } from '../../../utils/text.ts';
|
||||||
import { lookupPubkey } from '@/utils/lookup.ts';
|
import { lookupPubkey } from '../../../utils/lookup.ts';
|
||||||
import { languageSchema } from '@/schema.ts';
|
import { languageSchema } from '@/schema.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { assertAuthenticated, createEvent, paginated, paginatedList, parseBody, updateListEvent } from '@/utils/api.ts';
|
import {
|
||||||
import { getInvoice, getLnurl } from '@/utils/lnurl.ts';
|
assertAuthenticated,
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
createEvent,
|
||||||
import { getZapSplits } from '@/utils/zap-split.ts';
|
paginated,
|
||||||
|
paginatedList,
|
||||||
|
parseBody,
|
||||||
|
updateListEvent,
|
||||||
|
} from '../../../utils/api.ts';
|
||||||
|
import { getInvoice, getLnurl } from '../../../utils/lnurl.ts';
|
||||||
|
import { purifyEvent } from '../../../utils/purify.ts';
|
||||||
|
import { getZapSplits } from '../../../utils/zap-split.ts';
|
||||||
import { renderEventAccounts } from '@/views.ts';
|
import { renderEventAccounts } from '@/views.ts';
|
||||||
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ import { MuteListPolicy } from '@/policies/MuteListPolicy.ts';
|
||||||
import { getFeedPubkeys } from '@/queries.ts';
|
import { getFeedPubkeys } from '@/queries.ts';
|
||||||
import { AdminStore } from '@/storages/AdminStore.ts';
|
import { AdminStore } from '@/storages/AdminStore.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { getTokenHash } from '@/utils/auth.ts';
|
import { getTokenHash } from '../../../utils/auth.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../../utils/log.ts';
|
||||||
import { bech32ToPubkey, Time } from '@/utils.ts';
|
import { bech32ToPubkey, Time } from '@/utils.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
import { NotificationView } from '@/views/mastodon/NotificationView.ts';
|
import { NotificationView } from '@/views/mastodon/NotificationView.ts';
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { matchFilter } from 'nostr-tools';
|
||||||
|
|
||||||
import { AppContext, AppController } from '@/app.ts';
|
import { AppContext, AppController } from '@/app.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { paginated, paginatedList } from '@/utils/api.ts';
|
import { paginated, paginatedList } from '../../../utils/api.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../../utils/tags.ts';
|
||||||
import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
|
import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
|
||||||
|
|
||||||
export const suggestionsV1Controller: AppController = async (c) => {
|
export const suggestionsV1Controller: AppController = async (c) => {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { translationCache } from '@/caches/translationCache.ts';
|
||||||
import { MastodonTranslation } from '@/entities/MastodonTranslation.ts';
|
import { MastodonTranslation } from '@/entities/MastodonTranslation.ts';
|
||||||
import { getEvent } from '@/queries.ts';
|
import { getEvent } from '@/queries.ts';
|
||||||
import { localeSchema } from '@/schema.ts';
|
import { localeSchema } from '@/schema.ts';
|
||||||
import { parseBody } from '@/utils/api.ts';
|
import { parseBody } from '../../../utils/api.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
|
|
||||||
const translateSchema = z.object({
|
const translateSchema = z.object({
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ import { AppController } from '@/app.ts';
|
||||||
import { PreviewCard } from '@/entities/PreviewCard.ts';
|
import { PreviewCard } from '@/entities/PreviewCard.ts';
|
||||||
import { paginationSchema } from '@/schemas/pagination.ts';
|
import { paginationSchema } from '@/schemas/pagination.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { generateDateRange, Time } from '@/utils/time.ts';
|
import { generateDateRange, Time } from '../../../utils/time.ts';
|
||||||
import { unfurlCardCached } from '@/utils/unfurl.ts';
|
import { unfurlCardCached } from '../../../utils/unfurl.ts';
|
||||||
import { paginated } from '@/utils/api.ts';
|
import { paginated } from '../../../utils/api.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../../utils/log.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
|
|
||||||
interface MastodonTrendingHashtag {
|
interface MastodonTrendingHashtag {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { ErrorHandler } from '@hono/hono';
|
||||||
import { HTTPException } from '@hono/hono/http-exception';
|
import { HTTPException } from '@hono/hono/http-exception';
|
||||||
import { logi } from '@soapbox/logi';
|
import { logi } from '@soapbox/logi';
|
||||||
|
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../utils/log.ts';
|
||||||
|
|
||||||
export const errorHandler: ErrorHandler = (err, c) => {
|
export const errorHandler: ErrorHandler = (err, c) => {
|
||||||
c.header('Cache-Control', 'no-store');
|
c.header('Cache-Control', 'no-store');
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import { logi } from '@soapbox/logi';
|
||||||
import { Kysely } from 'kysely';
|
import { Kysely } from 'kysely';
|
||||||
|
|
||||||
import { AppMiddleware } from '@/app.ts';
|
import { AppMiddleware } from '@/app.ts';
|
||||||
import { getPathParams, MetadataEntities } from '@/utils/og-metadata.ts';
|
import { getPathParams, MetadataEntities } from '../../utils/og-metadata.ts';
|
||||||
import { getInstanceMetadata } from '@/utils/instance.ts';
|
import { getInstanceMetadata } from '../../utils/instance.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../utils/log.ts';
|
||||||
import { lookupPubkey } from '@/utils/lookup.ts';
|
import { lookupPubkey } from '../../utils/lookup.ts';
|
||||||
import { renderMetadata } from '@/views/meta.ts';
|
import { renderMetadata } from '@/views/meta.ts';
|
||||||
import { getAuthor, getEvent } from '@/queries.ts';
|
import { getAuthor, getEvent } from '@/queries.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { WebManifestCombined } from '@/types/webmanifest.ts';
|
import { WebManifestCombined } from '@/types/webmanifest.ts';
|
||||||
import { getInstanceMetadata } from '@/utils/instance.ts';
|
import { getInstanceMetadata } from '../../utils/instance.ts';
|
||||||
|
|
||||||
export const manifestController: AppController = async (c) => {
|
export const manifestController: AppController = async (c) => {
|
||||||
const meta = await getInstanceMetadata(c.var);
|
const meta = await getInstanceMetadata(c.var);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import denoJson from 'deno.json' with { type: 'json' };
|
import denoJson from 'deno.json' with { type: 'json' };
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { getInstanceMetadata } from '@/utils/instance.ts';
|
import { getInstanceMetadata } from '../../../utils/instance.ts';
|
||||||
|
|
||||||
const relayInfoController: AppController = async (c) => {
|
const relayInfoController: AppController = async (c) => {
|
||||||
const { conf } = c.var;
|
const { conf } = c.var;
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,12 @@ import {
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { relayInfoController } from '@/controllers/nostr/relay-info.ts';
|
import { relayInfoController } from '@/controllers/nostr/relay-info.ts';
|
||||||
import { RelayError } from '@/RelayError.ts';
|
import { RelayError } from '@/RelayError.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../../utils/log.ts';
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
import { purifyEvent } from '../../../utils/purify.ts';
|
||||||
import { MemoryRateLimiter } from '@/utils/ratelimiter/MemoryRateLimiter.ts';
|
import { MemoryRateLimiter } from '../../../utils/ratelimiter/MemoryRateLimiter.ts';
|
||||||
import { MultiRateLimiter } from '@/utils/ratelimiter/MultiRateLimiter.ts';
|
import { MultiRateLimiter } from '../../../utils/ratelimiter/MultiRateLimiter.ts';
|
||||||
import { RateLimiter } from '@/utils/ratelimiter/types.ts';
|
import { RateLimiter } from '../../../utils/ratelimiter/types.ts';
|
||||||
import { Time } from '@/utils/time.ts';
|
import { Time } from '../../../utils/time.ts';
|
||||||
import { DittoPipeline } from '@/DittoPipeline.ts';
|
import { DittoPipeline } from '@/DittoPipeline.ts';
|
||||||
import { EventsDB } from '@/storages/EventsDB.ts';
|
import { EventsDB } from '@/storages/EventsDB.ts';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { NostrJson } from '@nostrify/nostrify';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
import { localNip05Lookup } from '@/utils/nip05.ts';
|
import { localNip05Lookup } from '../../../utils/nip05.ts';
|
||||||
|
|
||||||
const nameSchema = z.string().min(1).regex(/^[\w.-]+$/);
|
const nameSchema = z.string().min(1).regex(/^[\w.-]+$/);
|
||||||
const emptyResult: NostrJson = { names: {}, relays: {} };
|
const emptyResult: NostrJson = { names: {}, relays: {} };
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import { HTTPException } from '@hono/hono/http-exception';
|
||||||
import { NostrEvent } from '@nostrify/nostrify';
|
import { NostrEvent } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { type AppContext, type AppMiddleware } from '@/app.ts';
|
import { type AppContext, type AppMiddleware } from '@/app.ts';
|
||||||
import { localRequest } from '@/utils/api.ts';
|
import { localRequest } from '../../utils/api.ts';
|
||||||
import { buildAuthEventTemplate, type ParseAuthRequestOpts, validateAuthEvent } from '@/utils/nip98.ts';
|
import { buildAuthEventTemplate, type ParseAuthRequestOpts, validateAuthEvent } from '../../utils/nip98.ts';
|
||||||
|
|
||||||
type UserRole = 'user' | 'admin';
|
type UserRole = 'user' | 'admin';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { AppMiddleware } from '@/app.ts';
|
import { AppMiddleware } from '@/app.ts';
|
||||||
import { PleromaConfigDB } from '@/utils/PleromaConfigDB.ts';
|
import { PleromaConfigDB } from '../../utils/PleromaConfigDB.ts';
|
||||||
import { getPleromaConfigs } from '@/utils/pleroma.ts';
|
import { getPleromaConfigs } from '../../utils/pleroma.ts';
|
||||||
|
|
||||||
let configDBCache: Promise<PleromaConfigDB> | undefined;
|
let configDBCache: Promise<PleromaConfigDB> | undefined;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import { nip19 } from 'nostr-tools';
|
||||||
|
|
||||||
import { ConnectSigner } from '@/signers/ConnectSigner.ts';
|
import { ConnectSigner } from '@/signers/ConnectSigner.ts';
|
||||||
import { ReadOnlySigner } from '@/signers/ReadOnlySigner.ts';
|
import { ReadOnlySigner } from '@/signers/ReadOnlySigner.ts';
|
||||||
import { aesDecrypt } from '@/utils/aes.ts';
|
import { aesDecrypt } from '../../utils/aes.ts';
|
||||||
import { getTokenHash } from '@/utils/auth.ts';
|
import { getTokenHash } from '../../utils/auth.ts';
|
||||||
|
|
||||||
/** We only accept "Bearer" type. */
|
/** We only accept "Bearer" type. */
|
||||||
const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`);
|
const BEARER_REGEX = new RegExp(`^Bearer (${nip19.BECH32_REGEX.source})$`);
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import { stringToBytes } from '@scure/base';
|
||||||
import { logi } from '@soapbox/logi';
|
import { logi } from '@soapbox/logi';
|
||||||
|
|
||||||
import { isNostrId } from '@/utils.ts';
|
import { isNostrId } from '@/utils.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../../utils/log.ts';
|
||||||
import { createEvent } from '@/utils/api.ts';
|
import { createEvent } from '../../utils/api.ts';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { NostrEvent, NostrRelayOK, NPolicy, NStore } from '@nostrify/nostrify';
|
import { NostrEvent, NostrRelayOK, NPolicy, NStore } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../utils/tags.ts';
|
||||||
|
|
||||||
export class MuteListPolicy implements NPolicy {
|
export class MuteListPolicy implements NPolicy {
|
||||||
constructor(private pubkey: string, private store: NStore) {}
|
constructor(private pubkey: string, private store: NStore) {}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { Kysely } from 'kysely';
|
||||||
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { fallbackAuthor } from '@/utils.ts';
|
import { fallbackAuthor } from '@/utils.ts';
|
||||||
import { findReplyTag, getTagSet } from '@/utils/tags.ts';
|
import { findReplyTag, getTagSet } from '../utils/tags.ts';
|
||||||
|
|
||||||
interface GetEventOpts {
|
interface GetEventOpts {
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { DittoConf } from '@ditto/conf';
|
||||||
import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify';
|
import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../utils/tags.ts';
|
||||||
|
|
||||||
/** A store that prevents banned users from being displayed. */
|
/** A store that prevents banned users from being displayed. */
|
||||||
export class AdminStore implements NStore {
|
export class AdminStore implements NStore {
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@ import { z } from 'zod';
|
||||||
|
|
||||||
import { RelayError } from '@/RelayError.ts';
|
import { RelayError } from '@/RelayError.ts';
|
||||||
import { isNostrId } from '@/utils.ts';
|
import { isNostrId } from '@/utils.ts';
|
||||||
import { abortError } from '@/utils/abort.ts';
|
import { abortError } from '../../utils/abort.ts';
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
import { purifyEvent } from '../../utils/purify.ts';
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { detectLanguage } from '@/utils/language.ts';
|
import { detectLanguage } from '../../utils/language.ts';
|
||||||
import { getMediaLinks } from '@/utils/note.ts';
|
import { getMediaLinks } from '../../utils/note.ts';
|
||||||
|
|
||||||
/** Function to decide whether or not to index a tag. */
|
/** Function to decide whether or not to index a tag. */
|
||||||
type TagCondition = (opts: TagConditionOpts) => boolean;
|
type TagCondition = (opts: TagConditionOpts) => boolean;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import { matchFilter } from 'nostr-tools';
|
||||||
import { Gauge } from 'prom-client';
|
import { Gauge } from 'prom-client';
|
||||||
|
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
import { purifyEvent } from '../../utils/purify.ts';
|
||||||
|
|
||||||
interface InternalRelayOpts {
|
interface InternalRelayOpts {
|
||||||
gauge?: Gauge;
|
gauge?: Gauge;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify';
|
import { NostrEvent, NostrFilter, NStore } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../utils/tags.ts';
|
||||||
|
|
||||||
export class UserStore implements NStore {
|
export class UserStore implements NStore {
|
||||||
private promise: Promise<DittoEvent[]> | undefined;
|
private promise: Promise<DittoEvent[]> | undefined;
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import { z } from 'zod';
|
||||||
|
|
||||||
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { type DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { fallbackAuthor } from '@/utils.ts';
|
import { fallbackAuthor } from '@/utils.ts';
|
||||||
import { findQuoteTag } from '@/utils/tags.ts';
|
import { findQuoteTag } from '../../utils/tags.ts';
|
||||||
import { findQuoteInContent } from '@/utils/note.ts';
|
import { findQuoteInContent } from '../../utils/note.ts';
|
||||||
import { getAmount } from '@/utils/bolt11.ts';
|
import { getAmount } from '../../utils/bolt11.ts';
|
||||||
|
|
||||||
interface HydrateOpts {
|
interface HydrateOpts {
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { NostrEvent } from '@nostrify/nostrify';
|
||||||
import { finalizeEvent, generateSecretKey, nip19 } from 'nostr-tools';
|
import { finalizeEvent, generateSecretKey, nip19 } from 'nostr-tools';
|
||||||
|
|
||||||
import { EventsDB } from '@/storages/EventsDB.ts';
|
import { EventsDB } from '@/storages/EventsDB.ts';
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
import { purifyEvent } from '../utils/purify.ts';
|
||||||
import { sql } from 'kysely';
|
import { sql } from 'kysely';
|
||||||
|
|
||||||
/** Import an event fixture by name in tests. */
|
/** Import an event fixture by name in tests. */
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import { logi } from '@soapbox/logi';
|
||||||
import { Kysely, sql } from 'kysely';
|
import { Kysely, sql } from 'kysely';
|
||||||
|
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from '../utils/log.ts';
|
||||||
import { Time } from '@/utils/time.ts';
|
import { Time } from '../utils/time.ts';
|
||||||
|
|
||||||
interface DittoTrendsOpts {
|
interface DittoTrendsOpts {
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
|
|
|
||||||
|
|
@ -83,4 +83,4 @@ function fallbackAuthor(pubkey: string): NostrEvent {
|
||||||
|
|
||||||
export { bech32ToPubkey, eventAge, fallbackAuthor, findTag, isNostrId, type Nip05, nostrDate, nostrNow, parseNip05 };
|
export { bech32ToPubkey, eventAge, fallbackAuthor, findTag, isNostrId, type Nip05, nostrDate, nostrNow, parseNip05 };
|
||||||
|
|
||||||
export { Time } from '@/utils/time.ts';
|
export { Time } from '../utils/time.ts';
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { NostrEvent, NostrFilter } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { AppContext } from '@/app.ts';
|
import { AppContext } from '@/app.ts';
|
||||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { paginated, paginatedList } from '@/utils/api.ts';
|
import { paginated, paginatedList } from '../utils/api.ts';
|
||||||
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
import { AccountView } from '@/views/mastodon/AccountView.ts';
|
||||||
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
import { StatusView } from '@/views/mastodon/StatusView.ts';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../utils/tags.ts';
|
||||||
import { renderAdminAccount, renderAdminAccountFromPubkey } from '@/views/mastodon/admin-accounts.ts';
|
import { renderAdminAccount, renderAdminAccountFromPubkey } from '@/views/mastodon/admin-accounts.ts';
|
||||||
|
|
||||||
/** Renders an Admin::Account entity from a name request event. */
|
/** Renders an Admin::Account entity from a name request event. */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { MastodonAttachment } from '@/entities/MastodonAttachment.ts';
|
import { MastodonAttachment } from '@/entities/MastodonAttachment.ts';
|
||||||
import { getUrlMediaType } from '@/utils/media.ts';
|
import { getUrlMediaType } from '../../../utils/media.ts';
|
||||||
|
|
||||||
/** Render Mastodon media attachment. */
|
/** Render Mastodon media attachment. */
|
||||||
function renderAttachment(
|
function renderAttachment(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { NostrEvent } from '@nostrify/nostrify';
|
import { NostrEvent } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { hasTag } from '@/utils/tags.ts';
|
import { hasTag } from '../../../utils/tags.ts';
|
||||||
|
|
||||||
interface RenderRelationshipOpts {
|
interface RenderRelationshipOpts {
|
||||||
sourcePubkey: string;
|
sourcePubkey: string;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
|
||||||
import { nostrDate } from '@/utils.ts';
|
import { nostrDate } from '@/utils.ts';
|
||||||
import { renderAdminAccount, renderAdminAccountFromPubkey } from '@/views/mastodon/admin-accounts.ts';
|
import { renderAdminAccount, renderAdminAccountFromPubkey } from '@/views/mastodon/admin-accounts.ts';
|
||||||
import { renderStatus } from '@/views/mastodon/statuses.ts';
|
import { renderStatus } from '@/views/mastodon/statuses.ts';
|
||||||
import { getTagSet } from '@/utils/tags.ts';
|
import { getTagSet } from '../../../utils/tags.ts';
|
||||||
|
|
||||||
/** Expects a `reportEvent` of kind 1984 and a `profile` of kind 0 of the person being reported */
|
/** Expects a `reportEvent` of kind 1984 and a `profile` of kind 0 of the person being reported */
|
||||||
async function renderReport(event: DittoEvent) {
|
async function renderReport(event: DittoEvent) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { DittoConf } from '@ditto/conf';
|
import { DittoConf } from '@ditto/conf';
|
||||||
import DOMPurify from 'isomorphic-dompurify';
|
import DOMPurify from 'isomorphic-dompurify';
|
||||||
|
|
||||||
import { html } from '@/utils/html.ts';
|
import { html } from '../../utils/html.ts';
|
||||||
import { MetadataEntities } from '@/utils/og-metadata.ts';
|
import { MetadataEntities } from '../../utils/og-metadata.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a series of meta tags from supplied metadata for injection into the served HTML page.
|
* Builds a series of meta tags from supplied metadata for injection into the served HTML page.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { assertEquals } from '@std/assert';
|
||||||
import data from '~/fixtures/config-db.json' with { type: 'json' };
|
import data from '~/fixtures/config-db.json' with { type: 'json' };
|
||||||
|
|
||||||
import { PleromaConfig } from '@/schemas/pleroma-api.ts';
|
import { PleromaConfig } from '@/schemas/pleroma-api.ts';
|
||||||
import { PleromaConfigDB } from '@/utils/PleromaConfigDB.ts';
|
import { PleromaConfigDB } from './PleromaConfigDB.ts';
|
||||||
|
|
||||||
Deno.test('PleromaConfigDB.getIn', () => {
|
Deno.test('PleromaConfigDB.getIn', () => {
|
||||||
const configDB = new PleromaConfigDB(data.configs as PleromaConfig[]);
|
const configDB = new PleromaConfigDB(data.configs as PleromaConfig[]);
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { SimpleLRU } from '@/utils/SimpleLRU.ts';
|
import { SimpleLRU } from './SimpleLRU.ts';
|
||||||
import { assertEquals, assertRejects } from '@std/assert';
|
import { assertEquals, assertRejects } from '@std/assert';
|
||||||
|
|
||||||
Deno.test("SimpleLRU doesn't repeat failed calls", async () => {
|
Deno.test("SimpleLRU doesn't repeat failed calls", async () => {
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { generateSecretKey } from 'nostr-tools';
|
import { generateSecretKey } from 'nostr-tools';
|
||||||
|
|
||||||
import { aesDecrypt, aesEncrypt } from '@/utils/aes.ts';
|
import { aesDecrypt, aesEncrypt } from './aes.ts';
|
||||||
|
|
||||||
Deno.bench('aesEncrypt', async (b) => {
|
Deno.bench('aesEncrypt', async (b) => {
|
||||||
const sk = generateSecretKey();
|
const sk = generateSecretKey();
|
||||||
|
|
@ -2,7 +2,7 @@ import { assertEquals } from '@std/assert';
|
||||||
import { encodeHex } from '@std/encoding/hex';
|
import { encodeHex } from '@std/encoding/hex';
|
||||||
import { generateSecretKey } from 'nostr-tools';
|
import { generateSecretKey } from 'nostr-tools';
|
||||||
|
|
||||||
import { aesDecrypt, aesEncrypt } from '@/utils/aes.ts';
|
import { aesDecrypt, aesEncrypt } from './aes.ts';
|
||||||
|
|
||||||
Deno.test('aesDecrypt & aesEncrypt', async () => {
|
Deno.test('aesDecrypt & aesEncrypt', async () => {
|
||||||
const sk = generateSecretKey();
|
const sk = generateSecretKey();
|
||||||
|
|
@ -10,8 +10,8 @@ import { type AppContext } from '@/app.ts';
|
||||||
import { RelayError } from '@/RelayError.ts';
|
import { RelayError } from '@/RelayError.ts';
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { nostrNow } from '@/utils.ts';
|
import { nostrNow } from '@/utils.ts';
|
||||||
import { parseFormData } from '@/utils/formdata.ts';
|
import { parseFormData } from './formdata.ts';
|
||||||
import { purifyEvent } from '@/utils/purify.ts';
|
import { purifyEvent } from './purify.ts';
|
||||||
|
|
||||||
/** EventTemplate with defaults. */
|
/** EventTemplate with defaults. */
|
||||||
type EventStub = TypeFest.SetOptional<EventTemplate, 'content' | 'created_at' | 'tags'>;
|
type EventStub = TypeFest.SetOptional<EventTemplate, 'content' | 'created_at' | 'tags'>;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { generateToken, getTokenHash } from '@/utils/auth.ts';
|
import { generateToken, getTokenHash } from './auth.ts';
|
||||||
|
|
||||||
Deno.bench('generateToken', async () => {
|
Deno.bench('generateToken', async () => {
|
||||||
await generateToken();
|
await generateToken();
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { assertEquals } from '@std/assert';
|
import { assertEquals } from '@std/assert';
|
||||||
import { decodeHex, encodeHex } from '@std/encoding/hex';
|
import { decodeHex, encodeHex } from '@std/encoding/hex';
|
||||||
|
|
||||||
import { generateToken, getTokenHash } from '@/utils/auth.ts';
|
import { generateToken, getTokenHash } from './auth.ts';
|
||||||
|
|
||||||
Deno.test('generateToken', async () => {
|
Deno.test('generateToken', async () => {
|
||||||
const sk = decodeHex('a0968751df8fd42f362213f08751911672f2a037113b392403bbb7dd31b71c95');
|
const sk = decodeHex('a0968751df8fd42f362213f08751911672f2a037113b392403bbb7dd31b71c95');
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { assertEquals } from '@std/assert';
|
import { assertEquals } from '@std/assert';
|
||||||
import { getAmount } from '@/utils/bolt11.ts';
|
import { getAmount } from './bolt11.ts';
|
||||||
|
|
||||||
Deno.test('Invoice is invalid', () => {
|
Deno.test('Invoice is invalid', () => {
|
||||||
assertEquals(getAmount('hello'), undefined);
|
assertEquals(getAmount('hello'), undefined);
|
||||||
6
packages/utils/deno.json
Normal file
6
packages/utils/deno.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "@ditto/utils",
|
||||||
|
"exports": {
|
||||||
|
".": "./mod.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ import { Kysely } from 'kysely';
|
||||||
import tldts from 'tldts';
|
import tldts from 'tldts';
|
||||||
|
|
||||||
import { nostrNow } from '@/utils.ts';
|
import { nostrNow } from '@/utils.ts';
|
||||||
import { SimpleLRU } from '@/utils/SimpleLRU.ts';
|
import { SimpleLRU } from './SimpleLRU.ts';
|
||||||
|
|
||||||
let faviconCache: SimpleLRU<string, URL> | undefined;
|
let faviconCache: SimpleLRU<string, URL> | undefined;
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { assertEquals, assertThrows } from '@std/assert';
|
import { assertEquals, assertThrows } from '@std/assert';
|
||||||
|
|
||||||
import { parseFormData } from '@/utils/formdata.ts';
|
import { parseFormData } from './formdata.ts';
|
||||||
|
|
||||||
Deno.test('parseFormData', () => {
|
Deno.test('parseFormData', () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { detectLanguage } from '@/utils/language.ts';
|
import { detectLanguage } from './language.ts';
|
||||||
import { assertEquals } from '@std/assert';
|
import { assertEquals } from '@std/assert';
|
||||||
|
|
||||||
Deno.test('Detect English language', () => {
|
Deno.test('Detect English language', () => {
|
||||||
|
|
@ -5,9 +5,9 @@ import { logi } from '@soapbox/logi';
|
||||||
import { safeFetch } from '@soapbox/safe-fetch';
|
import { safeFetch } from '@soapbox/safe-fetch';
|
||||||
import { JsonValue } from '@std/json';
|
import { JsonValue } from '@std/json';
|
||||||
|
|
||||||
import { SimpleLRU } from '@/utils/SimpleLRU.ts';
|
import { SimpleLRU } from './SimpleLRU.ts';
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from './log.ts';
|
||||||
import { Time } from '@/utils/time.ts';
|
import { Time } from './time.ts';
|
||||||
|
|
||||||
const lnurlCache = new SimpleLRU<string, LNURLDetails>(
|
const lnurlCache = new SimpleLRU<string, LNURLDetails>(
|
||||||
async (lnurl, { signal }) => {
|
async (lnurl, { signal }) => {
|
||||||
|
|
@ -8,7 +8,7 @@ import tldts from 'tldts';
|
||||||
|
|
||||||
import { getAuthor } from '@/queries.ts';
|
import { getAuthor } from '@/queries.ts';
|
||||||
import { bech32ToPubkey } from '@/utils.ts';
|
import { bech32ToPubkey } from '@/utils.ts';
|
||||||
import { resolveNip05 } from '@/utils/nip05.ts';
|
import { resolveNip05 } from './nip05.ts';
|
||||||
|
|
||||||
interface LookupAccountOpts {
|
interface LookupAccountOpts {
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { assertEquals } from '@std/assert';
|
import { assertEquals } from '@std/assert';
|
||||||
|
|
||||||
import { getUrlMediaType, isPermittedMediaType } from '@/utils/media.ts';
|
import { getUrlMediaType, isPermittedMediaType } from './media.ts';
|
||||||
|
|
||||||
Deno.test('getUrlMediaType', () => {
|
Deno.test('getUrlMediaType', () => {
|
||||||
assertEquals(getUrlMediaType('https://example.com/image.png'), 'image/png');
|
assertEquals(getUrlMediaType('https://example.com/image.png'), 'image/png');
|
||||||
0
packages/utils/mod.ts
Normal file
0
packages/utils/mod.ts
Normal file
|
|
@ -5,9 +5,9 @@ import { safeFetch } from '@soapbox/safe-fetch';
|
||||||
import { nip19 } from 'nostr-tools';
|
import { nip19 } from 'nostr-tools';
|
||||||
import tldts from 'tldts';
|
import tldts from 'tldts';
|
||||||
|
|
||||||
import { errorJson } from '@/utils/log.ts';
|
import { errorJson } from './log.ts';
|
||||||
import { SimpleLRU } from '@/utils/SimpleLRU.ts';
|
import { SimpleLRU } from './SimpleLRU.ts';
|
||||||
import { DittoConf } from '../../conf/mod.ts';
|
import { DittoConf } from '../conf/mod.ts';
|
||||||
|
|
||||||
let nip05Cache: SimpleLRU<string, nip19.ProfilePointer> | undefined;
|
let nip05Cache: SimpleLRU<string, nip19.ProfilePointer> | undefined;
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { EventTemplate, nip13 } from 'nostr-tools';
|
||||||
import { decode64Schema } from '@/schema.ts';
|
import { decode64Schema } from '@/schema.ts';
|
||||||
import { signedEventSchema } from '@/schemas/nostr.ts';
|
import { signedEventSchema } from '@/schemas/nostr.ts';
|
||||||
import { eventAge, findTag, nostrNow } from '@/utils.ts';
|
import { eventAge, findTag, nostrNow } from '@/utils.ts';
|
||||||
import { Time } from '@/utils/time.ts';
|
import { Time } from './time.ts';
|
||||||
|
|
||||||
/** Decode a Nostr event from a base64 encoded string. */
|
/** Decode a Nostr event from a base64 encoded string. */
|
||||||
const decode64EventSchema = decode64Schema.pipe(n.json()).pipe(signedEventSchema);
|
const decode64EventSchema = decode64Schema.pipe(n.json()).pipe(signedEventSchema);
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { assertEquals } from '@std/assert';
|
import { assertEquals } from '@std/assert';
|
||||||
|
|
||||||
import { eventFixture, testConf } from '@/test.ts';
|
import { eventFixture, testConf } from '@/test.ts';
|
||||||
import { getMediaLinks, parseNoteContent, stripimeta } from '@/utils/note.ts';
|
import { getMediaLinks, parseNoteContent, stripimeta } from './note.ts';
|
||||||
|
|
||||||
Deno.test('parseNoteContent', () => {
|
Deno.test('parseNoteContent', () => {
|
||||||
const conf = testConf();
|
const conf = testConf();
|
||||||
|
|
@ -5,8 +5,8 @@ import linkify from 'linkifyjs';
|
||||||
import { nip19, nip27 } from 'nostr-tools';
|
import { nip19, nip27 } from 'nostr-tools';
|
||||||
|
|
||||||
import { MastodonMention } from '@/entities/MastodonMention.ts';
|
import { MastodonMention } from '@/entities/MastodonMention.ts';
|
||||||
import { html } from '@/utils/html.ts';
|
import { html } from './html.ts';
|
||||||
import { getUrlMediaType, isPermittedMediaType } from '@/utils/media.ts';
|
import { getUrlMediaType, isPermittedMediaType } from './media.ts';
|
||||||
|
|
||||||
linkify.registerCustomProtocol('nostr', true);
|
linkify.registerCustomProtocol('nostr', true);
|
||||||
linkify.registerCustomProtocol('wss');
|
linkify.registerCustomProtocol('wss');
|
||||||
|
|
@ -3,7 +3,7 @@ import { match } from 'path-to-regexp';
|
||||||
|
|
||||||
import { MastodonAccount } from '@/entities/MastodonAccount.ts';
|
import { MastodonAccount } from '@/entities/MastodonAccount.ts';
|
||||||
import { MastodonStatus } from '@/entities/MastodonStatus.ts';
|
import { MastodonStatus } from '@/entities/MastodonStatus.ts';
|
||||||
import { InstanceMetadata } from '@/utils/instance.ts';
|
import { InstanceMetadata } from './instance.ts';
|
||||||
|
|
||||||
export interface MetadataEntities {
|
export interface MetadataEntities {
|
||||||
status?: MastodonStatus;
|
status?: MastodonStatus;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { createTestDB, eventFixture } from '@/test.ts';
|
import { createTestDB, eventFixture } from '@/test.ts';
|
||||||
import { getRelays } from '@/utils/outbox.ts';
|
import { getRelays } from './outbox.ts';
|
||||||
import { assertEquals } from '@std/assert';
|
import { assertEquals } from '@std/assert';
|
||||||
|
|
||||||
Deno.test('Get write relays - kind 10002', async () => {
|
Deno.test('Get write relays - kind 10002', async () => {
|
||||||
|
|
@ -3,7 +3,7 @@ import { NSchema as n, NStore } from '@nostrify/nostrify';
|
||||||
|
|
||||||
import { configSchema } from '@/schemas/pleroma-api.ts';
|
import { configSchema } from '@/schemas/pleroma-api.ts';
|
||||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { PleromaConfigDB } from '@/utils/PleromaConfigDB.ts';
|
import { PleromaConfigDB } from './PleromaConfigDB.ts';
|
||||||
|
|
||||||
interface GetPleromaConfigOpts {
|
interface GetPleromaConfigOpts {
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
|
|
@ -2,7 +2,7 @@ import { assertEquals } from '@std/assert';
|
||||||
import { sql } from 'kysely';
|
import { sql } from 'kysely';
|
||||||
|
|
||||||
import { createTestDB } from '@/test.ts';
|
import { createTestDB } from '@/test.ts';
|
||||||
import { getPubkeysBySearch } from '@/utils/search.ts';
|
import { getPubkeysBySearch } from './search.ts';
|
||||||
|
|
||||||
Deno.test('fuzzy search works', async () => {
|
Deno.test('fuzzy search works', async () => {
|
||||||
await using db = await createTestDB();
|
await using db = await createTestDB();
|
||||||
|
|
@ -2,7 +2,7 @@ import { assertEquals } from '@std/assert';
|
||||||
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
import { generateSecretKey, getPublicKey } from 'nostr-tools';
|
||||||
|
|
||||||
import { createTestDB, genEvent } from '@/test.ts';
|
import { createTestDB, genEvent } from '@/test.ts';
|
||||||
import { countAuthorStats, getAuthorStats, getEventStats, getFollowDiff, updateStats } from '@/utils/stats.ts';
|
import { countAuthorStats, getAuthorStats, getEventStats, getFollowDiff, updateStats } from './stats.ts';
|
||||||
|
|
||||||
Deno.test('updateStats with kind 1 increments notes count', async () => {
|
Deno.test('updateStats with kind 1 increments notes count', async () => {
|
||||||
await using db = await createTestDB();
|
await using db = await createTestDB();
|
||||||
|
|
@ -5,7 +5,7 @@ import { Insertable, Kysely, UpdateObject } from 'kysely';
|
||||||
import { SetRequired } from 'type-fest';
|
import { SetRequired } from 'type-fest';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { findQuoteTag, findReplyTag, getTagSet } from '@/utils/tags.ts';
|
import { findQuoteTag, findReplyTag, getTagSet } from './tags.ts';
|
||||||
|
|
||||||
interface UpdateStatsOpts {
|
interface UpdateStatsOpts {
|
||||||
conf: DittoConf;
|
conf: DittoConf;
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue