@foir/sdk 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +857 -4
- package/README.md +46 -15
- package/dist/auth/auth.d.ts +104 -1
- package/dist/auth/hosted.d.ts +22 -0
- package/dist/auth/index.d.ts +13 -7
- package/dist/auth/operations.d.ts +85 -64
- package/dist/auth/ops.d.ts +99 -0
- package/dist/auth.js +786 -106
- package/dist/chunk-IGNLWT3H.js +35 -0
- package/dist/chunk-OHYVKTGB.js +45 -0
- package/dist/chunk-TAL5H6VA.js +39 -0
- package/dist/client.js +25 -31
- package/dist/codegen/block-registry.d.ts +13 -19
- package/dist/codegen/block-registry.js +3 -31
- package/dist/codegen/block-scaffold.d.ts +12 -21
- package/dist/codegen/block-scaffold.js +3 -41
- package/dist/codegen/index.d.ts +9 -4
- package/dist/codegen/index.js +7 -11
- package/dist/codegen/item-registry.d.ts +28 -0
- package/dist/codegen/item-registry.js +7 -0
- package/dist/codegen/item-scaffold.d.ts +29 -0
- package/dist/codegen/item-scaffold.js +7 -0
- package/dist/codegen/preset.d.ts +14 -7
- package/dist/codegen/shared.d.ts +20 -9
- package/dist/content/content-renderer.d.ts +90 -24
- package/dist/content/index.d.ts +13 -7
- package/dist/content/richtext.d.ts +66 -18
- package/dist/content.js +227 -80
- package/dist/data/builtins.d.ts +369 -92
- package/dist/data/client.d.ts +97 -25
- package/dist/data/document.d.ts +251 -0
- package/dist/data/index.d.ts +38 -19
- package/dist/data/manifest.d.ts +290 -8
- package/dist/data/schema.d.ts +78 -8
- package/dist/data/selection.d.ts +231 -37
- package/dist/data/subjects.d.ts +221 -0
- package/dist/data/subscription-document.d.ts +75 -0
- package/dist/data/subscriptions.d.ts +181 -0
- package/dist/data/transport.d.ts +255 -37
- package/dist/data/ws-transport.d.ts +197 -0
- package/dist/data.js +1419 -45
- package/dist/graphql/cdn-route.d.ts +12 -28
- package/dist/media/index.d.ts +6 -2
- package/dist/media/media.d.ts +2 -2
- package/dist/media/screen-capture.d.ts +81 -0
- package/dist/media.js +97 -0
- package/dist/next.js +663 -182
- package/dist/push.js +700 -90
- package/dist/react/FoirFeedback.d.ts +62 -0
- package/dist/react/feedback-notes.d.ts +101 -0
- package/dist/react/index.d.ts +7 -1
- package/dist/react.js +1272 -194
- package/dist/realtime.js +1 -1
- package/dist/server/events-client.d.ts +279 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server.js +298 -0
- package/dist/transport/foir-http.d.ts +23 -6
- package/dist/transport/persisted-query.d.ts +68 -0
- package/dist/transport/retry.d.ts +1 -1
- package/package.json +13 -1
- package/dist/chunk-ADO5FJNM.js +0 -30
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_GRAPHQL_IMPORT,
|
|
3
|
+
DEFAULT_SDK_IMPORT,
|
|
4
|
+
collectItemMembers
|
|
5
|
+
} from "./chunk-TAL5H6VA.js";
|
|
6
|
+
|
|
7
|
+
// src/codegen/item-registry.ts
|
|
8
|
+
var plugin = (schema, _documents, config = {}) => {
|
|
9
|
+
const members = collectItemMembers(schema, config.unions);
|
|
10
|
+
const graphqlImport = config.graphqlImport ?? DEFAULT_GRAPHQL_IMPORT;
|
|
11
|
+
const sdkImport = config.sdkImport ?? DEFAULT_SDK_IMPORT;
|
|
12
|
+
const registryName = config.registryName ?? "ItemRegistry";
|
|
13
|
+
return [
|
|
14
|
+
"/* eslint-disable */",
|
|
15
|
+
"// Generated by @foir/sdk/codegen/item-registry. Do not edit by hand.",
|
|
16
|
+
"// Regenerated on every codegen run \u2014 omitting an item type is a compile error.",
|
|
17
|
+
`import type { ItemComponent } from '${sdkImport}';`,
|
|
18
|
+
`import type {`,
|
|
19
|
+
...members.map((m) => ` ${m},`),
|
|
20
|
+
`} from '${graphqlImport}';`,
|
|
21
|
+
"",
|
|
22
|
+
`/**`,
|
|
23
|
+
` * Exhaustive map of every item \`__typename\` in the project schema to the`,
|
|
24
|
+
` * component that renders it. Pass an instance to \`createContentRenderer\`.`,
|
|
25
|
+
` */`,
|
|
26
|
+
`export type ${registryName}<Ctx = unknown> = {`,
|
|
27
|
+
...members.map((m) => ` ${m}: ItemComponent<${m}, Ctx>;`),
|
|
28
|
+
`};`,
|
|
29
|
+
""
|
|
30
|
+
].join("\n");
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
plugin
|
|
35
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_GRAPHQL_IMPORT,
|
|
3
|
+
DEFAULT_SDK_IMPORT,
|
|
4
|
+
collectItemMembers
|
|
5
|
+
} from "./chunk-TAL5H6VA.js";
|
|
6
|
+
|
|
7
|
+
// src/codegen/item-scaffold.ts
|
|
8
|
+
var plugin = (schema, _documents, config = {}) => {
|
|
9
|
+
const members = collectItemMembers(schema, config.unions);
|
|
10
|
+
const graphqlImport = config.graphqlImport ?? DEFAULT_GRAPHQL_IMPORT;
|
|
11
|
+
const sdkImport = config.sdkImport ?? DEFAULT_SDK_IMPORT;
|
|
12
|
+
const registryImport = config.registryImport ?? "./item-registry";
|
|
13
|
+
const ctx = config.ctxType ?? "unknown";
|
|
14
|
+
const stub = (m) => [
|
|
15
|
+
`function ${m}View(props: ItemComponentProps<${m}, ${ctx}>) {`,
|
|
16
|
+
` // TODO: render ${m} from props.item (props.ctx, props.priority available)`,
|
|
17
|
+
` void props;`,
|
|
18
|
+
` return null;`,
|
|
19
|
+
`}`
|
|
20
|
+
].join("\n");
|
|
21
|
+
return [
|
|
22
|
+
"/* eslint-disable */",
|
|
23
|
+
"// Scaffolded once by @foir/sdk/codegen/item-scaffold \u2014 you own this file.",
|
|
24
|
+
"// Implement each stub; the build stays green until you do.",
|
|
25
|
+
`import { createContentRenderer, type ItemComponentProps } from '${sdkImport}';`,
|
|
26
|
+
`import type { ItemRegistry } from '${registryImport}';`,
|
|
27
|
+
`import type {`,
|
|
28
|
+
...members.map((m) => ` ${m},`),
|
|
29
|
+
`} from '${graphqlImport}';`,
|
|
30
|
+
...config.ctxImport ? ["", config.ctxImport] : [],
|
|
31
|
+
"",
|
|
32
|
+
...members.map(stub),
|
|
33
|
+
"",
|
|
34
|
+
`export const itemRegistry: ItemRegistry<${ctx}> = {`,
|
|
35
|
+
...members.map((m) => ` ${m}: ${m}View,`),
|
|
36
|
+
`};`,
|
|
37
|
+
"",
|
|
38
|
+
`export const ContentRenderer = createContentRenderer<${ctx}>(itemRegistry);`,
|
|
39
|
+
""
|
|
40
|
+
].join("\n");
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
plugin
|
|
45
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/codegen/shared.ts
|
|
2
|
+
import { isUnionType } from "graphql";
|
|
3
|
+
var DEFAULT_GRAPHQL_IMPORT = "./graphql";
|
|
4
|
+
var DEFAULT_SDK_IMPORT = "@foir/sdk/content";
|
|
5
|
+
var PASSAGE = "Passage";
|
|
6
|
+
function collectItemMembers(schema, unionNames) {
|
|
7
|
+
const members = /* @__PURE__ */ new Set();
|
|
8
|
+
const missing = [];
|
|
9
|
+
if (unionNames && unionNames.length > 0) {
|
|
10
|
+
for (const name of unionNames) {
|
|
11
|
+
const type = schema.getType(name);
|
|
12
|
+
if (!type || !isUnionType(type)) {
|
|
13
|
+
missing.push(name);
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
for (const member of type.getTypes()) members.add(member.name);
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
for (const type of Object.values(schema.getTypeMap())) {
|
|
20
|
+
if (!isUnionType(type)) continue;
|
|
21
|
+
const names = type.getTypes().map((m) => m.name);
|
|
22
|
+
if (!names.includes(PASSAGE)) continue;
|
|
23
|
+
for (const name of names) members.add(name);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
members.delete(PASSAGE);
|
|
27
|
+
if (members.size === 0) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`[foir codegen] no item members found. ` + (unionNames && unionNames.length > 0 ? `Looked for union(s): ${unionNames.join(", ")}` + (missing.length ? ` (not found or not a union: ${missing.join(", ")})` : "") : `No prose entries union (a union containing Passage) exists in the schema`) + `. Run \`foir push\`, then confirm the schema has a prose field that places models \u2014 a prose field's entries union is named by its materialised member set.`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return [...members].sort();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
DEFAULT_GRAPHQL_IMPORT,
|
|
37
|
+
DEFAULT_SDK_IMPORT,
|
|
38
|
+
collectItemMembers
|
|
39
|
+
};
|
package/dist/client.js
CHANGED
|
@@ -129,18 +129,14 @@ function readFoirEnvelope(json) {
|
|
|
129
129
|
return json.data;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// src/
|
|
133
|
-
var
|
|
134
|
-
function
|
|
135
|
-
|
|
136
|
-
if (isFoirPreview(env)) return false;
|
|
137
|
-
const apiKey = resolveFoirApiKey(env);
|
|
138
|
-
if (!apiKey?.startsWith("pk_")) return false;
|
|
139
|
-
return !/\bmutation\b/.test(documentText);
|
|
132
|
+
// src/transport/persisted-query.ts
|
|
133
|
+
var FOIR_CDN_GRAPHQL_PATH = "/cdn/graphql";
|
|
134
|
+
function persistedQueryExtension(hash) {
|
|
135
|
+
return { persistedQuery: { version: 1, sha256Hash: hash } };
|
|
140
136
|
}
|
|
141
137
|
function buildCdnUrl(endpoint, apiKey, hash, variables) {
|
|
142
138
|
const url = new URL(endpoint);
|
|
143
|
-
url.pathname = url.pathname.replace(/\/graphql\/?$/, "") +
|
|
139
|
+
url.pathname = url.pathname.replace(/\/graphql\/?$/, "") + FOIR_CDN_GRAPHQL_PATH;
|
|
144
140
|
url.searchParams.set("key", apiKey);
|
|
145
141
|
url.searchParams.set("extensions", JSON.stringify(persistedQueryExtension(hash)));
|
|
146
142
|
if (variables && Object.keys(variables).length > 0) {
|
|
@@ -148,18 +144,29 @@ function buildCdnUrl(endpoint, apiKey, hash, variables) {
|
|
|
148
144
|
}
|
|
149
145
|
return url.toString();
|
|
150
146
|
}
|
|
151
|
-
function persistedQueryExtension(hash) {
|
|
152
|
-
return { persistedQuery: { version: 1, sha256Hash: hash } };
|
|
153
|
-
}
|
|
154
147
|
async function documentHash(documentText) {
|
|
155
|
-
const digest = await crypto.subtle.digest(
|
|
156
|
-
"SHA-256",
|
|
157
|
-
new TextEncoder().encode(documentText)
|
|
158
|
-
);
|
|
148
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(documentText));
|
|
159
149
|
return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
160
150
|
}
|
|
161
151
|
var PERSISTED_QUERY_NOT_FOUND = "PERSISTED_QUERY_NOT_FOUND";
|
|
162
152
|
var NOT_SHAREABLE = "NOT_SHAREABLE";
|
|
153
|
+
async function hasFoirErrorCode(res, ...codes) {
|
|
154
|
+
try {
|
|
155
|
+
const body = await res.clone().json();
|
|
156
|
+
return body.errors?.some((e) => e.extensions?.code !== void 0 && codes.includes(e.extensions.code)) ?? false;
|
|
157
|
+
} catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/graphql/cdn-route.ts
|
|
163
|
+
function isCdnEligible(env, documentText, bearerToken) {
|
|
164
|
+
if (bearerToken) return false;
|
|
165
|
+
if (isFoirPreview(env)) return false;
|
|
166
|
+
const apiKey = resolveFoirApiKey(env);
|
|
167
|
+
if (!apiKey?.startsWith("pk_")) return false;
|
|
168
|
+
return !/\bmutation\b/.test(documentText);
|
|
169
|
+
}
|
|
163
170
|
|
|
164
171
|
// src/transport/retry.ts
|
|
165
172
|
var DEFAULT_ATTEMPTS = 3;
|
|
@@ -288,23 +295,10 @@ async function readErrorEnvelope(res) {
|
|
|
288
295
|
return errors;
|
|
289
296
|
}
|
|
290
297
|
async function isSharedRefusal(res) {
|
|
291
|
-
|
|
292
|
-
try {
|
|
293
|
-
const body = await res.clone().json();
|
|
294
|
-
return body.errors?.some((e) => e.extensions?.code === NOT_SHAREABLE) ?? false;
|
|
295
|
-
} catch {
|
|
296
|
-
return false;
|
|
297
|
-
}
|
|
298
|
+
return hasFoirErrorCode(res, NOT_SHAREABLE);
|
|
298
299
|
}
|
|
299
300
|
async function isPersistedQueryMiss(res) {
|
|
300
|
-
|
|
301
|
-
const body = await res.clone().json();
|
|
302
|
-
return body.errors?.some(
|
|
303
|
-
(e) => e.extensions?.code === PERSISTED_QUERY_NOT_FOUND
|
|
304
|
-
) ?? false;
|
|
305
|
-
} catch {
|
|
306
|
-
return false;
|
|
307
|
-
}
|
|
301
|
+
return hasFoirErrorCode(res, PERSISTED_QUERY_NOT_FOUND);
|
|
308
302
|
}
|
|
309
303
|
|
|
310
304
|
// src/graphql/content-client.ts
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@foir/sdk/codegen/block-registry` —
|
|
2
|
+
* `@foir/sdk/codegen/block-registry` — DEPRECATED alias.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* exhaustiveness by construction, replacing the hand-synced switch the
|
|
10
|
-
* storefront's `BlockDigester` used to carry.
|
|
4
|
+
* `block` was one project's name for a flexible field, never a platform
|
|
5
|
+
* concept (TTS-1391). The plugin moved to `@foir/sdk/codegen/item-registry`;
|
|
6
|
+
* this path re-exports it unchanged so an existing `codegen.ts` keeps working.
|
|
7
|
+
* Repoint the `plugins:` entry when convenient — this will be removed in a
|
|
8
|
+
* future major.
|
|
11
9
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* Note that the emitted type is now named `ItemRegistry` by default and its
|
|
11
|
+
* components are typed `ItemComponent`. If you import the generated
|
|
12
|
+
* `BlockRegistry` by name, either pass `registryName: 'BlockRegistry'` or
|
|
13
|
+
* update the import; `@foir/sdk/content` still exports `BlockRegistry` as a
|
|
14
|
+
* deprecated alias of `ItemRegistry`, so the types remain compatible.
|
|
15
15
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
export interface BlockRegistryConfig extends BlockPluginConfig {
|
|
19
|
-
/** Name of the generated registry type. Default `BlockRegistry`. */
|
|
20
|
-
registryName?: string;
|
|
21
|
-
}
|
|
22
|
-
/** graphql-codegen plugin entrypoint. */
|
|
23
|
-
export declare const plugin: (schema: GraphQLSchema, _documents: unknown, config?: BlockRegistryConfig) => string;
|
|
16
|
+
export { plugin } from './item-registry';
|
|
17
|
+
export type { ItemRegistryConfig, BlockRegistryConfig, } from './item-registry';
|
|
@@ -1,35 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
collectBlockMembers
|
|
6
|
-
} from "../chunk-ADO5FJNM.js";
|
|
7
|
-
|
|
8
|
-
// src/codegen/block-registry.ts
|
|
9
|
-
var plugin = (schema, _documents, config = {}) => {
|
|
10
|
-
const members = collectBlockMembers(schema, config.unions ?? DEFAULT_UNIONS);
|
|
11
|
-
const graphqlImport = config.graphqlImport ?? DEFAULT_GRAPHQL_IMPORT;
|
|
12
|
-
const sdkImport = config.sdkImport ?? DEFAULT_SDK_IMPORT;
|
|
13
|
-
const registryName = config.registryName ?? "BlockRegistry";
|
|
14
|
-
return [
|
|
15
|
-
"/* eslint-disable */",
|
|
16
|
-
"// Generated by @foir/sdk/codegen/block-registry. Do not edit by hand.",
|
|
17
|
-
"// Regenerated on every codegen run \u2014 omitting a block type is a compile error.",
|
|
18
|
-
`import type { BlockComponent } from '${sdkImport}';`,
|
|
19
|
-
`import type {`,
|
|
20
|
-
...members.map((m) => ` ${m},`),
|
|
21
|
-
`} from '${graphqlImport}';`,
|
|
22
|
-
"",
|
|
23
|
-
`/**`,
|
|
24
|
-
` * Exhaustive map of every block \`__typename\` in the project schema to the`,
|
|
25
|
-
` * component that renders it. Pass an instance to \`createContentRenderer\`.`,
|
|
26
|
-
` */`,
|
|
27
|
-
`export type ${registryName}<Ctx = unknown> = {`,
|
|
28
|
-
...members.map((m) => ` ${m}: BlockComponent<${m}, Ctx>;`),
|
|
29
|
-
`};`,
|
|
30
|
-
""
|
|
31
|
-
].join("\n");
|
|
32
|
-
};
|
|
2
|
+
plugin
|
|
3
|
+
} from "../chunk-IGNLWT3H.js";
|
|
4
|
+
import "../chunk-TAL5H6VA.js";
|
|
33
5
|
export {
|
|
34
6
|
plugin
|
|
35
7
|
};
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@foir/sdk/codegen/block-scaffold` —
|
|
2
|
+
* `@foir/sdk/codegen/block-scaffold` — DEPRECATED alias.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* `block` was one project's name for a flexible field, never a platform
|
|
5
|
+
* concept (TTS-1391). The plugin moved to `@foir/sdk/codegen/item-scaffold`;
|
|
6
|
+
* this path re-exports it unchanged so an existing `codegen.ts` keeps working.
|
|
7
|
+
* Repoint the `plugins:` entry when convenient — this will be removed in a
|
|
8
|
+
* future major.
|
|
9
|
+
*
|
|
10
|
+
* The scaffold is a one-shot generator, so a file scaffolded under the old name
|
|
11
|
+
* is yours and is untouched by this. Newly scaffolded files export
|
|
12
|
+
* `itemRegistry` rather than `blockRegistry` and take `props.item`.
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export interface BlockScaffoldConfig extends BlockPluginConfig {
|
|
16
|
-
/** Import path for the generated registry type. Default `./block-registry`. */
|
|
17
|
-
registryImport?: string;
|
|
18
|
-
/** Render-context type name threaded to every component. Default `unknown`. */
|
|
19
|
-
ctxType?: string;
|
|
20
|
-
/** Optional import line for the ctx type, e.g. `import type { Ctx } from '~/ctx'`. */
|
|
21
|
-
ctxImport?: string;
|
|
22
|
-
}
|
|
23
|
-
/** graphql-codegen plugin entrypoint. */
|
|
24
|
-
export declare const plugin: (schema: GraphQLSchema, _documents: unknown, config?: BlockScaffoldConfig) => string;
|
|
14
|
+
export { plugin } from './item-scaffold';
|
|
15
|
+
export type { ItemScaffoldConfig, BlockScaffoldConfig, } from './item-scaffold';
|
|
@@ -1,45 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
collectBlockMembers
|
|
6
|
-
} from "../chunk-ADO5FJNM.js";
|
|
7
|
-
|
|
8
|
-
// src/codegen/block-scaffold.ts
|
|
9
|
-
var plugin = (schema, _documents, config = {}) => {
|
|
10
|
-
const members = collectBlockMembers(schema, config.unions ?? DEFAULT_UNIONS);
|
|
11
|
-
const graphqlImport = config.graphqlImport ?? DEFAULT_GRAPHQL_IMPORT;
|
|
12
|
-
const sdkImport = config.sdkImport ?? DEFAULT_SDK_IMPORT;
|
|
13
|
-
const registryImport = config.registryImport ?? "./block-registry";
|
|
14
|
-
const ctx = config.ctxType ?? "unknown";
|
|
15
|
-
const stub = (m) => [
|
|
16
|
-
`function ${m}View(props: BlockComponentProps<${m}, ${ctx}>) {`,
|
|
17
|
-
` // TODO: render ${m} from props.block (props.ctx, props.priority available)`,
|
|
18
|
-
` void props;`,
|
|
19
|
-
` return null;`,
|
|
20
|
-
`}`
|
|
21
|
-
].join("\n");
|
|
22
|
-
return [
|
|
23
|
-
"/* eslint-disable */",
|
|
24
|
-
"// Scaffolded once by @foir/sdk/codegen/block-scaffold \u2014 you own this file.",
|
|
25
|
-
"// Implement each stub; the build stays green until you do.",
|
|
26
|
-
`import { createContentRenderer, type BlockComponentProps } from '${sdkImport}';`,
|
|
27
|
-
`import type { BlockRegistry } from '${registryImport}';`,
|
|
28
|
-
`import type {`,
|
|
29
|
-
...members.map((m) => ` ${m},`),
|
|
30
|
-
`} from '${graphqlImport}';`,
|
|
31
|
-
...config.ctxImport ? ["", config.ctxImport] : [],
|
|
32
|
-
"",
|
|
33
|
-
...members.map(stub),
|
|
34
|
-
"",
|
|
35
|
-
`export const blockRegistry: BlockRegistry<${ctx}> = {`,
|
|
36
|
-
...members.map((m) => ` ${m}: ${m}View,`),
|
|
37
|
-
`};`,
|
|
38
|
-
"",
|
|
39
|
-
`export const ContentRenderer = createContentRenderer<${ctx}>(blockRegistry);`,
|
|
40
|
-
""
|
|
41
|
-
].join("\n");
|
|
42
|
-
};
|
|
2
|
+
plugin
|
|
3
|
+
} from "../chunk-OHYVKTGB.js";
|
|
4
|
+
import "../chunk-TAL5H6VA.js";
|
|
43
5
|
export {
|
|
44
6
|
plugin
|
|
45
7
|
};
|
package/dist/codegen/index.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@foir/sdk/codegen` — Foir graphql-codegen preset +
|
|
2
|
+
* `@foir/sdk/codegen` — Foir graphql-codegen preset + item-registry plugin.
|
|
3
3
|
*
|
|
4
4
|
* Build-time only. `@graphql-codegen/cli` + `@graphql-codegen/client-preset`
|
|
5
|
-
* are optional peer dependencies (the consumer's devDeps). The
|
|
6
|
-
* and
|
|
7
|
-
* `@foir/sdk/codegen/
|
|
5
|
+
* are optional peer dependencies (the consumer's devDeps). The item-registry
|
|
6
|
+
* and item-scaffold plugins are wired by the preset and also available at
|
|
7
|
+
* `@foir/sdk/codegen/item-registry` / `@foir/sdk/codegen/item-scaffold`.
|
|
8
|
+
*
|
|
9
|
+
* The pre-TTS-1391 paths `@foir/sdk/codegen/block-registry` and
|
|
10
|
+
* `/block-scaffold` still resolve, re-exporting those modules unchanged.
|
|
8
11
|
*/
|
|
9
12
|
export { foirCodegen, foirScaffold } from './preset';
|
|
10
13
|
export type { FoirCodegenOptions, FoirScaffoldOptions } from './preset';
|
|
14
|
+
export type { ItemPluginConfig } from './shared';
|
|
15
|
+
/** @deprecated Renamed to `ItemPluginConfig`. */
|
|
11
16
|
export type { BlockPluginConfig } from './shared';
|
package/dist/codegen/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_UNIONS
|
|
3
|
-
} from "../chunk-ADO5FJNM.js";
|
|
4
|
-
|
|
5
1
|
// src/codegen/preset.ts
|
|
6
2
|
var DEFAULT_OUTPUT_DIR = "./app/gql/foir/";
|
|
7
3
|
var DEFAULT_DOCUMENTS = "app/graphql/foir/**/*.graphql";
|
|
@@ -30,8 +26,8 @@ function foirCodegen(options) {
|
|
|
30
26
|
const previewKey = options.previewKey ?? options.apiKey;
|
|
31
27
|
const outputDir = normalizeDir(options.outputDir ?? DEFAULT_OUTPUT_DIR);
|
|
32
28
|
const documents = options.documents ?? DEFAULT_DOCUMENTS;
|
|
33
|
-
const
|
|
34
|
-
const registryFile = options.registryFile ?? `${outputDir}
|
|
29
|
+
const unions = options.itemUnions ?? options.blockUnions;
|
|
30
|
+
const registryFile = options.registryFile ?? `${outputDir}item-registry.ts`;
|
|
35
31
|
return {
|
|
36
32
|
schema: schemaEntry(options.apiUrl, previewKey),
|
|
37
33
|
documents,
|
|
@@ -47,8 +43,8 @@ function foirCodegen(options) {
|
|
|
47
43
|
}
|
|
48
44
|
},
|
|
49
45
|
[registryFile]: {
|
|
50
|
-
plugins: ["@foir/sdk/codegen/
|
|
51
|
-
config: { unions
|
|
46
|
+
plugins: ["@foir/sdk/codegen/item-registry"],
|
|
47
|
+
config: { unions }
|
|
52
48
|
}
|
|
53
49
|
}
|
|
54
50
|
};
|
|
@@ -57,15 +53,15 @@ function foirScaffold(options) {
|
|
|
57
53
|
const previewKey = options.previewKey ?? options.apiKey;
|
|
58
54
|
const outputDir = normalizeDir(options.outputDir ?? DEFAULT_OUTPUT_DIR);
|
|
59
55
|
const scaffoldFile = options.scaffoldFile ?? `${outputDir}ContentRenderer.tsx`;
|
|
60
|
-
const
|
|
56
|
+
const unions = options.itemUnions ?? options.blockUnions;
|
|
61
57
|
return {
|
|
62
58
|
schema: schemaEntry(options.apiUrl, previewKey),
|
|
63
59
|
ignoreNoDocuments: true,
|
|
64
60
|
generates: {
|
|
65
61
|
[scaffoldFile]: {
|
|
66
|
-
plugins: ["@foir/sdk/codegen/
|
|
62
|
+
plugins: ["@foir/sdk/codegen/item-scaffold"],
|
|
67
63
|
config: {
|
|
68
|
-
unions
|
|
64
|
+
unions,
|
|
69
65
|
ctxType: options.ctxType,
|
|
70
66
|
ctxImport: options.ctxImport,
|
|
71
67
|
registryImport: options.registryImport
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@foir/sdk/codegen/item-registry` — a graphql-codegen plugin.
|
|
3
|
+
*
|
|
4
|
+
* Introspects the project's public schema, collects every member of the
|
|
5
|
+
* flexible union(s), and emits an EXHAUSTIVE `ItemRegistry` type — one key per
|
|
6
|
+
* item `__typename`, each typed `ItemComponent<ThatItem, Ctx>`. Because the
|
|
7
|
+
* type requires every key, a project that adds an inline model (→ a new item
|
|
8
|
+
* `__typename`) breaks the consumer's build until the new component is wired:
|
|
9
|
+
* exhaustiveness by construction, replacing the hand-synced switch a storefront
|
|
10
|
+
* would otherwise carry.
|
|
11
|
+
*
|
|
12
|
+
* Wired automatically by `foirCodegen()`. The generated file imports the item
|
|
13
|
+
* types from the codegen output (`./graphql`) and `ItemComponent` from
|
|
14
|
+
* `@foir/sdk/content`, so it pairs directly with `createContentRenderer`.
|
|
15
|
+
*
|
|
16
|
+
* Reachable at the pre-TTS-1391 path `@foir/sdk/codegen/block-registry` too,
|
|
17
|
+
* which re-exports this module unchanged.
|
|
18
|
+
*/
|
|
19
|
+
import type { GraphQLSchema } from 'graphql';
|
|
20
|
+
import { type ItemPluginConfig } from './shared';
|
|
21
|
+
export interface ItemRegistryConfig extends ItemPluginConfig {
|
|
22
|
+
/** Name of the generated registry type. Default `ItemRegistry`. */
|
|
23
|
+
registryName?: string;
|
|
24
|
+
}
|
|
25
|
+
/** @deprecated Renamed to {@link ItemRegistryConfig}. */
|
|
26
|
+
export type BlockRegistryConfig = ItemRegistryConfig;
|
|
27
|
+
/** graphql-codegen plugin entrypoint. */
|
|
28
|
+
export declare const plugin: (schema: GraphQLSchema, _documents: unknown, config?: ItemRegistryConfig) => string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@foir/sdk/codegen/item-scaffold` — a one-shot graphql-codegen plugin.
|
|
3
|
+
*
|
|
4
|
+
* Emits a ContentRenderer shell: a stub component per item `__typename`, an
|
|
5
|
+
* `itemRegistry` of the (exhaustive) `ItemRegistry` type, and a
|
|
6
|
+
* `createContentRenderer` wiring. Unlike the item-registry plugin (which
|
|
7
|
+
* regenerates every run), this is a STARTING POINT the dev then owns — run it
|
|
8
|
+
* once via `foirScaffold()`, then implement each stub. It compiles out of the
|
|
9
|
+
* box (each stub is a typed no-op) so the build stays green while you fill them
|
|
10
|
+
* in. Adding a new item type later surfaces as a compile error on
|
|
11
|
+
* `itemRegistry` (via the regenerated `ItemRegistry` type), not here.
|
|
12
|
+
*
|
|
13
|
+
* Reachable at the pre-TTS-1391 path `@foir/sdk/codegen/block-scaffold` too,
|
|
14
|
+
* which re-exports this module unchanged.
|
|
15
|
+
*/
|
|
16
|
+
import type { GraphQLSchema } from 'graphql';
|
|
17
|
+
import { type ItemPluginConfig } from './shared';
|
|
18
|
+
export interface ItemScaffoldConfig extends ItemPluginConfig {
|
|
19
|
+
/** Import path for the generated registry type. Default `./item-registry`. */
|
|
20
|
+
registryImport?: string;
|
|
21
|
+
/** Render-context type name threaded to every component. Default `unknown`. */
|
|
22
|
+
ctxType?: string;
|
|
23
|
+
/** Optional import line for the ctx type, e.g. `import type { Ctx } from '~/ctx'`. */
|
|
24
|
+
ctxImport?: string;
|
|
25
|
+
}
|
|
26
|
+
/** @deprecated Renamed to {@link ItemScaffoldConfig}. */
|
|
27
|
+
export type BlockScaffoldConfig = ItemScaffoldConfig;
|
|
28
|
+
/** graphql-codegen plugin entrypoint. */
|
|
29
|
+
export declare const plugin: (schema: GraphQLSchema, _documents: unknown, config?: ItemScaffoldConfig) => string;
|
package/dist/codegen/preset.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* a consumer's `codegen.ts` is ~3 lines instead of the ~109 every storefront
|
|
6
6
|
* hand-copies. It standardizes the Foir conventions (custom scalars,
|
|
7
7
|
* `enumValues: 'keep'`, the `X-Foir-Schema-Channel: draft` introspection header)
|
|
8
|
-
* AND wires the
|
|
8
|
+
* AND wires the item-registry plugin so the exhaustive `ItemRegistry` type is
|
|
9
9
|
* regenerated alongside the typed documents.
|
|
10
10
|
*
|
|
11
11
|
* `foirScaffold()` is the separate one-shot that writes the ContentRenderer
|
|
@@ -30,31 +30,38 @@ export interface FoirCodegenOptions {
|
|
|
30
30
|
outputDir?: string;
|
|
31
31
|
/** Operation document glob(s). Default `app/graphql/foir/**\/*.graphql`. */
|
|
32
32
|
documents?: string | string[];
|
|
33
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Entries union name(s) for the registry. When unset, every prose
|
|
35
|
+
* entries union in the schema (the unions carrying `Passage`) is
|
|
36
|
+
* discovered at introspection time. Set explicitly to narrow the
|
|
37
|
+
* registry to specific fields' unions.
|
|
38
|
+
*/
|
|
39
|
+
itemUnions?: string[];
|
|
40
|
+
/** @deprecated Renamed to `itemUnions`. Honoured when `itemUnions` is unset. */
|
|
34
41
|
blockUnions?: string[];
|
|
35
|
-
/** Generated registry file path. Default `<outputDir>
|
|
42
|
+
/** Generated registry file path. Default `<outputDir>item-registry.ts`. */
|
|
36
43
|
registryFile?: string;
|
|
37
44
|
/** Extra/override custom scalars merged onto the Foir defaults. */
|
|
38
45
|
scalars?: Record<string, unknown>;
|
|
39
46
|
}
|
|
40
47
|
/**
|
|
41
48
|
* Build the continuous Foir codegen config: typed documents + the exhaustive
|
|
42
|
-
*
|
|
49
|
+
* item registry. Drop it into `codegen.ts` and run `graphql-codegen`.
|
|
43
50
|
*/
|
|
44
51
|
export declare function foirCodegen(options: FoirCodegenOptions): CodegenConfig;
|
|
45
52
|
export interface FoirScaffoldOptions extends FoirCodegenOptions {
|
|
46
53
|
/** Output path for the scaffold. Default `<outputDir>ContentRenderer.tsx`. */
|
|
47
54
|
scaffoldFile?: string;
|
|
48
|
-
/** Render-context type threaded to every
|
|
55
|
+
/** Render-context type threaded to every item component. Default `unknown`. */
|
|
49
56
|
ctxType?: string;
|
|
50
57
|
/** Optional ctx-type import line, e.g. `import type { Ctx } from '~/ctx'`. */
|
|
51
58
|
ctxImport?: string;
|
|
52
|
-
/** Import path for the generated registry type. Default `./
|
|
59
|
+
/** Import path for the generated registry type. Default `./item-registry`. */
|
|
53
60
|
registryImport?: string;
|
|
54
61
|
}
|
|
55
62
|
/**
|
|
56
63
|
* Build the one-shot scaffold config — writes a ContentRenderer shell with a
|
|
57
|
-
* typed stub per
|
|
64
|
+
* typed stub per item type. Run once (`graphql-codegen --config scaffold.ts`),
|
|
58
65
|
* then own and implement the output.
|
|
59
66
|
*/
|
|
60
67
|
export declare function foirScaffold(options: FoirScaffoldOptions): CodegenConfig;
|
package/dist/codegen/shared.d.ts
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
* Shared introspection helpers for the Foir codegen plugins.
|
|
3
3
|
*/
|
|
4
4
|
import { type GraphQLSchema } from 'graphql';
|
|
5
|
-
export interface
|
|
5
|
+
export interface ItemPluginConfig {
|
|
6
6
|
/**
|
|
7
|
-
* Union type name(s) to collect
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Union type name(s) to collect item members from. When unset, the
|
|
8
|
+
* plugins DISCOVER the project's prose entries unions: every union whose
|
|
9
|
+
* member set includes `Passage` (each prose field's entries union is
|
|
10
|
+
* named by its materialised member set, so there is no single fixed
|
|
11
|
+
* name to configure). Set explicitly to narrow the registry to specific
|
|
12
|
+
* fields' unions.
|
|
10
13
|
*/
|
|
11
14
|
unions?: string[];
|
|
12
15
|
/** Import path for the codegen-generated types. Default `./graphql`. */
|
|
@@ -14,12 +17,20 @@ export interface BlockPluginConfig {
|
|
|
14
17
|
/** Import path for the SDK content primitives. Default `@foir/sdk/content`. */
|
|
15
18
|
sdkImport?: string;
|
|
16
19
|
}
|
|
17
|
-
|
|
20
|
+
/** @deprecated Renamed to {@link ItemPluginConfig}. */
|
|
21
|
+
export type BlockPluginConfig = ItemPluginConfig;
|
|
18
22
|
export declare const DEFAULT_GRAPHQL_IMPORT = "./graphql";
|
|
19
23
|
export declare const DEFAULT_SDK_IMPORT = "@foir/sdk/content";
|
|
20
24
|
/**
|
|
21
|
-
* Collect the deduped, sorted set of object-type member names across the
|
|
22
|
-
* union(s)
|
|
23
|
-
*
|
|
25
|
+
* Collect the deduped, sorted set of object-type member names across the
|
|
26
|
+
* named union(s) — or, when no names are given, across every prose entries
|
|
27
|
+
* union in the schema (the unions whose members include `Passage`).
|
|
28
|
+
* `Passage` itself is excluded: the content renderer owns passage
|
|
29
|
+
* rendering, so no registry component exists for it.
|
|
30
|
+
*
|
|
31
|
+
* Throws when nothing resolves — that almost always means a misconfigured
|
|
32
|
+
* union name, or a schema with no prose fields that place models.
|
|
24
33
|
*/
|
|
25
|
-
export declare function
|
|
34
|
+
export declare function collectItemMembers(schema: GraphQLSchema, unionNames?: string[]): string[];
|
|
35
|
+
/** @deprecated Renamed to {@link collectItemMembers}. */
|
|
36
|
+
export declare const collectBlockMembers: typeof collectItemMembers;
|