@foir/sdk 0.5.0 → 0.7.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.
Files changed (82) hide show
  1. package/CHANGELOG.md +325 -0
  2. package/README.md +63 -0
  3. package/dist/auth/auth.d.ts +140 -0
  4. package/dist/auth/hosted.d.ts +40 -0
  5. package/dist/auth/index.d.ts +15 -0
  6. package/dist/auth/operations.d.ts +123 -0
  7. package/dist/auth/session-client.d.ts +76 -0
  8. package/dist/auth-session.js +137 -0
  9. package/dist/auth.js +238 -26
  10. package/dist/client/platform-client.d.ts +29 -0
  11. package/dist/client.js +281 -37
  12. package/dist/codegen/block-registry.d.ts +4 -8
  13. package/dist/codegen/block-scaffold.d.ts +4 -8
  14. package/dist/codegen/index.d.ts +8 -62
  15. package/dist/codegen/preset.d.ts +60 -0
  16. package/dist/codegen/shared.d.ts +25 -0
  17. package/dist/components/EditorProvider.d.ts +36 -0
  18. package/dist/content/content-renderer.d.ts +47 -0
  19. package/dist/content/index.d.ts +12 -0
  20. package/dist/content/richtext.d.ts +70 -0
  21. package/dist/data/builtins.d.ts +296 -0
  22. package/dist/data/client.d.ts +94 -0
  23. package/dist/data/index.d.ts +54 -0
  24. package/dist/data/manifest.d.ts +161 -0
  25. package/dist/data/schema.d.ts +243 -0
  26. package/dist/data/selection.d.ts +330 -0
  27. package/dist/data/transport.d.ts +107 -0
  28. package/dist/data.js +309 -0
  29. package/dist/graphql/cdn-route.d.ts +42 -0
  30. package/dist/graphql/client.d.ts +30 -0
  31. package/dist/graphql/content-client.d.ts +66 -0
  32. package/dist/graphql/foir-request.d.ts +47 -0
  33. package/dist/hooks/useAutoResize.d.ts +22 -0
  34. package/dist/hooks/useEditor.d.ts +16 -0
  35. package/dist/index.d.ts +10 -394
  36. package/dist/media/BlurhashCanvas.d.ts +10 -0
  37. package/dist/media/ProgressiveMedia.d.ts +56 -0
  38. package/dist/media/index.d.ts +14 -0
  39. package/dist/media/media.d.ts +139 -0
  40. package/dist/media/useProgressiveLoad.d.ts +23 -0
  41. package/dist/media.js +5 -0
  42. package/dist/next/cookieAdapter.d.ts +26 -0
  43. package/dist/next/index.d.ts +15 -0
  44. package/dist/next/middleware.d.ts +49 -0
  45. package/dist/next/session.d.ts +53 -0
  46. package/dist/next.js +230 -26
  47. package/dist/protocol/constants.d.ts +6 -0
  48. package/dist/protocol/messages.d.ts +155 -0
  49. package/dist/protocol/validation.d.ts +8 -0
  50. package/dist/push/index.d.ts +14 -0
  51. package/dist/push/operations.d.ts +22 -0
  52. package/dist/push/web-push.d.ts +39 -0
  53. package/dist/push.js +230 -26
  54. package/dist/react/FoirProvider.d.ts +116 -0
  55. package/dist/react/OAuthButtons.d.ts +20 -0
  56. package/dist/react/SignIn.d.ts +22 -0
  57. package/dist/react/UserButton.d.ts +13 -0
  58. package/dist/react/index.d.ts +19 -0
  59. package/dist/react/localStorageAdapter.d.ts +10 -0
  60. package/dist/react.js +230 -26
  61. package/dist/{realtime.d.ts → realtime/index.d.ts} +35 -16
  62. package/dist/server/callback-client.d.ts +92 -0
  63. package/dist/server/index.d.ts +8 -0
  64. package/dist/server/operation-types.d.ts +134 -0
  65. package/dist/server/require-scoped-token.d.ts +76 -0
  66. package/dist/server/server-client.d.ts +34 -0
  67. package/dist/server/types.d.ts +54 -0
  68. package/dist/server/verify-scoped-token.d.ts +100 -0
  69. package/dist/server/webhook-helpers.d.ts +36 -0
  70. package/dist/transport/foir-http.d.ts +217 -0
  71. package/dist/transport/retry.d.ts +61 -0
  72. package/dist/types/index.d.ts +124 -0
  73. package/package.json +23 -13
  74. package/dist/auth.d.ts +0 -382
  75. package/dist/client.d.ts +0 -135
  76. package/dist/content.d.ts +0 -96
  77. package/dist/media.d.ts +0 -234
  78. package/dist/next.d.ts +0 -178
  79. package/dist/push.d.ts +0 -109
  80. package/dist/react.d.ts +0 -319
  81. package/dist/server.d.ts +0 -534
  82. package/dist/shared-DkWlEd2Z.d.ts +0 -18
