@fedify/fedify 2.3.0 → 2.4.0-dev.1422
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/{assert-OguE97r2.mjs → assert-DikXweDx.mjs} +1 -1
- package/dist/{assert_instance_of-DBC5X09g.mjs → assert_instance_of-C4Ri6VuN.mjs} +1 -1
- package/dist/{assert_not_equals-DkVK8oqV.mjs → assert_not_equals--wG9hV7u.mjs} +1 -1
- package/dist/{assert_rejects-DN60FHPX.mjs → assert_rejects-DQP-q39h.mjs} +2 -2
- package/dist/{assert_strict_equals-XEgZAlrj.mjs → assert_strict_equals-Dmjbg-bA.mjs} +1 -1
- package/dist/{assert_throws-BOkhLGYc.mjs → assert_throws-4NwKEy2q.mjs} +1 -1
- package/dist/{builder-DYXTKqvC.mjs → builder-Gef_ZeDE.mjs} +23 -3
- package/dist/codec-Bf-rTqks.mjs +94 -0
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/outgoing-jsonld.test.mjs +3 -3
- package/dist/compat/public-audience.test.mjs +3 -3
- package/dist/compat/transformers.test.mjs +5 -5
- package/dist/{context-DVoTs_wM.mjs → context-BrIOaBSs.mjs} +7 -1
- package/dist/{context-BBVLF7lx.d.cts → context-BuGH_Vft.d.cts} +286 -70
- package/dist/{context-BU6jSQdo.d.ts → context-CLtZxCu6.d.ts} +285 -70
- package/dist/{deno-ChfuM30K.mjs → deno-BmD7XRaO.mjs} +1 -1
- package/dist/{docloader-Bu-Oecom.mjs → docloader-B8AJowCx.mjs} +2 -2
- package/dist/federation/builder.test.mjs +5 -5
- package/dist/federation/circuit-breaker.test.mjs +5 -5
- package/dist/federation/collection.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +13 -13
- package/dist/federation/idempotency.test.mjs +6 -6
- package/dist/federation/inbox.test.mjs +3 -3
- package/dist/federation/keycache.test.mjs +5 -5
- package/dist/federation/kv.test.mjs +3 -3
- package/dist/federation/metrics.test.mjs +4 -4
- package/dist/federation/middleware.test.mjs +200 -19
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +3 -3
- package/dist/federation/mod.d.ts +3 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +5 -260
- package/dist/federation/negotiation.test.mjs +4 -4
- package/dist/federation/retry.test.mjs +3 -3
- package/dist/federation/router.test.mjs +5 -5
- package/dist/federation/send.test.mjs +10 -10
- package/dist/federation/tasks/codec.test.d.mts +2 -0
- package/dist/federation/tasks/codec.test.mjs +292 -0
- package/dist/federation/tasks/tasks.test.d.mts +2 -0
- package/dist/federation/tasks/tasks.test.mjs +651 -0
- package/dist/federation/temporal.test.mjs +4 -4
- package/dist/federation/webfinger.test.mjs +6 -6
- package/dist/{http-Q2nW0DHO.cjs → http-BCSQJ_gv.cjs} +1 -1
- package/dist/{http-CiPBp7Ax.js → http-CJ0WNyqA.js} +1 -1
- package/dist/{http-Cm_e9dY7.mjs → http-GQoPA_YT.mjs} +4 -4
- package/dist/{key-nrqRBwjx.mjs → key-BLy_TeTg.mjs} +2 -2
- package/dist/{kv-cache-BQLjC1KN.js → kv-cache-CjEcb9qH.js} +1 -1
- package/dist/{kv-cache-QkLiue07.cjs → kv-cache-DXwu7BtY.cjs} +1 -1
- package/dist/{kv-cache-B3Na5DMI.mjs → kv-cache-pw-kBdVz.mjs} +1 -1
- package/dist/{ld-CaRoGhYH.mjs → ld-CWgxPlZq.mjs} +3 -3
- package/dist/{metrics-BSUZSyQU.mjs → metrics-DUKoLd_E.mjs} +1 -1
- package/dist/{middleware-BIj0BBxb.js → middleware-2Us0G3Iy.js} +277 -10
- package/dist/{middleware-DXLo-UOS.cjs → middleware-BiCk4wGY.cjs} +277 -10
- package/dist/{middleware-BIctkZ9S.mjs → middleware-Dq-HhJHd.mjs} +1 -1
- package/dist/{middleware-CwJv5KxX.mjs → middleware-PZaroDUk.mjs} +182 -23
- package/dist/{mod-C0F6kvgS.d.cts → mod-DRokcHeU.d.cts} +1 -1
- package/dist/{mod-vPYVoa5n.d.ts → mod-r-1xOW_C.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +4 -4
- package/dist/mod.d.ts +4 -4
- package/dist/mod.js +4 -4
- package/dist/mq-CvJAzRz5.mjs +260 -0
- package/dist/nodeinfo/client.test.mjs +3 -3
- package/dist/nodeinfo/handler.test.mjs +5 -5
- package/dist/nodeinfo/types.test.mjs +4 -4
- package/dist/otel/exporter.test.mjs +3 -3
- package/dist/{outgoing-jsonld-L_DbOaFe.mjs → outgoing-jsonld-BgFLCJQ_.mjs} +1 -1
- package/dist/{owner-CyK8YW7-.mjs → owner-U0Z8Ex6i.mjs} +2 -2
- package/dist/{proof-CIUSLcHg.cjs → proof-DA3hLGSO.cjs} +1 -1
- package/dist/{proof-Ba14ORbL.js → proof-f7K32nz7.js} +1 -1
- package/dist/{proof-DXHo4Yon.mjs → proof-nb5tfciW.mjs} +5 -5
- package/dist/{send-B4Ld91pX.mjs → send-CLfW5Fdf.mjs} +3 -3
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/http.test.mjs +8 -8
- package/dist/sig/key.test.mjs +6 -6
- package/dist/sig/ld.test.mjs +7 -7
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +6 -6
- package/dist/sig/proof.test.mjs +8 -8
- package/dist/{std__assert-BBjXFNOb.mjs → std__assert-BTEgfoJo.mjs} +4 -4
- package/dist/{temporal-E7cF2Hsh.mjs → temporal-2ry_jdCK.mjs} +1 -1
- package/dist/testing/mod.d.mts +378 -7
- package/dist/testing/mod.mjs +3 -2
- package/dist/testing-CjYPStvE.mjs +55 -0
- package/dist/utils/docloader.test.mjs +6 -6
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +8 -6
- /package/dist/{accept-CPkZzmGN.mjs → accept-CceiKpCy.mjs} +0 -0
- /package/dist/{activity-listener-tztVvlNb.mjs → activity-listener-BeTGV3wc.mjs} +0 -0
- /package/dist/{assert_equals-C-ZRDbaf.mjs → assert_equals-Ew3jOFa3.mjs} +0 -0
- /package/dist/{circuit-breaker-CSWsyoef.mjs → circuit-breaker-hJBB6jwA.mjs} +0 -0
- /package/dist/{client-ByXmQhYD.mjs → client-B_A6mfn3.mjs} +0 -0
- /package/dist/{collection-Cc3DVAhE.mjs → collection-Dp5ky45w.mjs} +0 -0
- /package/dist/{keycache-BeU0LCII.mjs → keycache-CaOR6NYg.mjs} +0 -0
- /package/dist/{keys-DGu1NFwu.mjs → keys-C3kae-6B.mjs} +0 -0
- /package/dist/{kv-rV3vodCc.mjs → kv-x2IvBUyq.mjs} +0 -0
- /package/dist/{negotiation-DDstyBvc.mjs → negotiation-m_L2nyS3.mjs} +0 -0
- /package/dist/{public-audience-Cvbr2Gzt.mjs → public-audience-N3pyOx2p.mjs} +0 -0
- /package/dist/{retry-CXg_MBI-.mjs → retry-DI4O-zYl.mjs} +0 -0
- /package/dist/{types-J53Kw7so.mjs → types-BFowWFTT.mjs} +0 -0
package/dist/testing/mod.d.mts
CHANGED
|
@@ -2,11 +2,12 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
import { ExportResultCode } from "@opentelemetry/core";
|
|
4
4
|
import { Router } from "@fedify/uri-template";
|
|
5
|
-
import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab";
|
|
5
|
+
import { Activity, Actor, Collection, CryptographicKey, Hashtag, Link, LookupObjectOptions, Multikey, Note, Object as Object$1, Recipient, Tombstone, TraverseCollectionOptions } from "@fedify/vocab";
|
|
6
6
|
import { Link as Link$1, LookupWebFingerOptions, ResourceDescriptor } from "@fedify/webfinger";
|
|
7
7
|
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
8
8
|
import { DocumentLoader, GetUserAgentOptions } from "@fedify/vocab-runtime";
|
|
9
9
|
import { MeterProvider as MeterProvider$1, MetricReader } from "@opentelemetry/sdk-metrics";
|
|
10
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
10
11
|
|
|
11
12
|
//#region src/nodeinfo/types.d.ts
|
|
12
13
|
/**
|
|
@@ -580,6 +581,278 @@ type CustomCollectionCounter<TParam extends string, TContextData> = (context: Re
|
|
|
580
581
|
*/
|
|
581
582
|
type CustomCollectionCursor<TParam extends string, TContext extends Context<TContextData>, TContextData> = (context: TContext, values: Record<TParam, string>) => string | null | Promise<string | null>;
|
|
582
583
|
//#endregion
|
|
584
|
+
//#region src/federation/mq.d.ts
|
|
585
|
+
/**
|
|
586
|
+
* Additional options for enqueuing a message in a queue.
|
|
587
|
+
*
|
|
588
|
+
* @since 0.5.0
|
|
589
|
+
*/
|
|
590
|
+
interface MessageQueueEnqueueOptions {
|
|
591
|
+
/**
|
|
592
|
+
* The delay before the message is enqueued. No delay by default.
|
|
593
|
+
*
|
|
594
|
+
* It must not be negative.
|
|
595
|
+
*/
|
|
596
|
+
readonly delay?: Temporal.Duration;
|
|
597
|
+
/**
|
|
598
|
+
* An optional key that ensures messages with the same ordering key are
|
|
599
|
+
* processed sequentially (one at a time). Messages with different ordering
|
|
600
|
+
* keys (or no ordering key) may be processed in parallel.
|
|
601
|
+
*
|
|
602
|
+
* This is useful for ensuring that related messages are processed in order,
|
|
603
|
+
* such as ensuring that a `Delete` activity is processed after a `Create`
|
|
604
|
+
* activity for the same object.
|
|
605
|
+
*
|
|
606
|
+
* @since 2.0.0
|
|
607
|
+
*/
|
|
608
|
+
readonly orderingKey?: string;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Additional options for listening to a message queue.
|
|
612
|
+
*
|
|
613
|
+
* @since 1.0.0
|
|
614
|
+
*/
|
|
615
|
+
interface MessageQueueListenOptions {
|
|
616
|
+
/**
|
|
617
|
+
* The signal to abort listening to the message queue.
|
|
618
|
+
*/
|
|
619
|
+
signal?: AbortSignal;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* The number of messages waiting in a message queue.
|
|
623
|
+
*
|
|
624
|
+
* @since 2.3.0
|
|
625
|
+
*/
|
|
626
|
+
interface MessageQueueDepth {
|
|
627
|
+
/**
|
|
628
|
+
* The total number of messages still waiting in the backend queue.
|
|
629
|
+
*
|
|
630
|
+
* This does not include messages that have already been handed to a worker
|
|
631
|
+
* for processing.
|
|
632
|
+
*/
|
|
633
|
+
readonly queued: number;
|
|
634
|
+
/**
|
|
635
|
+
* The number of queued messages eligible for immediate processing.
|
|
636
|
+
*
|
|
637
|
+
* Queue backends that cannot cheaply distinguish ready and delayed messages
|
|
638
|
+
* may omit this field.
|
|
639
|
+
*/
|
|
640
|
+
readonly ready?: number;
|
|
641
|
+
/**
|
|
642
|
+
* The number of queued messages scheduled for later delivery.
|
|
643
|
+
*
|
|
644
|
+
* Queue backends that cannot cheaply distinguish ready and delayed messages
|
|
645
|
+
* may omit this field.
|
|
646
|
+
*/
|
|
647
|
+
readonly delayed?: number;
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* An abstract interface for a message queue.
|
|
651
|
+
*
|
|
652
|
+
* @since 0.5.0
|
|
653
|
+
*/
|
|
654
|
+
interface MessageQueue {
|
|
655
|
+
/**
|
|
656
|
+
* Whether the message queue backend provides native retry mechanisms.
|
|
657
|
+
* When `true`, Fedify will skip its own retry logic and rely on the backend
|
|
658
|
+
* to handle retries. When `false` or omitted, Fedify will handle retries
|
|
659
|
+
* using its own retry policies.
|
|
660
|
+
*
|
|
661
|
+
* @default `false`
|
|
662
|
+
* @since 1.7.0
|
|
663
|
+
*/
|
|
664
|
+
readonly nativeRetrial?: boolean;
|
|
665
|
+
/**
|
|
666
|
+
* Enqueues a message in the queue.
|
|
667
|
+
* @param message The message to enqueue.
|
|
668
|
+
* @param options Additional options for enqueuing the message.
|
|
669
|
+
*/
|
|
670
|
+
enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
|
|
671
|
+
/**
|
|
672
|
+
* Enqueues multiple messages in the queue. This operation is optional,
|
|
673
|
+
* and may not be supported by all implementations. If not supported,
|
|
674
|
+
* Fedify will invoke {@link enqueue} for each message.
|
|
675
|
+
*
|
|
676
|
+
* @param messages The messages to enqueue.
|
|
677
|
+
* @param options Additional options for enqueuing the messages.
|
|
678
|
+
*/
|
|
679
|
+
enqueueMany?: (messages: readonly any[], options?: MessageQueueEnqueueOptions) => Promise<void>;
|
|
680
|
+
/**
|
|
681
|
+
* Listens for messages in the queue.
|
|
682
|
+
* @param handler The handler for messages in the queue.
|
|
683
|
+
* @param options Additional options for listening to the message queue.
|
|
684
|
+
* @returns A promise that resolves when the listening is done. It never
|
|
685
|
+
* rejects, and is resolved when the signal is aborted. If no
|
|
686
|
+
* signal is provided, it never resolves.
|
|
687
|
+
*/
|
|
688
|
+
listen(handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>;
|
|
689
|
+
/**
|
|
690
|
+
* Gets the number of messages waiting in the queue.
|
|
691
|
+
*
|
|
692
|
+
* This operation is optional, and may not be supported by all
|
|
693
|
+
* implementations. The returned counts exclude messages currently being
|
|
694
|
+
* handled by a worker.
|
|
695
|
+
*
|
|
696
|
+
* @since 2.3.0
|
|
697
|
+
*/
|
|
698
|
+
getDepth?(): Promise<MessageQueueDepth>;
|
|
699
|
+
}
|
|
700
|
+
//#endregion
|
|
701
|
+
//#region src/federation/retry.d.ts
|
|
702
|
+
/**
|
|
703
|
+
* The context passed to a {@link RetryPolicy} callback.
|
|
704
|
+
* @since 0.12.0
|
|
705
|
+
*/
|
|
706
|
+
interface RetryContext {
|
|
707
|
+
/**
|
|
708
|
+
* The elapsed time since the first attempt.
|
|
709
|
+
*/
|
|
710
|
+
readonly elapsedTime: Temporal.Duration;
|
|
711
|
+
/**
|
|
712
|
+
* The number of attempts so far.
|
|
713
|
+
*/
|
|
714
|
+
readonly attempts: number;
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* A policy that determines the delay before the next retry.
|
|
718
|
+
* @param context The retry context.
|
|
719
|
+
* @returns The delay before the next retry, or `null` to stop retrying.
|
|
720
|
+
* It must not negative.
|
|
721
|
+
* @since 0.12.0
|
|
722
|
+
*/
|
|
723
|
+
type RetryPolicy = (context: RetryContext) => Temporal.Duration | null;
|
|
724
|
+
//#endregion
|
|
725
|
+
//#region src/federation/tasks/task.d.ts
|
|
726
|
+
/**
|
|
727
|
+
* A callback that processes a custom background task.
|
|
728
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
729
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
730
|
+
* schema.
|
|
731
|
+
* @param ctx The context for the worker processing the task.
|
|
732
|
+
* @param data The decoded and validated task payload.
|
|
733
|
+
* @since 2.x.x
|
|
734
|
+
*/
|
|
735
|
+
type TaskHandler<TContextData, TData> = (ctx: Context<TContextData>, data: TData) => Promise<void> | void;
|
|
736
|
+
/**
|
|
737
|
+
* Options for {@link TaskRegistry.defineTask}.
|
|
738
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
739
|
+
* @template TSchema The [Standard Schema](https://standardschema.dev/) that
|
|
740
|
+
* validates the task payload.
|
|
741
|
+
* @since 2.x.x
|
|
742
|
+
*/
|
|
743
|
+
interface TaskDefinitionOptions<TContextData, TSchema extends StandardSchemaV1> {
|
|
744
|
+
/**
|
|
745
|
+
* The [Standard Schema](https://standardschema.dev/) that validates the
|
|
746
|
+
* task payload. The payload type is inferred from this schema.
|
|
747
|
+
*
|
|
748
|
+
* The payload is validated twice: once at enqueue time (fail fast) and
|
|
749
|
+
* once at dequeue time (drift protection against payloads enqueued by an
|
|
750
|
+
* older deployment). Because the same schema runs on both sides, its
|
|
751
|
+
* validation must be idempotent: the validated output must itself be
|
|
752
|
+
* a valid input. Transforming schemas (e.g., Zod's `.transform()`) whose
|
|
753
|
+
* output differs in shape from their input are not supported.
|
|
754
|
+
*/
|
|
755
|
+
readonly schema: TSchema;
|
|
756
|
+
/**
|
|
757
|
+
* The callback that processes the task on a background worker.
|
|
758
|
+
*/
|
|
759
|
+
readonly handler: TaskHandler<TContextData, StandardSchemaV1.InferOutput<TSchema>>;
|
|
760
|
+
/**
|
|
761
|
+
* The retry policy for this task. If omitted, the federation-wide
|
|
762
|
+
* task retry policy is used, which defaults to an exponential backoff
|
|
763
|
+
* policy.
|
|
764
|
+
*/
|
|
765
|
+
readonly retryPolicy?: RetryPolicy;
|
|
766
|
+
/**
|
|
767
|
+
* A callback invoked when the {@link handler} throws an error, before
|
|
768
|
+
* a retry is scheduled.
|
|
769
|
+
* @param ctx The context for the worker processing the task.
|
|
770
|
+
* @param error The error thrown by the handler.
|
|
771
|
+
* @param data The decoded and validated task payload.
|
|
772
|
+
*/
|
|
773
|
+
readonly onError?: (ctx: Context<TContextData>, error: unknown, data: StandardSchemaV1.InferOutput<TSchema>) => Promise<void> | void;
|
|
774
|
+
/**
|
|
775
|
+
* The message queue dedicated to this task. If omitted, the task is
|
|
776
|
+
* routed to the federation-wide task queue, falling back to the outbox
|
|
777
|
+
* queue (unless `taskQueueResolution: "strict"` is configured).
|
|
778
|
+
*/
|
|
779
|
+
readonly queue?: MessageQueue;
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Phantom key binding a {@link TaskDefinition} to its federation's context
|
|
783
|
+
* data type. Declared only—no value exists at runtime, and the symbol is
|
|
784
|
+
* not exported, so the marker stays out of user-facing completions.
|
|
785
|
+
*/
|
|
786
|
+
declare const contextDataBrand: unique symbol;
|
|
787
|
+
/**
|
|
788
|
+
* The handle returned by {@link TaskRegistry.defineTask}. It carries the
|
|
789
|
+
* task name and schema so that {@link Context.enqueueTask} can validate the
|
|
790
|
+
* payload and infer its type at every call site.
|
|
791
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
792
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
793
|
+
* schema.
|
|
794
|
+
* @since 2.x.x
|
|
795
|
+
*/
|
|
796
|
+
interface TaskDefinition<TContextData, TData> {
|
|
797
|
+
/**
|
|
798
|
+
* The unique name of the task.
|
|
799
|
+
*/
|
|
800
|
+
readonly name: string;
|
|
801
|
+
/**
|
|
802
|
+
* The [Standard Schema](https://standardschema.dev/) that validates the
|
|
803
|
+
* task payload.
|
|
804
|
+
*/
|
|
805
|
+
readonly schema: StandardSchemaV1<unknown, TData>;
|
|
806
|
+
/**
|
|
807
|
+
* @internal Phantom marker binding the handle to its federation.
|
|
808
|
+
*/
|
|
809
|
+
readonly [contextDataBrand]?: TContextData;
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Registration of custom background tasks. Both {@link Federation} and
|
|
813
|
+
* {@link FederationBuilder} implement this interface.
|
|
814
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
815
|
+
* @since 2.x.x
|
|
816
|
+
*/
|
|
817
|
+
interface TaskRegistry<TContextData> {
|
|
818
|
+
/**
|
|
819
|
+
* Defines a custom background task. The returned handle is passed to
|
|
820
|
+
* {@link Context.enqueueTask} to enqueue the task.
|
|
821
|
+
*
|
|
822
|
+
* @example
|
|
823
|
+
* ``` typescript
|
|
824
|
+
* const sendDigest = federation.defineTask("sendDigest", {
|
|
825
|
+
* schema: digestSchema,
|
|
826
|
+
* handler: async (ctx, data) => {
|
|
827
|
+
* // …process the payload on a background worker…
|
|
828
|
+
* },
|
|
829
|
+
* });
|
|
830
|
+
* ```
|
|
831
|
+
*
|
|
832
|
+
* @param name The unique name of the task.
|
|
833
|
+
* @param options The task definition options. The payload type is
|
|
834
|
+
* inferred from `options.schema`.
|
|
835
|
+
* @returns The handle to pass to {@link Context.enqueueTask}.
|
|
836
|
+
* @throws {TypeError} If a task with the same name is already defined.
|
|
837
|
+
*/
|
|
838
|
+
defineTask<TSchema extends StandardSchemaV1>(name: string, options: TaskDefinitionOptions<TContextData, TSchema>): TaskDefinition<TContextData, StandardSchemaV1.InferOutput<TSchema>>;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Options for {@link Context.enqueueTask} and {@link Context.enqueueTaskMany}.
|
|
842
|
+
* @since 2.x.x
|
|
843
|
+
*/
|
|
844
|
+
interface TaskEnqueueOptions {
|
|
845
|
+
/**
|
|
846
|
+
* The delay before the task is processed. No delay by default.
|
|
847
|
+
*/
|
|
848
|
+
readonly delay?: Temporal.DurationLike;
|
|
849
|
+
/**
|
|
850
|
+
* An optional key that ensures tasks with the same ordering key are
|
|
851
|
+
* processed sequentially (one at a time).
|
|
852
|
+
*/
|
|
853
|
+
readonly orderingKey?: string;
|
|
854
|
+
}
|
|
855
|
+
//#endregion
|
|
583
856
|
//#region src/federation/queue.d.ts
|
|
584
857
|
interface SenderKeyJwkPair {
|
|
585
858
|
readonly keyId: string;
|
|
@@ -594,7 +867,7 @@ interface SenderKeyJwkPair {
|
|
|
594
867
|
* type.
|
|
595
868
|
* @since 1.6.0
|
|
596
869
|
*/
|
|
597
|
-
type Message = FanoutMessage | OutboxMessage | InboxMessage;
|
|
870
|
+
type Message = FanoutMessage | OutboxMessage | InboxMessage | TaskMessage;
|
|
598
871
|
interface FanoutMessage {
|
|
599
872
|
readonly type: "fanout";
|
|
600
873
|
readonly id: ReturnType<typeof crypto.randomUUID>;
|
|
@@ -648,6 +921,24 @@ interface OutboxMessage {
|
|
|
648
921
|
readonly circuitHeldSince?: string;
|
|
649
922
|
readonly traceContext: Readonly<Record<string, string>>;
|
|
650
923
|
}
|
|
924
|
+
/**
|
|
925
|
+
* A message that carries a custom background task. Every field is
|
|
926
|
+
* a string, number, or plain record so that the message survives both
|
|
927
|
+
* JSON serialization and structured clone on every queue backend.
|
|
928
|
+
* @since 2.x.x
|
|
929
|
+
*/
|
|
930
|
+
interface TaskMessage {
|
|
931
|
+
readonly type: "task";
|
|
932
|
+
readonly id: ReturnType<typeof crypto.randomUUID>;
|
|
933
|
+
readonly baseUrl: string;
|
|
934
|
+
readonly taskName: string;
|
|
935
|
+
/** devalue-encoded task data; vocab objects bridged to expanded JSON-LD. */
|
|
936
|
+
readonly data: string;
|
|
937
|
+
readonly started: string;
|
|
938
|
+
readonly attempt: number;
|
|
939
|
+
readonly orderingKey?: string;
|
|
940
|
+
readonly traceContext: Readonly<Record<string, string>>;
|
|
941
|
+
}
|
|
651
942
|
interface InboxMessage {
|
|
652
943
|
readonly type: "inbox";
|
|
653
944
|
readonly id: ReturnType<typeof crypto.randomUUID>;
|
|
@@ -707,18 +998,18 @@ interface FederationStartQueueOptions {
|
|
|
707
998
|
signal?: AbortSignal;
|
|
708
999
|
/**
|
|
709
1000
|
* Starts the task worker only for the specified queue. If unspecified,
|
|
710
|
-
* which is the default, the task worker starts for all
|
|
711
|
-
* inbox, outbox, and
|
|
1001
|
+
* which is the default, the task worker starts for all four queues:
|
|
1002
|
+
* inbox, outbox, fanout, and task.
|
|
712
1003
|
* @since 1.3.0
|
|
713
1004
|
*/
|
|
714
|
-
queue?: "inbox" | "outbox" | "fanout";
|
|
1005
|
+
queue?: "inbox" | "outbox" | "fanout" | "task";
|
|
715
1006
|
}
|
|
716
1007
|
/**
|
|
717
1008
|
* A common interface between {@link Federation} and {@link FederationBuilder}.
|
|
718
1009
|
* @template TContextData The context data to pass to the {@link Context}.
|
|
719
1010
|
* @since 1.6.0
|
|
720
1011
|
*/
|
|
721
|
-
interface Federatable<TContextData> {
|
|
1012
|
+
interface Federatable<TContextData> extends TaskRegistry<TContextData> {
|
|
722
1013
|
/**
|
|
723
1014
|
* Registers a NodeInfo dispatcher.
|
|
724
1015
|
* @param path The URI path pattern for the NodeInfo dispatcher. The syntax
|
|
@@ -1887,6 +2178,44 @@ interface Context<TContextData> {
|
|
|
1887
2178
|
* @since 1.3.0
|
|
1888
2179
|
*/
|
|
1889
2180
|
routeActivity(recipient: string | null, activity: Activity, options?: RouteActivityOptions): Promise<boolean>;
|
|
2181
|
+
/**
|
|
2182
|
+
* Enqueues a custom background task. The payload is validated against
|
|
2183
|
+
* the task's schema, serialized, and processed by the task's handler on
|
|
2184
|
+
* a background worker.
|
|
2185
|
+
*
|
|
2186
|
+
* @example
|
|
2187
|
+
* ``` typescript
|
|
2188
|
+
* await ctx.enqueueTask(sendDigest, { userId: "alice" });
|
|
2189
|
+
* ```
|
|
2190
|
+
*
|
|
2191
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
2192
|
+
* schema.
|
|
2193
|
+
* @param task The handle returned by {@link TaskRegistry.defineTask}.
|
|
2194
|
+
* @param data The task payload. It is validated against the task's
|
|
2195
|
+
* schema before being enqueued.
|
|
2196
|
+
* @param options Options for enqueuing the task.
|
|
2197
|
+
* @throws {TypeError} If the task is not defined on this federation,
|
|
2198
|
+
* if no message queue is configured for tasks, or if
|
|
2199
|
+
* the payload fails schema validation.
|
|
2200
|
+
* @since 2.x.x
|
|
2201
|
+
*/
|
|
2202
|
+
enqueueTask<TData>(task: TaskDefinition<TContextData, TData>, data: TData, options?: TaskEnqueueOptions): Promise<void>;
|
|
2203
|
+
/**
|
|
2204
|
+
* Enqueues multiple payloads for a custom background task at once.
|
|
2205
|
+
* Uses the queue's bulk enqueue operation when available, falling back
|
|
2206
|
+
* to parallel single enqueues.
|
|
2207
|
+
* @template TData The type of the task payload, inferred from the task's
|
|
2208
|
+
* schema.
|
|
2209
|
+
* @param task The handle returned by {@link TaskRegistry.defineTask}.
|
|
2210
|
+
* @param payloads The task payloads. Each is validated against the
|
|
2211
|
+
* task's schema before being enqueued.
|
|
2212
|
+
* @param options Options for enqueuing the tasks.
|
|
2213
|
+
* @throws {TypeError} If the task is not defined on this federation,
|
|
2214
|
+
* if no message queue is configured for tasks, or if
|
|
2215
|
+
* a payload fails schema validation.
|
|
2216
|
+
* @since 2.x.x
|
|
2217
|
+
*/
|
|
2218
|
+
enqueueTaskMany<TData>(task: TaskDefinition<TContextData, TData>, payloads: readonly TData[], options?: TaskEnqueueOptions): Promise<void>;
|
|
1890
2219
|
/**
|
|
1891
2220
|
* Builds the URI of a collection of objects with the given name and values.
|
|
1892
2221
|
* @param name The name of the collection, which can be a string or a symbol.
|
|
@@ -2470,9 +2799,51 @@ declare function createOutboxContext<TContextData>(args: Partial<OutboxContext<T
|
|
|
2470
2799
|
federation: Federation<TContextData>;
|
|
2471
2800
|
}): OutboxContext<TContextData>;
|
|
2472
2801
|
//#endregion
|
|
2802
|
+
//#region src/testing/tasks.d.ts
|
|
2803
|
+
/**
|
|
2804
|
+
* Builds a minimal [Standard Schema](https://standardschema.dev/) from a type
|
|
2805
|
+
* guard, for use as a task payload schema in tests.
|
|
2806
|
+
*/
|
|
2807
|
+
declare const makeSchema: <T>(check: (data: unknown) => data is T) => StandardSchemaV1<unknown, T>;
|
|
2808
|
+
declare const stringSchema: StandardSchemaV1<unknown, string>;
|
|
2809
|
+
declare const numberSchema: StandardSchemaV1<unknown, number>;
|
|
2810
|
+
/** A task payload that carries a vocabulary object, to exercise the codec's
|
|
2811
|
+
* vocab-to-JSON-LD bridging. */
|
|
2812
|
+
interface Envelope {
|
|
2813
|
+
note: Note;
|
|
2814
|
+
title: string;
|
|
2815
|
+
}
|
|
2816
|
+
declare const envelopeSchema: StandardSchemaV1<unknown, Envelope>;
|
|
2817
|
+
/** Options for {@link MockQueue}. */
|
|
2818
|
+
interface MockQueueOptions {
|
|
2819
|
+
readonly nativeRetrial?: boolean;
|
|
2820
|
+
readonly supportsEnqueueMany?: boolean;
|
|
2821
|
+
}
|
|
2822
|
+
/**
|
|
2823
|
+
* A {@link MessageQueue} that records what it was asked to enqueue and resolves
|
|
2824
|
+
* its `listen()` when the abort signal fires, so tests can inspect dispatch
|
|
2825
|
+
* without a real backend.
|
|
2826
|
+
*/
|
|
2827
|
+
declare class MockQueue implements MessageQueue {
|
|
2828
|
+
readonly nativeRetrial: boolean;
|
|
2829
|
+
readonly enqueued: {
|
|
2830
|
+
message: TaskMessage;
|
|
2831
|
+
options?: MessageQueueEnqueueOptions;
|
|
2832
|
+
}[];
|
|
2833
|
+
readonly enqueuedMany: {
|
|
2834
|
+
messages: readonly TaskMessage[];
|
|
2835
|
+
options?: MessageQueueEnqueueOptions;
|
|
2836
|
+
}[];
|
|
2837
|
+
listenCount: number;
|
|
2838
|
+
enqueueMany?: (messages: readonly TaskMessage[], options?: MessageQueueEnqueueOptions) => Promise<void>;
|
|
2839
|
+
constructor(options?: MockQueueOptions);
|
|
2840
|
+
enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
|
|
2841
|
+
listen(_handler: (message: any) => Promise<void> | void, options?: MessageQueueListenOptions): Promise<void>;
|
|
2842
|
+
}
|
|
2843
|
+
//#endregion
|
|
2473
2844
|
//#region ../fixture/dist/mod.d.ts
|
|
2474
2845
|
//#endregion
|
|
2475
2846
|
//#region src/test.d.ts
|
|
2476
2847
|
declare const testDefinitions: Deno.TestDefinition[];
|
|
2477
2848
|
//#endregion
|
|
2478
|
-
export { createInboxContext, createOutboxContext, createRequestContext, testDefinitions };
|
|
2849
|
+
export { type Envelope, MockQueue, type MockQueueOptions, createInboxContext, createOutboxContext, createRequestContext, envelopeSchema, makeSchema, numberSchema, stringSchema, testDefinitions };
|
package/dist/testing/mod.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { i as testDefinitions, n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-
|
|
5
|
-
|
|
4
|
+
import { i as testDefinitions, n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-BrIOaBSs.mjs";
|
|
5
|
+
import { a as stringSchema, i as numberSchema, n as envelopeSchema, r as makeSchema, t as MockQueue } from "../testing-CjYPStvE.mjs";
|
|
6
|
+
export { MockQueue, createInboxContext, createOutboxContext, createRequestContext, envelopeSchema, makeSchema, numberSchema, stringSchema, testDefinitions };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
2
|
+
import "urlpattern-polyfill";
|
|
3
|
+
globalThis.addEventListener = () => {};
|
|
4
|
+
import "./context-BrIOaBSs.mjs";
|
|
5
|
+
import { Note } from "@fedify/vocab";
|
|
6
|
+
//#region src/testing/tasks.ts
|
|
7
|
+
/**
|
|
8
|
+
* Builds a minimal [Standard Schema](https://standardschema.dev/) from a type
|
|
9
|
+
* guard, for use as a task payload schema in tests.
|
|
10
|
+
*/
|
|
11
|
+
const makeSchema = (check) => ({ "~standard": {
|
|
12
|
+
version: 1,
|
|
13
|
+
vendor: "fedify-test",
|
|
14
|
+
validate: (value) => check(value) ? { value } : { issues: [{ message: "Invalid task data." }] }
|
|
15
|
+
} });
|
|
16
|
+
const stringSchema = makeSchema((d) => typeof d === "string");
|
|
17
|
+
const numberSchema = makeSchema((d) => typeof d === "number");
|
|
18
|
+
const envelopeSchema = makeSchema((data) => typeof data === "object" && data != null && data.note instanceof Note && typeof data.title === "string");
|
|
19
|
+
/**
|
|
20
|
+
* A {@link MessageQueue} that records what it was asked to enqueue and resolves
|
|
21
|
+
* its `listen()` when the abort signal fires, so tests can inspect dispatch
|
|
22
|
+
* without a real backend.
|
|
23
|
+
*/
|
|
24
|
+
var MockQueue = class {
|
|
25
|
+
nativeRetrial;
|
|
26
|
+
enqueued = [];
|
|
27
|
+
enqueuedMany = [];
|
|
28
|
+
listenCount = 0;
|
|
29
|
+
enqueueMany;
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
this.nativeRetrial = options.nativeRetrial ?? false;
|
|
32
|
+
if (options.supportsEnqueueMany) this.enqueueMany = (messages, opts) => {
|
|
33
|
+
this.enqueuedMany.push({
|
|
34
|
+
messages,
|
|
35
|
+
options: opts
|
|
36
|
+
});
|
|
37
|
+
return Promise.resolve();
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
enqueue(message, options) {
|
|
41
|
+
this.enqueued.push({
|
|
42
|
+
message,
|
|
43
|
+
options
|
|
44
|
+
});
|
|
45
|
+
return Promise.resolve();
|
|
46
|
+
}
|
|
47
|
+
listen(_handler, options) {
|
|
48
|
+
this.listenCount++;
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
options?.signal?.addEventListener("abort", () => resolve());
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
//#endregion
|
|
55
|
+
export { stringSchema as a, numberSchema as i, envelopeSchema as n, makeSchema as r, MockQueue as t };
|
|
@@ -2,12 +2,12 @@ import { Temporal } from "@js-temporal/polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { t as esm_default } from "../esm-vrlUxr60.mjs";
|
|
5
|
-
import { t as assertEquals } from "../assert_equals-
|
|
6
|
-
import "../std__assert-
|
|
7
|
-
import { t as assertRejects } from "../assert_rejects-
|
|
8
|
-
import { l as verifyRequest } from "../http-
|
|
9
|
-
import { i as rsaPrivateKey2 } from "../keys-
|
|
10
|
-
import { t as getAuthenticatedDocumentLoader } from "../docloader-
|
|
5
|
+
import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
|
|
6
|
+
import "../std__assert-BTEgfoJo.mjs";
|
|
7
|
+
import { t as assertRejects } from "../assert_rejects-DQP-q39h.mjs";
|
|
8
|
+
import { l as verifyRequest } from "../http-GQoPA_YT.mjs";
|
|
9
|
+
import { i as rsaPrivateKey2 } from "../keys-C3kae-6B.mjs";
|
|
10
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-B8AJowCx.mjs";
|
|
11
11
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
12
12
|
import { UrlError } from "@fedify/vocab-runtime";
|
|
13
13
|
//#region src/utils/docloader.test.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as kvCache, t as MockKvStore } from "../kv-cache-
|
|
4
|
+
import { n as kvCache, t as MockKvStore } from "../kv-cache-pw-kBdVz.mjs";
|
|
5
5
|
import { deepStrictEqual, throws } from "node:assert";
|
|
6
6
|
import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
7
7
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
package/dist/utils/mod.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { Temporal } = require("@js-temporal/polyfill");
|
|
2
2
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
|
-
const require_kv_cache = require("../kv-cache-
|
|
4
|
+
const require_kv_cache = require("../kv-cache-DXwu7BtY.cjs");
|
|
5
5
|
exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
|
|
6
6
|
exports.kvCache = require_kv_cache.kvCache;
|
package/dist/utils/mod.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-
|
|
3
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-CjEcb9qH.js";
|
|
4
4
|
export { getAuthenticatedDocumentLoader, kvCache };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/fedify",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0-dev.1422+7668da16",
|
|
4
4
|
"description": "An ActivityPub server framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ActivityPub",
|
|
@@ -146,16 +146,18 @@
|
|
|
146
146
|
"@opentelemetry/sdk-metrics": "2.7.1",
|
|
147
147
|
"@opentelemetry/sdk-trace-base": "^2.7.1",
|
|
148
148
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
149
|
+
"@standard-schema/spec": "^1.1.0",
|
|
149
150
|
"byte-encodings": "^1.0.11",
|
|
151
|
+
"devalue": "^5.8.1",
|
|
150
152
|
"es-toolkit": "1.46.1",
|
|
151
153
|
"json-canon": "^1.0.1",
|
|
152
154
|
"jsonld": "^9.0.0",
|
|
153
155
|
"structured-field-values": "^2.0.4",
|
|
154
156
|
"urlpattern-polyfill": "^10.1.0",
|
|
155
|
-
"@fedify/uri-template": "2.
|
|
156
|
-
"@fedify/vocab": "2.
|
|
157
|
-
"@fedify/vocab
|
|
158
|
-
"@fedify/webfinger": "2.
|
|
157
|
+
"@fedify/uri-template": "2.4.0-dev.1422+7668da16",
|
|
158
|
+
"@fedify/vocab-runtime": "2.4.0-dev.1422+7668da16",
|
|
159
|
+
"@fedify/vocab": "2.4.0-dev.1422+7668da16",
|
|
160
|
+
"@fedify/webfinger": "2.4.0-dev.1422+7668da16"
|
|
159
161
|
},
|
|
160
162
|
"devDependencies": {
|
|
161
163
|
"@std/assert": "npm:@jsr/std__assert@^0.226.0",
|
|
@@ -168,7 +170,7 @@
|
|
|
168
170
|
"typescript": "^6.0.0",
|
|
169
171
|
"wrangler": "^4.17.0",
|
|
170
172
|
"@fedify/fixture": "2.0.0",
|
|
171
|
-
"@fedify/vocab-tools": "^2.
|
|
173
|
+
"@fedify/vocab-tools": "^2.4.0-dev.1422+7668da16"
|
|
172
174
|
},
|
|
173
175
|
"scripts": {
|
|
174
176
|
"build:self": "tsdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|