@nymbalhq/contract-tests 0.0.0-stage → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ // src/kinds.ts
2
+ var CONTRACT_KINDS = [
3
+ "payments",
4
+ "email",
5
+ "reviews",
6
+ "search",
7
+ "analytics",
8
+ "shipping",
9
+ "tax",
10
+ "ai",
11
+ "documentStore",
12
+ "eventBus",
13
+ "media"
14
+ ];
15
+
16
+ export {
17
+ CONTRACT_KINDS
18
+ };
19
+ //# sourceMappingURL=chunk-ABEL44IM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/kinds.ts"],"sourcesContent":["import type { Slot } from '@nymbalhq/types'\n\n// Its own entry (`@nymbalhq/contract-tests/kinds`), free of vitest: the CLI reads it in its own process, where\n// importing vitest outside a test run throws.\n\n/** The kinds `contractSuites` has a suite for. */\nexport const CONTRACT_KINDS = [\n 'payments',\n 'email',\n 'reviews',\n 'search',\n 'analytics',\n 'shipping',\n 'tax',\n 'ai',\n 'documentStore',\n 'eventBus',\n 'media',\n] as const satisfies readonly Slot[]\n"],"mappings":";AAMO,IAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
@@ -0,0 +1,149 @@
1
+ import { Slot, AdapterContext, DocumentStoreAdapter, EventBusAdapter, MediaStorage, PaymentsAdapter, EmailAdapter, ReviewsAdapter, SearchAdapter, SearchDocument, AnalyticsAdapter, ShippingAdapter, TaxAdapter, AiAdapter, SecurityAdapter, NymbalEvent } from '@nymbalhq/types';
2
+ export { CONTRACT_KINDS } from './kinds.js';
3
+
4
+ /** How long a health check, or a call on an unreachable dependency, may take to settle. */
5
+ declare const BOUND_MS = 6000;
6
+ /** Makes the adapter under test: a fresh, initialized one each time it is called. */
7
+ type Build<A> = () => A | Promise<A>;
8
+ /** The options every suite takes. */
9
+ interface ContractOptions<A = unknown> {
10
+ /**
11
+ * An adapter whose dependency cannot be reached. Given, the suite adds the downtime cases: `healthCheck()` reports
12
+ * `down`, and one representative operation rejects, each within 6 s. For a client that connects when it is built,
13
+ * build it while the dependency is up and then take the dependency away (close a proxy in front of it).
14
+ */
15
+ unreachable?: Build<A>;
16
+ }
17
+
18
+ /**
19
+ * The AdapterContext the kernel hands a package's `createAdapter`, with a silent logger: `config` is a commerce slot's
20
+ * `config` record or a primitive's connection block.
21
+ */
22
+ declare function adapterContext(slot: Slot, config: Record<string, unknown>, env?: NodeJS.ProcessEnv): AdapterContext;
23
+
24
+ interface DocumentStoreContractOptions extends ContractOptions<DocumentStoreAdapter> {
25
+ /** A clock the store reads: the TTL cases advance it instead of waiting a one-second TTL out. */
26
+ clock?: {
27
+ advance(ms: number): void | Promise<void>;
28
+ };
29
+ /** Two stores on one backend under different prefixes, for the prefix isolation cases. */
30
+ isolation?: () => Promise<[DocumentStoreAdapter, DocumentStoreAdapter]>;
31
+ }
32
+ type Make$1 = Build<DocumentStoreAdapter>;
33
+ /**
34
+ * The document store contract every implementation runs: the reference order and filter of
35
+ * `compareDocumentValues` and `matchesSortKey`, cursors that survive a delete, TTL, conditional puts, batches,
36
+ * isolation between collections (and, given `isolation`, between prefixes), the same as a property against the
37
+ * reference model, an atomic `replaceCollection`, and health (and, given `unreachable`, downtime). `make` returns an
38
+ * empty store each time.
39
+ */
40
+ declare function runDocumentStoreContract(name: string, make: Make$1, opts?: DocumentStoreContractOptions): void;
41
+
42
+ interface EventBusContractOptions extends ContractOptions<EventBusAdapter> {
43
+ /** Another instance on the same streams as the bus `make` returned last: only a shared bus passes it. */
44
+ second?: () => Promise<EventBusAdapter>;
45
+ /** The bus's own knobs, set small by the caller: the claim and timeout cases assert the windows they bound. */
46
+ timing?: {
47
+ claimIdleMs: number;
48
+ ackTimeoutMs: number;
49
+ };
50
+ }
51
+ type Make = Build<EventBusAdapter>;
52
+ /**
53
+ * The event bus contract every implementation runs. `publish` resolves only after every matching subscription's
54
+ * handler has finished (what a read straight after a command relies on); a throwing handler is logged and does not
55
+ * reject it; `replay` reaches `derived` subscriptions only; each subscription takes its events in order. With `second`,
56
+ * a named subscription is handled once across instances and an unnamed one on every instance. Then the delivery
57
+ * contract's cases, and health (and, given `unreachable`, downtime).
58
+ */
59
+ declare function runEventBusContract(name: string, make: Make, opts?: EventBusContractOptions): void;
60
+
61
+ interface MediaStorageContractOptions extends ContractOptions<MediaStorage> {
62
+ /** Reads back the bytes a URL `put` returned serves: the storage's public URL, or the file a local URL names. */
63
+ fetchUrl: (url: string) => Promise<Uint8Array>;
64
+ }
65
+ /**
66
+ * The media storage contract every implementation runs: `put` resolves with a URL, and the bytes read back from that
67
+ * URL (through `fetchUrl`, which knows where the storage serves from) are the bytes that were put; then health (and,
68
+ * given `unreachable`, downtime).
69
+ */
70
+ declare function runMediaStorageContract(name: string, make: Build<MediaStorage>, options: MediaStorageContractOptions): void;
71
+
72
+ interface PaymentsContractOptions extends ContractOptions<PaymentsAdapter> {
73
+ /** One webhook as the provider would deliver it, signed. Given, the suite parses it twice and compares. */
74
+ signedWebhook?: () => {
75
+ rawBody: string | Buffer;
76
+ signature: string;
77
+ };
78
+ }
79
+ declare function runPaymentsContract(name: string, build: Build<PaymentsAdapter>, options?: PaymentsContractOptions): void;
80
+
81
+ declare function runEmailContract(name: string, build: Build<EmailAdapter>, options?: ContractOptions<EmailAdapter>): void;
82
+
83
+ declare function runReviewsContract(name: string, build: Build<ReviewsAdapter>, options?: ContractOptions<ReviewsAdapter>): void;
84
+
85
+ interface SearchContractOptions extends ContractOptions<SearchAdapter> {
86
+ /** The adapter ranks by tiers (every term in the name, then every term in name, SKU or variant name), then score,
87
+ * then id. Native does; a vendor's need not, so the ranking case runs only when the runner says so. */
88
+ ranking?: boolean;
89
+ /** The adapter reports `facet` and counts `facet('categoryIds', {query, filters})` within the query's matches. */
90
+ facets?: boolean;
91
+ /** This adapter's cursor for an offset, valid or not (it encodes; only search validates), so the malformed-cursor
92
+ * case can build a negative and a non-integer cursor. Without it only the undecodable and the stale cursor run. */
93
+ cursorAt?: (offset: number) => string;
94
+ /** fast-check runs per property (default 25). */
95
+ numRuns?: number;
96
+ }
97
+ declare function runSearchContract(name: string, build: Build<SearchAdapter>, options?: SearchContractOptions): void;
98
+
99
+ /** The terms of a text, as search sees them. */
100
+ declare function searchTerms(text: string): string[];
101
+ /** A product as the search handler indexes it, before it is a SearchDocument. */
102
+ interface ContractProduct {
103
+ id: string;
104
+ name: string;
105
+ description: string;
106
+ variants: Array<{
107
+ sku: string;
108
+ name: string;
109
+ priceMinor: number;
110
+ }>;
111
+ categoryIds: string[];
112
+ }
113
+ /** The document the search handler indexes for the product. */
114
+ declare function toSearchDocument(p: ContractProduct): SearchDocument;
115
+ /** Does the product match the query. */
116
+ declare function matchesQuery(p: ContractProduct, query: string): boolean;
117
+
118
+ declare function runAnalyticsContract(name: string, build: Build<AnalyticsAdapter>, options?: ContractOptions<AnalyticsAdapter>): void;
119
+
120
+ declare function runShippingContract(name: string, build: Build<ShippingAdapter>, options?: ContractOptions<ShippingAdapter>): void;
121
+
122
+ declare function runTaxContract(name: string, build: Build<TaxAdapter>, options?: ContractOptions<TaxAdapter>): void;
123
+
124
+ declare function runAiContract(name: string, build: Build<AiAdapter>, options?: ContractOptions<AiAdapter>): void;
125
+
126
+ declare function runSecurityContract(name: string, build: Build<SecurityAdapter>, options?: ContractOptions<SecurityAdapter>): void;
127
+
128
+ interface ProjectionContractOptions {
129
+ /**
130
+ * Build a fresh projection handler context. Returns:
131
+ * - `handle(event)` — processes the event through the idempotency-guarded handler
132
+ * - `applicationCount()` — returns how many times the underlying handler actually ran
133
+ */
134
+ build: () => Promise<{
135
+ handle: (event: NymbalEvent) => Promise<void>;
136
+ applicationCount: () => Promise<number>;
137
+ }>;
138
+ }
139
+ declare function runProjectionContract(opts: ProjectionContractOptions): void;
140
+
141
+ /** What a suite certifies: a commerce slot or an infrastructure primitive. */
142
+ type ContractKind = Slot;
143
+ /** A kind's suite, as `nymbal test:contracts` calls it: `build` makes a fresh adapter for each case. */
144
+ type ContractSuite = (name: string, build: Build<unknown>, options?: Record<string, unknown>) => void;
145
+ /** Each kind's suite, one for every kind in CONTRACT_KINDS. Each is typed here, at the CLI's boundary. */
146
+ declare const contractSuites: Partial<Record<ContractKind, ContractSuite>>;
147
+
148
+ export { BOUND_MS, adapterContext, contractSuites, matchesQuery, runAiContract, runAnalyticsContract, runDocumentStoreContract, runEmailContract, runEventBusContract, runMediaStorageContract, runPaymentsContract, runProjectionContract, runReviewsContract, runSearchContract, runSecurityContract, runShippingContract, runTaxContract, searchTerms, toSearchDocument };
149
+ export type { Build, ContractKind, ContractOptions, ContractProduct, ContractSuite, DocumentStoreContractOptions, EventBusContractOptions, MediaStorageContractOptions, PaymentsContractOptions, ProjectionContractOptions, SearchContractOptions };