package/dist/client.d.ts DELETED
@@ -1,135 +0,0 @@
1
- import { TypedDocumentNode } from '@graphql-typed-document-node/core';
2
-
3
- /**
4
- * Foir GraphQL client — a single typed fetch wrapper for SSR/edge loaders.
5
- *
6
- * No GraphQL client (Apollo/urql) required: the Foir public API is a plain
7
- * `POST` with an `x-api-key` header, and the dominant consumers (Hydrogen on
8
- * Oxygen, React Router loaders, TanStack Start on CF Workers) fetch in
9
- * server-only loaders and render — so Apollo's `InMemoryCache`/`useQuery`
10
- * reactivity is dead weight, and a shared cache on a stateless multi-tenant
11
- * edge worker is a cross-tenant hazard. This helper carries only the
12
- * Foir-specific transport concerns (auth header, preview schema channel,
13
- * error shape). Consumers on a GraphQL client (Apollo / urql / react-query /
14
- * graphql-request) use the generated `TypedDocumentNode`s directly with their
15
- * own client and replicate the two Foir-specific headers below — the
16
- * `x-api-key` and, in preview, `X-Foir-Schema-Channel: draft`.
17
- *
18
- * Deduplicates the hand-copied `lib/foir/client.ts` that shipped identically
19
- * across the Foir storefronts.
20
- */
21
-
22
- interface FoirEnv {
23
- PLATFORM_API_URL?: string;
24
- PLATFORM_API_KEY?: string;
25
- PLATFORM_PREVIEW_API_KEY?: string;
26
- FOIR_PREVIEW?: string;
27
- }
28
- /**
29
- * Returns true when `FOIR_PREVIEW=true` is set in the environment.
30
- *
31
- * Preview is selected at the environment level, not per-request: load a
32
- * preview env file that sets `FOIR_PREVIEW=true` + a `sk_…`
33
- * `PLATFORM_PREVIEW_API_KEY` with `drafts:read` instead of the default env.
34
- * The site-wide mode keeps draft semantics consistent — every loader sees
35
- * the same preview/published view of the world. Intended for non-production
36
- * surfaces only.
37
- */
38
- declare function isFoirPreview(env: FoirEnv): boolean;
39
- /** Default Foir CDN origin used to absolutise relative media URLs. */
40
- declare const FOIR_CDN_BASE = "https://cdn.foir.dev/";
41
- /**
42
- * Foir returns `hlsManifestUrl` as a relative path while every other media
43
- * URL is absolute. Prefix relative paths with the CDN host so the browser
44
- * doesn't request them from the consumer's own origin. Already-absolute URLs
45
- * pass through untouched. `cdnBase` is overridable for non-default CDN hosts.
46
- */
47
- declare function absolutiseFoirMediaUrl(url: string | null | undefined, cdnBase?: string): string | undefined;
48
- interface FoirGraphQLErrorItem {
49
- message: string;
50
- path?: Array<string | number>;
51
- }
52
- declare class FoirRequestError extends Error {
53
- /** HTTP status code, when the request failed at the HTTP layer. */
54
- readonly status?: number;
55
- /** GraphQL errors, when the request failed with a no-data error envelope. */
56
- readonly graphQLErrors?: ReadonlyArray<FoirGraphQLErrorItem>;
57
- readonly cause?: unknown;
58
- constructor(message: string, options?: {
59
- cause?: unknown;
60
- status?: number;
61
- graphQLErrors?: ReadonlyArray<FoirGraphQLErrorItem>;
62
- });
63
- }
64
- /**
65
- * Execute a typed GraphQL document against the Foir platform.
66
- *
67
- * Throws `FoirRequestError` on HTTP failure or GraphQL errors so the caller
68
- * can decide whether to rethrow or fall back to local defaults. GraphQL can
69
- * return partial data alongside errors; when data is present the errors are
70
- * logged and the data returned (callers handle nulls), and we only throw when
71
- * there's no data at all.
72
- */
73
- interface FoirRequestOptions {
74
- /**
75
- * Customer bearer token. api-public still needs the `x-api-key` to resolve
76
- * the project; the bearer adds the customer identity for self-scoped reads
77
- * (e.g. `myProfile`). Used by `@foir/sdk/auth`'s post-login profile fetch.
78
- */
79
- bearerToken?: string;
80
- }
81
- declare function foirRequest<TData, TVariables>(env: FoirEnv, document: TypedDocumentNode<TData, TVariables>, variables?: TVariables, options?: FoirRequestOptions): Promise<TData>;
82
-
83
- /**
84
- * Session-bound content client — forwards the customer bearer on every read
85
- * when one is available, so auth/segment-targeted variants and customer-scoped
86
- * records resolve out of the box, with no per-query wiring to forget.
87
- *
88
- * Resolution keys off the request's principal (see the platform's two-gate
89
- * model): the `x-api-key` alone resolves the *anonymous baseline*
90
- * (`context.authStatus = ""`); adding the customer bearer resolves the request
91
- * as that customer (`context.authStatus = "authenticated"`, `customer_id` set).
92
- *
93
- * Caching: an api-key-only read is identical for every anonymous visitor and is
94
- * shared-cacheable; a bearer-bearing read resolves per-customer and is not.
95
- * Because the bearer only exists once a customer signs in, anonymous traffic
96
- * keeps hitting the shared-cacheable baseline — only signed-in reads become
97
- * per-customer. Bind this client wherever content is personalized (for most
98
- * apps, everywhere the customer may be signed in) and use plain `foirRequest`
99
- * for reads that must stay anonymous regardless of session.
100
- */
101
-
102
- /**
103
- * Supplies the current customer bearer. Sync or async so consumers can read a
104
- * cookie session (Hydrogen/Remix), a KV store, an in-memory value, etc. Returns
105
- * the token when signed in, or `null`/`undefined` when signed out.
106
- */
107
- type FoirTokenProvider = () => string | null | undefined | Promise<string | null | undefined>;
108
- interface FoirContentClientConfig {
109
- env: FoirEnv;
110
- /**
111
- * Resolves the current customer bearer before every request. When it yields a
112
- * token the token is forwarded, so `authStatus`/segment targeting and
113
- * customer-scoped records resolve as that customer; when it yields
114
- * null/undefined the read hits the anonymous baseline. Omit for a client that
115
- * is always anonymous (equivalent to calling `foirRequest` directly).
116
- */
117
- getToken?: FoirTokenProvider;
118
- }
119
- interface FoirContentClient {
120
- /**
121
- * Run a typed document, forwarding the bound customer bearer when available.
122
- * An explicit `options.bearerToken` still wins, so a single call can override
123
- * the bound token (or force anonymous by passing `undefined` — the bound
124
- * token only fills in when `options.bearerToken` is not supplied).
125
- */
126
- request<TData, TVariables>(document: TypedDocumentNode<TData, TVariables>, variables?: TVariables, options?: FoirRequestOptions): Promise<TData>;
127
- }
128
- /**
129
- * Create a {@link FoirContentClient} bound to an env + token source. Every
130
- * `request` forwards the customer bearer when `getToken` yields one, upgrading
131
- * that read from the anonymous baseline to the signed-in customer.
132
- */
133
- declare function createFoirContentClient(config: FoirContentClientConfig): FoirContentClient;
134
-
135
- export { FOIR_CDN_BASE, type FoirContentClient, type FoirContentClientConfig, type FoirEnv, FoirRequestError, type FoirRequestOptions, type FoirTokenProvider, absolutiseFoirMediaUrl, createFoirContentClient, foirRequest, isFoirPreview };
package/dist/content.d.ts DELETED
@@ -1,96 +0,0 @@
1
- import { ReactNode, JSX } from 'react';
2
- import * as react_jsx_runtime from 'react/jsx-runtime';
3
-
4
- /**
5
- * createContentRenderer — the generic content-dispatch primitive.
6
- *
7
- * It does NOT know any concrete block types. Given a registry that maps each
8
- * block `__typename` to a component, it renders a `flexible` field's block
9
- * array: looks each block up by `__typename`, renders unknown types as null,
10
- * keys by the block `_id`, assigns LCP `priority` to the first block that
11
- * actually renders, and threads a consumer-defined `Ctx` to every component.
12
- *
13
- * The "switch" is a typed object lookup. Exhaustiveness is enforced where the
14
- * registry is BUILT — against the exhaustive `BlockRegistry` type the codegen
15
- * plugin (EID-92) generates per project, so omitting a block type is a compile
16
- * error there, not a runtime surprise here. The consumer can supply different
17
- * registries per surface (e.g. web vs email).
18
- */
19
-
20
- /** Minimal shape every block in a `flexible` field carries. */
21
- interface BlockLike {
22
- __typename: string;
23
- _id?: string | null;
24
- }
25
- /** Props a block component receives from the content renderer. */
26
- interface BlockComponentProps<TBlock, TCtx = unknown> {
27
- block: TBlock;
28
- /** Consumer-defined render context (host product, locale, etc.). */
29
- ctx: TCtx;
30
- /** True only for the first block that renders — the LCP candidate. */
31
- priority: boolean;
32
- }
33
- /** A component that renders one block type. */
34
- type BlockComponent<TBlock, TCtx = unknown> = (props: BlockComponentProps<TBlock, TCtx>) => ReactNode;
35
- /**
36
- * A registry mapping `__typename` → block component. In practice this is the
37
- * exhaustive `BlockRegistry` type the codegen plugin emits for the project;
38
- * here it's the structural lower bound the renderer needs.
39
- */
40
- type BlockRegistry<TCtx = unknown> = Record<string, BlockComponent<any, TCtx>>;
41
- interface ContentRendererProps<TCtx> {
42
- blocks: readonly BlockLike[] | null | undefined;
43
- /** Consumer-defined context passed to every block component. */
44
- ctx: TCtx;
45
- }
46
- /**
47
- * Build a `<ContentRenderer>` bound to a block registry. Returns a component
48
- * that takes the `flexible` field's `blocks` array plus a `ctx`.
49
- */
50
- declare function createContentRenderer<TCtx = unknown>(registry: BlockRegistry<TCtx>): (props: ContentRendererProps<TCtx>) => ReactNode;
51
-
52
- /** A resolved typography token from the project's design tokens. */
53
- interface TypographyToken {
54
- /** Token key referenced by a Lexical node's `style`. */
55
- name: string;
56
- /** Rendered HTML element (paragraph / h1–h6 / blockquote). */
57
- tag?: string;
58
- value: {
59
- fontFamily: string[];
60
- fontSize: string | number;
61
- fontWeight: string | number;
62
- lineHeight: string | number;
63
- letterSpacing: string | number;
64
- textTransform?: string;
65
- };
66
- }
67
- /**
68
- * Provide the project's resolved typography tokens to every nested
69
- * `<RichTextRenderer>` so callers don't thread them through each usage. A
70
- * `tokens` prop on the renderer still takes precedence.
71
- */
72
- declare function RichTextTypographyProvider({ tokens, children, }: {
73
- tokens: TypographyToken[];
74
- children: ReactNode;
75
- }): react_jsx_runtime.JSX.Element;
76
- /** Read the injected typography tokens (null when no provider is mounted). */
77
- declare function useRichTextTypography(): TypographyToken[] | null;
78
- interface RichtextValueLike {
79
- html?: string | null;
80
- json?: unknown;
81
- }
82
- interface RichTextRendererProps {
83
- value: RichtextValueLike | null | undefined;
84
- className?: string;
85
- /**
86
- * Resolved typography tokens. Overrides any provided via
87
- * `<RichTextTypographyProvider>`. When neither is set, paragraphs render
88
- * with `fallbackTag` and no inline typography.
89
- */
90
- tokens?: TypographyToken[];
91
- /** Tag used for any paragraph with no token style and no Lexical tag. */
92
- fallbackTag?: keyof JSX.IntrinsicElements;
93
- }
94
- declare function RichTextRenderer({ value, className, tokens, fallbackTag, }: RichTextRendererProps): react_jsx_runtime.JSX.Element | null;
95
-
96
- export { type BlockComponent, type BlockComponentProps, type BlockLike, type BlockRegistry, type ContentRendererProps, RichTextRenderer, type RichTextRendererProps, RichTextTypographyProvider, type TypographyToken, createContentRenderer, useRichTextTypography };
package/dist/media.d.ts DELETED
@@ -1,234 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
-
3
- /**
4
- * Foir media types + adapters.
5
- *
6
- * Framework-agnostic plumbing for rendering Foir image/video fields with
7
- * `<ProgressiveMedia>`: the canonical source shapes, GraphQL-value → source
8
- * adapters (crop normalization, per-format variant sets, HLS URL
9
- * absolutising), and crop-aware dimension maths for CLS-free layout.
10
- *
11
- * HLS manifest URLs are absolutised via the shared `absolutiseFoirMediaUrl`
12
- * from the client transport — not re-implemented here.
13
- */
14
- /** One rendered tier: a URL + its TRUE (crop-aware) dims (for srcset `w` + CLS). */
15
- interface VariantTier {
16
- url: string;
17
- width?: number | null;
18
- height?: number | null;
19
- }
20
- /** Curated tier set in one format (Foir `ImageVariantSet`). */
21
- interface VariantSet {
22
- thumbnail?: VariantTier | null;
23
- small?: VariantTier | null;
24
- medium?: VariantTier | null;
25
- large?: VariantTier | null;
26
- xlarge?: VariantTier | null;
27
- _2xl?: VariantTier | null;
28
- _3xl?: VariantTier | null;
29
- _4xl?: VariantTier | null;
30
- }
31
- /** A `VariantSet` tier name. */
32
- type VariantTierKey = keyof VariantSet;
33
- /**
34
- * Default tier order, smallest→largest, for walking a `VariantSet`
35
- * deterministically when building a `srcset`. Override per `<ProgressiveMedia>`
36
- * via the `variantTiers` prop when a project curates a different tier set.
37
- */
38
- declare const DEFAULT_VARIANT_TIERS: readonly VariantTierKey[];
39
- /** Image source with progressive loading data. */
40
- interface ProgressiveImageSource {
41
- url: string;
42
- alt?: string;
43
- width?: number;
44
- height?: number;
45
- blurhash?: string;
46
- dominantColor?: string;
47
- thumbnailUrl?: string;
48
- /** Per-format tier sets (WebP universal; AVIF preferred via `<picture>`). */
49
- webp?: VariantSet | null;
50
- avif?: VariantSet | null;
51
- /**
52
- * Optional crop rectangle expressed as percentages of the source image
53
- * (`{x, y, width, height}` in 0–100). Foir's image pipeline serves the
54
- * cropped file at the cropped dimensions, so consumers need this to compute
55
- * correct `width`/`height` attrs for CLS-free rendering.
56
- */
57
- crop?: {
58
- x?: number;
59
- y?: number;
60
- width?: number;
61
- height?: number;
62
- };
63
- }
64
- /** Video source with progressive loading data + optional HLS. */
65
- interface ProgressiveVideoSource {
66
- url: string;
67
- width?: number;
68
- height?: number;
69
- blurhash?: string;
70
- dominantColor?: string;
71
- thumbnailUrl?: string;
72
- previewUrl?: string;
73
- hlsUrl?: string;
74
- duration?: number;
75
- }
76
- /**
77
- * Foir GraphQL `ImageValue`-like input — the shape a consumer's codegen
78
- * produces for an image field (intrinsic dims + per-format variant sets +
79
- * crop as opaque JSON). Structurally compatible with the generated type.
80
- */
81
- interface FoirImageInput {
82
- url?: string | null;
83
- alt?: string | null;
84
- width?: number | null;
85
- height?: number | null;
86
- blurhash?: string | null;
87
- dominantColor?: string | null;
88
- webp?: VariantSet | null;
89
- avif?: VariantSet | null;
90
- crop?: {
91
- [key: string]: unknown;
92
- } | null;
93
- }
94
- /** Foir GraphQL `VideoValue`-like input. */
95
- interface FoirVideoInput {
96
- url?: string | null;
97
- width?: number | null;
98
- height?: number | null;
99
- hlsManifestUrl?: string | null;
100
- thumbnailUrl?: string | null;
101
- previewUrl?: string | null;
102
- blurhash?: string | null;
103
- dominantColor?: string | null;
104
- }
105
- /**
106
- * Adapt a Foir image field to the `ProgressiveImageSource` consumed by
107
- * `<ProgressiveMedia>`. Returns `undefined` when the field is empty (the
108
- * caller falls back to a placeholder). Narrows the JSON-typed `crop` to the
109
- * numeric keys; out-of-range values are filtered in `effectiveImageDimensions`.
110
- */
111
- declare function toProgressiveImage(img: FoirImageInput | null | undefined): ProgressiveImageSource | undefined;
112
- /**
113
- * Adapt a Foir video field to the `ProgressiveVideoSource` consumed by
114
- * `<ProgressiveMedia>`. Absolutises the HLS manifest URL (Foir returns it
115
- * relative to its media proxy). Returns `undefined` when the field is empty.
116
- */
117
- declare function toProgressiveVideo(v: FoirVideoInput | null | undefined): ProgressiveVideoSource | undefined;
118
- /**
119
- * Resolve the dimensions of the file Foir's pipeline will actually serve,
120
- * applying any crop percentages to the source's intrinsic size. Returns null
121
- * when the source has no width/height. Drives both the wrapper aspect-ratio
122
- * and the `<img>` `width`/`height` attrs.
123
- */
124
- declare function effectiveImageDimensions(image: {
125
- width?: number | null;
126
- height?: number | null;
127
- crop?: unknown;
128
- } | null | undefined): {
129
- width: number;
130
- height: number;
131
- } | null;
132
- /**
133
- * Compute a CSS `aspect-ratio` string from a Foir image's natural dimensions
134
- * and optional crop. When a usable crop is set the cropped rectangle's aspect
135
- * wins; otherwise the intrinsic width/height; otherwise `null`.
136
- */
137
- declare function cropAspectRatio(image: {
138
- width?: number | null;
139
- height?: number | null;
140
- crop?: unknown;
141
- } | null | undefined): string | null;
142
-
143
- interface ProgressiveMediaProps {
144
- image?: ProgressiveImageSource;
145
- video?: ProgressiveVideoSource;
146
- alt?: string;
147
- className?: string;
148
- /** Fill the parent container instead of using intrinsic aspect ratio. */
149
- fill?: boolean;
150
- /**
151
- * Object-fit for fill mode. Defaults to 'cover'. Has no effect when `fill`
152
- * is false (the image renders at its intrinsic aspect ratio).
153
- */
154
- fit?: 'cover' | 'contain';
155
- /**
156
- * Solid-colour placeholder mode. When neither image nor video is provided,
157
- * render a flat coloured div. `aspectRatio` defaults to 16/10.
158
- */
159
- placeholder?: {
160
- color: string;
161
- aspectRatio?: number;
162
- };
163
- /** Video playback — autoplay on mount. Default true. */
164
- autoplay?: boolean;
165
- /** Video playback — muted. Default true (required for autoplay). */
166
- muted?: boolean;
167
- /** Video playback — loop on end. Default true. */
168
- loop?: boolean;
169
- /**
170
- * When false, skip loading the full media layer (no `<video>`/full `<img>`
171
- * mount, no HLS attach, no full-image preload). The lower layers — colour,
172
- * blurhash, thumbnail — still render. Used by responsive dual-render so the
173
- * CSS-hidden branch doesn't download its full asset. Default true.
174
- */
175
- active?: boolean;
176
- /**
177
- * `sizes` attribute applied to the full `<img>` — tells the browser how
178
- * wide the image renders so it can pick the right `srcset` entry. Default
179
- * `"100vw"`. Has no effect on video sources.
180
- */
181
- sizes?: string;
182
- /**
183
- * When true, treat this media as the page's LCP candidate: thumbnail and
184
- * full `<img>` get `fetchpriority="high"` + `loading="eager"`, and any
185
- * `<video>` mounts immediately. When false (default) below-fold behaviour:
186
- * `loading="lazy"` on `<img>`, and `<video>` is gated by an
187
- * IntersectionObserver so its `src`/HLS only attaches near the viewport.
188
- */
189
- priority?: boolean;
190
- /**
191
- * Tier order, smallest→largest, used to build the `srcset` from a
192
- * `VariantSet`. Defaults to {@link DEFAULT_VARIANT_TIERS}; override when a
193
- * project curates a different tier set.
194
- */
195
- variantTiers?: readonly VariantTierKey[];
196
- }
197
- declare function ProgressiveMedia({ image, video, alt, className, fill, fit, placeholder, autoplay, muted, loop, active, sizes, priority, variantTiers, }: ProgressiveMediaProps): react_jsx_runtime.JSX.Element | null;
198
-
199
- interface BlurhashCanvasProps {
200
- hash: string;
201
- className?: string;
202
- }
203
- /**
204
- * Decodes a BlurHash string to a 32×32 canvas. `blurhash` is an optional peer
205
- * dependency loaded via dynamic import — if it isn't installed the canvas
206
- * stays blank rather than throwing.
207
- */
208
- declare function BlurhashCanvas({ hash, className }: BlurhashCanvasProps): react_jsx_runtime.JSX.Element;
209
-
210
- type LoadStage = 'color' | 'blurhash' | 'thumbnail' | 'full';
211
- interface UseProgressiveLoadOptions {
212
- blurhash?: string;
213
- thumbnailUrl?: string;
214
- fullUrl?: string;
215
- /**
216
- * Optional srcset + sizes — when provided to image sources, the preloader
217
- * matches the variant the visible `<img>` will pick, so the browser dedupes
218
- * the fetch instead of downloading two sizes.
219
- */
220
- fullSrcSet?: string;
221
- fullSizes?: string;
222
- isVideo?: boolean;
223
- }
224
- /**
225
- * State machine for progressive media loading.
226
- * Stages advance forward only: color → blurhash → thumbnail → full.
227
- * Skips stages when data is missing. Never regresses.
228
- */
229
- declare function useProgressiveLoad({ blurhash, thumbnailUrl, fullUrl, fullSrcSet, fullSizes, isVideo, }: UseProgressiveLoadOptions): {
230
- stage: LoadStage;
231
- onFullReady: () => void;
232
- };
233
-
234
- export { BlurhashCanvas, type BlurhashCanvasProps, DEFAULT_VARIANT_TIERS, type FoirImageInput, type FoirVideoInput, type LoadStage, type ProgressiveImageSource, ProgressiveMedia, type ProgressiveMediaProps, type ProgressiveVideoSource, type UseProgressiveLoadOptions, type VariantSet, type VariantTier, type VariantTierKey, cropAspectRatio, effectiveImageDimensions, toProgressiveImage, toProgressiveVideo, useProgressiveLoad };
package/dist/next.d.ts DELETED
@@ -1,178 +0,0 @@
1
- /**
2
- * Foir GraphQL client — a single typed fetch wrapper for SSR/edge loaders.
3
- *
4
- * No GraphQL client (Apollo/urql) required: the Foir public API is a plain
5
- * `POST` with an `x-api-key` header, and the dominant consumers (Hydrogen on
6
- * Oxygen, React Router loaders, TanStack Start on CF Workers) fetch in
7
- * server-only loaders and render — so Apollo's `InMemoryCache`/`useQuery`
8
- * reactivity is dead weight, and a shared cache on a stateless multi-tenant
9
- * edge worker is a cross-tenant hazard. This helper carries only the
10
- * Foir-specific transport concerns (auth header, preview schema channel,
11
- * error shape). Consumers on a GraphQL client (Apollo / urql / react-query /
12
- * graphql-request) use the generated `TypedDocumentNode`s directly with their
13
- * own client and replicate the two Foir-specific headers below — the
14
- * `x-api-key` and, in preview, `X-Foir-Schema-Channel: draft`.
15
- *
16
- * Deduplicates the hand-copied `lib/foir/client.ts` that shipped identically
17
- * across the Foir storefronts.
18
- */
19
-
20
- interface FoirEnv {
21
- PLATFORM_API_URL?: string;
22
- PLATFORM_API_KEY?: string;
23
- PLATFORM_PREVIEW_API_KEY?: string;
24
- FOIR_PREVIEW?: string;
25
- }
26
-
27
- /**
28
- * Foir customer auth — framework-agnostic flows, token lifecycle, and guards.
29
- *
30
- * Session I/O is injected via {@link SessionAdapter} (no Hydrogen/React-Router
31
- * coupling). Pre-login flows authenticate with the project `x-api-key`;
32
- * post-login reads add the customer bearer. The project-specific profile (e.g.
33
- * `isAdmin`) is resolved by a consumer-supplied `resolveUser` — the SDK never
34
- * hardcodes the per-project customer profile shape.
35
- */
36
-
37
- /** The customer identity carried by an auth result. */
38
- interface FoirCustomer {
39
- id: string;
40
- email: string;
41
- }
42
- /**
43
- * Injected session store. Methods may be sync or async so consumers can plug
44
- * in a cookie session (Hydrogen/Remix), a KV store, etc.
45
- */
46
- interface SessionAdapter {
47
- get(key: string): string | null | undefined | Promise<string | null | undefined>;
48
- set(key: string, value: string): void | Promise<void>;
49
- unset(key: string): void | Promise<void>;
50
- }
51
-
52
- /**
53
- * The minimal cookie-store shape this adapter needs. It's satisfied by Next's
54
- * `cookies()` (route handlers / server actions — `await cookies()` on Next 15),
55
- * and by `NextResponse.cookies` in middleware. Kept structural on purpose so the
56
- * SDK doesn't import (or pin a version of) `next/headers`.
57
- */
58
- interface FoirCookieStore {
59
- get(name: string): {
60
- value: string;
61
- } | undefined;
62
- set(name: string, value: string, options?: Record<string, unknown>): void;
63
- delete(name: string): void;
64
- }
65
- interface CookieAdapterOptions {
66
- /** Cookie attributes for writes, merged over the secure defaults. */
67
- cookieOptions?: Record<string, unknown>;
68
- }
69
- declare function foirCookieName(key: string): string;
70
- /**
71
- * A {@link SessionAdapter} backed by an HttpOnly cookie store — the seam for
72
- * server-side (BFF) Foir sessions in Next.js. Pass the cookie store from a route
73
- * handler / server action (`await cookies()`) for reads and writes; a Server
74
- * Component's `cookies()` is read-only, so use it only for reads there.
75
- */
76
- declare function createFoirCookieAdapter(store: FoirCookieStore, opts?: CookieAdapterOptions): SessionAdapter;
77
-
78
- /**
79
- * Server-side session helpers for the Next.js BFF pattern. Each takes the Next
80
- * cookie store (`await cookies()` in a route handler / server action, or the
81
- * read-only `cookies()` in a Server Component for reads).
82
- *
83
- * Note on "verification": the customer access token is opaque to your app and
84
- * validated by the Foir API on use, so `getFoirSession` returns the identity
85
- * stored in the cookies rather than locally verifying a JWT. A rejected/expired
86
- * bearer surfaces when you call the API (and `@foir/sdk/auth`'s `authedRequest`
87
- * transparently refreshes it).
88
- */
89
- /** The signed-in customer from the session cookies, or null. */
90
- declare function getFoirSession(store: FoirCookieStore): Promise<FoirCustomer | null>;
91
- /** The current access token from the session cookies, or null. */
92
- declare function getFoirToken(store: FoirCookieStore): Promise<string | null>;
93
- /** Clear the session cookies (sign out). */
94
- declare function foirSignOut(store: FoirCookieStore, opts?: CookieAdapterOptions): Promise<void>;
95
- interface PasswordArgs {
96
- env: FoirEnv;
97
- store: FoirCookieStore;
98
- email: string;
99
- password: string;
100
- cookieOptions?: CookieAdapterOptions['cookieOptions'];
101
- }
102
- /** Password sign-in in a route handler; persists the session to cookies. */
103
- declare function foirSignInWithPassword({ env, store, email, password, cookieOptions, }: PasswordArgs): Promise<FoirCustomer>;
104
- /** Register a customer in a route handler; persists the session to cookies. */
105
- declare function foirRegisterWithPassword({ env, store, email, password, cookieOptions, }: PasswordArgs): Promise<FoirCustomer>;
106
- /** Complete an OTP sign-in in a route handler; persists the session to cookies. */
107
- declare function foirSignInWithOtp({ env, store, email, otp, cookieOptions, }: {
108
- env: FoirEnv;
109
- store: FoirCookieStore;
110
- email: string;
111
- otp: string;
112
- cookieOptions?: CookieAdapterOptions['cookieOptions'];
113
- }): Promise<FoirCustomer>;
114
- /**
115
- * Complete a provider (OAuth/OIDC) login in your callback route handler:
116
- * exchange the `code` + `state` for tokens and persist them to the session
117
- * cookies. Returns the customer.
118
- */
119
- declare function completeFoirProviderLogin(opts: {
120
- env: FoirEnv;
121
- store: FoirCookieStore;
122
- providerKey: string;
123
- code?: string;
124
- state?: string;
125
- cookieOptions?: CookieAdapterOptions['cookieOptions'];
126
- }): Promise<FoirCustomer>;
127
-
128
- /**
129
- * The slice of `NextRequest` the middleware reads. Typed structurally so the SDK
130
- * doesn't need `next` installed to build — a real `NextRequest` satisfies it, so
131
- * the returned function drops straight into `export const middleware`.
132
- */
133
- interface FoirMiddlewareRequest {
134
- cookies: {
135
- get(name: string): {
136
- value: string;
137
- } | undefined;
138
- };
139
- nextUrl: {
140
- pathname: string;
141
- search: string;
142
- };
143
- url: string;
144
- }
145
- interface FoirMiddlewareConfig {
146
- /** Where to send unauthenticated requests (path or absolute URL). */
147
- signInUrl: string;
148
- /**
149
- * The session cookie whose presence means "signed in". Defaults to the
150
- * access-token cookie the cookie adapter writes (`foir_token`).
151
- */
152
- cookieName?: string;
153
- /**
154
- * Return true for requests that require auth. Omit to protect every request
155
- * the middleware `matcher` passes through.
156
- */
157
- isProtected?(request: FoirMiddlewareRequest): boolean;
158
- /** Query param carrying the original path on the sign-in URL. Default `returnTo`. */
159
- returnParam?: string;
160
- }
161
- /**
162
- * Build a Next.js middleware that redirects unauthenticated requests to your
163
- * sign-in URL. Edge-safe: it checks for the presence of the session cookie only
164
- * — the bearer itself is validated server-side when you call the Foir API — so
165
- * pair it with a real `getFoirSession` check in protected route handlers /
166
- * server components. Returns a standard `Response` (redirect) or `undefined`
167
- * (continue), both of which Next.js middleware accepts.
168
- *
169
- * ```ts
170
- * // middleware.ts
171
- * import { createFoirMiddleware } from '@foir/sdk/next';
172
- * export const middleware = createFoirMiddleware({ signInUrl: '/sign-in' });
173
- * export const config = { matcher: ['/dashboard/:path*'] };
174
- * ```
175
- */
176
- declare function createFoirMiddleware(config: FoirMiddlewareConfig): (request: FoirMiddlewareRequest) => Response | undefined;
177
-
178
- export { type CookieAdapterOptions, type FoirCookieStore, type FoirCustomer, type FoirEnv, type FoirMiddlewareConfig, type FoirMiddlewareRequest, type SessionAdapter, completeFoirProviderLogin, createFoirCookieAdapter, createFoirMiddleware, foirCookieName, foirRegisterWithPassword, foirSignInWithOtp, foirSignInWithPassword, foirSignOut, getFoirSession, getFoirToken };